fea: pnpm.ignoredBuiltDependencies for muting warnings about ignored dependency builds (#8958)

close #8935

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
This commit is contained in:
btea
2025-01-12 09:17:44 +08:00
committed by GitHub
parent 040e67b88d
commit 7a9473b237
9 changed files with 46 additions and 4 deletions

View File

@@ -0,0 +1,7 @@
---
"@pnpm/default-reporter": minor
"@pnpm/build-modules": minor
"pnpm": minor
---
Added a new field "pnpm.ignoredBuiltDependencies" for explicitly listing packages that should not be built. When a package is in the list, pnpm will not print an info message about that package not being built [#8935](https://github.com/pnpm/pnpm/issues/8935).

View File

@@ -87,9 +87,11 @@ export function reportSummary (
}
if (ignoredScripts.packageNames && ignoredScripts.packageNames.length > 0) {
msg += EOL
msg += `The following dependencies have build scripts that were ignored: ${Array.from(ignoredScripts.packageNames).sort().join(', ')}`
msg += `The following dependencies have build scripts that were ignored: ${Array.from(ignoredScripts.packageNames).sort().join(', ')}.`
msg += EOL
msg += 'To allow the execution of build scripts for these packages, add their names to "pnpm.onlyBuiltDependencies" in your "package.json", then run "pnpm rebuild"'
msg += 'To allow the execution of build scripts for these packages, add their names to "pnpm.onlyBuiltDependencies" in your "package.json", then run "pnpm rebuild".'
msg += EOL
msg += 'If you don\'t want to build the package and see this message, add the package to the "pnpm.ignoredBuiltDependencies" list.'
msg += EOL
}
return Rx.of({ msg })

View File

@@ -16,6 +16,7 @@ export interface OptionsFromRootManifest {
neverBuiltDependencies?: string[]
onlyBuiltDependencies?: string[]
onlyBuiltDependenciesFile?: string
ignoredBuiltDependencies?: string[]
packageExtensions?: Record<string, PackageExtension>
ignoredOptionalDependencies?: string[]
patchedDependencies?: Record<string, string>
@@ -70,6 +71,7 @@ export function getOptionsFromRootManifest (manifestDir: string, manifest: Proje
peerDependencyRules,
patchedDependencies,
supportedArchitectures,
ignoredBuiltDependencies: manifest.pnpm?.ignoredBuiltDependencies,
}
if (onlyBuiltDependencies) {
settings.onlyBuiltDependencies = onlyBuiltDependencies

View File

@@ -23,6 +23,7 @@ export async function buildModules<T extends string> (
rootDepPaths: T[],
opts: {
allowBuild?: (pkgName: string) => boolean
ignoredBuiltDependencies?: string[]
childConcurrency?: number
depsToBuild?: Set<string>
depsStateCache: DepsStateCache
@@ -84,6 +85,13 @@ export async function buildModules<T extends string> (
)
})
await runGroups(opts.childConcurrency ?? 4, groups)
if (opts.ignoredBuiltDependencies?.length) {
for (const ignoredBuild of opts.ignoredBuiltDependencies) {
// We already ignore the build of this dependency.
// No need to report it.
ignoredPkgs.delete(ignoredBuild)
}
}
const packageNames = Array.from(ignoredPkgs)
ignoredScriptsLogger.debug({ packageNames })
return { ignoredBuilds: packageNames }

View File

@@ -134,6 +134,7 @@ export interface ProjectManifest extends BaseManifest {
neverBuiltDependencies?: string[]
onlyBuiltDependencies?: string[]
onlyBuiltDependenciesFile?: string
ignoredBuiltDependencies?: string[]
overrides?: Record<string, string>
packageExtensions?: Record<string, PackageExtension>
ignoredOptionalDependencies?: string[]

View File

@@ -65,6 +65,7 @@ export interface StrictInstallOptions {
rawConfig: Record<string, any> // eslint-disable-line @typescript-eslint/no-explicit-any
verifyStoreIntegrity: boolean
engineStrict: boolean
ignoredBuiltDependencies?: string[]
neverBuiltDependencies?: string[]
onlyBuiltDependencies?: string[]
onlyBuiltDependenciesFile?: string

View File

@@ -1109,6 +1109,7 @@ const _installInContext: InstallFunction = async (projects, ctx, opts) => {
}
ignoredBuilds = (await buildModules(dependenciesGraph, rootNodes, {
allowBuild,
ignoredBuiltDependencies: opts.ignoredBuiltDependencies,
childConcurrency: opts.childConcurrency,
depsStateCache,
depsToBuild: new Set(result.newDepPaths),

View File

@@ -469,23 +469,41 @@ test('throw an exception when both neverBuiltDependencies and onlyBuiltDependenc
test('selectively allow scripts in some dependencies by onlyBuiltDependencies', async () => {
prepareEmpty()
const reporter = sinon.spy()
const onlyBuiltDependencies = ['@pnpm.e2e/install-script-example']
const manifest = await addDependenciesToPackage({},
['@pnpm.e2e/pre-and-postinstall-scripts-example@1.0.0', '@pnpm.e2e/install-script-example'],
testDefaults({ fastUnpack: false, onlyBuiltDependencies })
testDefaults({ fastUnpack: false, onlyBuiltDependencies, reporter })
)
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()
{
const ignoredPkgsLog = reporter.getCalls().find((call) => call.firstArg.name === 'pnpm:ignored-scripts')?.firstArg
expect(ignoredPkgsLog.packageNames).toStrictEqual(['@pnpm.e2e/pre-and-postinstall-scripts-example'])
}
reporter.resetHistory()
rimraf('node_modules')
await install(manifest, testDefaults({ fastUnpack: false, frozenLockfile: true, onlyBuiltDependencies }))
await install(manifest, testDefaults({
fastUnpack: false,
frozenLockfile: true,
ignoredBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example'],
onlyBuiltDependencies,
reporter,
}))
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()
{
const ignoredPkgsLog = reporter.getCalls().find((call) => call.firstArg.name === 'pnpm:ignored-scripts')?.firstArg
expect(ignoredPkgsLog.packageNames).toStrictEqual([])
}
})
test('lifecycle scripts have access to package\'s own binary by binary name', async () => {

View File

@@ -106,6 +106,7 @@ export interface Project {
export interface HeadlessOptions {
neverBuiltDependencies?: string[]
ignoredBuiltDependencies?: string[]
onlyBuiltDependencies?: string[]
onlyBuiltDependenciesFile?: string
autoInstallPeers?: boolean
@@ -525,6 +526,7 @@ export async function headlessInstall (opts: HeadlessOptions): Promise<Installat
}
ignoredBuilds = (await buildModules(graph, Array.from(directNodes), {
allowBuild,
ignoredBuiltDependencies: opts.ignoredBuiltDependencies,
childConcurrency: opts.childConcurrency,
extraBinPaths,
extraEnv,