diff --git a/.changeset/tiny-pianos-mate.md b/.changeset/tiny-pianos-mate.md new file mode 100644 index 00000000000..0264b2b7eab --- /dev/null +++ b/.changeset/tiny-pianos-mate.md @@ -0,0 +1,6 @@ +--- +"@pnpm/config": major +"pnpm": major +--- + +By default don't run lifecycle scripts of dependencies during installation. In order to allow lifecycle scripts of specific dependencies, they should be listed in the `pnpm.onlyBuiltDependencies` field of `package.json` [#8897](https://github.com/pnpm/pnpm/pull/8897). diff --git a/config/config/src/getOptionsFromRootManifest.ts b/config/config/src/getOptionsFromRootManifest.ts index b9f51710351..042dc822b99 100644 --- a/config/config/src/getOptionsFromRootManifest.ts +++ b/config/config/src/getOptionsFromRootManifest.ts @@ -35,8 +35,11 @@ export function getOptionsFromRootManifest (manifestDir: string, manifest: Proje } ) const neverBuiltDependencies = manifest.pnpm?.neverBuiltDependencies - const onlyBuiltDependencies = manifest.pnpm?.onlyBuiltDependencies + let onlyBuiltDependencies = manifest.pnpm?.onlyBuiltDependencies const onlyBuiltDependenciesFile = manifest.pnpm?.onlyBuiltDependenciesFile + if (onlyBuiltDependenciesFile == null && neverBuiltDependencies == null) { + onlyBuiltDependencies = [] + } const packageExtensions = manifest.pnpm?.packageExtensions const ignoredOptionalDependencies = manifest.pnpm?.ignoredOptionalDependencies const peerDependencyRules = manifest.pnpm?.peerDependencyRules diff --git a/exec/plugin-commands-rebuild/test/index.ts b/exec/plugin-commands-rebuild/test/index.ts index 127c2f9bf61..a8167545381 100644 --- a/exec/plugin-commands-rebuild/test/index.ts +++ b/exec/plugin-commands-rebuild/test/index.ts @@ -375,7 +375,11 @@ test(`rebuild should not fail on incomplete ${WANTED_LOCKFILE}`, async () => { }) test('never build neverBuiltDependencies', async () => { - const project = prepare() + const project = prepare({ + pnpm: { + neverBuiltDependencies: [], + }, + }) const cacheDir = path.resolve('cache') const storeDir = path.resolve('store') diff --git a/pnpm/test/install/global.ts b/pnpm/test/install/global.ts index 934c5555764..d0f398419ab 100644 --- a/pnpm/test/install/global.ts +++ b/pnpm/test/install/global.ts @@ -74,7 +74,9 @@ test('run lifecycle events of global packages in correct working directory', asy prepare() const global = path.resolve('..', 'global') const pnpmHome = path.join(global, 'pnpm') - fs.mkdirSync(global) + const globalPkgDir = path.join(pnpmHome, 'global', String(LAYOUT_VERSION)) + fs.mkdirSync(globalPkgDir, { recursive: true }) + fs.writeFileSync(path.join(globalPkgDir, 'package.json'), JSON.stringify({ pnpm: { neverBuiltDependencies: [] } })) const env = { [PATH_NAME]: `${pnpmHome}${path.delimiter}${process.env[PATH_NAME]!}`, @@ -84,7 +86,7 @@ test('run lifecycle events of global packages in correct working directory', asy await execPnpm(['install', '-g', '@pnpm.e2e/postinstall-calls-pnpm@1.0.0'], { env }) - expect(fs.existsSync(path.join(global, `pnpm/global/${LAYOUT_VERSION}/node_modules/@pnpm.e2e/postinstall-calls-pnpm/created-by-postinstall`))).toBeTruthy() + expect(fs.existsSync(path.join(globalPkgDir, 'node_modules/@pnpm.e2e/postinstall-calls-pnpm/created-by-postinstall'))).toBeTruthy() }) test('global update to latest', async () => { diff --git a/pnpm/test/install/lifecycleScripts.ts b/pnpm/test/install/lifecycleScripts.ts index 80e628691c3..ca596c7e6c4 100644 --- a/pnpm/test/install/lifecycleScripts.ts +++ b/pnpm/test/install/lifecycleScripts.ts @@ -103,7 +103,12 @@ test('prepare is executed after argumentless installation', () => { }) test('dependency should not be added to package.json and lockfile if it was not built successfully', async () => { - const project = prepare({ name: 'foo', version: '1.0.0' }) + const initialPkg = { + name: 'foo', + version: '1.0.0', + pnpm: { neverBuiltDependencies: [] }, + } + const project = prepare(initialPkg) const result = execPnpmSync(['install', 'package-that-cannot-be-installed@0.0.0']) @@ -114,7 +119,7 @@ test('dependency should not be added to package.json and lockfile if it was not expect(project.readLockfile()).toBeFalsy() const { default: pkg } = await import(path.resolve('package.json')) - expect(pkg).toStrictEqual({ name: 'foo', version: '1.0.0' }) + expect(pkg).toStrictEqual(initialPkg) }) test('node-gyp is in the PATH', async () => { @@ -237,6 +242,9 @@ test('ignores pnpm.executionEnv specified by dependencies', async () => { // this package's package.json has pnpm.executionEnv.nodeVersion = '20.0.0' '@pnpm.e2e/has-execution-env': '1.0.0', }, + pnpm: { + neverBuiltDependencies: [], + }, }) await execPnpm(['install']) diff --git a/pnpm/test/monorepo/index.ts b/pnpm/test/monorepo/index.ts index 991bbebe5a2..eef545b2352 100644 --- a/pnpm/test/monorepo/index.ts +++ b/pnpm/test/monorepo/index.ts @@ -1230,6 +1230,14 @@ auto-install-peers=false`, 'utf8') test('dependencies of workspace projects are built during headless installation', async () => { const projects = preparePackages([ + { + location: '.', + package: { + pnpm: { + neverBuiltDependencies: [], + }, + }, + }, { name: 'project-1', version: '1.0.0',