fix: updateConfig in pnpm-workspace.yaml should not be ignored (#9501)

* fix: updateConfig in pnpm-workspace.yaml should not be ignored

close #9500

* fix: reading executionEnv from pnpm-workspace.yaml
This commit is contained in:
Zoltan Kochan
2025-05-08 12:24:43 +02:00
committed by GitHub
parent 62029d1794
commit 9362b5fb15
12 changed files with 53 additions and 45 deletions

View File

@@ -0,0 +1,8 @@
---
"@pnpm/plugin-commands-installation": patch
"@pnpm/plugin-commands-outdated": patch
"@pnpm/config": patch
"pnpm": patch
---
Read `updateConfig` from `pnpm-workspace.yaml` [#9500](https://github.com/pnpm/pnpm/issues/9500).

View File

@@ -28,19 +28,23 @@ export type OptionsFromRootManifest = {
patchedDependencies?: Record<string, string>
peerDependencyRules?: PeerDependencyRules
supportedArchitectures?: SupportedArchitectures
} & Pick<PnpmSettings, 'configDependencies' | 'auditConfig'>
} & Pick<PnpmSettings, 'configDependencies' | 'auditConfig' | 'executionEnv' | 'updateConfig'>
export function getOptionsFromRootManifest (manifestDir: string, manifest: ProjectManifest): OptionsFromRootManifest {
const settings: OptionsFromRootManifest = getOptionsFromPnpmSettings(manifestDir, {
...pick([
'allowedDeprecatedVersions',
'allowNonAppliedPatches',
'allowUnusedPatches',
'allowedDeprecatedVersions',
'auditConfig',
'auditConfig',
'auditConfig',
'configDependencies',
'executionEnv',
'executionEnv',
'ignorePatchFailures',
'ignoredBuiltDependencies',
'ignoredOptionalDependencies',
'ignorePatchFailures',
'neverBuiltDependencies',
'onlyBuiltDependencies',
'onlyBuiltDependenciesFile',
@@ -49,6 +53,7 @@ export function getOptionsFromRootManifest (manifestDir: string, manifest: Proje
'patchedDependencies',
'peerDependencyRules',
'supportedArchitectures',
'updateConfig',
], manifest.pnpm ?? {}),
// We read Yarn's resolutions field for compatibility
// but we really replace the version specs to any other version spec, not only to exact versions,

View File

@@ -165,6 +165,7 @@ export type RunOpts =
| 'dir'
| 'enablePrePostScripts'
| 'engineStrict'
| 'executionEnv'
| 'extraBinPaths'
| 'extraEnv'
| 'nodeOptions'
@@ -279,9 +280,8 @@ so you may run "pnpm -w run ${scriptName}"`,
stdio: (specifiedScripts.length > 1 && concurrency > 1) ? 'pipe' : 'inherit',
unsafePerm: true, // when running scripts explicitly, assume that they're trusted.
}
const executionEnv = manifest.pnpm?.executionEnv
if (executionEnv != null) {
lifecycleOpts.extraBinPaths = (await prepareExecutionEnv(opts, { executionEnv })).extraBinPaths
if (opts.executionEnv != null) {
lifecycleOpts.extraBinPaths = (await prepareExecutionEnv(opts, { executionEnv: opts.executionEnv })).extraBinPaths
}
const existsPnp = existsInDir.bind(null, '.pnp.cjs')
const pnpPath = (opts.workspaceDir && existsPnp(opts.workspaceDir)) ?? existsPnp(dir)

View File

@@ -762,11 +762,6 @@ test('pnpm run with node version', async () => {
scripts: {
'assert-node-version': 'node -e "assert.equal(process.version, \'v20.0.0\')"',
},
pnpm: {
executionEnv: {
nodeVersion: '20.0.0',
},
},
})
await run.handler({
@@ -778,5 +773,8 @@ test('pnpm run with node version', async () => {
pnpmHomeDir: process.cwd(),
rawConfig: {},
workspaceConcurrency: 1,
executionEnv: {
nodeVersion: '20.0.0',
},
}, ['assert-node-version'])
})

View File

@@ -316,6 +316,7 @@ export type InstallCommandOptions = Pick<Config,
| 'resolutionMode'
| 'ignoreWorkspaceCycles'
| 'disallowWorkspaceCycles'
| 'updateConfig'
> & CreateStoreControllerOptions & {
argv: {
original: string[]

View File

@@ -101,6 +101,7 @@ export type InstallDepsOptions = Pick<Config,
| 'ignoreWorkspaceCycles'
| 'disallowWorkspaceCycles'
| 'configDependencies'
| 'updateConfig'
> & CreateStoreControllerOptions & {
argv: {
original: string[]
@@ -270,7 +271,7 @@ when running add/update with the --workspace option')
let updateMatch: UpdateDepsMatcher | null
if (opts.update) {
if (params.length === 0) {
const ignoreDeps = manifest.pnpm?.updateConfig?.ignoreDependencies
const ignoreDeps = opts.updateConfig?.ignoreDependencies
if (ignoreDeps?.length) {
params = makeIgnorePatterns(ignoreDeps)
}

View File

@@ -194,12 +194,10 @@ async function interactiveUpdate (
manifest: await readProjectManifestOnly(opts.dir, opts),
},
]
const rootDir = opts.workspaceDir ?? opts.dir
const rootProject = projects.find((project) => project.rootDir === rootDir)
const outdatedPkgsOfProjects = await outdatedDepsOfProjects(projects, input, {
...opts,
compatible: opts.latest !== true,
ignoreDependencies: rootProject?.manifest?.pnpm?.updateConfig?.ignoreDependencies,
ignoreDependencies: opts.updateConfig?.ignoreDependencies,
include,
retry: {
factor: opts.fetchRetryFactor,

View File

@@ -284,11 +284,6 @@ test('interactively update should ignore dependencies from the ignoreDependencie
// has many versions that satisfy ^3.0.0
micromatch: '^3.0.0',
},
pnpm: {
updateConfig: {
ignoreDependencies: ['is-negative'],
},
},
})
const storeDir = path.resolve('pnpm-store')
@@ -317,6 +312,9 @@ test('interactively update should ignore dependencies from the ignoreDependencie
interactive: true,
linkWorkspacePackages: true,
storeDir,
updateConfig: {
ignoreDependencies: ['is-negative'],
},
})
expect(prompt.mock.calls[0][0].choices).toStrictEqual(

View File

@@ -276,14 +276,6 @@ test('ignore packages in package.json > updateConfig.ignoreDependencies fields i
'@pnpm.e2e/bar': '100.0.0',
'@pnpm.e2e/qar': '100.0.0',
},
pnpm: {
updateConfig: {
ignoreDependencies: [
'@pnpm.e2e/foo',
'@pnpm.e2e/bar',
],
},
},
})
await install.handler({
@@ -305,6 +297,12 @@ test('ignore packages in package.json > updateConfig.ignoreDependencies fields i
...DEFAULT_OPTS,
dir: process.cwd(),
latest: true,
updateConfig: {
ignoreDependencies: [
'@pnpm.e2e/foo',
'@pnpm.e2e/bar',
],
},
})
const lockfileUpdated = project.readLockfile()
@@ -323,13 +321,6 @@ test('not ignore packages if these are specified in parameter even if these are
'@pnpm.e2e/foo': '100.0.0',
'@pnpm.e2e/bar': '100.0.0',
},
pnpm: {
updateConfig: {
ignoreDependencies: [
'@pnpm.e2e/foo',
],
},
},
})
await install.handler({
@@ -348,6 +339,11 @@ test('not ignore packages if these are specified in parameter even if these are
await update.handler({
...DEFAULT_OPTS,
dir: process.cwd(),
updateConfig: {
ignoreDependencies: [
'@pnpm.e2e/foo',
],
},
}, ['@pnpm.e2e/foo@latest', '@pnpm.e2e/bar@latest'])
const lockfileUpdated = project.readLockfile()
@@ -363,13 +359,6 @@ test('do not update anything if all the dependencies are ignored and trying to u
dependencies: {
'@pnpm.e2e/foo': '100.0.0',
},
pnpm: {
updateConfig: {
ignoreDependencies: [
'@pnpm.e2e/foo',
],
},
},
})
await install.handler({
@@ -381,6 +370,11 @@ test('do not update anything if all the dependencies are ignored and trying to u
...DEFAULT_OPTS,
dir: process.cwd(),
latest: true,
updateConfig: {
ignoreDependencies: [
'@pnpm.e2e/foo',
],
},
}, [])
const lockfileUpdated = project.readLockfile()

View File

@@ -167,6 +167,7 @@ export type OutdatedCommandOptions = {
| 'strictSsl'
| 'tag'
| 'userAgent'
| 'updateConfig'
> & Partial<Pick<Config, 'userConfig'>>
export async function handler (
@@ -192,7 +193,7 @@ export async function handler (
const [outdatedPackages] = await outdatedDepsOfProjects(packages, params, {
...opts,
fullMetadata: opts.long,
ignoreDependencies: manifest?.pnpm?.updateConfig?.ignoreDependencies,
ignoreDependencies: opts.updateConfig?.ignoreDependencies,
include,
retry: {
factor: opts.fetchRetryFactor,

View File

@@ -53,11 +53,10 @@ export async function outdatedRecursive (
opts: OutdatedCommandOptions & { include: IncludedDependencies }
): Promise<{ output: string, exitCode: number }> {
const outdatedMap = {} as Record<string, OutdatedInWorkspace>
const rootManifest = pkgs.find(({ rootDir }) => rootDir === opts.lockfileDir)
const outdatedPackagesByProject = await outdatedDepsOfProjects(pkgs, params, {
...opts,
fullMetadata: opts.long,
ignoreDependencies: rootManifest?.manifest?.pnpm?.updateConfig?.ignoreDependencies,
ignoreDependencies: opts.updateConfig?.ignoreDependencies,
retry: {
factor: opts.fetchRetryFactor,
maxTimeout: opts.fetchRetryMaxtimeout,

View File

@@ -377,6 +377,11 @@ test('ignore packages in package.json > pnpm.updateConfig.ignoreDependencies in
const { output, exitCode } = await outdated.handler({
...OUTDATED_OPTIONS,
dir: withPnpmUpdateIgnore,
updateConfig: {
ignoreDependencies: [
'is-positive',
],
},
})
expect(exitCode).toBe(1)