mirror of
https://github.com/pnpm/pnpm.git
synced 2026-06-27 17:35:30 -04:00
fix: avoid updating allowBuilds when workspace is ignored (#12488)
pnpm install --ignore-workspace auto-populated ignored builds into the allowBuilds map of pnpm-workspace.yaml, overwriting committed true/false values with the "set this to true or false" placeholder — even under --frozen-lockfile, which must stay read-only. The ignore-workspace CLI flag is now a first-class Config field (ignoreWorkspace, mirroring ignoreWorkspaceCycles) instead of being read from the untyped cliOptions bag. handleIgnoredBuilds reads it directly and skips writing to allowBuilds when the workspace is ignored. The strict ignored-build failure is unchanged. Closes pnpm/pnpm#12469 --------- Co-authored-by: Zoltan Kochan <z@kochan.io>
This commit is contained in:
6
.changeset/ignore-workspace-allow-builds.md
Normal file
6
.changeset/ignore-workspace-allow-builds.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/installing.commands": patch
|
||||
"pnpm": patch
|
||||
---
|
||||
|
||||
Fixed `pnpm install --ignore-workspace` overwriting the `allowBuilds` map in `pnpm-workspace.yaml`. The ignored builds of a package with a build script were auto-populated into `allowBuilds` even though `--ignore-workspace` was passed, clobbering committed `true`/`false` values with the `set this to true or false` placeholder [#12469](https://github.com/pnpm/pnpm/issues/12469).
|
||||
@@ -232,6 +232,7 @@ export interface Config extends OptionsFromRootManifest {
|
||||
dedupePeerDependents?: boolean
|
||||
dedupePeers?: boolean
|
||||
patchesDir?: string
|
||||
ignoreWorkspace?: boolean
|
||||
ignoreWorkspaceCycles?: boolean
|
||||
disallowWorkspaceCycles?: boolean
|
||||
packGzipLevel?: number
|
||||
|
||||
@@ -8,6 +8,7 @@ import { lexCompare } from '@pnpm/util.lex-comparator'
|
||||
|
||||
export interface HandleIgnoredBuildsOpts {
|
||||
allowBuilds?: Record<string, boolean | string>
|
||||
ignoreWorkspace?: boolean
|
||||
rootProjectManifestDir?: string
|
||||
workspaceDir?: string
|
||||
strictDepBuilds?: boolean
|
||||
@@ -18,7 +19,9 @@ export async function handleIgnoredBuilds (
|
||||
ignoredBuilds: IgnoredBuilds | undefined
|
||||
): Promise<void> {
|
||||
if (!ignoredBuilds?.size) return
|
||||
await writeIgnoredBuildsToAllowBuilds(opts, ignoredBuilds)
|
||||
if (!opts.ignoreWorkspace) {
|
||||
await writeIgnoredBuildsToAllowBuilds(opts, ignoredBuilds)
|
||||
}
|
||||
if (opts.strictDepBuilds) {
|
||||
throw new IgnoredBuildsError(ignoredBuilds)
|
||||
}
|
||||
|
||||
@@ -117,6 +117,7 @@ export type InstallDepsOptions = Pick<Config,
|
||||
| 'workspaceDir'
|
||||
| 'workspacePackagePatterns'
|
||||
| 'extraEnv'
|
||||
| 'ignoreWorkspace'
|
||||
| 'ignoreWorkspaceCycles'
|
||||
| 'disallowWorkspaceCycles'
|
||||
| 'configDependencies'
|
||||
|
||||
31
installing/commands/test/handleIgnoredBuilds.ts
Normal file
31
installing/commands/test/handleIgnoredBuilds.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
|
||||
import { expect, test } from '@jest/globals'
|
||||
import { prepareEmpty } from '@pnpm/prepare'
|
||||
import type { DepPath } from '@pnpm/types'
|
||||
import { readYamlFileSync } from 'read-yaml-file'
|
||||
import { writeYamlFileSync } from 'write-yaml-file'
|
||||
|
||||
import { handleIgnoredBuilds } from '../lib/handleIgnoredBuilds.js'
|
||||
|
||||
test('handleIgnoredBuilds does not update pnpm-workspace.yaml when workspace is ignored', async () => {
|
||||
prepareEmpty()
|
||||
|
||||
const workspaceManifestFile = path.resolve('pnpm-workspace.yaml')
|
||||
const workspaceManifest = {
|
||||
allowBuilds: {
|
||||
esbuild: false,
|
||||
},
|
||||
}
|
||||
writeYamlFileSync(workspaceManifestFile, workspaceManifest)
|
||||
const workspaceManifestBefore = fs.readFileSync(workspaceManifestFile, 'utf8')
|
||||
|
||||
await handleIgnoredBuilds({
|
||||
ignoreWorkspace: true,
|
||||
rootProjectManifestDir: process.cwd(),
|
||||
}, new Set(['esbuild@0.25.0' as DepPath]))
|
||||
|
||||
expect(fs.readFileSync(workspaceManifestFile, 'utf8')).toBe(workspaceManifestBefore)
|
||||
expect(readYamlFileSync(workspaceManifestFile)).toStrictEqual(workspaceManifest)
|
||||
})
|
||||
@@ -333,6 +333,29 @@ test('auto-populated placeholders are merged with existing allowBuilds', async (
|
||||
expect(manifest?.allowBuilds?.['@pnpm.e2e/pre-and-postinstall-scripts-example']).toBe('set this to true or false')
|
||||
})
|
||||
|
||||
test('install --ignore-workspace does not overwrite allowBuilds in pnpm-workspace.yaml', () => {
|
||||
prepare({
|
||||
dependencies: {
|
||||
'@pnpm.e2e/pre-and-postinstall-scripts-example': '1.0.0',
|
||||
},
|
||||
})
|
||||
writeYamlFileSync('pnpm-workspace.yaml', {
|
||||
allowBuilds: {
|
||||
'@pnpm.e2e/pre-and-postinstall-scripts-example': false,
|
||||
},
|
||||
})
|
||||
const manifestBefore = fs.readFileSync('pnpm-workspace.yaml', 'utf8')
|
||||
|
||||
const { status, stdout, stderr } = execPnpmSync(['install', '--ignore-workspace'])
|
||||
|
||||
// The build is ignored (--ignore-workspace skips the allowBuilds entry), so the
|
||||
// install ends in ERR_PNPM_IGNORED_BUILDS — the same code path that would have
|
||||
// written the placeholder. The manifest must stay untouched regardless.
|
||||
expect(status).toBe(1)
|
||||
expect(`${stdout}${stderr}`).toContain('ERR_PNPM_IGNORED_BUILDS')
|
||||
expect(fs.readFileSync('pnpm-workspace.yaml', 'utf8')).toBe(manifestBefore)
|
||||
})
|
||||
|
||||
test('selective rebuild preserves ignoredBuilds for packages not being rebuilt', async () => {
|
||||
const project = prepare({})
|
||||
writeYamlFileSync('pnpm-workspace.yaml', {
|
||||
|
||||
Reference in New Issue
Block a user