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>
77 lines
2.8 KiB
Markdown
77 lines
2.8 KiB
Markdown
# Dependency and lockfile discipline
|
|
|
|
## Two npm realities
|
|
|
|
CI runners and the API Docker image use the node version pinned in
|
|
`.nvmrc` (node 20.19.4 with npm 10.8.2). A developer machine can run a newer
|
|
npm (for example npm 11). npm 10 and npm 11 resolve wildcard or range
|
|
dependencies differently at the same place in the dependency tree, and each
|
|
npm's platform-optional binary selection is not portable to a lockfile
|
|
regenerated by the other npm. A lockfile that passes `npm ci` under one npm
|
|
major version can fail it under the other with either an "Invalid: lock
|
|
file's ... does not satisfy" error or missing platform-optional binaries
|
|
(for example `@next/swc-linux-x64-gnu` breaking `next build`,
|
|
`@rollup/rollup-linux-x64-gnu` breaking the API Docker `tsup` build, or a
|
|
missing `lightningcss` variant breaking local `npm ci`).
|
|
|
|
## Pin wildcard-range dependencies with root overrides
|
|
|
|
When a transitive dependency declares a wildcard or wide range (for example
|
|
`react-native-worklets` depending on `@react-native/metro-config: "*"`), pin
|
|
the exact version the app needs in the root `package.json` `overrides` block
|
|
rather than leaving it to whichever npm resolved the lockfile last:
|
|
|
|
```json
|
|
"overrides": {
|
|
"rollup": "4.54.0",
|
|
"react-native": "0.85.3",
|
|
"expo": "~56.0.0",
|
|
"@react-native/metro-config": "0.85.3"
|
|
}
|
|
```
|
|
|
|
## Pin platform-optional binaries that must travel with the framework version
|
|
|
|
`apps/web/package.json` pins the `@next/swc` linux and darwin binaries as
|
|
direct `optionalDependencies` so npm does not have to infer them per
|
|
platform:
|
|
|
|
```json
|
|
"optionalDependencies": {
|
|
"@next/swc-linux-x64-gnu": "15.5.24",
|
|
"@next/swc-linux-x64-musl": "15.5.24",
|
|
"@next/swc-darwin-arm64": "15.5.24"
|
|
}
|
|
```
|
|
|
|
These versions must be bumped together with any `next` version bump, or the
|
|
pinned binaries will drift from the framework version and `npm ci` or
|
|
`next build` can fail on the platform that needs the stale binary.
|
|
|
|
## Validate a regenerated lockfile both ways
|
|
|
|
After changing `overrides` or any dependency version, regenerate
|
|
`package-lock.json` and validate it under both npm majors before committing:
|
|
|
|
```bash
|
|
# Local npm (matches this machine's npm major)
|
|
npm ci
|
|
npm run verify:fast
|
|
|
|
# The CI/Docker npm major, emulated on Apple Silicon
|
|
docker run --rm --platform linux/amd64 -v "$PWD:/repo" -w /repo node:20.19.4 npm ci
|
|
```
|
|
|
|
The `--platform linux/amd64` flag is mandatory on Apple Silicon: without it,
|
|
Docker runs the arm64 image and the platform-binary check proves nothing.
|
|
|
|
## After any bypassed push
|
|
|
|
Pushes to `staging` bypass required status checks. After any such push, check
|
|
`gh run list --branch staging` to confirm CI is actually green rather than
|
|
assuming it ran and passed.
|
|
|
|
Do not pipe `npm` commands through `tail` when diagnosing a lockfile or build
|
|
failure; it can swallow the command's exit code and the detail needed to find
|
|
the root cause.
|