Skip to content

fix(@angular/cli): respect min-release-age during version resolution#33278

Open
crimsondhaks wants to merge 2 commits into
angular:mainfrom
crimsondhaks:fix/min-release-age-version-resolution
Open

fix(@angular/cli): respect min-release-age during version resolution#33278
crimsondhaks wants to merge 2 commits into
angular:mainfrom
crimsondhaks:fix/min-release-age-version-resolution

Conversation

@crimsondhaks
Copy link
Copy Markdown

Fixes #33119.

If you set min-release-age (npm) or minimum-release-age (pnpm 10.x) in .npmrc, ng update and ng add blow up because the CLI happily picks the newest version off the registry, then the package manager refuses to install it. You get Process exited with code 1 from update and ETARGET from add.

The fix: when a cooldown is configured, PackageManager.getManifest filters candidate versions by the registry's time field before picking one. For a tag like latest, if the resolved version is too new it falls back to the newest one that's old enough so the command can still finish. For an explicit version that's too new, it returns null (same as the package manager would).

If no cooldown is configured, nothing changes — no extra registry calls, same behavior as before.

Not covered yet (left for follow-ups since the configs live elsewhere): pnpm 11+ minimumReleaseAge in pnpm-workspace.yaml, yarn berry npmMinimalAgeGate in .yarnrc.yml, bun install.minimumReleaseAge in bunfig.toml.

Tests: added unit coverage in min-release-age_spec.ts and package-manager_spec.ts. pnpm bazel test //packages/angular/cli:test passes (198 specs). Lint and prettier clean.

When a project configures a minimum release age cooldown via the package
manager (npm `min-release-age`, pnpm 10.x `minimum-release-age`), the
CLI must exclude versions younger than the cooldown from automatic
version selection. Otherwise `ng update` and `ng add` pick a version
that the package manager subsequently refuses to install, surfacing as
`Process exited with code 1` or `ETARGET`.

`PackageManager.getManifest` now reads the cooldown from `.npmrc` and
filters candidate versions accordingly when resolving `tag`/`range`/
`version` specifiers. When no cooldown is configured (the existing
default), behavior is unchanged and no extra registry calls are made.

When a tag points at a too-new version, the CLI falls back to the
newest version that satisfies the cooldown so commands continue to
make progress. For an explicit version that is too new, the lookup
returns null, mirroring what the package manager itself would do.

Fixes angular#33119
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for respecting the user-configured 'minimum release age' (install cooldown) from package managers during automatic version selection. The feedback suggests optimizing the implementation by bypassing registry metadata fetches and cooldown checks when an explicit version is requested, preserving pre-release preferences during tag fallback, updating corresponding unit tests, and improving repository root detection to support git submodules and worktrees.

Comment thread packages/angular/cli/src/package-managers/package-manager.ts Outdated
Comment thread packages/angular/cli/src/package-managers/package-manager.ts
Comment thread packages/angular/cli/src/package-managers/package-manager_spec.ts Outdated
Comment thread packages/angular/cli/src/package-managers/min-release-age.ts
Follow-up to the previous commit, addressing review feedback.

- Skip the metadata fetch for explicit version specifiers when a
  cooldown is configured. The package manager itself enforces the
  cooldown at install time, and an extra registry round-trip just
  slows down the common case (`ng add foo@1.2.3`).
- Pass `includePrerelease: true` to `maxSatisfying` on the tag
  fallback path so `next` does not silently downgrade to a stable
  release when its current pointer is too new.
- Detect a `.git` repo root by existence rather than `isDirectory()`
  so the `.npmrc` walk also stops at submodule and worktree roots,
  where `.git` is a regular file containing a `gitdir:` pointer.

New unit tests cover the prerelease fallback and the gitfile case.
@crimsondhaks
Copy link
Copy Markdown
Author

Thanks for the review — all three points addressed in the follow-up commit:

  • Explicit versions now skip the metadata fetch entirely. We only resolve locally for tag/range when a cooldown is set; foo@1.2.3 goes straight to getRegistryManifest and the package manager enforces the gate at install time.
  • Tag-fallback now passes includePrerelease: true to maxSatisfying so a too-new next falls back to the previous prerelease instead of silently downgrading to stable.
  • .git repo-root probe uses existence instead of isDirectory(), so the .npmrc walk also stops correctly in submodules and worktrees where .git is a gitfile. Added a test for that case.

200 specs pass locally; lint and prettier clean.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

minimum-release-age prevents ng update

1 participant