From cb367b95150dfcd56af4708599cd6ecda6ab878a Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Fri, 2 Jan 2026 12:22:42 +0100 Subject: [PATCH] feat!: deprecate old settings that were replaced by allowBuilds (#10382) --- .changeset/deploy-preserve-allow-builds.md | 5 ++ .changeset/global-install-allow-builds.md | 6 ++ .../remove-deprecated-build-settings.md | 30 +++++++ .../remove-deprecated-build-settings0.md | 13 +++ builder/policy/src/index.ts | 15 +--- builder/policy/test/index.ts | 32 ------- config/config/src/dependencyBuildOptions.ts | 2 - .../config/src/getOptionsFromRootManifest.ts | 12 +-- config/config/src/index.ts | 24 +++--- .../test/getOptionsFromRootManifest.test.ts | 7 +- config/config/test/index.ts | 32 ------- cspell.json | 1 + exec/build-commands/src/approveBuilds.ts | 31 +++---- exec/build-commands/src/ignoredBuilds.ts | 13 +-- .../__snapshots__/ignoredBuilds.test.ts.snap | 22 +++-- .../build-commands/test/approveBuilds.test.ts | 69 ++------------- .../build-commands/test/ignoredBuilds.test.ts | 20 +---- .../implementation/extendRebuildOptions.ts | 4 +- exec/plugin-commands-rebuild/test/index.ts | 56 ++----------- .../plugin-commands-rebuild/test/recursive.ts | 7 +- .../test/utils/index.ts | 1 - packages/types/src/package.ts | 4 - .../core/src/install/extendInstallOptions.ts | 7 +- pkg-manager/core/src/install/index.ts | 9 +- .../core/test/hoistedNodeLinker/install.ts | 9 +- .../core/test/install/lifecycleScripts.ts | 84 ++++++------------- pkg-manager/core/test/install/misc.ts | 2 +- .../core/test/install/optionalDependencies.ts | 4 +- .../core/test/install/peerDependencies.ts | 2 +- pkg-manager/core/test/install/sideEffects.ts | 6 ++ pkg-manager/core/test/utils/testDefaults.ts | 1 - pkg-manager/headless/src/index.ts | 2 - .../plugin-commands-installation/src/add.ts | 29 +++++-- .../src/installDeps.ts | 19 ++++- .../src/recursive.ts | 1 + pnpm-lock.yaml | 20 ++--- pnpm/test/configurationalDependencies.test.ts | 51 ----------- pnpm/test/install/global.ts | 16 ++-- pnpm/test/install/lifecycleScripts.ts | 65 ++++---------- pnpm/test/monorepo/index.ts | 21 +++-- pnpm/test/recursive/rebuild.ts | 8 +- releasing/plugin-commands-deploy/package.json | 6 +- .../src/createDeployFiles.ts | 13 +++ .../plugin-commands-deploy/src/deploy.ts | 15 +++- .../test/shared-lockfile.test.ts | 11 ++- workspace/manifest-writer/src/index.ts | 25 ------ .../test/updateWorkspaceManifest.test.ts | 9 +- 47 files changed, 304 insertions(+), 537 deletions(-) create mode 100644 .changeset/deploy-preserve-allow-builds.md create mode 100644 .changeset/global-install-allow-builds.md create mode 100644 .changeset/remove-deprecated-build-settings.md create mode 100644 .changeset/remove-deprecated-build-settings0.md diff --git a/.changeset/deploy-preserve-allow-builds.md b/.changeset/deploy-preserve-allow-builds.md new file mode 100644 index 0000000000..5fe4246efa --- /dev/null +++ b/.changeset/deploy-preserve-allow-builds.md @@ -0,0 +1,5 @@ +--- +"@pnpm/plugin-commands-deploy": minor +--- + +Preserve `allowBuilds` settings when deploying a project. The `allowBuilds` configuration is now written to `pnpm-workspace.yaml` in the deploy directory. diff --git a/.changeset/global-install-allow-builds.md b/.changeset/global-install-allow-builds.md new file mode 100644 index 0000000000..adb8470ae4 --- /dev/null +++ b/.changeset/global-install-allow-builds.md @@ -0,0 +1,6 @@ +--- +"@pnpm/config": minor +"pnpm": minor +--- + +Support reading `allowBuilds` from `pnpm-workspace.yaml` in the global package directory for global installs. diff --git a/.changeset/remove-deprecated-build-settings.md b/.changeset/remove-deprecated-build-settings.md new file mode 100644 index 0000000000..5d79a70329 --- /dev/null +++ b/.changeset/remove-deprecated-build-settings.md @@ -0,0 +1,30 @@ +--- +"pnpm": major +--- + +Remove deprecated build dependency settings: `onlyBuiltDependencies`, `onlyBuiltDependenciesFile`, `neverBuiltDependencies`, and `ignoredBuiltDependencies`. + +Use the `allowBuilds` setting instead. It is a map where keys are package name patterns and values are booleans: +- `true` means the package is allowed to run build scripts +- `false` means the package is explicitly denied from running build scripts + +Same as before, by default, none of the packages in the dependencies are allowed to run scripts. If a package has postinstall scripts and it isn't declared in `allowBuilds`, an error is printed. + +Before: +```yaml +onlyBuiltDependencies: + - electron +onlyBuiltDependenciesFile: 'allowed-builds.json' +neverBuiltDependencies: + - core-js +ignoredBuiltDependencies: + - esbuild +``` + +After: +```yaml +allowBuilds: + electron: true + core-js: false + esbuild: false +``` diff --git a/.changeset/remove-deprecated-build-settings0.md b/.changeset/remove-deprecated-build-settings0.md new file mode 100644 index 0000000000..80b39abc8e --- /dev/null +++ b/.changeset/remove-deprecated-build-settings0.md @@ -0,0 +1,13 @@ +--- +"@pnpm/types": major +"@pnpm/config": major +"@pnpm/core": major +"@pnpm/headless": major +"@pnpm/builder.policy": major +"@pnpm/exec.build-commands": major +"@pnpm/plugin-commands-installation": major +"@pnpm/plugin-commands-rebuild": major +"@pnpm/workspace.manifest-writer": major +--- + +Remove deprecated build dependency settings: `onlyBuiltDependencies`, `onlyBuiltDependenciesFile`, `neverBuiltDependencies`, and `ignoredBuiltDependencies`. diff --git a/builder/policy/src/index.ts b/builder/policy/src/index.ts index 1c1969533e..f0bff820dd 100644 --- a/builder/policy/src/index.ts +++ b/builder/policy/src/index.ts @@ -1,27 +1,16 @@ import { type AllowBuild } from '@pnpm/types' import { expandPackageVersionSpecs } from '@pnpm/config.version-policy' -import fs from 'fs' export function createAllowBuildFunction ( opts: { dangerouslyAllowAllBuilds?: boolean - neverBuiltDependencies?: string[] onlyBuiltDependencies?: string[] - onlyBuiltDependenciesFile?: string } ): undefined | AllowBuild { if (opts.dangerouslyAllowAllBuilds) return () => true - if (opts.onlyBuiltDependenciesFile != null || opts.onlyBuiltDependencies != null) { - const onlyBuiltDeps = opts.onlyBuiltDependencies ?? [] - if (opts.onlyBuiltDependenciesFile) { - onlyBuiltDeps.push(...JSON.parse(fs.readFileSync(opts.onlyBuiltDependenciesFile, 'utf8'))) - } - const onlyBuiltDependencies = expandPackageVersionSpecs(onlyBuiltDeps) + if (opts.onlyBuiltDependencies != null) { + const onlyBuiltDependencies = expandPackageVersionSpecs(opts.onlyBuiltDependencies) return (pkgName, version) => onlyBuiltDependencies.has(pkgName) || onlyBuiltDependencies.has(`${pkgName}@${version}`) } - if (opts.neverBuiltDependencies != null && opts.neverBuiltDependencies.length > 0) { - const neverBuiltDependencies = new Set(opts.neverBuiltDependencies) - return (pkgName) => !neverBuiltDependencies.has(pkgName) - } return undefined } diff --git a/builder/policy/test/index.ts b/builder/policy/test/index.ts index 0160faf93a..716d842730 100644 --- a/builder/policy/test/index.ts +++ b/builder/policy/test/index.ts @@ -1,15 +1,5 @@ -import path from 'path' import { createAllowBuildFunction } from '@pnpm/builder.policy' -it('should neverBuiltDependencies', () => { - const allowBuild = createAllowBuildFunction({ - neverBuiltDependencies: ['foo'], - }) - expect(typeof allowBuild).toBe('function') - expect(allowBuild!('foo', '1.0.0')).toBeFalsy() - expect(allowBuild!('bar', '1.0.0')).toBeTruthy() -}) - it('should onlyBuiltDependencies', () => { const allowBuild = createAllowBuildFunction({ onlyBuiltDependencies: ['foo', 'qar@1.0.0 || 2.0.0'], @@ -30,28 +20,6 @@ it('should not allow patterns in onlyBuiltDependencies', () => { expect(allowBuild!('is-odd', '1.0.0')).toBeFalsy() }) -it('should onlyBuiltDependencies set via a file', () => { - const allowBuild = createAllowBuildFunction({ - onlyBuiltDependenciesFile: path.join(import.meta.dirname, 'onlyBuild.json'), - }) - expect(typeof allowBuild).toBe('function') - expect(allowBuild!('zoo', '1.0.0')).toBeTruthy() - expect(allowBuild!('qar', '1.0.0')).toBeTruthy() - expect(allowBuild!('bar', '1.0.0')).toBeFalsy() -}) - -it('should onlyBuiltDependencies set via a file and config', () => { - const allowBuild = createAllowBuildFunction({ - onlyBuiltDependencies: ['bar'], - onlyBuiltDependenciesFile: path.join(import.meta.dirname, 'onlyBuild.json'), - }) - expect(typeof allowBuild).toBe('function') - expect(allowBuild!('zoo', '1.0.0')).toBeTruthy() - expect(allowBuild!('qar', '1.0.0')).toBeTruthy() - expect(allowBuild!('bar', '1.0.0')).toBeTruthy() - expect(allowBuild!('esbuild', '1.0.0')).toBeFalsy() -}) - it('should return undefined if no policy is set', () => { expect(createAllowBuildFunction({})).toBeUndefined() }) diff --git a/config/config/src/dependencyBuildOptions.ts b/config/config/src/dependencyBuildOptions.ts index 19e3c207c2..261831a51d 100644 --- a/config/config/src/dependencyBuildOptions.ts +++ b/config/config/src/dependencyBuildOptions.ts @@ -3,8 +3,6 @@ import { type Config } from './Config.js' export const DEPS_BUILD_CONFIG_KEYS = [ 'dangerouslyAllowAllBuilds', 'onlyBuiltDependencies', - 'onlyBuiltDependenciesFile', - 'neverBuiltDependencies', 'allowBuilds', ] as const satisfies Array diff --git a/config/config/src/getOptionsFromRootManifest.ts b/config/config/src/getOptionsFromRootManifest.ts index 08a34a6bee..a790d65806 100644 --- a/config/config/src/getOptionsFromRootManifest.ts +++ b/config/config/src/getOptionsFromRootManifest.ts @@ -17,9 +17,7 @@ export type OptionsFromRootManifest = { allowUnusedPatches?: boolean ignorePatchFailures?: boolean overrides?: Record - neverBuiltDependencies?: string[] onlyBuiltDependencies?: string[] - onlyBuiltDependenciesFile?: string ignoredBuiltDependencies?: string[] packageExtensions?: Record ignoredOptionalDependencies?: string[] @@ -37,15 +35,9 @@ export function getOptionsFromRootManifest (manifestDir: string, manifest: Proje 'allowUnusedPatches', 'allowedDeprecatedVersions', 'auditConfig', - 'auditConfig', - 'auditConfig', 'configDependencies', 'ignorePatchFailures', - 'ignoredBuiltDependencies', 'ignoredOptionalDependencies', - 'neverBuiltDependencies', - 'onlyBuiltDependencies', - 'onlyBuiltDependenciesFile', 'overrides', 'packageExtensions', 'patchedDependencies', @@ -74,9 +66,6 @@ export function getOptionsFromPnpmSettings (manifestDir: string | undefined, pnp settings.overrides = mapValues(createVersionReferencesReplacer(manifest), settings.overrides) } } - if (pnpmSettings.onlyBuiltDependenciesFile && manifestDir != null) { - settings.onlyBuiltDependenciesFile = path.join(manifestDir, pnpmSettings.onlyBuiltDependenciesFile) - } if (pnpmSettings.patchedDependencies) { settings.patchedDependencies = { ...pnpmSettings.patchedDependencies } for (const [dep, patchFile] of Object.entries(pnpmSettings.patchedDependencies)) { @@ -93,6 +82,7 @@ export function getOptionsFromPnpmSettings (manifestDir: string | undefined, pnp } if (pnpmSettings.allowBuilds) { + settings.allowBuilds = pnpmSettings.allowBuilds settings.onlyBuiltDependencies ??= [] settings.ignoredBuiltDependencies ??= [] for (const [packagePattern, build] of Object.entries(pnpmSettings.allowBuilds)) { diff --git a/config/config/src/index.ts b/config/config/src/index.ts index 0f3c521dbd..70b9f7fdcf 100644 --- a/config/config/src/index.ts +++ b/config/config/src/index.ts @@ -412,6 +412,17 @@ export async function getConfig (opts: { workspaceManifest, }) } + } else if (cliOptions['global']) { + // For global installs, read settings from pnpm-workspace.yaml in the global package directory + const workspaceManifest = await readWorkspaceManifest(pnpmConfig.globalPkgDir) + if (workspaceManifest) { + addSettingsFromWorkspaceManifestToConfig(pnpmConfig, { + configFromCliOpts, + projectManifest: pnpmConfig.rootProjectManifest, + workspaceDir: pnpmConfig.globalPkgDir, + workspaceManifest, + }) + } } } @@ -459,13 +470,8 @@ export async function getConfig (opts: { overrideSupportedArchitecturesWithCLI(pnpmConfig, cliOptions) - if (opts.cliOptions['global']) { - extractAndRemoveDependencyBuildOptions(pnpmConfig) + if (!hasDependencyBuildOptions(pnpmConfig)) { Object.assign(pnpmConfig, globalDepsBuildConfig) - } else { - if (!hasDependencyBuildOptions(pnpmConfig)) { - Object.assign(pnpmConfig, globalDepsBuildConfig) - } } if (opts.cliOptions['save-peer']) { if (opts.cliOptions['save-prod']) { @@ -621,12 +627,6 @@ export async function getConfig (opts: { pnpmConfig.dev = true } - if (pnpmConfig.dangerouslyAllowAllBuilds) { - if (pnpmConfig.neverBuiltDependencies && pnpmConfig.neverBuiltDependencies.length > 0) { - warnings.push('You have set dangerouslyAllowAllBuilds to true. The dependencies listed in neverBuiltDependencies will run their scripts.') - } - pnpmConfig.neverBuiltDependencies = [] - } if (pnpmConfig.ci) { // Using a global virtual store in CI makes little sense, // as there is never a warm cache in that environment. diff --git a/config/config/test/getOptionsFromRootManifest.test.ts b/config/config/test/getOptionsFromRootManifest.test.ts index 10e082206a..21731bf69d 100644 --- a/config/config/test/getOptionsFromRootManifest.test.ts +++ b/config/config/test/getOptionsFromRootManifest.test.ts @@ -93,7 +93,7 @@ test('getOptionsFromRootManifest() should return onlyBuiltDependencies as undefi test('getOptionsFromRootManifest() should return the list from onlyBuiltDependencies', () => { const options = getOptionsFromRootManifest(process.cwd(), { pnpm: { - onlyBuiltDependencies: ['electron'], + allowBuilds: { electron: true }, }, }) expect(options.onlyBuiltDependencies).toStrictEqual(['electron']) @@ -186,6 +186,11 @@ test('getOptionsFromRootManifest() converts allowBuilds', () => { }, }) expect(options).toStrictEqual({ + allowBuilds: { + foo: true, + bar: false, + qar: 'warn', + }, onlyBuiltDependencies: ['foo'], ignoredBuiltDependencies: ['bar'], }) diff --git a/config/config/test/index.ts b/config/config/test/index.ts index 65f7a33262..0cbfc6e18e 100644 --- a/config/config/test/index.ts +++ b/config/config/test/index.ts @@ -1281,38 +1281,6 @@ test('settings gitBranchLockfile in pnpm-workspace.yaml should take effect', asy expect(config.rawConfig['git-branch-lockfile']).toBe(true) }) -test('when dangerouslyAllowAllBuilds is set to true neverBuiltDependencies is set to an empty array', async () => { - const { config } = await getConfig({ - cliOptions: { - 'dangerously-allow-all-builds': true, - }, - packageManager: { - name: 'pnpm', - version: '1.0.0', - }, - }) - - expect(config.neverBuiltDependencies).toStrictEqual([]) -}) - -test('when dangerouslyAllowAllBuilds is set to true and neverBuiltDependencies not empty, a warning is returned', async () => { - const workspaceDir = f.find('never-built-dependencies') - process.chdir(workspaceDir) - const { config, warnings } = await getConfig({ - cliOptions: { - 'dangerously-allow-all-builds': true, - }, - packageManager: { - name: 'pnpm', - version: '1.0.0', - }, - workspaceDir, - }) - - expect(config.neverBuiltDependencies).toStrictEqual([]) - expect(warnings).toStrictEqual(['You have set dangerouslyAllowAllBuilds to true. The dependencies listed in neverBuiltDependencies will run their scripts.']) -}) - test('loads setting from environment variable pnpm_config_*', async () => { prepareEmpty() const { config } = await getConfig({ diff --git a/cspell.json b/cspell.json index 4d37bfb416..c0df34bf84 100644 --- a/cspell.json +++ b/cspell.json @@ -51,6 +51,7 @@ "diskusage", "dislink", "dpkg", + "drivelist", "duplexify", "eagain", "ebadplatform", diff --git a/exec/build-commands/src/approveBuilds.ts b/exec/build-commands/src/approveBuilds.ts index 28dccfbad5..f06feca378 100644 --- a/exec/build-commands/src/approveBuilds.ts +++ b/exec/build-commands/src/approveBuilds.ts @@ -2,7 +2,6 @@ import { type Config } from '@pnpm/config' import { globalInfo } from '@pnpm/logger' import { type StrictModules, writeModulesManifest } from '@pnpm/modules-yaml' import { lexCompare } from '@pnpm/util.lex-comparator' -import { type PnpmSettings } from '@pnpm/types' import renderHelp from 'render-help' import enquirer from 'enquirer' import chalk from 'chalk' @@ -92,25 +91,19 @@ export async function handler (opts: ApproveBuildsCommandOpts & RebuildCommandOp } as any) as any // eslint-disable-line @typescript-eslint/no-explicit-any const buildPackages = result.map(({ value }: { value: string }) => value) const ignoredPackages = automaticallyIgnoredBuilds.filter((automaticallyIgnoredBuild) => !buildPackages.includes(automaticallyIgnoredBuild)) - const updatedSettings: PnpmSettings = {} + const allowBuilds: Record = {} if (ignoredPackages.length) { - if (opts.ignoredBuiltDependencies == null) { - updatedSettings.ignoredBuiltDependencies = sortUniqueStrings(ignoredPackages) - } else { - updatedSettings.ignoredBuiltDependencies = sortUniqueStrings([ - ...opts.ignoredBuiltDependencies, - ...ignoredPackages, - ]) + for (const pkg of [...ignoredPackages, ...opts.ignoredBuiltDependencies ?? []]) { + allowBuilds[pkg] = false } } - if (buildPackages.length) { - if (opts.onlyBuiltDependencies == null) { - updatedSettings.onlyBuiltDependencies = sortUniqueStrings(buildPackages) - } else { - updatedSettings.onlyBuiltDependencies = sortUniqueStrings([ - ...opts.onlyBuiltDependencies, - ...buildPackages, - ]) + const onlyBuiltDependencies = [ + ...opts.onlyBuiltDependencies ?? [], + ...buildPackages, + ] + if (onlyBuiltDependencies.length) { + for (const pkg of onlyBuiltDependencies) { + allowBuilds[pkg] = true } } if (buildPackages.length) { @@ -130,12 +123,12 @@ Do you approve?`, await writeSettings({ ...opts, workspaceDir: opts.workspaceDir ?? opts.rootProjectManifestDir, - updatedSettings, + updatedSettings: { allowBuilds }, }) if (buildPackages.length) { return rebuild.handler({ ...opts, - onlyBuiltDependencies: updatedSettings.onlyBuiltDependencies, + onlyBuiltDependencies, }, buildPackages) } else if (modulesManifest) { delete modulesManifest.ignoredBuilds diff --git a/exec/build-commands/src/ignoredBuilds.ts b/exec/build-commands/src/ignoredBuilds.ts index c53153cbe2..441da71952 100644 --- a/exec/build-commands/src/ignoredBuilds.ts +++ b/exec/build-commands/src/ignoredBuilds.ts @@ -2,7 +2,7 @@ import { type Config } from '@pnpm/config' import renderHelp from 'render-help' import { getAutomaticallyIgnoredBuilds } from './getAutomaticallyIgnoredBuilds.js' -export type IgnoredBuildsCommandOpts = Pick +export type IgnoredBuildsCommandOpts = Pick export const commandNames = ['ignored-builds'] @@ -22,7 +22,7 @@ export function rcOptionsTypes (): Record { } export async function handler (opts: IgnoredBuildsCommandOpts): Promise { - const ignoredBuiltDependencies = opts.rootProjectManifest?.pnpm?.ignoredBuiltDependencies ?? [] + const ignoredBuiltDependencies = opts.ignoredBuiltDependencies ?? [] let { automaticallyIgnoredBuilds } = await getAutomaticallyIgnoredBuilds(opts) if (automaticallyIgnoredBuilds) { automaticallyIgnoredBuilds = automaticallyIgnoredBuilds @@ -35,12 +35,15 @@ export async function handler (opts: IgnoredBuildsCommandOpts): Promise output += ' None' } else { output += ` ${automaticallyIgnoredBuilds.join('\n ')} -hint: To allow the execution of build scripts for a package, add its name to "pnpm.onlyBuiltDependencies" in your "package.json", then run "pnpm rebuild". -hint: If you don't want to build a package, add it to the "pnpm.ignoredBuiltDependencies" list.` +hint: To allow the execution of build scripts for a package, add its name to "allowBuilds" and set to "true", then run "pnpm rebuild". +hint: For example: +hint: allowBuilds: +hint: esbuild: true +hint: If you don't want to build a package, set it to "false" instead.` } output += '\n' if (ignoredBuiltDependencies.length) { - output += `\nExplicitly ignored package builds (via pnpm.ignoredBuiltDependencies):\n ${ignoredBuiltDependencies.join('\n ')}\n` + output += `\nExplicitly ignored package builds (via allowBuilds):\n ${ignoredBuiltDependencies.join('\n ')}\n` } return output } diff --git a/exec/build-commands/test/__snapshots__/ignoredBuilds.test.ts.snap b/exec/build-commands/test/__snapshots__/ignoredBuilds.test.ts.snap index fa1b1dbd55..1b280bf6c4 100644 --- a/exec/build-commands/test/__snapshots__/ignoredBuilds.test.ts.snap +++ b/exec/build-commands/test/__snapshots__/ignoredBuilds.test.ts.snap @@ -1,10 +1,13 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`ignoredBuilds lists automatically ignored dependencies 1`] = ` "Automatically ignored builds during installation: foo -hint: To allow the execution of build scripts for a package, add its name to "pnpm.onlyBuiltDependencies" in your "package.json", then run "pnpm rebuild". -hint: If you don't want to build a package, add it to the "pnpm.ignoredBuiltDependencies" list. +hint: To allow the execution of build scripts for a package, add its name to "allowBuilds" and set to "true", then run "pnpm rebuild". +hint: For example: +hint: allowBuilds: +hint: esbuild: true +hint: If you don't want to build a package, set it to "false" instead. " `; @@ -12,10 +15,13 @@ exports[`ignoredBuilds lists both automatically and explicitly ignored dependenc "Automatically ignored builds during installation: foo bar -hint: To allow the execution of build scripts for a package, add its name to "pnpm.onlyBuiltDependencies" in your "package.json", then run "pnpm rebuild". -hint: If you don't want to build a package, add it to the "pnpm.ignoredBuiltDependencies" list. +hint: To allow the execution of build scripts for a package, add its name to "allowBuilds" and set to "true", then run "pnpm rebuild". +hint: For example: +hint: allowBuilds: +hint: esbuild: true +hint: If you don't want to build a package, set it to "false" instead. -Explicitly ignored package builds (via pnpm.ignoredBuiltDependencies): +Explicitly ignored package builds (via allowBuilds): qar zoo " @@ -25,7 +31,7 @@ exports[`ignoredBuilds lists explicitly ignored dependencies 1`] = ` "Automatically ignored builds during installation: None -Explicitly ignored package builds (via pnpm.ignoredBuiltDependencies): +Explicitly ignored package builds (via allowBuilds): bar " `; @@ -34,7 +40,7 @@ exports[`ignoredBuilds prints an info message when there is no node_modules 1`] "Automatically ignored builds during installation: Cannot identify as no node_modules found -Explicitly ignored package builds (via pnpm.ignoredBuiltDependencies): +Explicitly ignored package builds (via allowBuilds): qar zoo " diff --git a/exec/build-commands/test/approveBuilds.test.ts b/exec/build-commands/test/approveBuilds.test.ts index f84d43ae69..7161004fe1 100644 --- a/exec/build-commands/test/approveBuilds.test.ts +++ b/exec/build-commands/test/approveBuilds.test.ts @@ -4,12 +4,10 @@ import { install } from '@pnpm/plugin-commands-installation' import { type ApproveBuildsCommandOpts } from '@pnpm/exec.build-commands' import { type RebuildCommandOpts } from '@pnpm/plugin-commands-rebuild' import { prepare } from '@pnpm/prepare' -import { type ProjectManifest } from '@pnpm/types' import { getConfig } from '@pnpm/config' import { readModulesManifest } from '@pnpm/modules-yaml' import { REGISTRY_MOCK_PORT } from '@pnpm/registry-mock' import { jest } from '@jest/globals' -import { loadJsonFileSync } from 'load-json-file' import { omit } from 'ramda' import { tempDir } from '@pnpm/prepare-temp-dir' import { writePackageSync } from 'write-package' @@ -88,16 +86,15 @@ test('approve selected build', async () => { '@pnpm.e2e/pre-and-postinstall-scripts-example': '1.0.0', '@pnpm.e2e/install-script-example': '*', }, - pnpm: { - overrides: {}, - }, }) await approveSomeBuilds() - const manifest = loadJsonFileSync(path.resolve('package.json')) - expect(manifest.pnpm?.onlyBuiltDependencies).toStrictEqual(['@pnpm.e2e/pre-and-postinstall-scripts-example']) - expect(manifest.pnpm?.ignoredBuiltDependencies).toStrictEqual(['@pnpm.e2e/install-script-example']) + const workspaceManifest = readYamlFile(path.resolve('pnpm-workspace.yaml')) // eslint-disable-line + expect(workspaceManifest.allowBuilds).toStrictEqual({ + '@pnpm.e2e/install-script-example': false, + '@pnpm.e2e/pre-and-postinstall-scripts-example': true, + }) expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-preinstall.js')).toBeTruthy() expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-postinstall.js')).toBeTruthy() @@ -155,62 +152,6 @@ test("works when root project manifest doesn't exist in a workspace", async () = }) }) -test('should update onlyBuiltDependencies when package.json exists with ignoredBuiltDependencies defined', async () => { - const temp = tempDir() - const rootProjectManifest = { - dependencies: { - '@pnpm.e2e/pre-and-postinstall-scripts-example': '1.0.0', - '@pnpm.e2e/install-script-example': '*', - }, - pnpm: { - ignoredBuiltDependencies: ['@pnpm.e2e/install-script-example'], - }, - } - - prepare(rootProjectManifest, { - tempDir: temp, - }) - - const workspaceManifestFile = path.join(temp, 'pnpm-workspace.yaml') - writeYamlFile(workspaceManifestFile, { packages: ['packages/*'] }) - await approveSomeBuilds({ workspaceDir: temp, rootProjectManifestDir: temp, rootProjectManifest }) - - expect(readYamlFile(workspaceManifestFile)).toStrictEqual({ - packages: ['packages/*'], - }) - expect(loadJsonFileSync(path.join(temp, 'package.json'))!.pnpm).toStrictEqual({ - ignoredBuiltDependencies: ['@pnpm.e2e/install-script-example'], - onlyBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example'], - }) -}) - -test('should approve builds when package.json exists with onlyBuiltDependencies defined', async () => { - const temp = tempDir() - - prepare({ - dependencies: { - '@pnpm.e2e/pre-and-postinstall-scripts-example': '1.0.0', - '@pnpm.e2e/install-script-example': '*', - }, - pnpm: { - onlyBuiltDependencies: ['@pnpm.e2e/install-script-example'], - }, - }, { - tempDir: temp, - }) - - const workspaceManifestFile = path.join(temp, 'pnpm-workspace.yaml') - writeYamlFile(workspaceManifestFile, { packages: ['packages/*'] }) - await approveSomeBuilds({ workspaceDir: temp, rootProjectManifestDir: temp }) - - expect(readYamlFile(workspaceManifestFile)).toStrictEqual({ - packages: ['packages/*'], - }) - expect(loadJsonFileSync(path.join(temp, 'package.json'))!.pnpm).toStrictEqual({ - onlyBuiltDependencies: ['@pnpm.e2e/install-script-example', '@pnpm.e2e/pre-and-postinstall-scripts-example'], - }) -}) - test('should approve builds with package.json that has no onlyBuiltDependencies and ignoredBuiltDependencies fields defined', async () => { const temp = tempDir() diff --git a/exec/build-commands/test/ignoredBuilds.test.ts b/exec/build-commands/test/ignoredBuilds.test.ts index 213247848f..2d2ced4da1 100644 --- a/exec/build-commands/test/ignoredBuilds.test.ts +++ b/exec/build-commands/test/ignoredBuilds.test.ts @@ -36,7 +36,7 @@ test('ignoredBuilds lists automatically ignored dependencies', async () => { const output = await ignoredBuilds.handler({ dir, modulesDir, - rootProjectManifest: {}, + ignoredBuiltDependencies: [], }) expect(output).toMatchSnapshot() }) @@ -52,11 +52,7 @@ test('ignoredBuilds lists explicitly ignored dependencies', async () => { const output = await ignoredBuilds.handler({ dir, modulesDir, - rootProjectManifest: { - pnpm: { - ignoredBuiltDependencies: ['bar'], - }, - }, + ignoredBuiltDependencies: ['bar'], }) expect(output).toMatchSnapshot() }) @@ -72,11 +68,7 @@ test('ignoredBuilds lists both automatically and explicitly ignored dependencies const output = await ignoredBuilds.handler({ dir, modulesDir, - rootProjectManifest: { - pnpm: { - ignoredBuiltDependencies: ['qar', 'zoo'], - }, - }, + ignoredBuiltDependencies: ['qar', 'zoo'], }) expect(output).toMatchSnapshot() }) @@ -87,11 +79,7 @@ test('ignoredBuilds prints an info message when there is no node_modules', async const output = await ignoredBuilds.handler({ dir, modulesDir, - rootProjectManifest: { - pnpm: { - ignoredBuiltDependencies: ['qar', 'zoo'], - }, - }, + ignoredBuiltDependencies: ['qar', 'zoo'], }) expect(output).toMatchSnapshot() }) diff --git a/exec/plugin-commands-rebuild/src/implementation/extendRebuildOptions.ts b/exec/plugin-commands-rebuild/src/implementation/extendRebuildOptions.ts index 72005796c2..bdf6f6ef6a 100644 --- a/exec/plugin-commands-rebuild/src/implementation/extendRebuildOptions.ts +++ b/exec/plugin-commands-rebuild/src/implementation/extendRebuildOptions.ts @@ -51,7 +51,7 @@ export type StrictRebuildOptions = { peersSuffixMaxLength: number strictStorePkgContentCheck: boolean fetchFullMetadata?: boolean -} & Pick +} & Pick export type RebuildOptions = Partial & Pick & Pick @@ -106,7 +106,7 @@ export async function extendRebuildOptions ( ...(opts.rootProjectManifest ? getOptionsFromRootManifest(opts.rootProjectManifestDir, opts.rootProjectManifest) : {}), } extendedOpts.registries = normalizeRegistries(extendedOpts.registries) - if (extendedOpts.neverBuiltDependencies == null && extendedOpts.onlyBuiltDependencies == null && extendedOpts.onlyBuiltDependenciesFile == null) { + if (extendedOpts.onlyBuiltDependencies == null) { extendedOpts.onlyBuiltDependencies = [] } return extendedOpts diff --git a/exec/plugin-commands-rebuild/test/index.ts b/exec/plugin-commands-rebuild/test/index.ts index 47cd58041c..7f9c7519cc 100644 --- a/exec/plugin-commands-rebuild/test/index.ts +++ b/exec/plugin-commands-rebuild/test/index.ts @@ -50,6 +50,7 @@ test('rebuilds dependencies', async () => { pending: false, registries: modulesManifest!.registries!, storeDir, + onlyBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example', 'test-git-fetch'], }, []) modules = project.readModulesManifest() @@ -139,6 +140,7 @@ test('skipIfHasSideEffectsCache', async () => { registries: modulesManifest!.registries!, skipIfHasSideEffectsCache: true, storeDir, + onlyBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example'], }, []) modules = project.readModulesManifest() @@ -176,6 +178,7 @@ test('rebuild does not fail when a linked package is present', async () => { pending: false, registries: modulesManifest!.registries!, storeDir, + onlyBuiltDependencies: ['local-pkg', 'is-positive'], }, []) // see related issue https://github.com/pnpm/pnpm/issues/1155 @@ -206,6 +209,7 @@ test('rebuilds specific dependencies', async () => { pending: false, registries: modulesManifest!.registries!, storeDir, + onlyBuiltDependencies: ['install-scripts-example-for-pnpm'], }, ['install-scripts-example-for-pnpm']) project.hasNot('@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-preinstall') @@ -265,6 +269,7 @@ test('rebuild with pending option', async () => { pending: true, registries: modules!.registries!, storeDir, + onlyBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example', 'install-scripts-example-for-pnpm'], }, []) modules = project.readModulesManifest() @@ -318,6 +323,7 @@ test('rebuild dependencies in correct order', async () => { pending: false, registries: modules!.registries!, storeDir, + onlyBuiltDependencies: ['@pnpm.e2e/with-postinstall-a', '@pnpm.e2e/with-postinstall-b'], }, []) modules = project.readModulesManifest() @@ -359,6 +365,7 @@ test('rebuild links bins', async () => { pending: true, registries: modules!.registries!, storeDir, + onlyBuiltDependencies: ['@pnpm.e2e/has-generated-bins-as-dep', '@pnpm.e2e/generated-bins'], }, []) project.isExecutable('.bin/cmd1') @@ -400,51 +407,6 @@ test(`rebuild should not fail on incomplete ${WANTED_LOCKFILE}`, async () => { registries: modules!.registries!, reporter, storeDir, + onlyBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example', '@pnpm.e2e/not-compatible-with-any-os'], }, []) -}) - -test('never build neverBuiltDependencies', async () => { - const project = prepare({ - pnpm: { - neverBuiltDependencies: [], - }, - }) - const cacheDir = path.resolve('cache') - const storeDir = path.resolve('store') - - await execa('node', [ - pnpmBin, - 'add', - '@pnpm.e2e/install-script-example@1.0.0', - '@pnpm.e2e/pre-and-postinstall-scripts-example@1.0.0', - `--registry=${REGISTRY}`, - `--store-dir=${storeDir}`, - `--cache-dir=${cacheDir}`, - '--config.enableGlobalVirtualStore=false', - ]) - - const modulesManifest = project.readModulesManifest() - await rebuild.handler( - { - ...DEFAULT_OPTS, - neverBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example'], - cacheDir, - dir: process.cwd(), - pending: false, - registries: modulesManifest!.registries!, - storeDir, - }, - [] - ) - - expect( - fs.existsSync( - 'node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-prepare.js' - ) - ).toBeFalsy() - expect( - fs.existsSync( - 'node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-preinstall.js' - ) - ).toBeTruthy() -}) +}) \ No newline at end of file diff --git a/exec/plugin-commands-rebuild/test/recursive.ts b/exec/plugin-commands-rebuild/test/recursive.ts index 9fb8da7f48..3be910ff27 100644 --- a/exec/plugin-commands-rebuild/test/recursive.ts +++ b/exec/plugin-commands-rebuild/test/recursive.ts @@ -58,6 +58,7 @@ test('pnpm recursive rebuild', async () => { registries: modulesManifest!.registries!, selectedProjectsGraph, workspaceDir: process.cwd(), + onlyBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example'], }, []) projects['project-1'].has('@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-preinstall.js') @@ -136,6 +137,7 @@ test('pnpm recursive rebuild with hoisted node linker', async () => { selectedProjectsGraph, lockfileDir: process.cwd(), workspaceDir: process.cwd(), + onlyBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example'], }, []) rootProject.has('@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-preinstall.js') @@ -215,13 +217,14 @@ test('rebuild multiple packages in correct order', async () => { recursive: true, selectedProjectsGraph, workspaceDir: process.cwd(), + onlyBuiltDependencies: ['project-1', 'project-2', 'project-3'], }, []) expect(server1.getLines()).toStrictEqual(['project-1', 'project-2']) expect(server2.getLines()).toStrictEqual(['project-1', 'project-3']) }) -test('never build neverBuiltDependencies', async () => { +test('only build onlyBuiltDependencies (not others)', async () => { const projects = preparePackages([ { name: 'project-1', @@ -285,7 +288,7 @@ test('never build neverBuiltDependencies', async () => { await rebuild.handler( { ...DEFAULT_OPTS, - neverBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example'], + onlyBuiltDependencies: ['@pnpm.e2e/install-script-example'], allProjects, dir: process.cwd(), recursive: true, diff --git a/exec/plugin-commands-rebuild/test/utils/index.ts b/exec/plugin-commands-rebuild/test/utils/index.ts index 9ca4163d28..cb58673eca 100644 --- a/exec/plugin-commands-rebuild/test/utils/index.ts +++ b/exec/plugin-commands-rebuild/test/utils/index.ts @@ -28,7 +28,6 @@ export const DEFAULT_OPTS = { localAddress: undefined, lock: false, lockStaleDuration: 90, - neverBuiltDependencies: [], networkConcurrency: 16, offline: false, pending: false, diff --git a/packages/types/src/package.ts b/packages/types/src/package.ts index 8d9efa9a33..e6d83932e5 100644 --- a/packages/types/src/package.ts +++ b/packages/types/src/package.ts @@ -151,11 +151,7 @@ export interface AuditConfig { export interface PnpmSettings { configDependencies?: ConfigDependencies - neverBuiltDependencies?: string[] // deprecated - onlyBuiltDependencies?: string[] // deprecated - onlyBuiltDependenciesFile?: string // deprecated allowBuilds?: Record - ignoredBuiltDependencies?: string[] overrides?: Record packageExtensions?: Record ignoredOptionalDependencies?: string[] diff --git a/pkg-manager/core/src/install/extendInstallOptions.ts b/pkg-manager/core/src/install/extendInstallOptions.ts index 4fcc71177e..4e83ec7f93 100644 --- a/pkg-manager/core/src/install/extendInstallOptions.ts +++ b/pkg-manager/core/src/install/extendInstallOptions.ts @@ -72,9 +72,7 @@ export interface StrictInstallOptions { verifyStoreIntegrity: boolean engineStrict: boolean ignoredBuiltDependencies?: string[] - neverBuiltDependencies?: string[] onlyBuiltDependencies?: string[] - onlyBuiltDependenciesFile?: string nodeExecPath?: string nodeLinker: 'isolated' | 'hoisted' | 'pnp' nodeVersion?: string @@ -291,12 +289,9 @@ export function extendOptions ( } } } - if (opts.neverBuiltDependencies == null && opts.onlyBuiltDependencies == null && opts.onlyBuiltDependenciesFile == null) { + if (opts.onlyBuiltDependencies == null) { opts.onlyBuiltDependencies = [] } - if (opts.onlyBuiltDependencies && opts.neverBuiltDependencies) { - throw new PnpmError('CONFIG_CONFLICT_BUILT_DEPENDENCIES', 'Cannot have both neverBuiltDependencies and onlyBuiltDependencies') - } const defaultOpts = defaults(opts) const extendedOpts: ProcessedInstallOptions = { ...defaultOpts, diff --git a/pkg-manager/core/src/install/index.ts b/pkg-manager/core/src/install/index.ts index 4dd988f321..704f94828f 100644 --- a/pkg-manager/core/src/install/index.ts +++ b/pkg-manager/core/src/install/index.ts @@ -370,11 +370,9 @@ export async function mutateModules ( if (!opts.ignoreScripts && ignoredBuilds?.size) { ignoredBuilds = await runUnignoredDependencyBuilds(opts, ignoredBuilds) } - if (!opts.neverBuiltDependencies) { - ignoredScriptsLogger.debug({ - packageNames: ignoredBuilds ? dedupePackageNamesFromIgnoredBuilds(ignoredBuilds) : [], - }) - } + ignoredScriptsLogger.debug({ + packageNames: ignoredBuilds ? dedupePackageNamesFromIgnoredBuilds(ignoredBuilds) : [], + }) if ((reporter != null) && typeof reporter === 'function') { streamParser.removeListener('data', reporter) @@ -1085,7 +1083,6 @@ type InstallFunction = ( patchedDependencies?: PatchGroupRecord makePartialCurrentLockfile: boolean needsFullResolution: boolean - neverBuiltDependencies?: string[] onlyBuiltDependencies?: string[] overrides?: Record updateLockfileMinorVersion: boolean diff --git a/pkg-manager/core/test/hoistedNodeLinker/install.ts b/pkg-manager/core/test/hoistedNodeLinker/install.ts index 5e6512d50e..c990906121 100644 --- a/pkg-manager/core/test/hoistedNodeLinker/install.ts +++ b/pkg-manager/core/test/hoistedNodeLinker/install.ts @@ -184,7 +184,12 @@ test('run pre/postinstall scripts. bin files should be linked in a hoisted node_ const project = prepareEmpty() await addDependenciesToPackage({}, ['@pnpm.e2e/pre-and-postinstall-scripts-example'], - testDefaults({ fastUnpack: false, nodeLinker: 'hoisted', targetDependenciesField: 'devDependencies' }) + testDefaults({ + fastUnpack: false, + nodeLinker: 'hoisted', + targetDependenciesField: 'devDependencies', + onlyBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example'], + }) ) expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-prepare.js')).toBeFalsy() @@ -212,7 +217,7 @@ test('running install scripts in a workspace that has no root project', async () }, mutation: 'install', rootDir: path.resolve('project-1') as ProjectRootDir, - }, testDefaults({ fastUnpack: false, nodeLinker: 'hoisted' })) + }, testDefaults({ fastUnpack: false, nodeLinker: 'hoisted', onlyBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example'] })) expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-preinstall.js')).toBeTruthy() }) diff --git a/pkg-manager/core/test/install/lifecycleScripts.ts b/pkg-manager/core/test/install/lifecycleScripts.ts index 33ac9a2065..b1e4be2d02 100644 --- a/pkg-manager/core/test/install/lifecycleScripts.ts +++ b/pkg-manager/core/test/install/lifecycleScripts.ts @@ -27,7 +27,7 @@ test('run pre/postinstall scripts', async () => { const project = prepareEmpty() const { updatedManifest: manifest } = await addDependenciesToPackage({}, ['@pnpm.e2e/pre-and-postinstall-scripts-example@1.0.0'], - testDefaults({ fastUnpack: false, targetDependenciesField: 'devDependencies' }) + testDefaults({ fastUnpack: false, targetDependenciesField: 'devDependencies', onlyBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example'] }) ) { @@ -46,7 +46,7 @@ test('run pre/postinstall scripts', async () => { // testing that the packages are not installed even though they are in lockfile // and that their scripts are not tried to be executed - await install(manifest, testDefaults({ fastUnpack: false, production: true })) + await install(manifest, testDefaults({ fastUnpack: false, production: true, onlyBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example'] })) { const generatedByPreinstall = project.requireModule('@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-preinstall') @@ -95,6 +95,7 @@ test('run pre/postinstall scripts, when PnP is used and no symlinks', async () = enablePnp: true, symlink: false, targetDependenciesField: 'devDependencies', + onlyBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example'], }) ) @@ -108,7 +109,7 @@ test('testing that the bins are linked when the package with the bins was alread const project = prepareEmpty() const { updatedManifest: manifest } = await addDependenciesToPackage({}, ['@pnpm.e2e/hello-world-js-bin'], testDefaults({ fastUnpack: false })) - await addDependenciesToPackage(manifest, ['@pnpm.e2e/pre-and-postinstall-scripts-example@1.0.0'], testDefaults({ fastUnpack: false, targetDependenciesField: 'devDependencies' })) + await addDependenciesToPackage(manifest, ['@pnpm.e2e/pre-and-postinstall-scripts-example@1.0.0'], testDefaults({ fastUnpack: false, targetDependenciesField: 'devDependencies', onlyBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example'] })) const generatedByPreinstall = project.requireModule('@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-preinstall') expect(typeof generatedByPreinstall).toBe('function') @@ -119,7 +120,7 @@ test('testing that the bins are linked when the package with the bins was alread test('run install scripts', async () => { const project = prepareEmpty() - await addDependenciesToPackage({}, ['@pnpm.e2e/install-script-example'], testDefaults({ fastUnpack: false })) + await addDependenciesToPackage({}, ['@pnpm.e2e/install-script-example'], testDefaults({ fastUnpack: false, onlyBuiltDependencies: ['@pnpm.e2e/install-script-example'] })) const generatedByInstall = project.requireModule('@pnpm.e2e/install-script-example/generated-by-install') expect(typeof generatedByInstall).toBe('function') @@ -202,6 +203,7 @@ test('INIT_CWD is always set to lockfile directory', async () => { }, testDefaults({ fastUnpack: false, lockfileDir: rootDir, + onlyBuiltDependencies: ['@pnpm.e2e/write-lifecycle-env'], })) const childEnv = loadJsonFileSync<{ INIT_CWD: string }>(path.join(rootDir, 'node_modules/@pnpm.e2e/write-lifecycle-env/env.json')) @@ -217,7 +219,7 @@ test("reports child's output", async () => { const reporter = sinon.spy() - await addDependenciesToPackage({}, ['@pnpm.e2e/count-to-10'], testDefaults({ fastUnpack: false, reporter })) + await addDependenciesToPackage({}, ['@pnpm.e2e/count-to-10'], testDefaults({ fastUnpack: false, reporter, onlyBuiltDependencies: ['@pnpm.e2e/count-to-10'] })) expect(reporter.calledWithMatch({ depPath: '@pnpm.e2e/count-to-10@1.0.0', @@ -265,7 +267,7 @@ test("reports child's close event", async () => { const reporter = sinon.spy() await expect( - addDependenciesToPackage({}, ['@pnpm.e2e/failing-postinstall'], testDefaults({ reporter })) + addDependenciesToPackage({}, ['@pnpm.e2e/failing-postinstall'], testDefaults({ reporter, onlyBuiltDependencies: ['@pnpm.e2e/failing-postinstall'] })) ).rejects.toThrow() expect(reporter.calledWithMatch({ @@ -293,7 +295,7 @@ testOnNonWindows('lifecycle scripts have access to node-gyp', async () => { !p.includes(`${path.sep}.npm${path.sep}`)) .join(path.delimiter) - await addDependenciesToPackage({}, ['drivelist@5.1.8'], testDefaults({ fastUnpack: false })) + await addDependenciesToPackage({}, ['drivelist@5.1.8'], testDefaults({ fastUnpack: false, onlyBuiltDependencies: ['drivelist'] })) process.env[PATH] = initialPath }) @@ -301,7 +303,7 @@ testOnNonWindows('lifecycle scripts have access to node-gyp', async () => { test('run lifecycle scripts of dependent packages after running scripts of their deps', async () => { const project = prepareEmpty() - await addDependenciesToPackage({}, ['@pnpm.e2e/with-postinstall-a'], testDefaults({ fastUnpack: false })) + await addDependenciesToPackage({}, ['@pnpm.e2e/with-postinstall-a'], testDefaults({ fastUnpack: false, onlyBuiltDependencies: ['@pnpm.e2e/with-postinstall-a', '@pnpm.e2e/with-postinstall-b'] })) expect(+project.requireModule('.pnpm/@pnpm.e2e+with-postinstall-b@1.0.0/node_modules/@pnpm.e2e/with-postinstall-b/output.json')[0] < +project.requireModule('@pnpm.e2e/with-postinstall-a/output.json')[0]).toBeTruthy() }) @@ -330,7 +332,7 @@ test('run prepare script for git-hosted dependencies', async () => { test('lifecycle scripts run before linking bins', async () => { const project = prepareEmpty() - const { updatedManifest: manifest } = await addDependenciesToPackage({}, ['@pnpm.e2e/generated-bins'], testDefaults({ fastUnpack: false })) + const { updatedManifest: manifest } = await addDependenciesToPackage({}, ['@pnpm.e2e/generated-bins'], testDefaults({ fastUnpack: false, onlyBuiltDependencies: ['@pnpm.e2e/generated-bins'] })) project.isExecutable('.bin/cmd1') project.isExecutable('.bin/cmd2') @@ -341,7 +343,7 @@ test('lifecycle scripts run before linking bins', async () => { manifest, mutation: 'install', rootDir: process.cwd() as ProjectRootDir, - }, testDefaults({ frozenLockfile: true })) + }, testDefaults({ frozenLockfile: true, onlyBuiltDependencies: ['@pnpm.e2e/generated-bins'] })) project.isExecutable('.bin/cmd1') project.isExecutable('.bin/cmd2') @@ -350,7 +352,7 @@ test('lifecycle scripts run before linking bins', async () => { test('hoisting does not fail on commands that will be created by lifecycle scripts on a later stage', async () => { prepareEmpty() - const { updatedManifest: manifest } = await addDependenciesToPackage({}, ['@pnpm.e2e/has-generated-bins-as-dep'], testDefaults({ fastUnpack: false, hoistPattern: '*' })) + const { updatedManifest: manifest } = await addDependenciesToPackage({}, ['@pnpm.e2e/has-generated-bins-as-dep'], testDefaults({ fastUnpack: false, hoistPattern: '*', onlyBuiltDependencies: ['@pnpm.e2e/has-generated-bins-as-dep', '@pnpm.e2e/generated-bins'] })) // project.isExecutable('.pnpm/node_modules/.bin/cmd1') // project.isExecutable('.pnpm/node_modules/.bin/cmd2') @@ -362,7 +364,7 @@ test('hoisting does not fail on commands that will be created by lifecycle scrip manifest, mutation: 'install', rootDir: process.cwd() as ProjectRootDir, - }, testDefaults({ frozenLockfile: true, hoistPattern: '*' })) + }, testDefaults({ frozenLockfile: true, hoistPattern: '*', onlyBuiltDependencies: ['@pnpm.e2e/has-generated-bins-as-dep', '@pnpm.e2e/generated-bins'] })) // project.isExecutable('.pnpm/node_modules/.bin/cmd1') // project.isExecutable('.pnpm/node_modules/.bin/cmd2') @@ -423,7 +425,7 @@ test('dependency should not be added to current lockfile if it was not built suc manifest, mutation: 'install', rootDir: process.cwd() as ProjectRootDir, - }, testDefaults({ frozenLockfile: true })) + }, testDefaults({ frozenLockfile: true, onlyBuiltDependencies: ['package-that-cannot-be-installed'] })) ).rejects.toThrow() expect(project.readCurrentLockfile()).toBeFalsy() @@ -435,53 +437,19 @@ test('scripts have access to unlisted bins when hoisting is used', async () => { await addDependenciesToPackage( {}, ['@pnpm.e2e/pkg-that-calls-unlisted-dep-in-hooks'], - testDefaults({ fastUnpack: false, hoistPattern: '*' }) + testDefaults({ fastUnpack: false, hoistPattern: '*', onlyBuiltDependencies: ['@pnpm.e2e/pkg-that-calls-unlisted-dep-in-hooks'] }) ) expect(project.requireModule('@pnpm.e2e/pkg-that-calls-unlisted-dep-in-hooks/output.json')).toStrictEqual(['Hello world!']) }) -test('selectively ignore scripts in some dependencies by neverBuiltDependencies', async () => { - prepareEmpty() - const neverBuiltDependencies = ['@pnpm.e2e/pre-and-postinstall-scripts-example'] - const { updatedManifest: manifest } = await addDependenciesToPackage({}, - ['@pnpm.e2e/pre-and-postinstall-scripts-example@1.0.0', '@pnpm.e2e/install-script-example'], - testDefaults({ fastUnpack: false, neverBuiltDependencies }) - ) - - expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-preinstall.js')).toBeFalsy() - expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-postinstall.js')).toBeFalsy() - expect(fs.existsSync('node_modules/@pnpm.e2e/install-script-example/generated-by-install.js')).toBeTruthy() - - rimraf('node_modules') - - await install(manifest, testDefaults({ fastUnpack: false, frozenLockfile: true, neverBuiltDependencies })) - - expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-preinstall.js')).toBeFalsy() - expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-postinstall.js')).toBeFalsy() - expect(fs.existsSync('node_modules/@pnpm.e2e/install-script-example/generated-by-install.js')).toBeTruthy() -}) - -test('throw an exception when both neverBuiltDependencies and onlyBuiltDependencies are used', async () => { - prepareEmpty() - - await expect( - addDependenciesToPackage( - {}, - ['@pnpm.e2e/pre-and-postinstall-scripts-example@1.0.0'], - testDefaults({ onlyBuiltDependencies: ['@pnpm.e2e/foo'], neverBuiltDependencies: ['@pnpm.e2e/bar'] }) - ) - ).rejects.toThrow(/Cannot have both/) -}) - test('selectively allow scripts in some dependencies by onlyBuiltDependencies', async () => { prepareEmpty() const reporter = sinon.spy() const onlyBuiltDependencies = ['@pnpm.e2e/install-script-example'] - const neverBuiltDependencies: string[] | undefined = undefined const { updatedManifest: manifest } = await addDependenciesToPackage({}, ['@pnpm.e2e/pre-and-postinstall-scripts-example@1.0.0', '@pnpm.e2e/install-script-example'], - testDefaults({ fastUnpack: false, onlyBuiltDependencies, neverBuiltDependencies, reporter }) + testDefaults({ fastUnpack: false, onlyBuiltDependencies, reporter }) ) expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-preinstall.js')).toBeFalsy() @@ -500,7 +468,6 @@ test('selectively allow scripts in some dependencies by onlyBuiltDependencies', fastUnpack: false, frozenLockfile: true, ignoredBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example'], - neverBuiltDependencies, onlyBuiltDependencies, reporter, })) @@ -519,10 +486,9 @@ test('selectively allow scripts in some dependencies by onlyBuiltDependencies us prepareEmpty() const reporter = sinon.spy() const onlyBuiltDependencies = ['@pnpm.e2e/install-script-example@1.0.0'] - const neverBuiltDependencies: string[] | undefined = undefined const { updatedManifest: manifest } = await addDependenciesToPackage({}, ['@pnpm.e2e/pre-and-postinstall-scripts-example@1.0.0', '@pnpm.e2e/install-script-example'], - testDefaults({ fastUnpack: false, onlyBuiltDependencies, neverBuiltDependencies, reporter }) + testDefaults({ fastUnpack: false, onlyBuiltDependencies, reporter }) ) expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-preinstall.js')).toBeFalsy() @@ -541,7 +507,6 @@ test('selectively allow scripts in some dependencies by onlyBuiltDependencies us fastUnpack: false, frozenLockfile: true, ignoredBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example'], - neverBuiltDependencies, onlyBuiltDependencies, reporter, })) @@ -560,7 +525,7 @@ test('lifecycle scripts have access to package\'s own binary by binary name', as const project = prepareEmpty() await addDependenciesToPackage({}, ['@pnpm.e2e/runs-own-bin'], - testDefaults({ fastUnpack: false }) + testDefaults({ fastUnpack: false, onlyBuiltDependencies: ['@pnpm.e2e/runs-own-bin'] }) ) project.isExecutable('.pnpm/@pnpm.e2e+runs-own-bin@1.0.0/node_modules/@pnpm.e2e/runs-own-bin/node_modules/.bin/runs-own-bin') @@ -580,7 +545,7 @@ test('lifecycle scripts run after linking root dependencies', async () => { manifest, mutation: 'install', rootDir: process.cwd() as ProjectRootDir, - }, testDefaults({ fastUnpack: false })) + }, testDefaults({ fastUnpack: false, onlyBuiltDependencies: ['@pnpm.e2e/postinstall-requires-is-positive'] })) rimraf('node_modules') @@ -588,7 +553,7 @@ test('lifecycle scripts run after linking root dependencies', async () => { manifest, mutation: 'install', rootDir: process.cwd() as ProjectRootDir, - }, testDefaults({ fastUnpack: false, frozenLockfile: true })) + }, testDefaults({ fastUnpack: false, frozenLockfile: true, onlyBuiltDependencies: ['@pnpm.e2e/postinstall-requires-is-positive'] })) // if there was no exception, the test passed }) @@ -718,6 +683,7 @@ test('run pre/postinstall scripts in a workspace that uses node-linker=hoisted', allProjects, fastUnpack: false, nodeLinker: 'hoisted', + onlyBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example'], })) const rootProject = assertProject(process.cwd()) rootProject.has('@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-preinstall.js') @@ -736,7 +702,7 @@ test('run pre/postinstall scripts in a project that uses node-linker=hoisted. Sh const project = prepareEmpty() const { updatedManifest: manifest } = await addDependenciesToPackage({}, ['@pnpm.e2e/pre-and-postinstall-scripts-example@1.0.0'], - testDefaults({ fastUnpack: false, targetDependenciesField: 'devDependencies', nodeLinker: 'hoisted', sideEffectsCacheRead: true, sideEffectsCacheWrite: true }) + testDefaults({ fastUnpack: false, targetDependenciesField: 'devDependencies', nodeLinker: 'hoisted', sideEffectsCacheRead: true, sideEffectsCacheWrite: true, onlyBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example'] }) ) { @@ -760,6 +726,7 @@ test('run pre/postinstall scripts in a project that uses node-linker=hoisted. Sh reporter, sideEffectsCacheRead: true, sideEffectsCacheWrite: true, + onlyBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example'], }) ) @@ -771,13 +738,11 @@ test('run pre/postinstall scripts in a project that uses node-linker=hoisted. Sh test('build dependencies that were not previously built after onlyBuiltDependencies changes', async () => { prepareEmpty() - const neverBuiltDependencies: string[] | undefined = undefined const { updatedManifest: manifest } = await addDependenciesToPackage({}, ['@pnpm.e2e/pre-and-postinstall-scripts-example@1.0.0', '@pnpm.e2e/install-script-example'], testDefaults({ fastUnpack: false, onlyBuiltDependencies: ['@pnpm.e2e/install-script-example'], - neverBuiltDependencies, }) ) @@ -789,7 +754,6 @@ test('build dependencies that were not previously built after onlyBuiltDependenc fastUnpack: false, frozenLockfile: true, ignoredBuiltDependencies: [], - neverBuiltDependencies, onlyBuiltDependencies: ['@pnpm.e2e/install-script-example', '@pnpm.e2e/pre-and-postinstall-scripts-example@1.0.0'], })) diff --git a/pkg-manager/core/test/install/misc.ts b/pkg-manager/core/test/install/misc.ts index a544e84a18..fe847b8308 100644 --- a/pkg-manager/core/test/install/misc.ts +++ b/pkg-manager/core/test/install/misc.ts @@ -549,7 +549,7 @@ test('bin specified in the directories property symlinked to .bin folder when pr testOnNonWindows('building native addons', async () => { prepareEmpty() - await addDependenciesToPackage({}, ['diskusage@1.1.3'], testDefaults({ fastUnpack: false })) + await addDependenciesToPackage({}, ['diskusage@1.1.3'], testDefaults({ fastUnpack: false, onlyBuiltDependencies: ['diskusage'] })) expect(fs.existsSync('node_modules/diskusage/build')).toBeTruthy() }) diff --git a/pkg-manager/core/test/install/optionalDependencies.ts b/pkg-manager/core/test/install/optionalDependencies.ts index 84cbbdab6b..beeb3ad090 100644 --- a/pkg-manager/core/test/install/optionalDependencies.ts +++ b/pkg-manager/core/test/install/optionalDependencies.ts @@ -578,7 +578,9 @@ test('fail on a package with failing postinstall if the package is both an optio '@pnpm.e2e/has-failing-postinstall-dep': '1.0.0', }, }, - testDefaults({}) + testDefaults({ + onlyBuiltDependencies: ['@pnpm.e2e/has-failing-postinstall-dep', '@pnpm.e2e/failing-postinstall'], + }) ) ).rejects.toThrow() }) diff --git a/pkg-manager/core/test/install/peerDependencies.ts b/pkg-manager/core/test/install/peerDependencies.ts index 588e86023f..784b1db3c7 100644 --- a/pkg-manager/core/test/install/peerDependencies.ts +++ b/pkg-manager/core/test/install/peerDependencies.ts @@ -822,7 +822,7 @@ test('peer bins are linked', async () => { test('run pre/postinstall scripts of each variations of packages with peer dependencies', async () => { await addDistTag({ package: '@pnpm.e2e/peer-c', version: '1.0.0', distTag: 'latest' }) prepareEmpty() - await addDependenciesToPackage({}, ['@pnpm.e2e/parent-of-pkg-with-events-and-peers', '@pnpm.e2e/pkg-with-events-and-peers', '@pnpm.e2e/peer-c@2.0.0'], testDefaults({ fastUnpack: false })) + await addDependenciesToPackage({}, ['@pnpm.e2e/parent-of-pkg-with-events-and-peers', '@pnpm.e2e/pkg-with-events-and-peers', '@pnpm.e2e/peer-c@2.0.0'], testDefaults({ fastUnpack: false, onlyBuiltDependencies: ['@pnpm.e2e/pkg-with-events-and-peers'] })) const pkgVariation1 = path.resolve('node_modules/.pnpm/@pnpm.e2e+pkg-with-events-and-peers@1.0.0_@pnpm.e2e+peer-c@1.0.0/node_modules') await okFile(path.join(pkgVariation1, '@pnpm.e2e/pkg-with-events-and-peers', 'generated-by-preinstall.js')) diff --git a/pkg-manager/core/test/install/sideEffects.ts b/pkg-manager/core/test/install/sideEffects.ts index 6c1119d0dd..abd54e357e 100644 --- a/pkg-manager/core/test/install/sideEffects.ts +++ b/pkg-manager/core/test/install/sideEffects.ts @@ -79,6 +79,7 @@ test('using side effects cache', async () => { sideEffectsCacheRead: true, sideEffectsCacheWrite: true, verifyStoreIntegrity: false, + onlyBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example'], }, {}, {}, { packageImportMethod: 'copy' }) const { updatedManifest: manifest } = await addDependenciesToPackage({}, ['@pnpm.e2e/pre-and-postinstall-scripts-example@1.0.0'], opts) @@ -111,6 +112,7 @@ test('using side effects cache', async () => { sideEffectsCacheWrite: true, storeDir: opts.storeDir, verifyStoreIntegrity: false, + onlyBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example'], }, {}, {}, { packageImportMethod: 'copy' }) await addDependenciesToPackage(manifest, ['@pnpm.e2e/pre-and-postinstall-scripts-example@1.0.0'], opts2) @@ -159,6 +161,7 @@ test('uploading errors do not interrupt installation', async () => { fastUnpack: false, sideEffectsCacheRead: true, sideEffectsCacheWrite: true, + onlyBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example'], }) opts.storeController.upload = async () => { throw new Error('an unexpected error') @@ -179,6 +182,7 @@ test('a postinstall script does not modify the original sources added to the sto fastUnpack: false, sideEffectsCacheRead: true, sideEffectsCacheWrite: true, + onlyBuiltDependencies: ['@pnpm/postinstall-modifies-source'], }, {}, {}, { packageImportMethod: 'hardlink' }) await addDependenciesToPackage({}, ['@pnpm/postinstall-modifies-source@1.0.0'], opts) @@ -211,6 +215,7 @@ test('a corrupted side-effects cache is ignored', async () => { fastUnpack: false, sideEffectsCacheRead: true, sideEffectsCacheWrite: true, + onlyBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example'], }) const { updatedManifest: manifest } = await addDependenciesToPackage({}, ['@pnpm.e2e/pre-and-postinstall-scripts-example@1.0.0'], opts) @@ -242,6 +247,7 @@ test('a corrupted side-effects cache is ignored', async () => { sideEffectsCacheRead: true, sideEffectsCacheWrite: true, storeDir: opts.storeDir, + onlyBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example'], }) await install(manifest, opts2) diff --git a/pkg-manager/core/test/utils/testDefaults.ts b/pkg-manager/core/test/utils/testDefaults.ts index eefe900577..7d8ce17ac6 100644 --- a/pkg-manager/core/test/utils/testDefaults.ts +++ b/pkg-manager/core/test/utils/testDefaults.ts @@ -35,7 +35,6 @@ export function testDefaults ( }) const result = { cacheDir, - neverBuiltDependencies: [] as string[], registries: { default: registry, }, diff --git a/pkg-manager/headless/src/index.ts b/pkg-manager/headless/src/index.ts index a016bc7dfb..17fde6effb 100644 --- a/pkg-manager/headless/src/index.ts +++ b/pkg-manager/headless/src/index.ts @@ -104,10 +104,8 @@ export interface Project { export interface HeadlessOptions { ignorePatchFailures?: boolean - neverBuiltDependencies?: string[] ignoredBuiltDependencies?: string[] onlyBuiltDependencies?: string[] - onlyBuiltDependenciesFile?: string autoInstallPeers?: boolean childConcurrency?: number currentLockfile?: LockfileObject diff --git a/pkg-manager/plugin-commands-installation/src/add.ts b/pkg-manager/plugin-commands-installation/src/add.ts index 05af3875c0..c6dab4644a 100644 --- a/pkg-manager/plugin-commands-installation/src/add.ts +++ b/pkg-manager/plugin-commands-installation/src/add.ts @@ -263,28 +263,41 @@ export async function handler ( if (opts.argv.original.includes('--allow-build')) { throw new PnpmError('ALLOW_BUILD_MISSING_PACKAGE', 'The --allow-build flag is missing a package name. Please specify the package name(s) that are allowed to run installation scripts.') } - if (opts.rootProjectManifest?.pnpm?.ignoredBuiltDependencies?.length) { - const overlapDependencies = opts.rootProjectManifest.pnpm.ignoredBuiltDependencies.filter((dep) => opts.allowBuild?.includes(dep)) + if (opts.rootProjectManifest?.pnpm?.allowBuilds) { + const ignoredBuiltDependencies = Object.keys(opts.rootProjectManifest.pnpm.allowBuilds) + .filter(pkg => opts.rootProjectManifest!.pnpm!.allowBuilds![pkg] === false) + const overlapDependencies = ignoredBuiltDependencies.filter((dep) => opts.allowBuild?.includes(dep)) if (overlapDependencies.length) { throw new PnpmError('OVERRIDING_IGNORED_BUILT_DEPENDENCIES', `The following dependencies are ignored by the root project, but are allowed to be built by the current command: ${overlapDependencies.join(', ')}`, { - hint: 'If you are sure you want to allow those dependencies to run installation scripts, remove them from the pnpm.ignoredBuiltDependencies list.', + hint: 'If you are sure you want to allow those dependencies to run installation scripts, remove them from the pnpm.allowBuilds list (or change their value to true).', }) } } - opts.onlyBuiltDependencies = Array.from(new Set([ - ...(opts.onlyBuiltDependencies ?? []), - ...opts.allowBuild, - ])).sort((a, b) => a.localeCompare(b)) + const allowBuilds: Record = {} + for (const pkg of opts.allowBuild) { + allowBuilds[pkg] = true + } if (opts.rootProjectManifestDir) { opts.rootProjectManifest = opts.rootProjectManifest ?? {} await writeSettings({ ...opts, workspaceDir: opts.workspaceDir ?? opts.rootProjectManifestDir, updatedSettings: { - onlyBuiltDependencies: opts.onlyBuiltDependencies, + allowBuilds, }, }) } + // Pass the allowed packages to onlyBuiltDependencies so they can build during this install + return installDeps({ + ...opts, + onlyBuiltDependencies: [ + ...opts.onlyBuiltDependencies ?? [], + ...opts.allowBuild, + ], + fetchFullMetadata: getFetchFullMetadata(opts), + include, + includeDirect: include, + }, params) } return installDeps({ ...opts, diff --git a/pkg-manager/plugin-commands-installation/src/installDeps.ts b/pkg-manager/plugin-commands-installation/src/installDeps.ts index 314ad56515..941fcac390 100644 --- a/pkg-manager/plugin-commands-installation/src/installDeps.ts +++ b/pkg-manager/plugin-commands-installation/src/installDeps.ts @@ -95,6 +95,7 @@ export type InstallDepsOptions = Pick = { ...opts, - ...getOptionsFromRootManifest(opts.dir, (opts.dir === opts.rootProjectManifestDir ? opts.rootProjectManifest ?? manifest : manifest)), + ...rootManifestOpts, + // Preserve onlyBuiltDependencies from opts if explicitly passed (e.g., from --allow-build flag) + // and merge with any from the manifest + onlyBuiltDependencies: [ + ...rootManifestOpts.onlyBuiltDependencies ?? [], + ...opts.onlyBuiltDependencies ?? [], + ], forceHoistPattern, forcePublicHoistPattern, // In case installation is done in a multi-package repository diff --git a/pkg-manager/plugin-commands-installation/src/recursive.ts b/pkg-manager/plugin-commands-installation/src/recursive.ts index 0b2e0b3120..482b6273d3 100755 --- a/pkg-manager/plugin-commands-installation/src/recursive.ts +++ b/pkg-manager/plugin-commands-installation/src/recursive.ts @@ -67,6 +67,7 @@ export type RecursiveOptions = CreateStoreControllerOptions & Pick { - prepare({}) - writeYamlFile('pnpm-workspace.yaml', { - configDependencies: { - '@pnpm.e2e/build-allow-list': `1.0.0+${getIntegrity('@pnpm.e2e/build-allow-list', '1.0.0')}`, - }, - onlyBuiltDependenciesFile: 'node_modules/.pnpm-config/@pnpm.e2e/build-allow-list/list.json', - strictDepBuilds: false, - }) - - await execPnpm(['add', '@pnpm.e2e/pre-and-postinstall-scripts-example@1.0.0', '@pnpm.e2e/install-script-example']) - - expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-preinstall.js')).toBeFalsy() - expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-postinstall.js')).toBeFalsy() - expect(fs.existsSync('node_modules/@pnpm.e2e/install-script-example/generated-by-install.js')).toBeTruthy() - - rimraf('node_modules') - - await execPnpm(['install']) - - expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-preinstall.js')).toBeFalsy() - expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-postinstall.js')).toBeFalsy() - expect(fs.existsSync('node_modules/@pnpm.e2e/install-script-example/generated-by-install.js')).toBeTruthy() -}) - -test('selectively allow scripts in some dependencies by onlyBuiltDependenciesFile and onlyBuiltDependencies', async () => { - prepare() - writeYamlFile('pnpm-workspace.yaml', { - configDependencies: { - '@pnpm.e2e/build-allow-list': `1.0.0+${getIntegrity('@pnpm.e2e/build-allow-list', '1.0.0')}`, - }, - onlyBuiltDependenciesFile: 'node_modules/.pnpm-config/@pnpm.e2e/build-allow-list/list.json', - onlyBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example'], - }) - - await execPnpm(['add', '@pnpm.e2e/pre-and-postinstall-scripts-example@1.0.0', '@pnpm.e2e/install-script-example']) - - expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-preinstall.js')).toBeTruthy() - expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-postinstall.js')).toBeTruthy() - expect(fs.existsSync('node_modules/@pnpm.e2e/install-script-example/generated-by-install.js')).toBeTruthy() - - rimraf('node_modules') - - await execPnpm(['install']) - - expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-preinstall.js')).toBeTruthy() - expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-postinstall.js')).toBeTruthy() - expect(fs.existsSync('node_modules/@pnpm.e2e/install-script-example/generated-by-install.js')).toBeTruthy() -}) - test('catalog applied by configurational dependency hook', async () => { const project = prepare({ dependencies: { diff --git a/pnpm/test/install/global.ts b/pnpm/test/install/global.ts index 86c6e85804..ee4042bc92 100644 --- a/pnpm/test/install/global.ts +++ b/pnpm/test/install/global.ts @@ -5,6 +5,7 @@ import { LAYOUT_VERSION } from '@pnpm/constants' import { prepare } from '@pnpm/prepare' import { type ProjectManifest } from '@pnpm/types' import isWindows from 'is-windows' +import writeYamlFile from 'write-yaml-file' import { addDistTag, execPnpm, @@ -100,7 +101,12 @@ test('run lifecycle events of global packages in correct working directory', asy const pnpmHome = path.join(global, 'pnpm') 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: [] } })) + fs.writeFileSync(path.join(globalPkgDir, 'package.json'), JSON.stringify({})) + writeYamlFile.sync(path.join(globalPkgDir, 'pnpm-workspace.yaml'), { + allowBuilds: { + '@pnpm.e2e/postinstall-calls-pnpm': true, + }, + }) const env = { [PATH_NAME]: `${pnpmHome}${path.delimiter}${process.env[PATH_NAME]!}`, @@ -124,7 +130,7 @@ test.skip('dangerously-allow-all-builds=true in global config', async () => { version: '0.0.0', private: true, pnpm: { - onlyBuiltDependencies: [], // don't allow any dependencies to be built + allowBuilds: {}, // don't allow any dependencies to be built }, } @@ -160,7 +166,7 @@ test.skip('dangerously-allow-all-builds=true in global config', async () => { expect(fs.readdirSync(path.resolve('node_modules/@pnpm.e2e/postinstall-calls-pnpm'))).not.toContain('created-by-postinstall') // global config should be used if local config did not specify - delete manifest.pnpm!.onlyBuiltDependencies + delete manifest.pnpm!.allowBuilds project.writePackageJson(manifest) fs.rmSync('node_modules', { recursive: true }) fs.rmSync('pnpm-lock.yaml') @@ -179,7 +185,7 @@ test.skip('dangerously-allow-all-builds=false in global config', async () => { version: '0.0.0', private: true, pnpm: { - onlyBuiltDependencies: ['@pnpm.e2e/postinstall-calls-pnpm'], + allowBuilds: { '@pnpm.e2e/postinstall-calls-pnpm': true }, }, } @@ -215,7 +221,7 @@ test.skip('dangerously-allow-all-builds=false in global config', async () => { expect(fs.readdirSync(path.resolve('node_modules/@pnpm.e2e/postinstall-calls-pnpm'))).toContain('created-by-postinstall') // global config should be used if local config did not specify - delete manifest.pnpm!.onlyBuiltDependencies + delete manifest.pnpm!.allowBuilds project.writePackageJson(manifest) fs.rmSync('node_modules', { recursive: true }) fs.rmSync('pnpm-lock.yaml') diff --git a/pnpm/test/install/lifecycleScripts.ts b/pnpm/test/install/lifecycleScripts.ts index 3a4af58e1d..9ed45b9194 100644 --- a/pnpm/test/install/lifecycleScripts.ts +++ b/pnpm/test/install/lifecycleScripts.ts @@ -2,12 +2,10 @@ import fs from 'fs' import path from 'path' import { prepare } from '@pnpm/prepare' import { type PackageManifest, type ProjectManifest } from '@pnpm/types' -import { sync as rimraf } from '@zkochan/rimraf' import PATH from 'path-name' import { loadJsonFileSync } from 'load-json-file' import writeYamlFile from 'write-yaml-file' import { execPnpmSync, pnpmBinLocation } from '../utils/index.js' -import { getIntegrity } from '@pnpm/registry-mock' import { readWorkspaceManifest } from '@pnpm/workspace.read-manifest' const pkgRoot = path.join(import.meta.dirname, '..', '..') @@ -108,9 +106,9 @@ test('dependency should not be added to package.json and lockfile if it was not const initialPkg = { name: 'foo', version: '1.0.0', - pnpm: { neverBuiltDependencies: [] }, } const project = prepare(initialPkg) + await writeYamlFile('pnpm-workspace.yaml', { allowBuilds: { 'package-that-cannot-be-installed': true } }) const result = execPnpmSync(['install', 'package-that-cannot-be-installed@0.0.0']) @@ -145,36 +143,6 @@ test('node-gyp is in the PATH', async () => { expect(result.status).toBe(0) }) -test('selectively allow scripts in some dependencies by onlyBuiltDependenciesFile', async () => { - prepare({ - pnpm: { - configDependencies: { - '@pnpm.e2e/build-allow-list': `1.0.0+${getIntegrity('@pnpm.e2e/build-allow-list', '1.0.0')}`, - }, - onlyBuiltDependenciesFile: 'node_modules/.pnpm-config/@pnpm.e2e/build-allow-list/list.json', - }, - }) - execPnpmSync(['add', '@pnpm.e2e/pre-and-postinstall-scripts-example@1.0.0', '@pnpm.e2e/install-script-example']) - - expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-preinstall.js')).toBeFalsy() - expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-postinstall.js')).toBeFalsy() - expect(fs.existsSync('node_modules/@pnpm.e2e/install-script-example/generated-by-install.js')).toBeTruthy() - - rimraf('node_modules') - - execPnpmSync(['install', '--frozen-lockfile']) - - expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-preinstall.js')).toBeFalsy() - expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-postinstall.js')).toBeFalsy() - expect(fs.existsSync('node_modules/@pnpm.e2e/install-script-example/generated-by-install.js')).toBeTruthy() - - execPnpmSync(['rebuild']) - - expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-preinstall.js')).toBeFalsy() - expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-postinstall.js')).toBeFalsy() - expect(fs.existsSync('node_modules/@pnpm.e2e/install-script-example/generated-by-install.js')).toBeTruthy() -}) - test('selectively allow scripts in some dependencies by --allow-build flag', async () => { const project = prepare({}) execPnpmSync(['add', '--allow-build=@pnpm.e2e/install-script-example', '@pnpm.e2e/pre-and-postinstall-scripts-example@1.0.0', '@pnpm.e2e/install-script-example']) @@ -183,10 +151,7 @@ test('selectively allow scripts in some dependencies by --allow-build flag', asy expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-postinstall.js')).toBeFalsy() expect(fs.existsSync('node_modules/@pnpm.e2e/install-script-example/generated-by-install.js')).toBeTruthy() - const manifest = loadJsonFileSync('package.json') - expect(manifest.pnpm?.onlyBuiltDependencies).toBeUndefined() const modulesManifest = await readWorkspaceManifest(project.dir()) - expect(modulesManifest?.onlyBuiltDependencies).toBeUndefined() expect(modulesManifest?.allowBuilds).toStrictEqual({ '@pnpm.e2e/install-script-example': true }) }) @@ -201,22 +166,8 @@ test('--allow-build flag should specify the package', async () => { expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-postinstall.js')).toBeFalsy() expect(fs.existsSync('node_modules/@pnpm.e2e/install-script-example/generated-by-install.js')).toBeFalsy() - const manifest = loadJsonFileSync('package.json') - expect(manifest.pnpm?.onlyBuiltDependencies).toBeUndefined() const modulesManifest = await readWorkspaceManifest(project.dir()) - expect(modulesManifest?.onlyBuiltDependencies).toBeUndefined() -}) - -test('selectively allow scripts in some dependencies by --allow-build flag overlap ignoredBuiltDependencies', async () => { - prepare({ - pnpm: { - ignoredBuiltDependencies: ['@pnpm.e2e/install-script-example'], - }, - }) - const result = execPnpmSync(['add', '--allow-build=@pnpm.e2e/install-script-example', '@pnpm.e2e/pre-and-postinstall-scripts-example@1.0.0', '@pnpm.e2e/install-script-example']) - - expect(result.status).toBe(1) - expect(result.stdout.toString()).toContain('The following dependencies are ignored by the root project, but are allowed to be built by the current command: @pnpm.e2e/install-script-example') + expect(modulesManifest?.allowBuilds).toBeUndefined() }) test('preinstall script does not trigger verify-deps-before-run (#8954)', async () => { @@ -310,3 +261,15 @@ test('git dependencies with preparation scripts should be installed when dangero expect(result.status).toBe(0) expect(fs.existsSync('node_modules/test-git-fetch/dist/index.js')).toBeTruthy() }) + +test('--allow-build flag should error when conflicting with allowBuilds: false', async () => { + prepare({ + pnpm: { + allowBuilds: { '@pnpm.e2e/install-script-example': false }, + }, + }) + const result = execPnpmSync(['add', '--allow-build=@pnpm.e2e/install-script-example', '@pnpm.e2e/pre-and-postinstall-scripts-example@1.0.0', '@pnpm.e2e/install-script-example']) + + expect(result.status).toBe(1) + expect(result.stdout.toString()).toContain('The following dependencies are ignored by the root project, but are allowed to be built by the current command: @pnpm.e2e/install-script-example') +}) diff --git a/pnpm/test/monorepo/index.ts b/pnpm/test/monorepo/index.ts index 630fcaacba..1aa6f4651d 100644 --- a/pnpm/test/monorepo/index.ts +++ b/pnpm/test/monorepo/index.ts @@ -1251,11 +1251,7 @@ test('dependencies of workspace projects are built during headless installation' const projects = preparePackages([ { location: '.', - package: { - pnpm: { - neverBuiltDependencies: [], - }, - }, + package: {}, }, { name: 'project-1', @@ -1270,6 +1266,9 @@ test('dependencies of workspace projects are built during headless installation' writeYamlFile('pnpm-workspace.yaml', { packages: ['**', '!store/**'], sharedWorkspaceLockfile: false, + allowBuilds: { + '@pnpm.e2e/pre-and-postinstall-scripts-example': true, + }, }) await execPnpm(['install', '--lockfile-only']) @@ -1890,9 +1889,6 @@ test('deploy should keep files created by lifecycle scripts', async () => { name: 'root', version: '0.0.0', private: true, - pnpm: { - neverBuiltDependencies: [], - }, }, 'project-0': { name: 'project-0', @@ -1914,6 +1910,9 @@ test('deploy should keep files created by lifecycle scripts', async () => { writeYamlFile('pnpm-workspace.yaml', { packages: ['**', '!store/**'], injectWorkspacePackages: true, + allowBuilds: { + '@pnpm.e2e/install-script-example': true, + }, }) const monorepoRoot = process.cwd() @@ -1941,9 +1940,6 @@ test('rebuild in a directory created with "pnpm deploy" and with "pnpm.neverBuil name: 'root', version: '0.0.0', private: true, - pnpm: { - neverBuiltDependencies: [], - }, }, 'project-0': { name: 'project-0', @@ -1965,6 +1961,9 @@ test('rebuild in a directory created with "pnpm deploy" and with "pnpm.neverBuil writeYamlFile('pnpm-workspace.yaml', { packages: ['**', '!store/**'], injectWorkspacePackages: true, + allowBuilds: { + '@pnpm.e2e/install-script-example': true, + }, }) const monorepoRoot = process.cwd() diff --git a/pnpm/test/recursive/rebuild.ts b/pnpm/test/recursive/rebuild.ts index 9446e0f3dc..ec9c389e03 100644 --- a/pnpm/test/recursive/rebuild.ts +++ b/pnpm/test/recursive/rebuild.ts @@ -5,11 +5,7 @@ test('`pnpm recursive rebuild` specific dependencies', async () => { const projects = preparePackages([ { location: '.', - package: { - pnpm: { - neverBuiltDependencies: [], - }, - }, + package: {}, }, { name: 'project-1', @@ -42,7 +38,7 @@ test('`pnpm recursive rebuild` specific dependencies', async () => { projects['project-2'].hasNot('@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-preinstall.js') projects['project-2'].hasNot('@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-postinstall.js') - await execPnpm(['recursive', 'rebuild', 'install-scripts-example-for-pnpm']) + await execPnpm(['recursive', 'rebuild', 'install-scripts-example-for-pnpm', '--config.dangerouslyAllowAllBuilds=true']) projects['project-1'].hasNot('@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-preinstall.js') projects['project-1'].hasNot('@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-postinstall.js') diff --git a/releasing/plugin-commands-deploy/package.json b/releasing/plugin-commands-deploy/package.json index 1fab11f1c1..a1786974cb 100644 --- a/releasing/plugin-commands-deploy/package.json +++ b/releasing/plugin-commands-deploy/package.json @@ -49,7 +49,8 @@ "@zkochan/rimraf": "catalog:", "normalize-path": "catalog:", "ramda": "catalog:", - "render-help": "catalog:" + "render-help": "catalog:", + "write-yaml-file": "catalog:" }, "peerDependencies": { "@pnpm/logger": "catalog:" @@ -63,8 +64,7 @@ "@pnpm/registry-mock": "catalog:", "@pnpm/test-fixtures": "workspace:*", "@pnpm/workspace.filter-packages-from-dir": "workspace:*", - "@types/ramda": "catalog:", - "write-yaml-file": "catalog:" + "@types/ramda": "catalog:" }, "engines": { "node": ">=20.19" diff --git a/releasing/plugin-commands-deploy/src/createDeployFiles.ts b/releasing/plugin-commands-deploy/src/createDeployFiles.ts index 4ff0c2b023..d6c04842f4 100644 --- a/releasing/plugin-commands-deploy/src/createDeployFiles.ts +++ b/releasing/plugin-commands-deploy/src/createDeployFiles.ts @@ -30,11 +30,17 @@ export interface CreateDeployFilesOptions { selectedProjectManifest: ProjectManifest projectId: ProjectId rootProjectManifestDir: string + allowBuilds?: Record +} + +export interface DeployWorkspaceManifest { + allowBuilds?: Record } export interface DeployFiles { lockfile: LockfileObject manifest: ProjectManifest + workspaceManifest?: DeployWorkspaceManifest } export function createDeployFiles ({ @@ -46,6 +52,7 @@ export function createDeployFiles ({ selectedProjectManifest, projectId, rootProjectManifestDir, + allowBuilds, }: CreateDeployFilesOptions): DeployFiles { const deployedProjectRealPath = path.resolve(lockfileDir, projectId) const inputSnapshot = lockfile.importers[projectId] @@ -160,6 +167,12 @@ export function createDeployFiles ({ } } + if (allowBuilds) { + result.workspaceManifest = { + allowBuilds, + } + } + return result } diff --git a/releasing/plugin-commands-deploy/src/deploy.ts b/releasing/plugin-commands-deploy/src/deploy.ts index eb754cc0c6..61b391c605 100644 --- a/releasing/plugin-commands-deploy/src/deploy.ts +++ b/releasing/plugin-commands-deploy/src/deploy.ts @@ -3,6 +3,7 @@ import path from 'path' import { pick } from 'ramda' import { docsUrl } from '@pnpm/cli-utils' import { type Config, types as configTypes } from '@pnpm/config' +import { WORKSPACE_MANIFEST_FILENAME } from '@pnpm/constants' import { fetchFromDir } from '@pnpm/directory-fetcher' import { createIndexedPkgImporter } from '@pnpm/fs.indexed-pkg-importer' import { isEmptyDirOrNothing } from '@pnpm/fs.is-empty-dir-or-nothing' @@ -12,6 +13,7 @@ import { PnpmError } from '@pnpm/error' import { getLockfileImporterId, readWantedLockfile, writeWantedLockfile } from '@pnpm/lockfile.fs' import rimraf from '@zkochan/rimraf' import renderHelp from 'render-help' +import writeYamlFile from 'write-yaml-file' import { deployHook } from './deployHook.js' import { logger, globalWarn } from '@pnpm/logger' import { type Project } from '@pnpm/types' @@ -78,7 +80,7 @@ export function help (): string { export type DeployOptions = & Omit - & Pick + & Pick export async function handler (opts: DeployOptions, params: string[]): Promise { if (!opts.workspaceDir) { @@ -240,15 +242,22 @@ async function deployFromSharedLockfile ( selectedProjectManifest: selectedProject.manifest, projectId, rootProjectManifestDir, + allowBuilds: opts.allowBuilds, }) - await Promise.all([ + const filesToWrite: Array> = [ fs.promises.writeFile( path.join(deployDir, 'package.json'), JSON.stringify(deployFiles.manifest, undefined, 2) + '\n' ), writeWantedLockfile(deployDir, deployFiles.lockfile), - ]) + ] + if (deployFiles.workspaceManifest) { + filesToWrite.push( + writeYamlFile(path.join(deployDir, WORKSPACE_MANIFEST_FILENAME), deployFiles.workspaceManifest) + ) + } + await Promise.all(filesToWrite) try { await install.handler({ diff --git a/releasing/plugin-commands-deploy/test/shared-lockfile.test.ts b/releasing/plugin-commands-deploy/test/shared-lockfile.test.ts index 9b406c0ba0..cd6734574b 100644 --- a/releasing/plugin-commands-deploy/test/shared-lockfile.test.ts +++ b/releasing/plugin-commands-deploy/test/shared-lockfile.test.ts @@ -278,7 +278,7 @@ test('the deploy manifest should inherit some fields from the pnpm object from t version: '0.0.0', private: true, pnpm: { - onlyBuiltDependencies: ['from-root'], + allowBuilds: { 'from-root': true }, overrides: { 'is-positive': '2.0.0', }, @@ -292,7 +292,7 @@ test('the deploy manifest should inherit some fields from the pnpm object from t 'is-positive': '3.1.0', }, pnpm: { - onlyBuiltDependencies: ['from-project-0'], + allowBuilds: { 'from-project-0': true }, overrides: { 'is-positive': '=1.0.0', }, @@ -344,7 +344,7 @@ test('the deploy manifest should inherit some fields from the pnpm object from t const manifest = readPackageJson('deploy') as ProjectManifest expect(manifest.pnpm).toStrictEqual({ - onlyBuiltDependencies: preparedManifests.root.pnpm!.onlyBuiltDependencies, + allowBuilds: preparedManifests.root.pnpm!.allowBuilds, } as ProjectManifest['pnpm']) expect(readPackageJson('deploy/node_modules/is-positive/')).toHaveProperty(['version'], preparedManifests.root.pnpm!.overrides!['is-positive']) @@ -1079,9 +1079,6 @@ test('deploy with a shared lockfile should keep files created by lifecycle scrip name: 'root', version: '0.0.0', private: true, - pnpm: { - neverBuiltDependencies: [], - }, }, 'project-0': { name: 'project-0', @@ -1117,6 +1114,7 @@ test('deploy with a shared lockfile should keep files created by lifecycle scrip rootProjectManifestDir: process.cwd(), recursive: true, lockfileDir: process.cwd(), + onlyBuiltDependencies: ['@pnpm.e2e/install-script-example'], workspaceDir: process.cwd(), }) expect(fs.existsSync('pnpm-lock.yaml')).toBeTruthy() @@ -1132,6 +1130,7 @@ test('deploy with a shared lockfile should keep files created by lifecycle scrip selectedProjectsGraph, sharedWorkspaceLockfile: true, lockfileDir: process.cwd(), + onlyBuiltDependencies: ['@pnpm.e2e/install-script-example'], workspaceDir: process.cwd(), }, ['deploy']) diff --git a/workspace/manifest-writer/src/index.ts b/workspace/manifest-writer/src/index.ts index cfacd3d463..e4aad7a866 100644 --- a/workspace/manifest-writer/src/index.ts +++ b/workspace/manifest-writer/src/index.ts @@ -45,32 +45,7 @@ export async function updateWorkspaceManifest (dir: string, opts: { shouldBeUpdated = removePackagesFromWorkspaceCatalog(manifest, opts.allProjects ?? []) || shouldBeUpdated } - // If the current manifest has allowBuilds, convert old fields to allowBuilds format const updatedFields = { ...opts.updatedFields } - if (manifest.allowBuilds != null || (manifest.onlyBuiltDependencies == null && manifest.ignoredBuiltDependencies == null)) { - const allowBuilds: Record = { ...manifest.allowBuilds } - - // Convert onlyBuiltDependencies to allowBuilds with true values - if (updatedFields.onlyBuiltDependencies != null) { - for (const pattern of updatedFields.onlyBuiltDependencies) { - allowBuilds[pattern] = true - } - } - - // Convert ignoredBuiltDependencies to allowBuilds with false values - if (updatedFields.ignoredBuiltDependencies != null) { - for (const pattern of updatedFields.ignoredBuiltDependencies) { - allowBuilds[pattern] = false - } - } - - // Update allowBuilds instead of the old fields - if (manifest.allowBuilds != null || Object.keys(allowBuilds).length > 0) { - updatedFields.allowBuilds = allowBuilds - } - delete updatedFields.onlyBuiltDependencies - delete updatedFields.ignoredBuiltDependencies - } for (const [key, value] of Object.entries(updatedFields)) { if (!equals(manifest[key as keyof WorkspaceManifest], value)) { diff --git a/workspace/manifest-writer/test/updateWorkspaceManifest.test.ts b/workspace/manifest-writer/test/updateWorkspaceManifest.test.ts index 6d45b3bcd6..93315c3b5b 100644 --- a/workspace/manifest-writer/test/updateWorkspaceManifest.test.ts +++ b/workspace/manifest-writer/test/updateWorkspaceManifest.test.ts @@ -8,13 +8,13 @@ import { sync as writeYamlFile } from 'write-yaml-file' test('updateWorkspaceManifest adds a new setting', async () => { const dir = tempDir(false) const filePath = path.join(dir, WORKSPACE_MANIFEST_FILENAME) - writeYamlFile(filePath, { packages: ['*'], onlyBuiltDependencies: [] }) + writeYamlFile(filePath, { packages: ['*'], allowBuilds: {} }) await updateWorkspaceManifest(dir, { - updatedFields: { onlyBuiltDependencies: [] }, + updatedFields: { allowBuilds: {} }, }) expect(readYamlFile(filePath)).toStrictEqual({ packages: ['*'], - onlyBuiltDependencies: [], + allowBuilds: {}, }) }) @@ -48,14 +48,13 @@ test('updateWorkspaceManifest updates allowBuilds', async () => { const filePath = path.join(dir, WORKSPACE_MANIFEST_FILENAME) writeYamlFile(filePath, { packages: ['*'], allowBuilds: { qar: 'warn' } }) await updateWorkspaceManifest(dir, { - updatedFields: { onlyBuiltDependencies: ['foo'], ignoredBuiltDependencies: ['bar'] }, + updatedFields: { allowBuilds: { foo: true, bar: false } }, }) expect(readYamlFile(filePath)).toStrictEqual({ packages: ['*'], allowBuilds: { bar: false, foo: true, - qar: 'warn', }, }) })