Skip to content

Commit

Permalink
feat(plugin-js-packages): add audit post-processing to filter out dup…
Browse files Browse the repository at this point in the history
…licates
  • Loading branch information
Tlacenka committed Apr 3, 2024
1 parent 5e411f7 commit 6d011d0
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 16 deletions.
33 changes: 33 additions & 0 deletions packages/plugin-js-packages/src/lib/runner/audit/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
PackageManager,
} from '../../config';
import { dependencyGroupToLong } from '../../constants';
import { filterAuditResult } from '../utils';
import { AuditResult } from './types';
import {
npmToAuditResult,
Expand Down Expand Up @@ -32,6 +33,38 @@ export const normalizeAuditMapper: Record<
pnpm: pnpmToAuditResult,
};

const filterNpmAuditResults = (
results: Record<DependencyGroup, AuditResult>,
) => ({
prod: results.prod,
dev: filterAuditResult(results.dev, 'name', results.prod),
optional: filterAuditResult(results.optional, 'name', results.prod),
});

const filterPnpmAuditResults = (
results: Record<DependencyGroup, AuditResult>,
) => ({
prod: results.prod,
dev: results.dev,
optional: filterAuditResult(
filterAuditResult(results.optional, 'id', results.prod),
'id',
results.dev,
),
});

export const postProcessingAuditMapper: Partial<
Record<
PackageManager,
(
result: Record<DependencyGroup, AuditResult>,
) => Record<DependencyGroup, AuditResult>
>
> = {
npm: filterNpmAuditResults, // prod dependencies need to be filtered out manually since v10
pnpm: filterPnpmAuditResults, // optional dependencies don't have an exclusive option so they need duplicates filtered out
};

const npmDependencyOptions: Record<DependencyGroup, string[]> = {
prod: ['--omit=dev', '--omit=optional'],
dev: ['--include=dev', '--omit=optional'],
Expand Down
1 change: 1 addition & 0 deletions packages/plugin-js-packages/src/lib/runner/audit/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export type Yarnv2AuditResultJson = {
/* eslint-disable @typescript-eslint/naming-convention */
export type PnpmAuditAdvisory = {
module_name: string;
id: number;
severity: PackageAuditLevel;
vulnerable_versions: string;
recommendation: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ export function pnpmToAuditResult(output: string): AuditResult {
const vulnerabilities = Object.values(pnpmResult.advisories).map(
({
module_name: name,
id,
title,
url,
severity,
Expand All @@ -217,6 +218,7 @@ export function pnpmToAuditResult(output: string): AuditResult {

return {
name,
id,
title,
url,
severity,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ describe('pnpmToAuditResult', () => {
advisories: {
'123': {
module_name: '@cypress/request',
id: 123,
severity: 'high',
vulnerable_versions: '<2.88.12',
recommendation: 'Upgrade to version 2.88.12 or later',
Expand All @@ -381,6 +382,7 @@ describe('pnpmToAuditResult', () => {
vulnerabilities: [
{
name: '@cypress/request',
id: 123,
severity: 'high',
versionRange: '<2.88.12',
fixInformation: 'Upgrade to version 2.88.12 or later',
Expand Down
25 changes: 9 additions & 16 deletions packages/plugin-js-packages/src/lib/runner/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@ import {
dependencyGroups,
} from '../config';
import { pkgManagerCommands } from '../constants';
import { auditArgs, normalizeAuditMapper } from './audit/constants';
import {
auditArgs,
normalizeAuditMapper,
postProcessingAuditMapper,
} from './audit/constants';
import { auditResultToAuditOutput } from './audit/transform';
import { AuditResult } from './audit/types';
import { PLUGIN_CONFIG_PATH, RUNNER_OUTPUT_PATH } from './constants';
import { normalizeOutdatedMapper, outdatedArgs } from './outdated/constants';
import { outdatedResultToAuditOutput } from './outdated/transform';
import { filterAuditResult } from './utils';

export async function createRunnerConfig(
scriptPath: string,
Expand Down Expand Up @@ -61,7 +64,7 @@ async function processOutdated(packageManager: PackageManager) {
command: pkgManagerCommands[packageManager],
args: ['outdated', '--json', ...outdatedArgs[packageManager]],
cwd: process.cwd(),
ignoreExitCode: true, // npm outdated returns exit code 1 when outdated dependencies are found
ignoreExitCode: true, // outdated returns exit code 1 when outdated dependencies are found
});

const normalizedResult = normalizeOutdatedMapper[packageManager](stdout);
Expand All @@ -87,7 +90,8 @@ async function processAudit(
command: pkgManagerCommands[packageManager],
args: getAuditCommandArgs(packageManager, dep),
cwd: process.cwd(),
ignoreExitCode: packageManager === 'yarn-classic', // yarn v1 does not have exit code configuration
ignoreExitCode:
packageManager === 'yarn-classic' || packageManager === 'pnpm', // yarn v1 and PNPM do not have exit code configuration
});
return [dep, normalizeAuditMapper[packageManager](stdout)];
},
Expand All @@ -109,9 +113,8 @@ async function processAudit(
auditResults.filter(isPromiseFulfilledResult).map(x => x.value),
);

// For npm, one needs to filter out prod dependencies as there is no way to omit them
const uniqueResults =
packageManager === 'npm' ? filterNpmAuditResults(fulfilled) : fulfilled;
postProcessingAuditMapper[packageManager]?.(fulfilled) ?? fulfilled;

return supportedDepGroups.map(group =>
auditResultToAuditOutput(
Expand All @@ -134,13 +137,3 @@ function getAuditCommandArgs(
...auditArgs(group)[packageManager],
];
}

function filterNpmAuditResults(
results: Record<DependencyGroup, AuditResult>,
): Record<DependencyGroup, AuditResult> {
return {
prod: results.prod,
dev: filterAuditResult(results.dev, 'name', results.prod),
optional: filterAuditResult(results.optional, 'name', results.prod),
};
}

0 comments on commit 6d011d0

Please sign in to comment.