Skip to content

Commit 9fda367

Browse files
auxesisclaude
andcommitted
fix(ci): link the musl @cipherstash/auth binary with musl
The linux-x64-musl leg of _build-auth-artifacts.yml targeted x86_64-unknown-linux-musl but had no musl linker, so cargo linked the binary against the runner's glibc. auth-preflight's libc check caught it: "linux-x64-musl links glibc — it is the gnu binary". Such a binary fails to load on musl systems such as Alpine. The suite's published @cipherstash/auth-linux-x64-musl 0.44.0 has the same fault, because its workflow built musl the same way. Mirror _build-ffi-artifacts.yml, whose musl binary passes the same check: fetch the musl.cc toolchain with its pinned digest, link with x86_64-linux-musl-gcc, and turn off crt-static so the binary links musl dynamically. Tests check the musl leg's setup, and that both workflows pin the same toolchain digest. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PaY5xYydZUWhv8Nex9Sw8a
1 parent 4f11f41 commit 9fda367

2 files changed

Lines changed: 53 additions & 3 deletions

File tree

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

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,34 @@ jobs:
6565
ref: ${{ inputs.ref }}
6666
persist-credentials: false
6767

68-
- name: Install musl tools (linux-x64-musl)
68+
# The musl leg must LINK with musl, not only target it. With musl-tools
69+
# alone, cargo linked the binary against the runner's glibc, and the
70+
# published linux-x64-musl package failed to load on musl systems; the
71+
# suite's 0.44.0 has that fault. This mirrors _build-ffi-artifacts.yml,
72+
# whose musl binary passes the same libc check in its preflight.
73+
#
74+
# The toolchain is fetched from musl.cc over plain HTTPS with no
75+
# signature, and it links a binary published with provenance, so the
76+
# digest is pinned: the same tarball and digest as _build-ffi-artifacts.yml.
77+
# If musl.cc rebuilds it, this step fails; re-verify the new tarball and
78+
# update both digests, do not delete the check.
79+
- name: Install the musl toolchain (linux-x64-musl)
6980
if: ${{ matrix.platform == 'linux-x64-musl' }}
81+
env:
82+
MUSL_TOOLCHAIN_URL: https://musl.cc/x86_64-linux-musl-native.tgz
83+
MUSL_TOOLCHAIN_SHA256: eb1db6f0f3c2bdbdbfb993d7ef7e2eeef82ac1259f6a6e1757c33a97dbcef3ad
7084
run: |
7185
set -euo pipefail
72-
sudo apt-get update
73-
sudo apt-get install -y musl-tools
86+
wget -4 -O musl-native.tgz "$MUSL_TOOLCHAIN_URL"
87+
echo "${MUSL_TOOLCHAIN_SHA256} musl-native.tgz" | sha256sum -c - || {
88+
echo "::error::musl toolchain digest mismatch — got $(sha256sum musl-native.tgz | cut -d' ' -f1)"
89+
exit 1; }
90+
sudo tar zxf musl-native.tgz -C /opt/
91+
echo "/opt/x86_64-linux-musl-native/bin" >> "$GITHUB_PATH"
92+
echo "CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER=x86_64-linux-musl-gcc" >> "$GITHUB_ENV"
93+
# Keeps the binary dynamically linked against musl, which a shared
94+
# library needs, and which auth-preflight.yml's libc check reads.
95+
echo "RUSTFLAGS=-C target-feature=-crt-static" >> "$GITHUB_ENV"
7496
7597
# Rust 1.94.1 from the root mise.toml, the toolchain the crate is tested
7698
# with. `cache: false` is required here, not a default.

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,34 @@ describe('_build-auth-artifacts.yml', () => {
7373
expect(check).toBeGreaterThan(build)
7474
})
7575

76+
it('links the musl binding with musl, from a pinned toolchain', () => {
77+
// Targeting musl is not enough: without a musl linker, cargo links the
78+
// binary against the runner's glibc, and it fails to load on musl.
79+
const musl = (binaries?.steps ?? []).filter((step) =>
80+
String(step?.if ?? '').includes("'linux-x64-musl'"),
81+
)
82+
const run = musl.map((step) => String(step?.run ?? '')).join('\n')
83+
const env = Object.assign({}, ...musl.map((step) => step?.env ?? {}))
84+
expect(env.MUSL_TOOLCHAIN_SHA256).toMatch(/^[0-9a-f]{64}$/)
85+
expect(run).toContain('sha256sum -c')
86+
expect(run).toContain(
87+
'CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER=x86_64-linux-musl-gcc',
88+
)
89+
expect(run).toContain('RUSTFLAGS=-C target-feature=-crt-static')
90+
})
91+
92+
it('pins the same musl toolchain as the FFI build', () => {
93+
const ffi = readFileSync(
94+
join(REPO_ROOT, '.github/workflows/_build-ffi-artifacts.yml'),
95+
'utf8',
96+
)
97+
const digest = (text) =>
98+
text.match(/MUSL_TOOLCHAIN_SHA256: ([0-9a-f]{64})/)?.[1]
99+
const auth = readFileSync(join(REPO_ROOT, WORKFLOW), 'utf8')
100+
expect(digest(auth)).toBeDefined()
101+
expect(digest(auth)).toBe(digest(ffi))
102+
})
103+
76104
it('packs the wrapper with pnpm, which rewrites its workspace peers', () => {
77105
const packs = runs(wrapper).filter((run) => /\bpack\b/.test(run))
78106
expect(packs.some((run) => /\bpnpm\b.*\bpack\b/.test(run))).toBe(true)

0 commit comments

Comments
 (0)