6666 # (used by mdex_native) downloads the correct precompiled NIF for the
6767 # target platform. Cross-compiling from Ubuntu caused the Linux NIF to
6868 # be bundled into macOS/Windows releases, making MDEx unavailable at
69- # runtime (see CRY-40).
69+ # runtime (see CRY-40). Linux targets also get a pre-compile step that
70+ # forces the musl NIF variant, since Ubuntu runners auto-select the
71+ # glibc NIF but Burrito Linux binaries run on musl-based systems (see
72+ # EXT-7).
7073 matrix :
7174 include :
7275 - target : macos_aarch64
@@ -104,6 +107,27 @@ jobs:
104107 version : " 0.16.0"
105108 -
106109 run : mix deps.get
110+ -
111+ # rustler_precompiled resolves the NIF target at compile time from
112+ # :erlang.system_info(:system_architecture), which is always glibc on
113+ # Ubuntu runners. Burrito bundles its own musl runtime for Linux and
114+ # the container runs Alpine - both need the musl NIF, not glibc.
115+ # TARGET_ABI=musl tells rustler_precompiled to download the musl
116+ # variant. cc_precompiler (used by exqlite) also reads TARGET_ABI, but
117+ # is safe here for two reasons: (a) the env: block is step-scoped, so
118+ # mix release in the next step does not inherit TARGET_ABI, and (b) mix
119+ # deps.compile only compiles the named deps, not exqlite, so
120+ # cc_precompiler never runs during this step. mix release sees mdex_native already
121+ # compiled and skips it, bundling the musl .so from _build/prod.
122+ # rustler_precompiled is listed first because mix deps.compile only
123+ # compiles the named deps (not their transitive deps), and mdex_native
124+ # uses it via `use RustlerPrecompiled` at compile time. See EXT-7.
125+ if : startsWith(matrix.target, 'linux_')
126+ name : Pre-compile mdex_native with the musl NIF
127+ env :
128+ MIX_ENV : prod
129+ TARGET_ABI : musl
130+ run : mix deps.compile rustler_precompiled mdex_native
107131 -
108132 name : Build the ${{ matrix.target }} target
109133 run : MIX_ENV=prod BURRITO_TARGET=${{ matrix.target }} mix release lc
@@ -316,6 +340,17 @@ jobs:
316340 -
317341 run : mix deps.get
318342 working-directory : app
343+ -
344+ # Same reasoning as the burrito-build pre-compile step: Ubuntu runners
345+ # default to the glibc NIF, but the container image runs Alpine (musl).
346+ # rustler_precompiled listed first for the same reason as there. See
347+ # EXT-7.
348+ name : Pre-compile mdex_native with the musl NIF
349+ env :
350+ MIX_ENV : prod
351+ TARGET_ABI : musl
352+ run : mix deps.compile rustler_precompiled mdex_native
353+ working-directory : app
319354 -
320355 name : Build the linux_x86_64 target (container's payload)
321356 run : MIX_ENV=prod BURRITO_TARGET=linux_x86_64 mix release lc
@@ -325,6 +360,22 @@ jobs:
325360 env :
326361 APP_VERSION : ${{ needs.burrito-package.outputs.tag_name }}
327362 run : ./ci/build_image.sh "${{ needs.burrito-package.outputs.tag_name }}"
363+ -
364+ # Verify the musl NIF actually loads on Alpine before publishing.
365+ # Analogous to the linux_aarch64 native smoke test in burrito-build:
366+ # `lc version` boots the OTP app, loads all NIFs (exqlite via
367+ # elixir_make/Zig, mdex_native via rustler_precompiled with the musl
368+ # NIF bundled by the pre-compile step above), prints the version, and
369+ # exits 0. No API key or network needed. ci/build_image.sh prefers
370+ # Podman, so the image lives in Podman's local storage; we run it
371+ # directly rather than loading a tarball. LINEAR_CLI_DAEMON is
372+ # overridden to false (the image bakes in true so the default CMD
373+ # starts the daemon; without this override the app ignores `version`
374+ # and stays alive as a daemon, timing out the step). See EXT-7.
375+ name : Smoke-test the container image boots and NIFs load on Alpine/musl
376+ timeout-minutes : 1
377+ run : |
378+ podman run --rm -e LINEAR_CLI_DAEMON=false "linear-cli:${{ needs.burrito-package.outputs.tag_name }}" lc version
328379 -
329380 # ci/build_image.sh prefers Podman over Docker (both are present on
330381 # GitHub-hosted runners), so the image above lives only in Podman's
0 commit comments