How to move all
@angular-builders/*packages and example apps to a new Angular major. Runs ~twice a year. Designed to be executed by an agent following these steps — the scripts handle the mechanical bumps; the agent handles the judgment (resolving internal-API breakage, fixing example apps, migration coverage).
A new Angular major reaches RC (start prework so PRs are ready when GA lands) or GA. Builder major versions track the Angular major 1:1.
- Mechanical (scripts):
scripts/update-package.js(bumps builder Angular dep ranges) andscripts/update-example.js(runsng updateper example). Invoked viayarn update:packages <N>/yarn update:examples <N>, or theupdate.ymlworkflow dispatch. - Judgment (agent): resolve internal-API moves and schema changes that break builders, fix example apps, ensure migration coverage, handle RC→GA.
- Clean root install:
yarn install(a stalenode_modulesbreaks Husky hooks — e.g.yarn commitlintnot resolving — and builds). - Node satisfies the target Angular's requirement (Angular 20+:
^20.19 || ^22.12 || >=24).
Create a long-lived integration branch off master:
git checkout master && git checkout -b release/v<N>All v<N>-bound feature branches and held breaking PRs (breaking-change label) base on / rebase onto this branch. When GA lands and the branch is green, it merges to master.
yarn update:packages <N> # e.g. 22update-package.js sets stable deps (@angular/build, @angular-devkit/build-angular, @angular-devkit/core, @angular/compiler[-cli]) to ^<N>.0.0 and @angular-devkit/architect to >=0.<N>00.0 < 0.<N+1>00.0.
Root
resolutions(auto-maintained): the rootpackage.jsonpins@angular-devkit/architectand@angular-devkit/coreto exact versions (added in PR #2307) to stop the builders' wide architect range from re-resolving to an older architect than@angular/buildpins for a given patch train — the duplicate architect produces twoBuilderContext/Loggertype identities that break thecustom-esbuildtsc build.update-package.jsrewrites these pins only when given an explicit version with a minor/patch (e.g.yarn update:packages 22.1.0), since exact pins need a precise version:@angular-devkit/coregets the plain version (22.1.0),@angular-devkit/architectgets the0.<major><minor padded to 2>.<patch>form (22.1.0→0.2201.0,22.0.3→0.2200.3, prerelease tags carried). A bare major (yarn update:packages 22) leaves the pins untouched and logs a notice — so after a bare-major bump, verify the pins by hand or re-run with the full version. On a major where the duplication no longer occurs, drop theresolutionsblock deliberately.
RC caveat (current tooling gap): the script takes an integer major and writes
^<N>.0.0, which by semver excludes prereleases like<N>.0.0-rc.2. For RC prework you must either (a) temporarily pin the explicit RC versions, or (b) extendupdate-package.js/update-example.jsto accept an explicit version/tag (recommended — makes RC prework first-class and agent-runnable).@angular/cli@nextresolves to the current RC;@angular/cli@<N>resolves to the latest stable<N>(nonexistent during RC).
yarn update:examples <N>Runs npx @angular/cli@<N> update @angular/core@<N> @angular/cli@<N> --create-commits in each examples/* app (~7: custom-esbuild ×2, custom-webpack ×3, jest ×2). For RC, target @next/explicit RC per the caveat above. Review each app's generated commit.
yarn install
yarn build:packages:all
yarn test:local # integration matrix against examples/*This is the judgment core. Expect breakage in the packages layer — internal Angular API moves (renamed/moved packages or exports) and builder-option schema changes are the most common (see packages/AGENTS.md). Fix per-package, rebuild, re-run until green.
For the major, enumerate every breaking-change-labeled PR targeting it (gh pr list --label breaking-change). For each breaking change, confirm BOTH exist:
- a migration step (auto-transform or logged advisory) in the builder's
migrations.json(see the builder-schematics design +@angular-builders/common/schematics), and - a
MIGRATION.MDentry for the major, annotated ✅ automated byng updatevs⚠️ manual.
This is an invariant: a breaking change must not land in a major without both. CHANGELOGs are auto-generated from commits (orthogonal).
Validated against @angular/cli@22.0.0-rc.2 on 2026-06-03 via the ng-update-jest-v21-smoke e2e
(scripts/e2e-jest-migration.js):
ng update @angular-builders/jest --migrate-only --from=20.0.0 --to=22.0.0runs all migrations whose version falls in the(from, to]window in one step — observedmigration-v21(the heavy config transform) and themigration-v22advisory both firing. So a user on an old major who jumps straight to 22 gets the spanned migrations; they are not skipped.- Supported flow for older users: upgrade the Angular framework to 22, then run
ng update @angular-builders/jestonce (or--migrate-only --from=<old>to run only the builder's migrations). The post-migration config builds and tests green under v22 — proven by the e2e, which runsng build+ng teston the migrated app. - E2E coverage of the migration output itself lives in
packages/jest/tests/integration.js(ng-update-jest-v21-smoke); the ng-add paths are theng-add-*entries there and in thecustom-esbuild/custom-webpackintegration files.
Develop/rebase v<N>-bound features (e.g. schematics) and held breaking PRs on release/v<N>.
When the major reaches GA: bump ranges from RC to final (update:packages <N> now resolves stable), re-run install + matrix, finalize MIGRATION.MD, merge release/v<N> → master, then graduate-publish (CI dispatch release_type: graduate).
- Internal API moves in
@angular/build/@angular-devkit/*— imports the builders rely on get renamed/relocated (~every major). Felt inpackages/*/src. - Schema/option changes in Angular's base builder schemas — affects
custom-esbuild/custom-webpackschema merging (merge-schemes.ts) and option pass-through. - Jest/test toolchain majors (jest-preset-angular, Jest) — historically large (see jest
@21migration).
- Scripts:
scripts/update-package.js,scripts/update-example.js,scripts/AGENTS.md - Workflow:
.github/workflows/update.yml(manual dispatch, input = version) - Per-major user guide:
MIGRATION.MD - Breakage context:
packages/AGENTS.md, rootAGENTS.md→ "Angular Major Version Upgrade Process"