diff --git a/.changeset/smooth-toes-press.md b/.changeset/smooth-toes-press.md new file mode 100644 index 0000000000..eaf6b537b4 --- /dev/null +++ b/.changeset/smooth-toes-press.md @@ -0,0 +1,5 @@ +--- +"@pnpm/plugin-commands-audit": minor +--- + +New CLI option added: `--ignore-registry-errors`. When used, audit exits with 0 exit code, when the registry responds with a non-200 status code. diff --git a/packages/plugin-commands-audit/package.json b/packages/plugin-commands-audit/package.json index 6a920be6cc..4cc2a7e2a6 100644 --- a/packages/plugin-commands-audit/package.json +++ b/packages/plugin-commands-audit/package.json @@ -32,6 +32,7 @@ "@pnpm/types": "workspace:7.2.0", "@types/ramda": "0.27.39", "@types/zkochan__table": "npm:@types/table@6.0.0", + "nock": "12.0.3", "strip-ansi": "^6.0.0" }, "dependencies": { diff --git a/packages/plugin-commands-audit/src/audit.ts b/packages/plugin-commands-audit/src/audit.ts index b0829bae00..c9ba83b9b5 100644 --- a/packages/plugin-commands-audit/src/audit.ts +++ b/packages/plugin-commands-audit/src/audit.ts @@ -1,4 +1,4 @@ -import audit, { AuditVulnerabilityCounts } from '@pnpm/audit' +import audit, { AuditReport, AuditVulnerabilityCounts } from '@pnpm/audit' import { docsUrl, TABLE_OPTIONS } from '@pnpm/cli-utils' import { Config, types as allTypes, UniversalOptions } from '@pnpm/config' import { WANTED_LOCKFILE } from '@pnpm/constants' @@ -39,6 +39,7 @@ export function cliOptionsTypes () { 'registry', ], allTypes), 'audit-level': ['low', 'moderate', 'high', 'critical'], + 'ignore-registry-errors': Boolean, } } @@ -79,6 +80,10 @@ export function help () { description: 'Don\'t audit "optionalDependencies"', name: '--no-optional', }, + { + description: 'Use exit code 0 if the registry responds with an error. Useful when audit checks are used in CI. A build should fail because the registry has issues.', + name: '--ignore-registry-errors', + }, ], }, ], @@ -90,6 +95,7 @@ export function help () { export async function handler ( opts: Pick & { auditLevel?: 'low' | 'moderate' | 'high' | 'critical' + ignoreRegistryErrors?: boolean json?: boolean lockfileDir?: string registries: Registries @@ -104,17 +110,27 @@ export async function handler ( devDependencies: opts.dev !== false, optionalDependencies: opts.optional !== false, } - const auditReport = await audit(lockfile, { - include, - registry: opts.registries.default, - retry: { - factor: opts.fetchRetryFactor, - maxTimeout: opts.fetchRetryMaxtimeout, - minTimeout: opts.fetchRetryMintimeout, - retries: opts.fetchRetries, - }, - timeout: opts.fetchTimeout, - }) + let auditReport!: AuditReport + try { + auditReport = await audit(lockfile, { + include, + registry: opts.registries.default, + retry: { + factor: opts.fetchRetryFactor, + maxTimeout: opts.fetchRetryMaxtimeout, + minTimeout: opts.fetchRetryMintimeout, + retries: opts.fetchRetries, + }, + timeout: opts.fetchTimeout, + }) + } catch (err) { + if (opts.ignoreRegistryErrors) { + return { + exitCode: 0, + output: err.message, + } + } + } const vulnerabilities = auditReport.metadata.vulnerabilities const totalVulnerabilityCount = Object.values(vulnerabilities) .reduce((sum: number, vulnerabilitiesCount: number) => sum + vulnerabilitiesCount, 0) diff --git a/packages/plugin-commands-audit/test/index.ts b/packages/plugin-commands-audit/test/index.ts index 918ce2cf4e..8a6f9b349b 100644 --- a/packages/plugin-commands-audit/test/index.ts +++ b/packages/plugin-commands-audit/test/index.ts @@ -1,5 +1,6 @@ import path from 'path' import { audit } from '@pnpm/plugin-commands-audit' +import nock from 'nock' import stripAnsi from 'strip-ansi' const skipOnNode10 = process.version.split('.')[0] === 'v10' ? test.skip : test @@ -83,3 +84,22 @@ test.skip('audit does not exit with code 1 if the found vulnerabilities are havi expect(stripAnsi(output)).toBe(`1 vulnerabilities found Severity: 1 moderate`) }) + +test('audit does not exit with code 1 if the registry responds with a non-200 reponse and ignoreRegistryErrors is used', async () => { + const registry = 'https://registry-error.com' + nock(registry) + .post('/-/npm/v1/security/audits') + .reply(500, { message: 'Something bad happened' }) + const { output, exitCode } = await audit.handler({ + dir: path.join(__dirname, 'packages/has-vulnerabilities'), + dev: true, + ignoreRegistryErrors: true, + production: false, + registries: { + default: registry, + }, + }) + + expect(exitCode).toBe(0) + expect(stripAnsi(output)).toBe('The audit endpoint (at https://registry-error.com/-/npm/v1/security/audits) responded with 500: {"message":"Something bad happened"}') +}) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ed13d9f50e..2d836eb3fd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1704,6 +1704,7 @@ importers: '@types/zkochan__table': npm:@types/table@6.0.0 '@zkochan/table': ^1.0.0 chalk: ^4.1.0 + nock: 12.0.3 ramda: ^0.27.1 render-help: ^1.0.1 strip-ansi: ^6.0.0 @@ -1723,6 +1724,7 @@ importers: '@pnpm/types': link:../types '@types/ramda': 0.27.39 '@types/zkochan__table': /@types/table/6.0.0 + nock: 12.0.3 strip-ansi: 6.0.0 packages/plugin-commands-import: