Files
jjbruntonandClaude Fable 5 7a76936829 docs(agents): promote v1.0.8 release learnings
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>
2026-08-31 16:03:02 +01:00

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.