fix(config): default minimumReleaseAgeStrict to true when user sets minimumReleaseAge (#11436)

* fix(config): default minimumReleaseAgeStrict to true when user sets minimumReleaseAge

Without this, a user-set `minimumReleaseAge` would silently fall back to
installing an immature version when no mature version satisfied the
requested range, making the setting look like it had no effect (#11433).

The built-in default of `minimumReleaseAge` (1440) stays non-strict for
backward compatibility, and an explicit `minimumReleaseAgeStrict: false`
is still respected.

* chore(changeset): downgrade to patch

* fix(config): apply minimumReleaseAgeStrict default after env var parsing

Move the strict-default logic to run after `parseEnvVars` so
`pnpm_config_minimum_release_age` is also covered.

* test(config): also assert minimumReleaseAge in the strict=false test
This commit is contained in:
Zoltan Kochan
2026-05-03 01:13:03 +02:00
parent c1d29d2258
commit 42a8f29f41
3 changed files with 103 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
---
"@pnpm/config.reader": patch
"pnpm": patch
---
`minimumReleaseAgeStrict` now defaults to `true` whenever the user explicitly sets `minimumReleaseAge` (via `pnpm-workspace.yaml`, the global `config.yaml`, the CLI, or `pnpm_config_*` env vars). Previously, an explicitly configured `minimumReleaseAge` could silently fall back to installing an immature version when no mature version satisfied the requested range, making the setting look like it had no effect [#11433](https://github.com/pnpm/pnpm/issues/11433). Set `minimumReleaseAgeStrict: false` to opt back into the silent fallback behavior. The built-in default (1440) remains non-strict, preserving the existing behavior for users who haven't configured the setting.

View File

@@ -472,6 +472,20 @@ export async function getConfig (opts: {
}
}
// When the user explicitly sets `minimumReleaseAge`, treat it as strict by
// default. Without this, a user-set value would silently fall back to
// installing an immature version when no mature version satisfies the
// requested range — making the setting look like it had no effect.
// The built-in default for `minimumReleaseAge` is intentionally non-strict
// for backward compatibility. This must run after env var parsing so
// pnpm_config_minimum_release_age also enables strict mode.
if (
pnpmConfig.explicitlySetKeys.has('minimumReleaseAge') &&
pnpmConfig.minimumReleaseAgeStrict == null
) {
pnpmConfig.minimumReleaseAgeStrict = true
}
overrideSupportedArchitecturesWithCLI(pnpmConfig, cliOptions)
pnpmConfig.useLockfile = (() => {

View File

@@ -316,6 +316,89 @@ test('.npmrc does not load pnpm settings', async () => {
expect(config.authConfig.packages).toBeUndefined()
})
describe('minimumReleaseAgeStrict default', () => {
test('defaults to true when minimumReleaseAge is set in pnpm-workspace.yaml', async () => {
prepareEmpty()
writeYamlFileSync('pnpm-workspace.yaml', {
minimumReleaseAge: 60,
})
const { config } = await getConfig({
cliOptions: {},
packageManager: { name: 'pnpm', version: '1.0.0' },
workspaceDir: process.cwd(),
})
expect(config.minimumReleaseAge).toBe(60)
expect(config.minimumReleaseAgeStrict).toBe(true)
})
test('defaults to true when minimumReleaseAge is set on the CLI', async () => {
prepareEmpty()
const { config } = await getConfig({
cliOptions: {
'minimum-release-age': 60,
},
packageManager: { name: 'pnpm', version: '1.0.0' },
workspaceDir: process.cwd(),
})
expect(config.minimumReleaseAge).toBe(60)
expect(config.minimumReleaseAgeStrict).toBe(true)
})
test('defaults to true when minimumReleaseAge is set via pnpm_config_* env var', async () => {
prepareEmpty()
const { config } = await getConfig({
cliOptions: {},
env: {
pnpm_config_minimum_release_age: '60',
},
packageManager: { name: 'pnpm', version: '1.0.0' },
workspaceDir: process.cwd(),
})
expect(config.minimumReleaseAge).toBe(60)
expect(config.minimumReleaseAgeStrict).toBe(true)
})
test('respects an explicit minimumReleaseAgeStrict=false from pnpm-workspace.yaml', async () => {
prepareEmpty()
writeYamlFileSync('pnpm-workspace.yaml', {
minimumReleaseAge: 60,
minimumReleaseAgeStrict: false,
})
const { config } = await getConfig({
cliOptions: {},
packageManager: { name: 'pnpm', version: '1.0.0' },
workspaceDir: process.cwd(),
})
expect(config.minimumReleaseAge).toBe(60)
expect(config.minimumReleaseAgeStrict).toBe(false)
})
test('does not become strict when only the built-in default for minimumReleaseAge applies', async () => {
prepareEmpty()
writeYamlFileSync('pnpm-workspace.yaml', {})
const { config } = await getConfig({
cliOptions: {},
packageManager: { name: 'pnpm', version: '1.0.0' },
workspaceDir: process.cwd(),
})
expect(config.minimumReleaseAge).toBe(1440)
expect(config.minimumReleaseAgeStrict).toBeUndefined()
})
})
test('camelCase settings from pnpm-workspace.yaml are read into typed Config properties', async () => {
prepareEmpty()