feat: new parameter --fail-if-no-match supported (#7409)

close #7403

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
This commit is contained in:
Simon He
2023-12-26 21:06:10 +08:00
committed by GitHub
parent 4d2923858a
commit 4e71066ddc
7 changed files with 24 additions and 3 deletions

View File

@@ -0,0 +1,8 @@
---
"@pnpm/common-cli-options-help": minor
"@pnpm/config": minor
"pnpm": minor
---
Use `--fail-if-no-match` if you want the CLI fail if no packages were matched by the command [#7403](https://github.com/pnpm/pnpm/issues/7403).

View File

@@ -116,6 +116,10 @@ export const FILTERING = {
description: 'Restricts the scope to package names matching the given pattern similar to --filter, but it ignores devDependencies when searching for dependencies and dependents.', description: 'Restricts the scope to package names matching the given pattern similar to --filter, but it ignores devDependencies when searching for dependencies and dependents.',
name: '--filter-prod <pattern>', name: '--filter-prod <pattern>',
}, },
{
description: 'If no projects are matched by the command, exit with exit code 1 (fail)',
name: '--fail-if-no-match',
},
], ],
title: 'Filtering options (run the command only on packages that satisfy at least one of the selectors)', title: 'Filtering options (run the command only on packages that satisfy at least one of the selectors)',
} }

View File

@@ -22,6 +22,7 @@ export interface Config {
excludeLinksFromLockfile: boolean excludeLinksFromLockfile: boolean
extraBinPaths: string[] extraBinPaths: string[]
extraEnv: Record<string, string> extraEnv: Record<string, string>
failIfNoMatch: boolean
filter: string[] filter: string[]
filterProd: string[] filterProd: string[]
rawLocalConfig: Record<string, any>, // eslint-disable-line rawLocalConfig: Record<string, any>, // eslint-disable-line

View File

@@ -145,7 +145,8 @@ export const types = Object.assign({
'embed-readme': Boolean, 'embed-readme': Boolean,
'update-notifier': Boolean, 'update-notifier': Boolean,
'registry-supports-time-field': Boolean, 'registry-supports-time-field': Boolean,
// eslint-disable-next-line @typescript-eslint/no-explicit-any 'fail-if-no-match': Boolean,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as Partial<Record<keyof KebabCaseConfig, any>>, npmTypes.types) } as Partial<Record<keyof KebabCaseConfig, any>>, npmTypes.types)
export type CliOptions = Record<string, unknown> & { dir?: string } export type CliOptions = Record<string, unknown> & { dir?: string }
@@ -210,6 +211,7 @@ export async function getConfig (
'enable-modules-dir': true, 'enable-modules-dir': true,
'exclude-links-from-lockfile': false, 'exclude-links-from-lockfile': false,
'extend-node-path': true, 'extend-node-path': true,
'fail-if-no-match': false,
'fetch-retries': 2, 'fetch-retries': 2,
'fetch-retry-factor': 10, 'fetch-retry-factor': 10,
'fetch-retry-maxtimeout': 60000, 'fetch-retry-maxtimeout': 60000,

View File

@@ -53,6 +53,7 @@ export const GLOBAL_OPTIONS = pick([
'workspace-packages', 'workspace-packages',
'workspace-root', 'workspace-root',
'include-workspace-root', 'include-workspace-root',
'fail-if-no-match',
], allTypes) ], allTypes)
export type CommandResponse = string | { output?: string, exitCode: number } export type CommandResponse = string | { output?: string, exitCode: number }

View File

@@ -214,7 +214,7 @@ export async function main (inputArgv: string[]) {
if (printLogs) { if (printLogs) {
console.log(`No projects found in "${wsDir}"`) console.log(`No projects found in "${wsDir}"`)
} }
process.exitCode = 0 process.exitCode = config.failIfNoMatch ? 1 : 0
return return
} }
config.allProjectsGraph = filterResults.allProjectsGraph config.allProjectsGraph = filterResults.allProjectsGraph
@@ -223,7 +223,7 @@ export async function main (inputArgv: string[]) {
if (printLogs) { if (printLogs) {
console.log(`No projects matched the filters in "${wsDir}"`) console.log(`No projects matched the filters in "${wsDir}"`)
} }
process.exitCode = 0 process.exitCode = config.failIfNoMatch ? 1 : 0
return return
} }
if (filterResults.unmatchedFilters.length !== 0 && printLogs) { if (filterResults.unmatchedFilters.length !== 0 && printLogs) {

View File

@@ -37,6 +37,11 @@ test('no projects matched the filters', async () => {
const { stdout } = execPnpmSync(['list', '--filter=not-exists']) const { stdout } = execPnpmSync(['list', '--filter=not-exists'])
expect(stdout.toString()).toMatch(/^No projects matched the filters in/) expect(stdout.toString()).toMatch(/^No projects matched the filters in/)
} }
{
const { stdout, status } = execPnpmSync(['list', '--filter=not-exists', '--fail-if-no-match'])
expect(stdout.toString()).toMatch(/^No projects matched the filters in/)
expect(status).toBe(1)
}
{ {
const { stdout } = execPnpmSync(['list', '--filter=not-exists', '--parseable']) const { stdout } = execPnpmSync(['list', '--filter=not-exists', '--parseable'])
expect(stdout.toString()).toBe('') // don't print anything if --parseable is used expect(stdout.toString()).toBe('') // don't print anything if --parseable is used