Skip to content

Commit 3942675

Browse files
auxesisclaude
andcommitted
ci: check each Linux auth binary's C library as it is built
Only auth-preflight.yml read which C library each Linux binary links, and nothing runs it automatically. release.yml's publish-auth job builds through _build-auth-artifacts.yml and publishes, so a musl binary that links glibc would have published unless someone ran the preflight first. That is how the suite shipped its broken one. Run the same readelf check in _build-auth-artifacts.yml, after each Linux build and before the package is packed: the gnu binaries must need libc.so.6, and the musl binary must not. A test checks the step comes before the pack and covers both rules. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PaY5xYydZUWhv8Nex9Sw8a
1 parent 9fda367 commit 3942675

2 files changed

Lines changed: 46 additions & 0 deletions

File tree

‎.github/workflows/_build-auth-artifacts.yml‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,32 @@ jobs:
152152
mv "stack-auth-node.${PLATFORM}.node" "platforms/${PLATFORM}/"
153153
test -s "platforms/${PLATFORM}/stack-auth-node.${PLATFORM}.node"
154154
155+
# Every build checks which C library its binary links, so a release
156+
# cannot publish a musl binary that links glibc even if nobody ran
157+
# auth-preflight first. The same check as auth-preflight.yml's smoke test.
158+
# Into a variable, never into `grep -q`, so readelf cannot die on EPIPE.
159+
- name: Check which C library the binary links
160+
if: ${{ runner.os == 'Linux' }}
161+
working-directory: languages/typescript/packages/auth
162+
env:
163+
PLATFORM: ${{ matrix.platform }}
164+
run: |
165+
set -euo pipefail
166+
dynamic=$(readelf -d "platforms/${PLATFORM}/stack-auth-node.${PLATFORM}.node")
167+
case "$PLATFORM" in
168+
linux-x64-gnu|linux-arm64-gnu)
169+
grep -q 'NEEDED.*libc\.so\.6' <<< "$dynamic" || {
170+
echo "::error::$PLATFORM does not link glibc"; exit 1; } ;;
171+
linux-x64-musl)
172+
if grep -q 'NEEDED.*libc\.so\.6' <<< "$dynamic" ; then
173+
echo "::error::linux-x64-musl links glibc — it is the gnu binary"
174+
exit 1
175+
fi ;;
176+
*)
177+
echo "::error::no C library rule for $PLATFORM"; exit 1 ;;
178+
esac
179+
echo "$PLATFORM: links the expected C library"
180+
155181
# `npm pack`, not `pnpm pack`: a platform package has no `workspace:`
156182
# dependency to rewrite. The wrapper does, and is packed with pnpm below.
157183
- name: Pack the platform package

‎scripts/__tests__/auth-build-artifacts.test.mjs‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,26 @@ describe('_build-auth-artifacts.yml', () => {
8989
expect(run).toContain('RUSTFLAGS=-C target-feature=-crt-static')
9090
})
9191

92+
it('checks the C library of every Linux binary before it is packed', () => {
93+
// Without this, only a hand-run auth-preflight sees a glibc-linked musl
94+
// binary, and a release would publish it.
95+
const steps = binaries?.steps ?? []
96+
const check = steps.findIndex((step) =>
97+
String(step?.run ?? '').includes('readelf -d'),
98+
)
99+
const pack = steps.findIndex((step) =>
100+
/\bnpm pack\b/.test(String(step?.run ?? '')),
101+
)
102+
expect(check).toBeGreaterThan(-1)
103+
expect(check).toBeLessThan(pack)
104+
const run = String(steps[check].run)
105+
expect(String(steps[check].if)).toContain("runner.os == 'Linux'")
106+
expect(run).toMatch(
107+
/linux-x64-gnu\|linux-arm64-gnu\)[\s\S]*libc\\\.so\\\.6/,
108+
)
109+
expect(run).toContain('linux-x64-musl links glibc')
110+
})
111+
92112
it('pins the same musl toolchain as the FFI build', () => {
93113
const ffi = readFileSync(
94114
join(REPO_ROOT, '.github/workflows/_build-ffi-artifacts.yml'),

0 commit comments

Comments
 (0)