mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-27 18:46:18 -04:00
feat!: remove deprecated managePackageManagerVersions / packageManagerStrict / packageManagerStrictVersion (#11278)
* feat!: remove managePackageManagerVersions / packageManagerStrict / packageManagerStrictVersion
These three settings existed only to derive the `onFail` behavior for
the legacy `packageManager` field. The `pmOnFail` setting introduced
in #11275 subsumes all three — it directly sets `onFail` for both
`packageManager` and `devEngines.packageManager`.
Legacy `packageManager` now defaults to `onFail: 'download'` when no
override is set. `COREPACK_ENABLE_STRICT` is no longer read (it only
gated `packageManagerStrict`); `pmOnFail` is the replacement.
Also drops pass-through `packageManagerStrict*` option fields from
cli.utils / workspace.projects-reader (they were unused) and the
unused `managePackageManagerVersions` Pick in engine.pm.commands'
`SelfUpdateCommandOptions`.
* fix: use kebab-case setting name in BAD_PM_VERSION hint
Copilot review feedback: user-facing error hints for configuration keys
conventionally use the kebab-case form that matches both the CLI flag
(`--pm-on-fail`) and the `.npmrc` key, consistent with the prior hint
text that referenced `package-manager-strict`. The `pnpm-workspace.yaml`
field (`pmOnFail`) is camelCase but that mapping is documented
elsewhere.
* Revert "fix: use kebab-case setting name in BAD_PM_VERSION hint"
This reverts commit e03c29b17. pnpm-workspace.yaml uses camelCase
(`pmOnFail`) — the primary config location for pnpm 11 — so the
hint keeps the camelCase form. The CLI flag is already shown
alongside.
This commit is contained in:
19
.changeset/deprecate-pm-settings.md
Normal file
19
.changeset/deprecate-pm-settings.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
"@pnpm/cli.utils": major
|
||||
"@pnpm/config.reader": major
|
||||
"@pnpm/engine.pm.commands": major
|
||||
"@pnpm/workspace.projects-reader": major
|
||||
"pnpm": major
|
||||
---
|
||||
|
||||
**Breaking:** removed the `managePackageManagerVersions`, `packageManagerStrict`, and `packageManagerStrictVersion` settings. They existed only to derive the `onFail` behavior for the legacy `packageManager` field, and the `pmOnFail` setting introduced alongside `pnpm with` subsumes all three — it directly sets the `onFail` behavior of both `packageManager` and `devEngines.packageManager`. The `COREPACK_ENABLE_STRICT` environment variable is no longer honored (it only gated `packageManagerStrict`); use `pmOnFail` instead.
|
||||
|
||||
Migration:
|
||||
|
||||
| Removed setting | Replace with |
|
||||
| ------------------------------------- | -------------------- |
|
||||
| `managePackageManagerVersions: true` | `pmOnFail: download` (default) |
|
||||
| `managePackageManagerVersions: false` | `pmOnFail: ignore` |
|
||||
| `packageManagerStrict: false` | `pmOnFail: warn` |
|
||||
| `packageManagerStrictVersion: true` | `pmOnFail: error` |
|
||||
| `COREPACK_ENABLE_STRICT=0` | `pmOnFail: warn` |
|
||||
@@ -84,8 +84,8 @@ for bin in "${VARIANT_BINS[@]}"; do
|
||||
done
|
||||
|
||||
for i in "${!VARIANTS[@]}"; do
|
||||
# Run --version from BENCH_DIR to avoid pnpm's manage-package-manager-versions
|
||||
# switching the CLI based on a packageManager field in the current directory.
|
||||
# Run --version from BENCH_DIR to avoid pnpm's automatic version switching
|
||||
# based on a packageManager field in the current directory.
|
||||
echo "${VARIANTS[$i]}: $(cd "$BENCH_DIR" && node "${VARIANT_BINS[$i]}" --version) (${VARIANT_DIRS[$i]})"
|
||||
done
|
||||
echo "workdir: $BENCH_DIR"
|
||||
|
||||
@@ -13,8 +13,6 @@ export function packageIsInstallable (
|
||||
libc?: string[]
|
||||
},
|
||||
opts: {
|
||||
packageManagerStrict?: boolean
|
||||
packageManagerStrictVersion?: boolean
|
||||
engineStrict?: boolean
|
||||
nodeVersion?: string
|
||||
supportedArchitectures?: SupportedArchitectures
|
||||
|
||||
@@ -5,8 +5,6 @@ import { packageIsInstallable } from './packageIsInstallable.js'
|
||||
|
||||
export interface ReadProjectManifestOpts {
|
||||
engineStrict?: boolean
|
||||
packageManagerStrict?: boolean
|
||||
packageManagerStrictVersion?: boolean
|
||||
nodeVersion?: string
|
||||
supportedArchitectures?: SupportedArchitectures
|
||||
}
|
||||
|
||||
@@ -235,12 +235,9 @@ export interface Config extends OptionsFromRootManifest {
|
||||
dedupeInjectedDeps?: boolean
|
||||
nodeOptions?: string
|
||||
pmOnFail?: 'download' | 'error' | 'warn' | 'ignore'
|
||||
packageManagerStrict?: boolean
|
||||
packageManagerStrictVersion?: boolean
|
||||
virtualStoreDirMaxLength: number
|
||||
peersSuffixMaxLength?: number
|
||||
strictStorePkgContentCheck: boolean
|
||||
managePackageManagerVersions: boolean
|
||||
strictDepBuilds: boolean
|
||||
syncInjectedDepsAfterScripts?: string[]
|
||||
initPackageManager: boolean
|
||||
|
||||
@@ -95,7 +95,6 @@ export const excludedPnpmKeys = [
|
||||
'lockfile-dir',
|
||||
'lockfile-include-tarball-url',
|
||||
'lockfile-only',
|
||||
'manage-package-manager-versions',
|
||||
'modules-dir',
|
||||
'node-linker',
|
||||
'offline',
|
||||
@@ -104,8 +103,6 @@ export const excludedPnpmKeys = [
|
||||
'patches-dir',
|
||||
'pnpmfile',
|
||||
'pm-on-fail',
|
||||
'package-manager-strict',
|
||||
'package-manager-strict-version',
|
||||
'prefer-workspace-packages',
|
||||
'preserve-absolute-paths',
|
||||
'production',
|
||||
|
||||
@@ -170,15 +170,12 @@ export async function getConfig (opts: {
|
||||
'inject-workspace-packages': false,
|
||||
'link-workspace-packages': false,
|
||||
'lockfile-include-tarball-url': false,
|
||||
'manage-package-manager-versions': true,
|
||||
'minimum-release-age': 24 * 60, // 1 day
|
||||
'modules-cache-max-age': 7 * 24 * 60, // 7 days
|
||||
'dlx-cache-max-age': 24 * 60, // 1 day
|
||||
'node-linker': 'isolated',
|
||||
'package-lock': npmDefaults['package-lock'],
|
||||
pending: false,
|
||||
'package-manager-strict': process.env.COREPACK_ENABLE_STRICT !== '0',
|
||||
'package-manager-strict-version': false,
|
||||
'prefer-workspace-packages': false,
|
||||
'public-hoist-pattern': [],
|
||||
'recursive-install': true,
|
||||
@@ -619,22 +616,14 @@ export async function getConfig (opts: {
|
||||
|
||||
// The `pmOnFail` config setting overrides whatever onFail the
|
||||
// wantedPackageManager carried, so users (and internal callers) can force
|
||||
// a specific behavior without editing the manifest.
|
||||
// Otherwise, for the legacy packageManager field, derive onFail from config
|
||||
// settings. devEngines.packageManager already has onFail set during parsing.
|
||||
// a specific behavior without editing the manifest. Otherwise, the legacy
|
||||
// `packageManager` field defaults to `download` — `devEngines.packageManager`
|
||||
// already has onFail set during parsing.
|
||||
if (pnpmConfig.wantedPackageManager) {
|
||||
if (pnpmConfig.pmOnFail) {
|
||||
pnpmConfig.wantedPackageManager.onFail = pnpmConfig.pmOnFail
|
||||
} else if (pnpmConfig.wantedPackageManager.onFail == null) {
|
||||
if (pnpmConfig.packageManagerStrict === false) {
|
||||
pnpmConfig.wantedPackageManager.onFail = 'warn'
|
||||
} else if (pnpmConfig.managePackageManagerVersions) {
|
||||
pnpmConfig.wantedPackageManager.onFail = 'download'
|
||||
} else if (pnpmConfig.packageManagerStrictVersion) {
|
||||
pnpmConfig.wantedPackageManager.onFail = 'error'
|
||||
} else {
|
||||
pnpmConfig.wantedPackageManager.onFail = 'ignore'
|
||||
}
|
||||
pnpmConfig.wantedPackageManager.onFail = 'download'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,6 @@ export const pnpmTypes = {
|
||||
'lockfile-include-tarball-url': Boolean,
|
||||
'lockfile-only': Boolean,
|
||||
loglevel: ['silent', 'error', 'warn', 'info', 'debug'],
|
||||
'manage-package-manager-versions': Boolean,
|
||||
maxsockets: Number,
|
||||
'modules-cache-max-age': Number,
|
||||
'dlx-cache-max-age': Number,
|
||||
@@ -85,8 +84,6 @@ export const pnpmTypes = {
|
||||
'patches-dir': String,
|
||||
pnpmfile: String,
|
||||
'pm-on-fail': ['download', 'error', 'warn', 'ignore'],
|
||||
'package-manager-strict': Boolean,
|
||||
'package-manager-strict-version': Boolean,
|
||||
'prefer-frozen-lockfile': Boolean,
|
||||
'prefer-offline': Boolean,
|
||||
'prefer-symlinked-executables': Boolean,
|
||||
|
||||
@@ -49,7 +49,6 @@ export function help (): string {
|
||||
export type SelfUpdateCommandOptions = CreateStoreControllerOptions & Pick<Config,
|
||||
| 'globalPkgDir'
|
||||
| 'lockfileDir'
|
||||
| 'managePackageManagerVersions'
|
||||
| 'modulesDir'
|
||||
| 'pnpmHomeDir'
|
||||
> & Pick<ConfigContext,
|
||||
|
||||
@@ -65,7 +65,6 @@ function prepareOptions (dir: string) {
|
||||
cacheDir: path.join(dir, '.cache'),
|
||||
virtualStoreDirMaxLength: process.platform === 'win32' ? 60 : 120,
|
||||
dir,
|
||||
managePackageManagerVersions: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,7 +225,6 @@ test('should update packageManager field when a newer pnpm version is available'
|
||||
|
||||
const output = await selfUpdate.handler({
|
||||
...opts,
|
||||
managePackageManagerVersions: true,
|
||||
wantedPackageManager: {
|
||||
name: 'pnpm',
|
||||
version: '8.0.0',
|
||||
@@ -249,7 +247,6 @@ test('should not update packageManager field when current version matches latest
|
||||
|
||||
const output = await selfUpdate.handler({
|
||||
...opts,
|
||||
managePackageManagerVersions: true,
|
||||
wantedPackageManager: {
|
||||
name: 'pnpm',
|
||||
version: '9.0.0',
|
||||
@@ -274,7 +271,6 @@ test('should update devEngines.packageManager version when a newer pnpm version
|
||||
|
||||
const output = await selfUpdate.handler({
|
||||
...opts,
|
||||
managePackageManagerVersions: true,
|
||||
wantedPackageManager: {
|
||||
name: 'pnpm',
|
||||
version: '8.0.0',
|
||||
@@ -304,7 +300,6 @@ test('should update pnpm entry in devEngines.packageManager array', async () =>
|
||||
|
||||
const output = await selfUpdate.handler({
|
||||
...opts,
|
||||
managePackageManagerVersions: true,
|
||||
wantedPackageManager: {
|
||||
name: 'pnpm',
|
||||
version: '8.0.0',
|
||||
@@ -332,7 +327,6 @@ test('should not modify devEngines.packageManager range when resolved version st
|
||||
|
||||
const output = await selfUpdate.handler({
|
||||
...opts,
|
||||
managePackageManagerVersions: true,
|
||||
wantedPackageManager: {
|
||||
name: 'pnpm',
|
||||
version: '>=8.0.0',
|
||||
@@ -362,7 +356,6 @@ test('should fall back to ^version when complex range cannot accommodate the new
|
||||
|
||||
await selfUpdate.handler({
|
||||
...opts,
|
||||
managePackageManagerVersions: true,
|
||||
wantedPackageManager: {
|
||||
name: 'pnpm',
|
||||
version: '>=8.0.0 <9.0.0',
|
||||
@@ -387,7 +380,6 @@ test('should update devEngines.packageManager range when resolved version no lon
|
||||
|
||||
const output = await selfUpdate.handler({
|
||||
...opts,
|
||||
managePackageManagerVersions: true,
|
||||
wantedPackageManager: {
|
||||
name: 'pnpm',
|
||||
version: '^8',
|
||||
@@ -480,7 +472,6 @@ test('self-update updates the packageManager field in package.json', async () =>
|
||||
})
|
||||
const opts = {
|
||||
...prepareOptions(process.cwd()),
|
||||
managePackageManagerVersions: true,
|
||||
wantedPackageManager: {
|
||||
name: 'pnpm',
|
||||
version: '9.0.0',
|
||||
|
||||
@@ -337,8 +337,6 @@ gitChecks: false
|
||||
hoistPattern:
|
||||
- jest-runner
|
||||
|
||||
managePackageManagerVersions: true
|
||||
|
||||
minimumReleaseAge: 1440 # At least a day
|
||||
|
||||
minimumReleaseAgeExclude:
|
||||
|
||||
@@ -95,16 +95,14 @@ const pnpmPackageJson = JSON.parse(fs.readFileSync(pathLib.join(import.meta.dirn
|
||||
const { status } = childProcess.spawnSync(nodeBin, [
|
||||
'--enable-source-maps',
|
||||
pathLib.resolve(import.meta.dirname, 'dist/pnpm.mjs'),
|
||||
'--config.manage-package-manager-versions=false',
|
||||
'--pm-on-fail=ignore',
|
||||
...process.argv.slice(2),
|
||||
], {
|
||||
stdio: 'inherit',
|
||||
env: {
|
||||
...process.env,
|
||||
// During local development we don't want to switch to another version of pnpm
|
||||
// NOTE: Disabling through env variable stopped working for some reasone!
|
||||
// We need to check why. We set it through CLI argument for now.
|
||||
npm_config_manage_package_manager_versions: false,
|
||||
// During local development we don't want to switch to another version of pnpm.
|
||||
pnpm_config_pm_on_fail: 'ignore',
|
||||
},
|
||||
})
|
||||
process.exit(status)
|
||||
|
||||
@@ -403,7 +403,7 @@ function checkPackageManager (pm: EngineDependency): void {
|
||||
const msg = `This project is configured to use ${pm.version} of pnpm. Your current pnpm is v${currentPnpmVersion}`
|
||||
if (shouldError) {
|
||||
throw new PnpmError('BAD_PM_VERSION', msg, {
|
||||
hint: 'If you want to bypass this version check, you can set the "package-manager-strict" configuration to "false" or set the "COREPACK_ENABLE_STRICT" environment variable to "0". If using "devEngines.packageManager", you can set its "onFail" to "warn" or "ignore"',
|
||||
hint: 'If you want to bypass this version check, you can set the "pmOnFail" configuration to "warn" or "ignore" (e.g. via --pm-on-fail=ignore). If using "devEngines.packageManager", you can set its "onFail" to "warn" or "ignore"',
|
||||
})
|
||||
} else {
|
||||
globalWarn(msg)
|
||||
|
||||
@@ -93,7 +93,6 @@ test('global install warns when project has packageManager configured', async ()
|
||||
'add',
|
||||
'--global',
|
||||
'is-positive',
|
||||
'--config.package-manager-strict=true',
|
||||
], { env })
|
||||
|
||||
expect(status).toBe(0)
|
||||
|
||||
@@ -37,8 +37,8 @@ test('version switch reuses pnpm previously installed by self-update', async ()
|
||||
XDG_DATA_HOME: path.resolve('data'),
|
||||
}
|
||||
|
||||
// self-update without managePackageManagerVersions installs pnpm 10.0.0
|
||||
// globally (with GVS enabled), populating the global virtual store
|
||||
// self-update installs pnpm 10.0.0 globally (with GVS enabled),
|
||||
// populating the global virtual store
|
||||
await execPnpm(['self-update', '10.0.0'], { env })
|
||||
|
||||
// Write packageManager field so the version switch triggers.
|
||||
|
||||
@@ -27,9 +27,9 @@ test('install should not fail if the used pnpm version does not satisfy the pnpm
|
||||
packageManager: 'pnpm@0.0.0',
|
||||
})
|
||||
|
||||
expect(execPnpmSync(['install', '--config.manage-package-manager-versions=false']).status).toBe(0)
|
||||
expect(execPnpmSync(['install', '--pm-on-fail=ignore']).status).toBe(0)
|
||||
|
||||
const { status, stderr } = execPnpmSync(['install', '--config.manage-package-manager-versions=false', '--config.package-manager-strict-version=true'])
|
||||
const { status, stderr } = execPnpmSync(['install', '--pm-on-fail=error'])
|
||||
|
||||
expect(status).toBe(1)
|
||||
expect(stderr.toString()).toContain('This project is configured to use 0.0.0 of pnpm. Your current pnpm is')
|
||||
@@ -43,12 +43,12 @@ test('install should fail if the project requires a different package manager',
|
||||
packageManager: 'yarn@4.0.0',
|
||||
})
|
||||
|
||||
const { status, stderr } = execPnpmSync(['install', '--config.manage-package-manager-versions=true'])
|
||||
const { status, stderr } = execPnpmSync(['install'])
|
||||
|
||||
expect(status).toBe(1)
|
||||
expect(stderr.toString()).toContain('This project is configured to use yarn')
|
||||
|
||||
expect(execPnpmSync(['install', '--config.package-manager-strict=false']).status).toBe(0)
|
||||
expect(execPnpmSync(['install', '--pm-on-fail=warn']).status).toBe(0)
|
||||
})
|
||||
|
||||
test('install should not fail for packageManager field with hash', async () => {
|
||||
|
||||
@@ -21,12 +21,12 @@ test('switch to the pnpm version specified in the packageManager field of packag
|
||||
expect(stdout.toString()).toContain('Version 9.3.0')
|
||||
})
|
||||
|
||||
test('do not switch to the pnpm version specified in the packageManager field of package.json, if managePackageManagerVersions is set to false', async () => {
|
||||
test('do not switch to the pnpm version specified in the packageManager field of package.json, if pmOnFail is set to ignore', async () => {
|
||||
prepare()
|
||||
const pnpmHome = path.resolve('pnpm')
|
||||
const env = { PNPM_HOME: pnpmHome }
|
||||
writeYamlFileSync('pnpm-workspace.yaml', {
|
||||
managePackageManagerVersions: false,
|
||||
pmOnFail: 'ignore',
|
||||
})
|
||||
writeJsonFileSync('package.json', {
|
||||
packageManager: 'pnpm@9.3.0',
|
||||
@@ -180,9 +180,6 @@ test('devEngines.packageManager without onFail=download does not switch version'
|
||||
prepare()
|
||||
const pnpmHome = path.resolve('pnpm')
|
||||
const env = { PNPM_HOME: pnpmHome }
|
||||
writeYamlFileSync('pnpm-workspace.yaml', {
|
||||
managePackageManagerVersions: false,
|
||||
})
|
||||
writeJsonFileSync('package.json', {
|
||||
devEngines: {
|
||||
packageManager: {
|
||||
@@ -201,7 +198,6 @@ test('devEngines.packageManager without onFail=download does not switch version'
|
||||
|
||||
test('throws error if pnpm binary in store is corrupt', () => {
|
||||
prepare()
|
||||
const config = ['--config.manage-package-manager-versions=true'] as const
|
||||
const pnpmHome = path.resolve('pnpm')
|
||||
const storeDir = path.resolve('store')
|
||||
const env = { PNPM_HOME: pnpmHome, pnpm_config_store_dir: storeDir }
|
||||
@@ -212,7 +208,7 @@ test('throws error if pnpm binary in store is corrupt', () => {
|
||||
})
|
||||
|
||||
// Run pnpm once to ensure pnpm is installed to the store.
|
||||
execPnpmSync([...config, 'help'], { env })
|
||||
execPnpmSync(['help'], { env })
|
||||
|
||||
// Find the pnpm binary in the global virtual store and corrupt it.
|
||||
const entries = fs.readdirSync(storeDir, { recursive: true }) as string[]
|
||||
@@ -226,6 +222,6 @@ test('throws error if pnpm binary in store is corrupt', () => {
|
||||
fs.rmSync(path.join(storeDir, pnpmBinEntry + '.cmd'))
|
||||
}
|
||||
|
||||
const { stderr } = execPnpmSync([...config, 'help'], { env })
|
||||
const { stderr } = execPnpmSync(['help'], { env })
|
||||
expect(stderr.toString()).toContain('Failed to switch pnpm to v9.3.0. Looks like pnpm CLI is missing')
|
||||
})
|
||||
|
||||
@@ -18,8 +18,6 @@ export interface FindWorkspaceProjectsOpts {
|
||||
patterns?: string[]
|
||||
|
||||
engineStrict?: boolean
|
||||
packageManagerStrict?: boolean
|
||||
packageManagerStrictVersion?: boolean
|
||||
nodeVersion?: string
|
||||
sharedWorkspaceLockfile?: boolean
|
||||
supportedArchitectures?: SupportedArchitectures
|
||||
|
||||
Reference in New Issue
Block a user