Skip to content

Commit 90d2a49

Browse files
committed
build: restore libc discriminator on linux lockfile entries
npm 11 silently strips the `libc` field from @optave/codegraph-linux-* entries in package-lock.json on `npm install`, even though the published packages declare it correctly. Without the discriminator, npm cannot tell linux-x64-gnu apart from linux-x64-musl when resolving the lockfile, so the wrong native binary may load on Alpine/musl hosts. Restore the field and add a CI guard (run before `npm install` in the lint job) that fails any PR which lands a lockfile missing the discriminator — Dependabot bumps and contributor installs would otherwise silently regress this again. Closes #1160
1 parent 81150e4 commit 90d2a49

3 files changed

Lines changed: 63 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ jobs:
2121
with:
2222
node-version: 22
2323

24+
# Runs before `npm install` because npm 11 silently strips the `libc`
25+
# field from optional-dependency lockfile entries (see #1160). If the
26+
# check ran post-install we'd flag every CI run instead of the PRs that
27+
# actually introduce the regression.
28+
- name: Verify lockfile libc discriminators
29+
run: node scripts/verify-lockfile-libc.mjs
30+
2431
- name: Install dependencies
2532
timeout-minutes: 20
2633
shell: bash

package-lock.json

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/verify-lockfile-libc.mjs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/env node
2+
// Verifies that @optave/codegraph-linux-* entries in package-lock.json declare
3+
// the `libc` discriminator. npm 11 silently strips this field when generating
4+
// the lockfile on non-Linux hosts (and sometimes on Linux too), even though the
5+
// published packages declare it. Without it, npm cannot disambiguate
6+
// linux-x64-gnu vs linux-x64-musl when resolving from the lockfile and may
7+
// install (or load) the wrong native binary on Alpine/musl hosts.
8+
//
9+
// Run via `npm run lint` (or directly) in CI to catch silent regressions from
10+
// Dependabot bumps and contributor `npm install` runs.
11+
import { readFileSync } from 'node:fs';
12+
13+
const EXPECTED_LIBC = {
14+
'@optave/codegraph-linux-arm64-gnu': 'glibc',
15+
'@optave/codegraph-linux-x64-gnu': 'glibc',
16+
'@optave/codegraph-linux-x64-musl': 'musl',
17+
};
18+
19+
const lock = JSON.parse(readFileSync('package-lock.json', 'utf8'));
20+
const failures = [];
21+
22+
for (const [pkgName, expectedLibc] of Object.entries(EXPECTED_LIBC)) {
23+
const entry = lock.packages?.[`node_modules/${pkgName}`];
24+
if (!entry) {
25+
failures.push(`${pkgName}: missing from package-lock.json`);
26+
continue;
27+
}
28+
const libc = entry.libc;
29+
if (!Array.isArray(libc) || !libc.includes(expectedLibc)) {
30+
failures.push(
31+
`${pkgName}: expected libc=["${expectedLibc}"], got ${JSON.stringify(libc)}`,
32+
);
33+
}
34+
}
35+
36+
if (failures.length > 0) {
37+
console.error('package-lock.json libc discriminator check failed:\n');
38+
for (const f of failures) console.error(` - ${f}`);
39+
console.error(
40+
'\nnpm install may have stripped the libc field. Restore it by editing\n' +
41+
'package-lock.json so each @optave/codegraph-linux-* entry includes\n' +
42+
'its libc field (see expected values above). Tracked in #1160.',
43+
);
44+
process.exit(1);
45+
}
46+
47+
console.log('package-lock.json libc discriminators OK');

0 commit comments

Comments
 (0)