Skip to content

fix(@angular/cli): respect client-side release age settings during update resolution#33468

Open
clydin wants to merge 1 commit into
angular:mainfrom
clydin:fix-update-resolver-release-age
Open

fix(@angular/cli): respect client-side release age settings during update resolution#33468
clydin wants to merge 1 commit into
angular:mainfrom
clydin:fix-update-resolver-release-age

Conversation

@clydin

@clydin clydin commented Jun 25, 2026

Copy link
Copy Markdown
Member

Query the active package manager's release age gate configuration (like pnpm's minimum-release-age or yarn's npmMinimalAgeGate) and parse it into milliseconds.

This config limit is passed to the RegistryClient in resolveUserUpdatePlan and is used to filter out version candidates that violate the release-age gate by checking the package's publish timestamps in the metadata time record. This guarantees that ng update resolves targeting versions that satisfy all active client-side release-age restrictions.

@clydin clydin force-pushed the fix-update-resolver-release-age branch 3 times, most recently from dc88f1f to b4ea3b0 Compare June 25, 2026 20:54
@clydin clydin marked this pull request as ready for review June 25, 2026 21:03

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

Copy link
Copy Markdown

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 a minimum release age gate configuration (such as minimum-release-age for pnpm, npmMinimalAgeGate for yarn, or environment variables) to filter out package versions that were published too recently. It updates the RegistryClient and PackageManager to retrieve and respect this configuration when resolving package versions, and adds corresponding tests and parsers. The review feedback suggests extracting the release age validation logic into a reusable helper function isReleaseAgeSatisfied to reduce code duplication across several functions and safely handle potential NaN values from Date.parse.

Comment thread packages/angular/cli/src/commands/update/update-resolver.ts Outdated
Comment thread packages/angular/cli/src/commands/update/update-resolver.ts Outdated
Comment thread packages/angular/cli/src/commands/update/update-resolver.ts Outdated
Comment thread packages/angular/cli/src/commands/update/update-resolver.ts Outdated
…date resolution

Query the active package manager's release age gate configuration (like pnpm's `minimum-release-age` or yarn's `npmMinimalAgeGate`) and parse it into milliseconds.

This config limit is passed to the `RegistryClient` in `resolveUserUpdatePlan` and is used to filter out version candidates that violate the release-age gate by checking the package's publish timestamps in the metadata `time` record. This guarantees that `ng update` resolves targeting versions that satisfy all active client-side release-age restrictions.
@clydin clydin force-pushed the fix-update-resolver-release-age branch from b4ea3b0 to f4ad109 Compare June 25, 2026 21:06
@clydin clydin added target: minor This PR is targeted for the next minor release action: review The PR is still awaiting reviews from at least one requested reviewer labels Jun 25, 2026
@clydin clydin requested a review from alan-agius4 June 25, 2026 21:19
});

describe('getMinimumReleaseAge', () => {
it('should return 0 when the package manager descriptor does not support getReleaseAgeConfigCommand', async () => {

@alan-agius4 alan-agius4 Jun 26, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

NPM supports minReleaseAge though it can be defined from multiple places.

https://gist.github.com/mcollina/b294a6c39ee700d24073c0e5a4e93104

return 0;
}

// Parse Yarn duration format (e.g. "3d", "24h") or a raw millisecond/unitless value.

@alan-agius4 alan-agius4 Jun 26, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

});

describe('getMinimumReleaseAge', () => {
it('should return 0 when the package manager descriptor does not support getReleaseAgeConfigCommand', async () => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

NPM supports minReleaseAge it can be set in a number of ways.

https://gist.github.com/mcollina/b294a6c39ee700d24073c0e5a4e93104

expect(manifest).toEqual({ name: 'foo', version: '1.0.0' });
});
});

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

}
}

const envValue =

@alan-agius4 alan-agius4 Jun 26, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I am confused by why this is needed. IE: the env variable and yarn parsing logic as fallback.
In NPM don't ENV variables override what is defined in the config?

}

const envValue =
process.env.NPM_CONFIG_MIN_RELEASE_AGE ??

@alan-agius4 alan-agius4 Jun 26, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

These Env variables can also be defined in lower case

}
}

function isReleaseAgeSatisfied(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Technically, this isn't 100% accurate behavior, since packages can also be explicitly excluded. Although handling this, would make this far more complex.

@alan-agius4 alan-agius4 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

See comments.

}

async #resolveMinimumReleaseAge(): Promise<number> {
if (this.descriptor.getReleaseAgeConfigCommand && this.descriptor.outputParsers.getReleaseAge) {

@alan-agius4 alan-agius4 Jun 26, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Based on the package manager and versions this will return incorrect results.

Example, In pnpm 11 and yarn 6 this will return undefined, but by default this is 1440, before that it was 0

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

Labels

action: review The PR is still awaiting reviews from at least one requested reviewer area: @angular/cli target: minor This PR is targeted for the next minor release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants