fix(config): fix infinite loop when using pre/post install scripts and verifyDepsBeforeInstall (#10062)

* fix(config): fix loop when using pre/post install scripts and verifyDepsBeforeInstall

If pre/post install scripts were used and `verifyDepsBeforeInstall` was
set to `install` and aforementioned scripts called other pnpm scripts,
pnpm would enter an infinite loop

close #10060

* fix: correct order of priority for reading verifyDepsBeforeRun

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
This commit is contained in:
sadan4
2025-10-10 12:32:39 -04:00
committed by GitHub
parent 1b15e45ae9
commit 986516756c
3 changed files with 41 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
---
"@pnpm/config": patch
"pnpm": patch
---
Fix a bug where pnpm would infinitely recurse when using `verifyDepsBeforeInstall: install` and pre/post install scripts that called other pnpm scripts [#10060](https://github.com/pnpm/pnpm/issues/10060).

View File

@@ -382,6 +382,15 @@ export async function getConfig (opts: {
pnpmConfig[key] = value
pnpmConfig.rawConfig[kebabCase(key)] = value
}
// All the pnpm_config_ env variables should override the settings from pnpm-workspace.yaml,
// as it happens with .npmrc.
// Until that is fixed, we should at the very least keep the right priority for verifyDepsBeforeRun,
// or else, we'll get infinite recursion.
// Related issue: https://github.com/pnpm/pnpm/issues/10060
if (process.env.pnpm_config_verify_deps_before_run != null) {
pnpmConfig.verifyDepsBeforeRun = process.env.pnpm_config_verify_deps_before_run as VerifyDepsBeforeRun
pnpmConfig.rawConfig['verify-deps-before-run'] = pnpmConfig.verifyDepsBeforeRun
}
pnpmConfig.catalogs = getCatalogsFromWorkspaceManifest(workspaceManifest)
}
}

View File

@@ -329,6 +329,32 @@ test('preinstall script does not trigger verify-deps-before-run (#8954)', async
expect(output.stdout.toString()).toContain('hello world')
})
test('preinstall and postinstall scripts do not trigger verify-deps-before-run when using settings from a config file (#10060)', async () => {
const pnpm = `${process.execPath} ${pnpmBinLocation}` // this would fail if either paths happen to contain spaces
prepare({
name: 'preinstall-script-does-not-trigger-verify-deps-before-run-config-file',
version: '1.0.0',
private: true,
scripts: {
sayHello: 'echo hello world',
preinstall: `${pnpm} run sayHello`,
postinstall: `${pnpm} run sayHello`,
},
dependencies: {
cowsay: '1.5.0', // to make the default state outdated, any dependency will do
},
})
await writeYamlFile('pnpm-workspace.yaml', { verifyDepsBeforeRun: 'install' })
// 20s timeout because if it fails it will run for 3 minutes instead
const output = execPnpmSync(['install'], { expectSuccess: true, timeout: 20_000 })
expect(output.status).toBe(0)
expect(output.stdout.toString()).toContain('hello world')
})
test('throw an error when strict-dep-builds is true and there are ignored scripts', async () => {
const project = prepare({})
const result = execPnpmSync(['add', '@pnpm.e2e/pre-and-postinstall-scripts-example@1.0.0', '--config.strict-dep-builds=true'])