Skip to content

chore: move the Angular train to 21.2.23 and run on Node 24 - #218

Open
adamjohnwright wants to merge 12 commits into
mainfrom
chore/angular-21-2-23
Open

adamjohnwright wants to merge 12 commits into
mainfrom
chore/angular-21-2-23

Conversation

@adamjohnwright

@adamjohnwright adamjohnwright commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Two changes that turned out to be the same problem.

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. This moves
the whole train to 21.2.23.

Node 24. engines pinned node: 22.x and npm: >=10 <11, which is why
the lockfile and a current machine could never agree — npm 11 records optional
platform packages npm 10 omits, so a lockfile from either is a desync to the
other. Angular 21 declares >=24.0.0 and 24 is Latest LTS, so engines,
.nvmrc, all four workflows, both Dockerfiles and the local setup doc move to
24 together.

No dependency changes version

Compared across every path in the tree, not just the top level:

purely added (new platform entries): 91
packages removed:                     0
packages that LOST a version:         0

The 91 are all optional platform binaries — @napi-rs/nice-*, @oxc-parser
bindings, @emnapi. Angular stays on 21.2.x throughout.

--legacy-peer-deps stays, and now we know why

Dropping it requires @analogjs/vitest-angular to move off 2.3.1, because that
is what pins vitest 3 against @angular/build's vitest 4. Letting npm
re-resolve to get there produced 207 top-level version changes, including
React 18 → 19, @angular-devkit 21 → 22, vite 6 → 7 and a batch of
downgrades. That is a separate decision, not a side effect of changing Node.
Noted on #215.

A gate that wasn't reproducing CI

scripts/preflight.sh ran a bare npm ci --dry-run while every workflow
installs with --legacy-peer-deps. The gate whose entire purpose is to catch
CI failures before the email was running a different command, and failing on a
peer conflict the real build never sees — the kind of false alarm that teaches
you to push with --no-verify. 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, download smoke.

Closes #161.

🤖 Generated with Claude Code

adamjohnwright and others added 12 commits September 16, 2026 17:56
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>
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>
`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>
@adamjohnwright adamjohnwright changed the title chore(deps): move the whole Angular train to 21.2.23 chore: move the Angular train to 21.2.23 and run on Node 24 Sep 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant