From 8cc2cf0a5e9faf1a283cae5112ed9c60a16ca03c Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Fri, 18 Jul 2025 14:06:36 -0500 Subject: [PATCH] Fix Docker deployment with Gleam integration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Update gleam_compile task to handle missing mix_gleam/gleam binary - Add fallback to use pre-compiled BEAM files from priv/gleam - Include pre-compiled aprsme@encoding.beam for Docker builds - Update both Dockerfiles to ensure priv/gleam directory exists - Fix module name filter from "aprs@" to "aprsme@" in fallback logic This ensures Docker builds work without requiring gleam or mix_gleam to be installed in the production container. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- Dockerfile | 9 +++ Dockerfile.distroless | 12 ++++ .../erlang/aprsme/ebin/aprsme@encoding.beam | Bin 0 -> 4864 bytes lib/mix/tasks/gleam_compile.ex | 52 +++++++++++++----- priv/gleam/aprsme@encoding.beam | Bin 0 -> 4864 bytes test-docker-build.sh | 16 ++++++ 6 files changed, 75 insertions(+), 14 deletions(-) create mode 100644 build/dev/erlang/aprsme/ebin/aprsme@encoding.beam create mode 100644 priv/gleam/aprsme@encoding.beam create mode 100755 test-docker-build.sh diff --git a/Dockerfile b/Dockerfile index cf8f7c6..0f78669 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,6 +21,9 @@ WORKDIR /app # Install Hex and Rebar RUN mix local.hex --force && mix local.rebar --force +# Install mix_gleam archive (required for Gleam compilation) +RUN mix archive.install hex mix_gleam 0.6.2 --force + # Set build environment ENV MIX_ENV="prod" @@ -37,6 +40,12 @@ COPY priv priv COPY lib lib COPY assets assets COPY rel rel +# Copy Gleam source files and configuration +COPY src src +COPY gleam.toml gleam.toml +# Ensure pre-compiled Gleam BEAM files are available +# This helps when mix_gleam or gleam binary are not available +RUN mkdir -p priv/gleam # Compile assets RUN mix assets.deploy diff --git a/Dockerfile.distroless b/Dockerfile.distroless index 7512670..22f2ee7 100644 --- a/Dockerfile.distroless +++ b/Dockerfile.distroless @@ -26,11 +26,16 @@ WORKDIR /app RUN mix local.hex --force && \ mix local.rebar --force +# Install mix_gleam archive (required for Gleam compilation) +RUN mix archive.install hex mix_gleam 0.6.2 --force + # set build ENV ENV MIX_ENV="prod" # install mix dependencies COPY mix.exs mix.lock ./ +# Copy vendor directory for local dependencies +COPY vendor vendor RUN mix deps.get --only $MIX_ENV RUN mkdir config @@ -46,6 +51,13 @@ COPY lib lib COPY assets assets +# Copy Gleam source files and configuration +COPY src src +COPY gleam.toml gleam.toml +# Ensure pre-compiled Gleam BEAM files are available +# This helps when mix_gleam or gleam binary are not available +RUN mkdir -p priv/gleam + # compile assets RUN mix assets.deploy diff --git a/build/dev/erlang/aprsme/ebin/aprsme@encoding.beam b/build/dev/erlang/aprsme/ebin/aprsme@encoding.beam new file mode 100644 index 0000000000000000000000000000000000000000..1fb10cf1122569753aaae4ea4ca087f5a3ca67b1 GIT binary patch literal 4864 zcmbUlTWlOxb!KPRd+){*-`&}G^Kjyu*pA=!+DYs@NHdA!I4NyoHA#*5U_IWw>m7S{ zW|^7wgQoR{R8=bqq=6KT6p>I>MWPSViWVUi5n7NCs!CcY6a-Q$RaM1T6hSE}C7e4u zUT>3>kBoHoo;h>g=bqVn=Fri52LvJZ@qy9(ckg#j>=cB6Aqc`ygI2Wc0#lihHZ!_0 z9nYAlDcwnFmZdGG95a>IZKsY|dCi!{Q;QBu+4|R5{dAsbg_P}N^7>T63csD#(=1@l zu4aZ^vRH~OXlW}t`Zz06Z*kOy!G0SFa@|vR?1KfPc$?gO@ z7PuDijH;Y7lGXDLvr+}ESaC(IumopJ-B_Cj=ZsX^G#ty!r_wpi0xv*sJ?NXZv|^4G zm|a&<5d_tR23s?92jcQAHB>BBy~H3`F(3n$&6}E&vb8J=dGW3)YT$E)9JI{>3mT@u zFeDO~b8G=uv_THIo+-^{14DHcb#-}WOgp){Dc#VlMM=x&>wK9~vB<16@RFQnr{mTUNmW8Xd$AiNQ#)OPts=-B&aHJRcckE zEvl%v$#9ZfU=p1l|WIe zI}XCTO49CU*WOpZZla@3NEh=>;!c^lBE8k8O(f{Wro@=}PrEr=)v@(>wPT(k!C zZUC-0_XstHNm<34ytJc4IC;@UYs2KyE;#{)5>-P9Zm7|c*NA8hH`FdSj(NY*7$r&a zl$4;6O;SuyMAWE8nk!g>TU_g+bzqTF5v{vbtn+QT zns~is3hvU1yWn5T9z~|yyjdB_V*8> zE^6X&Z*~!dxZ5GqTl{^5HV1*(MO(roSt)soSMpXw-h~>qxTp;zI#m(1UXa@)$fz3W zf*wI_7v!zV%I($*a(m0lZTkheW82DYhZ^bTLY*$!3hH_w@m(%z_d8GS_F4~01T5Y4 zl&VTlmEwNmp$;#ZgOJR@YV8MkBKs}5M?^im_Acu5w&DPA4OF=Xe6C&*^}49b>(KZO z9UA9ZkGrVbvyue)WK}-t%lC<>&qY1Z*;glm$*AA0auooPlaI^l4`lUC8FtSd9q?Rim-pf32}$jd_f1IScnOGnEyId0Oh}U=+Q)Z_*Rv|$ zXdbrTy#z+LgV6&W@(5l6Bio@L2=v3`SwaF6Qt_1M4ZMpEK?V<1GkAz+aMY3yifF_| zJD`9lJ|UH{syq;)S0|J+_%ghGhTsORnUF4G71|l-(j{C5Bg0^XA_86KSy3*ZI!n2= zD^+V_U~Q~wZEVHbLC^6~bu3v4;SjjYb3F!H@029rm}4D>{~-}x)WVTM5pb~{&_)0W zAP67=K+_9#0G!4l0uTU@0agQW9{%4J1>p1;fKr360eqQ<>t5zb`1EzKuJ>^++XTSv zaJw4;xa?+tEk51?YikYO;p1GU7l7;MI1h`CACJSj*2fzTl?<+*%W=DW<@^T# zyepJ?;v67whV|%s{Z-)fyL5-k4g>66IG>)JoYVkj-(Y3o`Rq?$`)J=cj($2*zIHzP zh5vp~|FreTKRo&5f1b2Hc;)pb;kj>;_l3Keqk(Mi={(n(3(ON{Xj6HXNoC>O1?O1X zdoUj%JxNv^sV@FoMM(YLr z_p=S39)9-0%}XEtdGMW6PxYMJ{N5*{yWV(gyY}~^jrTA7_1c%Op8VJMatB|0sq<$K zKY!_=`!1rt}-Ek8PEmidrvEZvv-F~7yU19khmJ!Z^P%+S z5c@}REImv0ECd6iREg2NY0la-ug@~7I~1%@e*&X?0=reH{@kYBc4_Xf4UmtSFgbo+ zO`1kb1KQc~Q%@a}0ynM9l(+Kkvt#S+JE_+?83!jWjb1)2Q;(U# zT<*V$=)CUac*b?eDs0eOd4A()e*3aeNkk7e9a>#7nr0PvP_URs0(M4gM|u9ey3Zg`dOE;~(P}@K5jwJb`!O z{rCVL`9H51LEsezpUwmD^Tq0h>q!c$cS+YPmk=P-Ckf5hZ^D|Zv@+#q7=A5PX-idE Xv5GCN*r>1z`>M}=S$$UapZ(&0{EKY? literal 0 HcmV?d00001 diff --git a/lib/mix/tasks/gleam_compile.ex b/lib/mix/tasks/gleam_compile.ex index ef4fe73..4dcc0a2 100644 --- a/lib/mix/tasks/gleam_compile.ex +++ b/lib/mix/tasks/gleam_compile.ex @@ -79,21 +79,45 @@ defmodule Mix.Tasks.GleamCompile do Mix.shell().info("Gleam output directory #{gleam_output} does not exist") end else - # Last resort: try to copy from dev build if available - dev_ebin = "_build/dev/lib/aprsme/ebin" - test_ebin = "_build/#{env}/lib/aprsme/ebin" - - if File.exists?(dev_ebin) and env != :dev do - File.mkdir_p!(test_ebin) - - dev_ebin - |> File.ls!() - |> Enum.filter(&String.starts_with?(&1, "aprs@")) - |> Enum.each(fn beam_file -> - src = Path.join(dev_ebin, beam_file) - dest = Path.join(test_ebin, beam_file) + # Last resort: Check for pre-compiled BEAM files in priv/gleam + Mix.shell().info("No Gleam compiler available, checking for pre-compiled BEAM files...") + + priv_gleam = "priv/gleam" + ebin_dir = "_build/#{env}/lib/aprsme/ebin" + + if File.exists?(priv_gleam) do + File.mkdir_p!(ebin_dir) + + # Look specifically for our Gleam module + beam_file = "aprsme@encoding.beam" + src = Path.join(priv_gleam, beam_file) + + if File.exists?(src) do + dest = Path.join(ebin_dir, beam_file) File.copy!(src, dest) - end) + Mix.shell().info("Copied pre-compiled #{beam_file} from priv/gleam") + else + Mix.shell().error("Pre-compiled #{beam_file} not found in priv/gleam") + end + else + # Try to copy from dev build if available + dev_ebin = "_build/dev/lib/aprsme/ebin" + + if File.exists?(dev_ebin) and env != :dev do + File.mkdir_p!(ebin_dir) + + dev_ebin + |> File.ls!() + |> Enum.filter(&String.starts_with?(&1, "aprsme@")) + |> Enum.each(fn beam_file -> + src = Path.join(dev_ebin, beam_file) + dest = Path.join(ebin_dir, beam_file) + File.copy!(src, dest) + Mix.shell().info("Copied #{beam_file} from dev build") + end) + else + Mix.shell().error("Unable to find Gleam compiled files. Please ensure Gleam code is compiled before deployment.") + end end end end diff --git a/priv/gleam/aprsme@encoding.beam b/priv/gleam/aprsme@encoding.beam new file mode 100644 index 0000000000000000000000000000000000000000..1fb10cf1122569753aaae4ea4ca087f5a3ca67b1 GIT binary patch literal 4864 zcmbUlTWlOxb!KPRd+){*-`&}G^Kjyu*pA=!+DYs@NHdA!I4NyoHA#*5U_IWw>m7S{ zW|^7wgQoR{R8=bqq=6KT6p>I>MWPSViWVUi5n7NCs!CcY6a-Q$RaM1T6hSE}C7e4u zUT>3>kBoHoo;h>g=bqVn=Fri52LvJZ@qy9(ckg#j>=cB6Aqc`ygI2Wc0#lihHZ!_0 z9nYAlDcwnFmZdGG95a>IZKsY|dCi!{Q;QBu+4|R5{dAsbg_P}N^7>T63csD#(=1@l zu4aZ^vRH~OXlW}t`Zz06Z*kOy!G0SFa@|vR?1KfPc$?gO@ z7PuDijH;Y7lGXDLvr+}ESaC(IumopJ-B_Cj=ZsX^G#ty!r_wpi0xv*sJ?NXZv|^4G zm|a&<5d_tR23s?92jcQAHB>BBy~H3`F(3n$&6}E&vb8J=dGW3)YT$E)9JI{>3mT@u zFeDO~b8G=uv_THIo+-^{14DHcb#-}WOgp){Dc#VlMM=x&>wK9~vB<16@RFQnr{mTUNmW8Xd$AiNQ#)OPts=-B&aHJRcckE zEvl%v$#9ZfU=p1l|WIe zI}XCTO49CU*WOpZZla@3NEh=>;!c^lBE8k8O(f{Wro@=}PrEr=)v@(>wPT(k!C zZUC-0_XstHNm<34ytJc4IC;@UYs2KyE;#{)5>-P9Zm7|c*NA8hH`FdSj(NY*7$r&a zl$4;6O;SuyMAWE8nk!g>TU_g+bzqTF5v{vbtn+QT zns~is3hvU1yWn5T9z~|yyjdB_V*8> zE^6X&Z*~!dxZ5GqTl{^5HV1*(MO(roSt)soSMpXw-h~>qxTp;zI#m(1UXa@)$fz3W zf*wI_7v!zV%I($*a(m0lZTkheW82DYhZ^bTLY*$!3hH_w@m(%z_d8GS_F4~01T5Y4 zl&VTlmEwNmp$;#ZgOJR@YV8MkBKs}5M?^im_Acu5w&DPA4OF=Xe6C&*^}49b>(KZO z9UA9ZkGrVbvyue)WK}-t%lC<>&qY1Z*;glm$*AA0auooPlaI^l4`lUC8FtSd9q?Rim-pf32}$jd_f1IScnOGnEyId0Oh}U=+Q)Z_*Rv|$ zXdbrTy#z+LgV6&W@(5l6Bio@L2=v3`SwaF6Qt_1M4ZMpEK?V<1GkAz+aMY3yifF_| zJD`9lJ|UH{syq;)S0|J+_%ghGhTsORnUF4G71|l-(j{C5Bg0^XA_86KSy3*ZI!n2= zD^+V_U~Q~wZEVHbLC^6~bu3v4;SjjYb3F!H@029rm}4D>{~-}x)WVTM5pb~{&_)0W zAP67=K+_9#0G!4l0uTU@0agQW9{%4J1>p1;fKr360eqQ<>t5zb`1EzKuJ>^++XTSv zaJw4;xa?+tEk51?YikYO;p1GU7l7;MI1h`CACJSj*2fzTl?<+*%W=DW<@^T# zyepJ?;v67whV|%s{Z-)fyL5-k4g>66IG>)JoYVkj-(Y3o`Rq?$`)J=cj($2*zIHzP zh5vp~|FreTKRo&5f1b2Hc;)pb;kj>;_l3Keqk(Mi={(n(3(ON{Xj6HXNoC>O1?O1X zdoUj%JxNv^sV@FoMM(YLr z_p=S39)9-0%}XEtdGMW6PxYMJ{N5*{yWV(gyY}~^jrTA7_1c%Op8VJMatB|0sq<$K zKY!_=`!1rt}-Ek8PEmidrvEZvv-F~7yU19khmJ!Z^P%+S z5c@}REImv0ECd6iREg2NY0la-ug@~7I~1%@e*&X?0=reH{@kYBc4_Xf4UmtSFgbo+ zO`1kb1KQc~Q%@a}0ynM9l(+Kkvt#S+JE_+?83!jWjb1)2Q;(U# zT<*V$=)CUac*b?eDs0eOd4A()e*3aeNkk7e9a>#7nr0PvP_URs0(M4gM|u9ey3Zg`dOE;~(P}@K5jwJb`!O z{rCVL`9H51LEsezpUwmD^Tq0h>q!c$cS+YPmk=P-Ckf5hZ^D|Zv@+#q7=A5PX-idE Xv5GCN*r>1z`>M}=S$$UapZ(&0{EKY? literal 0 HcmV?d00001 diff --git a/test-docker-build.sh b/test-docker-build.sh new file mode 100755 index 0000000..ce15203 --- /dev/null +++ b/test-docker-build.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -e + +echo "Testing Docker build with Gleam support..." + +# Build the Docker image +echo "Building Docker image..." +docker build -t aprsme-test:latest . + +echo "Docker build completed successfully!" + +# Test if the image runs +echo "Testing if the image can run..." +docker run --rm aprsme-test:latest bin/aprsme eval "IO.puts(:ok)" + +echo "All tests passed!" \ No newline at end of file