Skip to content

Commit

Permalink
feat: return fix summary & meta
Browse files Browse the repository at this point in the history
  • Loading branch information
lili2311 committed Mar 12, 2021
1 parent 4c1b250 commit bdbe589
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 86 deletions.
25 changes: 20 additions & 5 deletions packages/snyk-fix/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import * as debugLib from 'debug';
import * as pMap from 'p-map';
import * as ora from 'ora';
import * as chalk from 'chalk';
import stripAnsi = require('strip-ansi');

import { showResultsSummary } from './lib/output-formatters/show-results-summary';
import * as outputFormatter from './lib/output-formatters/show-results-summary';
import { loadPlugin } from './plugins/load-plugin';
import { FixHandlerResultByPlugin } from './plugins/types';

Expand All @@ -17,10 +18,13 @@ export async function fix(
options: FixOptions = {
dryRun: false,
quiet: false,
stripAnsi: false,
},
): Promise<{
resultsByPlugin: FixHandlerResultByPlugin;
exceptionsByScanType: ErrorsByEcoSystem;
results: FixHandlerResultByPlugin;
exceptions: ErrorsByEcoSystem;
meta: { fixed: number; failed: number };
fixSummary: string;
}> {
const spinner = ora({ isSilent: options.quiet });
let resultsByPlugin: FixHandlerResultByPlugin = {};
Expand All @@ -45,15 +49,26 @@ export async function fix(
concurrency: 3,
},
);
const fixSummary = await showResultsSummary(
const fixSummary = await outputFormatter.showResultsSummary(
resultsByPlugin,
exceptionsByScanType,
);

const failed = outputFormatter.calculateFailed(
resultsByPlugin,
exceptionsByScanType,
);
const fixed = outputFormatter.calculateFixed(resultsByPlugin);

spinner.start();
spinner.stopAndPersist({ text: 'Done', symbol: chalk.green('✔') });
spinner.stopAndPersist({ text: `\n${fixSummary}` });
return { resultsByPlugin, exceptionsByScanType };
return {
results: resultsByPlugin,
exceptions: exceptionsByScanType,
fixSummary: options.stripAnsi ? stripAnsi(fixSummary) : fixSummary,
meta: { fixed, failed },
};
}

