Skip to content

Commit 7d000a0

Browse files
fix(release): build musl in Alpine per step, not as the job container
GitHub runs its JavaScript actions inside the job container and refuses to do so for an Alpine image on an arm64 runner, so checkout failed outright and the aarch64-musl artifact was never built -- taking the whole publish down with it, since nothing ships until every platform does. The actions now run on the host and only the build enters Alpine. Both targets stay native builds on native hardware.
1 parent eb292da commit 7d000a0

1 file changed

Lines changed: 30 additions & 29 deletions

File tree

.github/workflows/release.yml

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,6 @@ jobs:
193193
build-musl:
194194
name: ${{ matrix.target }}
195195
runs-on: ${{ matrix.host }}
196-
container: node:22-alpine
197196
needs: guard
198197
strategy:
199198
fail-fast: false
@@ -202,39 +201,41 @@ jobs:
202201
- { host: ubuntu-latest, target: x86_64-unknown-linux-musl }
203202
- { host: ubuntu-24.04-arm, target: aarch64-unknown-linux-musl }
204203

205-
env:
206-
RUSTFLAGS: '-C target-feature=-crt-static'
207-
204+
# Alpine is entered per step rather than declared as the job's `container:`.
205+
# GitHub runs its JavaScript actions -- checkout and upload-artifact among
206+
# them -- inside the job container, and refuses to do that for an Alpine
207+
# image on an arm64 runner: "JavaScript Actions in Alpine containers are
208+
# only supported on x64 Linux runners". Keeping the actions on the host and
209+
# putting only the build in Alpine is what lets one job serve both
210+
# architectures, and both remain native builds on native hardware.
208211
steps:
209212
- uses: actions/checkout@v7
210213

211-
- name: Install toolchain
212-
run: apk add --no-cache build-base clang clang-dev llvm-dev rust cargo make bash python3 git
213-
214-
- name: Install dependencies
215-
run: npm ci --no-audit --no-fund
216-
working-directory: ${{ env.NODE_DIR }}
217-
218-
- name: Build the C hash engine
219-
run: make build-core BUILD_TYPE=release
220-
221-
- name: Build native addon
222-
run: npm run build
223-
working-directory: ${{ env.NODE_DIR }}
224-
225-
# The whole point of building in Alpine instead of cross-compiling.
226-
- name: Verify the artifact loads and computes
227-
run: node scripts/verify-artifact.js
228-
working-directory: ${{ env.NODE_DIR }}
229-
230-
# A native build is named by the host, so this is also the check that the
231-
# runner really was musl and not a glibc image that quietly stood in.
232-
- name: Confirm the artifact is the musl one
233-
shell: sh
214+
- name: Build and verify inside Alpine
234215
run: |
235-
cd "$NODE_DIR"
216+
cat > "$RUNNER_TEMP/build-musl.sh" <<'SCRIPT'
217+
set -eu
218+
apk add --no-cache build-base clang clang-dev llvm-dev rust cargo make bash python3 git
219+
cd "/work/$NODE_DIR"
220+
npm ci --no-audit --no-fund
221+
cd /work
222+
make build-core BUILD_TYPE=release
223+
cd "/work/$NODE_DIR"
224+
npm run build
225+
# The whole point of building in Alpine instead of cross-compiling.
226+
node scripts/verify-artifact.js
227+
# A native build is named by the host, so this is also the check that
228+
# the runner really was musl and not a glibc image standing in.
236229
ls *.node
237-
test -f retrigger-nodejs-bindings.$(node -p "process.arch === 'x64' ? 'linux-x64-musl' : 'linux-arm64-musl'").node
230+
test -f "retrigger-nodejs-bindings.$(node -p "process.arch === 'x64' ? 'linux-x64-musl' : 'linux-arm64-musl'").node"
231+
SCRIPT
232+
docker run --rm \
233+
-v "$PWD:/work" \
234+
-v "$RUNNER_TEMP/build-musl.sh:/build-musl.sh:ro" \
235+
-w /work \
236+
-e NODE_DIR="$NODE_DIR" \
237+
-e RUSTFLAGS='-C target-feature=-crt-static' \
238+
node:22-alpine sh /build-musl.sh
238239
239240
- uses: actions/upload-artifact@v7
240241
with:

0 commit comments

Comments
 (0)