mirror of
https://github.com/jjbrunton/Sauci.git
synced 2026-10-31 18:19:43 +00:00
Record three confirmed v1.0.8 failure modes (expo prebuild native regressions, npm 10/11 lockfile divergence, local EAS build preconditions) and promote each into docs/releasing.md, a new docs/development/dependencies.md, and the release-preflight script. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
56 lines
2.4 KiB
Markdown
56 lines
2.4 KiB
Markdown
---
|
|
id: 2026-08-31-npm-lockfile-divergence
|
|
date: 2026-08-31
|
|
status: promoted
|
|
scope: root package.json, package-lock.json, apps/web dependencies, CI
|
|
evidence: v1.0.8 lockfile investigation, commits 90cde4a, 9609a90
|
|
destination: docs/development/dependencies.md
|
|
review_after: 2026-11-30
|
|
---
|
|
|
|
## Symptom
|
|
|
|
CI and the API Docker image (node 20.19.4/npm 10.8.2, per .nvmrc) broke
|
|
invisibly while a lockfile regenerated on this dev machine (node 26/npm
|
|
11.19) passed local `npm ci`. Pushes to staging bypass required status
|
|
checks, so the red CI ran unnoticed for hours.
|
|
|
|
## Reproduction
|
|
|
|
Regenerate package-lock.json with npm 11 on a wildcard-range dependency
|
|
(react-native-worklets depends on `@react-native/metro-config: "*"`), then
|
|
run `npm ci` under node 20.19.4/npm 10.8.2. npm 10 requires 0.85.3 at that
|
|
tree position; npm 11 resolves/hoists 0.87.x there. `npm ci` fails with
|
|
"Invalid: lock file's ... does not satisfy". The reverse direction also
|
|
fails: a lock regenerated by npm 10 fails `npm ci` under npm 11 with missing
|
|
platform-optional binaries (@next/swc-linux-x64-gnu breaking `next build`,
|
|
@rollup/rollup-linux-x64-gnu breaking the API Docker tsup build, lightningcss
|
|
variants breaking local npm ci), matching the npm/cli#4828-style
|
|
optional-dependency resolution gap.
|
|
|
|
## Cause
|
|
|
|
Two different npm major versions in active use (CI/Docker on npm 10, this
|
|
dev machine on npm 11) resolve wildcard/range dependencies to different
|
|
versions at the same tree position, and each npm's own platform-optional
|
|
binary selection is not portable to the other npm's lockfile.
|
|
|
|
## Remediation
|
|
|
|
Pin the wildcard-range dependency via a root package.json override
|
|
(`"@react-native/metro-config": "0.85.3"`, alongside the existing
|
|
rollup/react-native/expo pins). Pin apps/web `@next/swc` linux/darwin
|
|
binaries as direct optionalDependencies (must be bumped together with any
|
|
`next` version bump). Regenerate the lock and validate it both ways: local
|
|
`npm ci` plus `npm run verify:fast`, and
|
|
`docker run --platform linux/amd64 node:20.19.4 ... npm ci` (the
|
|
`--platform` flag is mandatory; Apple Silicon Docker otherwise runs arm64
|
|
and the platform-binary check is meaningless). After any push that bypassed
|
|
required status checks, check `gh run list --branch staging`.
|
|
|
|
## Evidence
|
|
|
|
commits 90cde4a and 9609a90 add the override and optionalDependencies pins
|
|
and record a lockfile that passes both the amd64-emulated `npm ci` under
|
|
node 20.19.4 and local `npm ci` plus `npm run verify:fast`.
|