chore: stop installing with --legacy-peer-deps - #215
adamjohnwright wants to merge 10 commits into
Conversation
It was on every install here -- CI, deploy, release verification, the Dockerfile, the local setup guide -- and the tree stopped needing it long ago. Measured 2026-09-16: `npm ci` on main resolves and installs strictly, 2109 packages, and a strict `npm install` leaves the lockfile untouched. It was not free while it stayed. It accepts an inconsistent tree, so a dependency bump that cannot resolve at all passed every check: Angular's packages peer-depend on one another at exact versions, dependabot's group moved eleven of them and left `platform-browser-dynamic` and `compiler-cli` behind, and CI was green. The only thing that objected was this repo's pre-push hook, which runs `npm ci` without the flag -- so the gate existed locally and not where it mattered. Removing it makes CI the check it was meant to be. A bump that cannot resolve now fails where it is raised rather than where someone happens to push from. CONTRIBUTING says why, so it is not added back the next time an install fails on peers. If an install fails on peer dependencies the tree is wrong; the fix is the versions, not telling npm to stop looking. Left alone deliberately: the Dockerfile still uses `npm install` rather than `npm ci`. Making container builds reproducible is worth doing and is a different change from this one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Do not merge this as it stands — the premise is wrong. I claimed So removing the flag breaks every CI run, which is exactly what this branch has What the finding is actually worthThe underlying point still holds — the flag masks broken dependency trees, and it The real fix is to align CI's Node with what developers run. CI is on 22 That deserves its own PR with its own testing, so this one should wait for it CorrectionThis is the second claim I have made from the wrong instrument today. Testing an |
`engines` pinned `node: 22.x` and `npm: >=10 <11`, which is why the lockfile and the local machine could not agree: npm 11 records optional platform packages that npm 10 leaves out, so a lockfile generated by either is a desync to the other. The pin was the cause, not the cure. Angular 21 declares `^20.19.0 || ^22.12.0 || >=24.0.0` and 24 is Latest LTS, so this moves engines, `.nvmrc`, all four workflows, both Dockerfiles and the local setup document to 24 together. **No dependency changes versions.** Compared across every path in the tree: 91 packages added, all of them optional platform binaries (@napi-rs/nice, @oxc-parser bindings, @emnapi); 0 removed; 0 that lost a version. Angular stays on 21.2.x throughout. `--legacy-peer-deps` stays, and now with a measured reason. Dropping it needs @analogjs/vitest-angular to move off 2.3.1, and letting npm re-resolve to get there dragged in 207 top-level version changes including React 18 -> 19 and @Angular-devkit 21 -> 22. That is a separate decision, not a side effect of changing Node. Recorded on #215. `scripts/preflight.sh` was running a bare `npm ci --dry-run` while every workflow installs with `--legacy-peer-deps`, so the gate whose whole job is to reproduce CI was running a different command and failing on a peer conflict the real build never sees. It now runs CI's command, and says which Node to run on. Verified: preflight green end to end on Node 24 / npm 11 — lockfile in sync, format, types, lint, dead code, unit tests, and the download smoke. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Measured while moving the project to Node 24 (#218), so the cost of dropping The blocker is one package. Letting npm re-resolve to clear it does work — a real
By contrast, keeping the flag and regenerating under npm 11 changes no So this is not a cleanup that can ride along with a Node bump. The honest #218 therefore keeps |
* chore(deps): move the whole Angular train to 21.2.23 Replaces dependabot's #161, which cannot be merged as it stands. That PR moves eleven Angular packages from 21.2.20 to 21.2.22 and leaves `@angular/platform-browser-dynamic` and `@angular/compiler-cli` behind. Angular's packages peer-depend on one another at **exact** versions, so the result does not resolve: Conflicting peer dependency: @angular/core@21.2.23 peer @angular/core@"21.2.23" from @angular/platform-browser-dynamic@21.2.23 Its checks pass only because CI installs with `--legacy-peer-deps`, which accepts an inconsistent tree. #215 removes that flag; after it, #161 fails honestly. So the train moves together: core, common, compiler, compiler-cli, forms, router, elements, localize, platform-browser and platform-browser-dynamic to 21.2.23, and the CLI train -- cli, ssr, build-angular -- to its own 21.2.23. The lockfile is regenerated from scratch rather than hand-resolved, because a partially-merged lock is what produced the conflict in the first place. It resolves **strictly**: `npm ci --dry-run` with no `--legacy-peer-deps`. Verified: 242 unit tests, types, lint 652, dead code 145, format, a full build, and 49 e2e cases against the resulting build -- interactors, the threshold, the custom-resource dialog, the homepage, content pages and the back button. The diagram is what an Angular bump would break, so it is what was exercised. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * chore(deps): move the whole Angular train to 21.2.23, on the right npm Two fixes, and the second explains why this branch failed CI all day. **The Angular train moves together.** Dependabot's #161 bumps eleven packages and leaves `platform-browser-dynamic` and `compiler-cli` behind; Angular's packages peer-depend at exact versions, so that set cannot resolve. Core, common, compiler, compiler-cli, forms, router, elements, localize, platform-browser and platform-browser-dynamic all go to 21.2.23, and the CLI train with them. **The lockfile is regenerated under Node 22, which is what CI runs.** I generated the first one on Node 24 / npm 11, and npm 10 rejected it: EBADPLATFORM lightningcss-android-arm64 wanted os "android", got linux npm 11 records optional platform packages in a shape npm 10 tries to install. Regenerated with `node:22` in docker, the android entries are `optional: true, os: ["android"]` and `npm ci` adds 2212 packages cleanly. `engines` is tightened from `>=22` to `22.x` so this cannot recur silently. `.nvmrc` has said 22 all along and CI has always used it; only `engines` was permissive enough to let a lockfile be written by the wrong npm. CONTRIBUTING records both failure signatures, because each looks like a dependency problem rather than a version problem. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * chore: run on Node 24, the LTS the toolchain already supports `engines` pinned `node: 22.x` and `npm: >=10 <11`, which is why the lockfile and the local machine could not agree: npm 11 records optional platform packages that npm 10 leaves out, so a lockfile generated by either is a desync to the other. The pin was the cause, not the cure. Angular 21 declares `^20.19.0 || ^22.12.0 || >=24.0.0` and 24 is Latest LTS, so this moves engines, `.nvmrc`, all four workflows, both Dockerfiles and the local setup document to 24 together. **No dependency changes versions.** Compared across every path in the tree: 91 packages added, all of them optional platform binaries (@napi-rs/nice, @oxc-parser bindings, @emnapi); 0 removed; 0 that lost a version. Angular stays on 21.2.x throughout. `--legacy-peer-deps` stays, and now with a measured reason. Dropping it needs @analogjs/vitest-angular to move off 2.3.1, and letting npm re-resolve to get there dragged in 207 top-level version changes including React 18 -> 19 and @Angular-devkit 21 -> 22. That is a separate decision, not a side effect of changing Node. Recorded on #215. `scripts/preflight.sh` was running a bare `npm ci --dry-run` while every workflow installs with `--legacy-peer-deps`, so the gate whose whole job is to reproduce CI was running a different command and failing on a peer conflict the real build never sees. It now runs CI's command, and says which Node to run on. Verified: preflight green end to end on Node 24 / npm 11 — lockfile in sync, format, types, lint, dead code, unit tests, and the download smoke. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
You were right that it reads like a workaround. It is one, and the tree stopped
needing it a long time ago.
It is not needed
Measured today on main, in a clean directory:
No flag, no failure. It appears to have come in with the first CI pipeline and was
never revisited.
It was not free
The flag accepts an inconsistent dependency tree, so a bump that cannot resolve
at all passed every check. Angular's packages peer-depend on one another at
exact versions; dependabot's group (#161) moved eleven of them and left
platform-browser-dynamicandcompiler-clibehind:Six green checks. The only thing that objected was this repo's pre-push hook,
which runs
npm ciwithout the flag — so the gate existed on a developer'smachine and not in CI, which is exactly backwards.
What changes
--legacy-peer-depsis removed from CI, deploy, release verification, theDockerfile and the local setup guide. CONTRIBUTING says why, so it is not added
back the next time an install fails on peers:
What this will do
It will make some future dependabot PRs fail, including #161 as it stands. That
is the point — they fail now at the PR that introduces them, rather than passing
and leaving a tree that only installs when you ask npm not to look.
Deliberately not in this PR
The Dockerfile still uses
npm installrather thannpm ci. Reproduciblecontainer builds are worth having and are a separate change from this one — I
started making it, noticed it was scope creep, and put it back.
🤖 Generated with Claude Code