Skip to content

Upgrade to Angular 22 + TypeScript 6.0 - #5445

Merged
norman-abramovitz merged 4 commits into
cloudfoundry:developfrom
nabramovitz:try/angular-22-upgrade
Jun 14, 2026
Merged

Upgrade to Angular 22 + TypeScript 6.0#5445
norman-abramovitz merged 4 commits into
cloudfoundry:developfrom
nabramovitz:try/angular-22-upgrade

Conversation

@nabramovitz

Copy link
Copy Markdown
Contributor

Upgrades the frontend from Angular 21.2 to Angular 22.0.1 and TypeScript 6.0, with two follow-on cleanups. Three commits, each independently green.

1. Angular 22 + TypeScript 6.0 (ba9166c1)

  • Bumps Angular / CDK / CLI / devkit / @angular-eslint → 22; @analogjs/* → 2.6.1 (the package that unblocked this — supports Angular 22 and keeps vitest 4, so no zoneless/NG0203 regression); ng2-charts 8 → 10; @angular-builders/custom-webpack → 22; TypeScript 5.9 → 6.0 (required by Angular 22).
  • Mostly the ng update migration (safe-navigation wrapping, hydration/withXhr).
  • Key decision: Angular 22's builder defaults strict on; this codebase runs non-strict, so the base tsconfig explicitly opts back out (strict/strictNullChecks/strictPropertyInitialization: false) to keep the upgrade behavior-neutral. The latent strict-null findings this surfaces are deferred to a dedicated workstream (see below). Also adds ignoreDeprecations: "6.0" for baseUrl.

2. OnPush migration + strict-null down-payment (c16bbfed)

  • Converts the 21 components still on the renamed ChangeDetectionStrategy.Eager (Angular 22's rename of legacy Default) to OnPush, and restores @angular-eslint/prefer-on-push-component-change-detection to error (0 violations).
  • As a down-payment on the broader strict-null work, the same 21 components are made strict-null clean (10 fixes: definite-assignment on @Input/lifecycle props, real null-guards in kubernetes-node-summary-card, removed a dead field).

3. ESLint warning cleanup (8237b6dc)

  • Clears 47 safe warnings (107 → 60): ~43 dead imports/spec locals removed, _-prefixed unused caught-error/param, regex-escape + letconst. No behavior change.

Validation (all three commits)

  • ✅ Production build: 0 errors
  • ✅ Vitest: 2604 passed / 0 failed (no NG0203 under zoneless)
  • ✅ ESLint: 0 errors, 60 warnings

Deferred (tracked separately)

  • Global strict-null flip (~1295 latent findings) — the real strict-mode adoption, its own workstream.
  • Remaining 60 ESLint warnings@Output/@Input renames, template a11y, prefer-standalone/prefer-inject, etc.
  • Backend Go tests + E2E not run here (orthogonal to a frontend framework bump).

Bumps Angular 21.2.16 -> 22.0.1 and TypeScript 5.9 -> 6.0 (required by
Angular 22), plus the supporting toolchain: @angular/build, CDK, CLI,
@Angular-devkit, @angular-eslint -> 22; @analogjs/* -> 2.6.1 (Angular 22
+ vitest 4 support, which unblocked this upgrade); ng2-charts 8 -> 10;
@angular-builders/custom-webpack -> 22.

Most of the diff is the `ng update` migration (safe-navigation wrapping,
provideClientHydration/withXhr migrations). Three deliberate config
decisions make it green while preserving current behavior:

- src/tsconfig.json: explicitly set strict/strictNullChecks/
  strictPropertyInitialization: false. Angular 22's builder flips strict
  on by default; the codebase runs non-strict today, so this opts back
  out to keep the upgrade behavior-neutral. The ~1295 latent strict-null
  findings this surfaces are tracked as a separate modernization ticket.
- src/tsconfig.json: ignoreDeprecations "6.0" for the deprecated baseUrl
  (TS 6.0 hard-errors otherwise).
- eslint.config.mjs: downgrade @angular-eslint/prefer-on-push-component-
  change-detection to warn (Angular 22 promoted it to error). Adopting
  OnPush across the 21 flagged components is a separate ticket.

Also strips the migration's self-contradictory extendedDiagnostics +
strictTemplates:false combo from 9 tsconfigs (NG4003).

Validation (frontend gates all green):
- Production build: 0 errors
- Vitest: 2604 passed / 2 skipped / 0 failed (no NG0203 under zoneless)
- ESLint: 0 errors, 128 warnings (matches develop baseline)
Follows up the Angular 22 upgrade. Converts the 21 components still on
the renamed ChangeDetectionStrategy.Eager (Angular 22's rename of the
legacy Default) to OnPush across 15 files, and restores the
@angular-eslint/prefer-on-push-component-change-detection rule to error
(0 violations remain) instead of the warn downgrade from the upgrade
commit.

As a down-payment on the broader strict-null-checks workstream, the same
components are made strict-null clean (10 fixes in 4 files), verified via
a temporary strict-island tsconfig:
- @input / ngOnInit-assigned props get definite-assignment (!): metric,
  unit, max$, mean$ (metric-stats-card); formControl get() (unlimited-
  input).
- showAllVersions initialized to false (chart-details-versions).
- stratos-title `title` typed optional (it is documented optional).
- kubernetes-node-summary-card: caaspNode$ typed Observable<… | null>,
  nodeData null-guarded, sibling maps default to false when null; the
  dead, never-assigned/never-read caaspVersion$ field removed.

A strict island could not be wired into the gate for enforcement: these
files import the non-strict core, so strict-checking pulls the whole
closure (~341 pre-existing core findings). Enforcement waits for the
global strict flip; these files are already done.

Validation: prod build 0 errors; vitest 2604 passed / 0 failed; eslint
0 errors / 107 warnings.
Mechanical, zero-behavior-change lint cleanup on the Angular 22 branch,
taking the warning count 107 -> 60:

- Remove ~43 genuinely-unused imports and spec-only locals (verified
  unreferenced per file/template); cascade-removed orphaned vi /
  BehaviorSubject in two specs.
- Rename unused caught error / positional param to _-prefixed
  (_err in write-with-job; _refresh in kubernetes.analysis.service).
- Drop 3 unnecessary regex escapes in natural-sort; one let -> const.

Left untouched (out of scope for a safe pass): the 6 intentional `T`
public-API generics, and the behavior/API-affecting categories
(@Output/@input renames, template a11y, prefer-standalone/inject,
empty-object-type, declaration-merging) — candidates for the broader
ESLint-tail ticket.

Validation: prod build 0 errors; vitest 2604 passed / 0 failed;
eslint 0 errors / 60 warnings.
The `@stratos/builders` workspace package runs `prepare: tsc` during
`bun install` using the root's TypeScript. Under TS 6.0 its tsconfig
errored TS5107 (`moduleResolution: "node"` deprecated), failing the
install step for every CI job before any test ran.

- Add `ignoreDeprecations: "6.0"` to the builder tsconfig (same as the
  app tsconfig in ba9166c).
- Bump the builder's @Angular-devkit deps 21 -> 22 to match root, so it
  can't pick up a skewed architect copy (the local TS2345 BuilderContext
  mismatch was a stale isolated node_modules; CI resolves to root 22).

Verified: builder `tsc` clean against root devkit 22; full prod build
0 errors.

@norman-abramovitz norman-abramovitz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM Intermediate step to a full Angular 22 with stricter code.

@norman-abramovitz
norman-abramovitz merged commit b6fa597 into cloudfoundry:develop Jun 14, 2026
12 checks passed
@nabramovitz
nabramovitz deleted the try/angular-22-upgrade branch June 14, 2026 06:16
norman-abramovitz pushed a commit that referenced this pull request Jun 14, 2026
Fix latent strict-null / strictPropertyInitialization findings in the
store and core packages so they pass under full `strict: true`. Real
guards and source-type fixes, not blanket non-null silencing:

- store: 118 findings (entity-catalog, services, favorites, helpers,
  test helpers). Made APISuccessOrFailedAction.apiAction and
  IApiEndpointInfo.User optional/nullable at the source where the wire
  shape genuinely allows absence.
- core: 358 findings (features, shared components/services, core
  internals). Definite-assignment (!) used only for Angular
  @Input/@ViewChild/@ContentChild and lifecycle/router-guaranteed
  fields, each with a justifying // strict: comment.

Base tsconfig flags NOT yet flipped; enforced via measurement config
until all packages are clean. Tracked from #5445.
norman-abramovitz pushed a commit that referenced this pull request Jun 14, 2026
…5446)

Fix the cloud-foundry package's strict-null findings and resolve the
connected TS2344/TS2430 action-builder type cascade at its root.

- Action-builder root (store + cf + kubernetes): the concrete
  *ActionBuilders interfaces failed to satisfy OrchestratedActionBuilders'
  index signature under strict function-parameter contravariance. Fixed
  by broadening the trailing-arg tail of the core builder function types
  (...extraArgs: any[] in a contravariant parameter position) and
  collapsing a deferred-vs-resolved conditional type on StratosCatalogEntity.
  Type-only; no runtime change. Clears all 46 cascade errors across both
  consumer packages.
- cloud-foundry findings (features, shared, entity-action-builders,
  entity catalog/generator/factory). Real guards and source-type fixes;
  ! only for lifecycle/router/filter-narrowing guarantees with comments.

2 pre-existing TS2344 in kubernetes-entity-generator (analysisReport
registered with undefined metadata) are a separate root, deferred.

Tracked from #5445.
norman-abramovitz pushed a commit that referenced this pull request Jun 14, 2026
…ip strict on (#5446)

Complete the strict-null/strict adoption and flip the base tsconfig to
`strict: true` globally.

- kubernetes, cf-autoscaler, devkit, git: remaining strict-null findings
  fixed with real guards / source-type fixes. devkit Map index misuse
  (map[key] -> map.get(key)); minimal ambient fs-extra.d.ts (real
  signatures, not import silencing).
- cloud-foundry cleanup: cf.helpers.ts + scattered feature files missed
  by the first pass.
- core test-framework mocks: null -> '' for logo/link in test fixtures.
- Adversarial triage: dead never-assigned fields on KubernetesEndpointService
  (info$, kubeDashboardVersion$) changed from a lying `!` to honest optional.
- **Base tsconfig flipped to `strict: true`** (removed the
  strictNullChecks/strictPropertyInitialization:false opt-outs from #5445).
- Strict templates (on under strict) surfaced 9 template-binding findings
  across 6 components (optional chaining on form .get(), optional @input
  link, guarded signal commit, endpoint guid). Fixed.

Verified: full production `ng build` succeeds under strict (0 errors).
4 pre-existing TS6.0 demo-spec syntax errors in example-extensions remain
(not in the production build; out of scope).

Closes #5446. Tracked from #5445.
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.

2 participants