export function groupEntitiesPerScanType(
Expand Down
36 changes: 25 additions & 11 deletions packages/snyk-fix/src/lib/output-formatters/show-results-summary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,27 +99,41 @@ export function generateFixedAndFailedSummary(
): string {
const sectionTitle = 'Summary:';
const formattedTitleHeader = `${chalk.bold(sectionTitle)}`;
let fixedItems = 0;
let failedItems = 0;
const fixedItems = calculateFixed(resultsByPlugin);
const failedItems = calculateFailed(resultsByPlugin, exceptionsByScanType);

return `${formattedTitleHeader}\n\n${PADDING_SPACE}${chalk.bold.red(
failedItems,
)} items were not fixed\n${PADDING_SPACE}${chalk.green.bold(
fixedItems,
)} items were successfully fixed`;
}

export function calculateFixed(
resultsByPlugin: FixHandlerResultByPlugin,
): number {
let fixed = 0;
for (const plugin of Object.keys(resultsByPlugin)) {
fixedItems += resultsByPlugin[plugin].succeeded.length;
fixed += resultsByPlugin[plugin].succeeded.length;
}
return fixed;
}

export function calculateFailed(
resultsByPlugin: FixHandlerResultByPlugin,
exceptionsByScanType: ErrorsByEcoSystem,
): number {
let failed = 0;
for (const plugin of Object.keys(resultsByPlugin)) {
const results = resultsByPlugin[plugin];
failedItems += results.failed.length + results.skipped.length;
failed += results.failed.length + results.skipped.length;
}

if (Object.keys(exceptionsByScanType).length) {
for (const ecosystem of Object.keys(exceptionsByScanType)) {
const unresolved = exceptionsByScanType[ecosystem];
failedItems += unresolved.originals.length;
failed += unresolved.originals.length;
}
}

return `${formattedTitleHeader}\n\n${PADDING_SPACE}${chalk.bold.red(
failedItems,
)} items were not fixed\n${PADDING_SPACE}${chalk.green.bold(
fixedItems,
)} items were successfully fixed`;
return failed;
}
1 change: 1 addition & 0 deletions packages/snyk-fix/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,4 +221,5 @@ export interface ErrorsByEcoSystem {
export interface FixOptions {
dryRun?: boolean;
quiet?: boolean;
stripAnsi?: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,14 @@ describe('fix *req*.txt / *.txt Python projects', () => {
};

// Act
const result = await snykFix.fix([entityToFix], { quiet: true });
const result = await snykFix.fix([entityToFix], {
quiet: true,
stripAnsi: true,
});
// Assert
expect(result).toMatchObject({
exceptionsByScanType: {},
resultsByPlugin: {
exceptions: {},
results: {
python: {
failed: [],
skipped: [
Expand Down Expand Up @@ -136,7 +139,10 @@ describe('fix *req*.txt / *.txt Python projects', () => {
};

// Act
const result = await snykFix.fix([entityToFix], { quiet: true });
const result = await snykFix.fix([entityToFix], {
quiet: true,
stripAnsi: true,
});

// Assert
const expectedManifest =
Expand All @@ -145,8 +151,8 @@ describe('fix *req*.txt / *.txt Python projects', () => {
const fixedFileContent = fs.readFileSync(fixedFilePath, 'utf-8');
expect(fixedFileContent).toEqual(expectedManifest);
expect(result).toMatchObject({
exceptionsByScanType: {},
resultsByPlugin: {
exceptions: {},
results: {
python: {
failed: [],
skipped: [],
Expand Down Expand Up @@ -224,7 +230,10 @@ describe('fix *req*.txt / *.txt Python projects', () => {
};

// Act
const result = await snykFix.fix([entityToFix], { quiet: true });
const result = await snykFix.fix([entityToFix], {
quiet: true,
stripAnsi: true,
});

// Assert
const expectedManifest =
Expand All @@ -233,8 +242,8 @@ describe('fix *req*.txt / *.txt Python projects', () => {
const fixedFileContent = fs.readFileSync(fixedFilePath, 'utf-8');
expect(fixedFileContent).toEqual(expectedManifest);
expect(result).toMatchObject({
exceptionsByScanType: {},
resultsByPlugin: {
exceptions: {},
results: {
python: {
failed: [],
skipped: [],
Expand Down Expand Up @@ -312,7 +321,10 @@ describe('fix *req*.txt / *.txt Python projects', () => {
};

// Act
const result = await snykFix.fix([entityToFix], { quiet: true });
const result = await snykFix.fix([entityToFix], {
quiet: true,
stripAnsi: true,
});

// Assert
const expectedManifest =
Expand All @@ -322,8 +334,8 @@ describe('fix *req*.txt / *.txt Python projects', () => {
const fixedFileContent = fs.readFileSync(fixedFilePath, 'utf-8');
expect(fixedFileContent).toEqual(expectedManifest);
expect(result).toMatchObject({
exceptionsByScanType: {},
resultsByPlugin: {
exceptions: {},
results: {
python: {
failed: [],
skipped: [],
Expand Down Expand Up @@ -396,7 +408,10 @@ describe('fix *req*.txt / *.txt Python projects', () => {
};

// Act
const result = await snykFix.fix([entityToFix], { quiet: true });
const result = await snykFix.fix([entityToFix], {
quiet: true,
stripAnsi: true,
});

// Assert
const expectedManifest = 'django==2.0.1\n';
Expand All @@ -405,8 +420,8 @@ describe('fix *req*.txt / *.txt Python projects', () => {
const fixedFileContent = fs.readFileSync(fixedFilePath, 'utf-8');
expect(fixedFileContent).toEqual(expectedManifest);
expect(result).toMatchObject({
exceptionsByScanType: {},
resultsByPlugin: {
exceptions: {},
results: {
python: {
failed: [],
skipped: [],
Expand Down Expand Up @@ -476,7 +491,10 @@ describe('fix *req*.txt / *.txt Python projects', () => {
};

// Act
const result = await snykFix.fix([entityToFix], { quiet: true });
const result = await snykFix.fix([entityToFix], {
quiet: true,
stripAnsi: true,
});

// Assert
const expectedManifest = 'Django==2.0.1';
Expand All @@ -485,8 +503,8 @@ describe('fix *req*.txt / *.txt Python projects', () => {
const fixedFileContent = fs.readFileSync(fixedFilePath, 'utf-8');
expect(fixedFileContent).toEqual(expectedManifest);
expect(result).toMatchObject({
exceptionsByScanType: {},
resultsByPlugin: {
exceptions: {},
results: {
python: {
failed: [],
skipped: [],
Expand Down Expand Up @@ -555,7 +573,10 @@ describe('fix *req*.txt / *.txt Python projects', () => {
};

// Act
const result = await snykFix.fix([entityToFix], { quiet: true });
const result = await snykFix.fix([entityToFix], {
quiet: true,
stripAnsi: true,
});

// Assert
const expectedManifest = 'foo==55.66.7\n';
Expand All @@ -564,8 +585,8 @@ describe('fix *req*.txt / *.txt Python projects', () => {
const fixedFileContent = fs.readFileSync(fixedFilePath, 'utf-8');
expect(fixedFileContent).toEqual(expectedManifest);
expect(result).toMatchObject({
exceptionsByScanType: {},
resultsByPlugin: {
exceptions: {},
results: {
python: {
failed: [],
skipped: [],
Expand Down Expand Up @@ -639,7 +660,10 @@ describe('fix *req*.txt / *.txt Python projects', () => {
};

// Act
const result = await snykFix.fix([entityToFix], { quiet: true });
const result = await snykFix.fix([entityToFix], {
quiet: true,
stripAnsi: true,
});

// Assert
const expectedManifest = 'django>=2.0.1\nclick>7.1\n';
Expand All @@ -648,8 +672,8 @@ describe('fix *req*.txt / *.txt Python projects', () => {
const fixedFileContent = fs.readFileSync(fixedFilePath, 'utf-8');
expect(fixedFileContent).toEqual(expectedManifest);
expect(result).toMatchObject({
exceptionsByScanType: {},
resultsByPlugin: {
exceptions: {},
results: {
python: {
failed: [],
skipped: [],
Expand Down Expand Up @@ -721,14 +745,17 @@ describe('fix *req*.txt / *.txt Python projects', () => {
};

// Act
const result = await snykFix.fix([entityToFix], { quiet: true });
const result = await snykFix.fix([entityToFix], {
quiet: true,
stripAnsi: true,
});

// Assert
const fixedFileContent = fs.readFileSync(fixedFilePath, 'utf-8');
expect(fixedFileContent).toMatchSnapshot();
expect(result).toMatchObject({
exceptionsByScanType: {},
resultsByPlugin: {
exceptions: {},
results: {
python: {
failed: [],
skipped: [],
Expand Down
41 changes: 37 additions & 4 deletions packages/snyk-fix/test/unit/__snapshots__/fix.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

exports[`Error handling Snyk fix returns error when called with unsupported type 1`] = `
Object {
"exceptionsByScanType": Object {
"exceptions": Object {
"npm": Object {
"originals": Array [
Object {
Expand Down Expand Up @@ -57,14 +57,47 @@ Object {
"userMessage": "npm is not supported.",
},
},
"resultsByPlugin": Object {},
"fixSummary": "✖ No successful fixes
Unresolved items:
package.json
npm is not supported.
Summary:
1 items were not fixed
0 items were successfully fixed",
"meta": Object {
"failed": 1,
"fixed": 0,
},
"results": Object {},
}
`;

exports[`Snyk fix Snyk fix returns results for supported & unsupported type 1`] = `
Object {
"exceptionsByScanType": Object {},
"resultsByPlugin": Object {
"exceptions": Object {},
"fixSummary": "Successful fixes:
requirements.txt
Pinned django from 1.6.1 to 2.0.1
Unresolved items:
Pipfile
Pipfile is not supported
Summary:
1 items were not fixed
1 items were successfully fixed",
"meta": Object {
"failed": 1,
"fixed": 1,
},
"results": Object {
"python": Object {
"failed": Array [],
"skipped": Array [
Expand Down
Loading

0 comments on commit bdbe589

Please sign in to comment.