Skip to content

Commit

Permalink
feat: skip failed snyk test paths when fixing
Browse files Browse the repository at this point in the history
  • Loading branch information
lili2311 committed Mar 29, 2021
1 parent 34df01d commit 4ef96f5
Show file tree
Hide file tree
Showing 8 changed files with 819 additions and 160 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
"micromatch": "4.0.2",
"needle": "2.6.0",
"open": "^7.0.3",
"ora": "5.3.0",
"os-name": "^3.0.0",
"promise-queue": "^2.2.5",
"proxy-agent": "^3.1.1",
Expand Down
79 changes: 57 additions & 22 deletions src/cli/commands/fix/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ export = fix;

import * as Debug from 'debug';
import * as snykFix from '@snyk/fix';
import * as pathLib from 'path';
import * as ora from 'ora';

import { MethodArgs } from '../../args';
import * as snyk from '../../../lib';
Expand All @@ -14,26 +16,33 @@ import { validateCredentials } from '../test/validate-credentials';
import { validateTestOptions } from '../test/validate-test-options';
import { setDefaultTestOptions } from '../test/set-default-test-options';
import { validateFixCommandIsSupported } from './validate-fix-command-is-supported';
import { Options, TestOptions } from '../../../lib/types';

const debug = Debug('snyk-fix');
const snykFixFeatureFlag = 'cliSnykFix';

interface FixOptions {
dryRun?: boolean;
quiet?: boolean;
}
async function fix(...args: MethodArgs): Promise<string> {
const { options: rawOptions, paths } = await processCommandArgs(...args);
const options = setDefaultTestOptions(rawOptions);
const { options: rawOptions, paths } = await processCommandArgs<FixOptions>(
...args,
);
const options = setDefaultTestOptions<FixOptions>(rawOptions);
debug(options);
await validateFixCommandIsSupported(options);
validateTestOptions(options);
validateCredentials(options);

const results: snykFix.EntityToFix[] = [];
results.push(...(await runSnykTestLegacy(options, paths)));

// fix
debug(
`Organization has ${snykFixFeatureFlag} feature flag enabled for experimental Snyk fix functionality`,
);
const { fixSummary, meta } = await snykFix.fix(results);

const { dryRun, quiet } = options;
const { fixSummary, meta } = await snykFix.fix(results, { dryRun, quiet });
if (meta.fixed === 0) {
throw new Error(fixSummary);
}
Expand All @@ -45,31 +54,57 @@ async function fix(...args: MethodArgs): Promise<string> {
* we should be calling test via new Ecosystems instead
*/
async function runSnykTestLegacy(
options,
paths,
options: Options & TestOptions & FixOptions,
paths: string[],
): Promise<snykFix.EntityToFix[]> {
const results: snykFix.EntityToFix[] = [];
const stdOutSpinner = ora({
isSilent: options.quiet,
stream: process.stdout,
});
const stdErrSpinner = ora({
isSilent: options.quiet,
stream: process.stdout,
});
stdErrSpinner.start();
stdOutSpinner.start();

for (const path of paths) {
// Create a copy of the options so a specific test can
// modify them i.e. add `options.file` etc. We'll need
// these options later.
const snykTestOptions = {
...options,
path,
projectName: options['project-name'],
};
let relativePath = path;
try {
const { dir } = pathLib.parse(path);
relativePath = pathLib.relative(process.cwd(), dir);
stdOutSpinner.info(`Running \`snyk test\` for ${relativePath}`);
// Create a copy of the options so a specific test can
// modify them i.e. add `options.file` etc. We'll need
// these options later.
const snykTestOptions = {
...options,
path,
projectName: options['project-name'],
};

let testResults: TestResult | TestResult[];
const testResults: TestResult[] = [];

try {
testResults = await snyk.test(path, snykTestOptions);
const testResultForPath: TestResult | TestResult[] = await snyk.test(
path,
{ ...snykTestOptions, quiet: true },
);
testResults.push(
...(Array.isArray(testResultForPath)
? testResultForPath
: [testResultForPath]),
);
const newRes = convertLegacyTestResultToFixEntities(testResults, path);
results.push(...newRes);
} catch (error) {
const testError = formatTestError(error);
throw testError;
const userMessage = `Test for ${relativePath} failed with error: ${testError.message}.\nRun \`snyk test ${relativePath} -d\` for more information.`;
stdErrSpinner.fail(userMessage);
debug(userMessage);
}
const resArray = Array.isArray(testResults) ? testResults : [testResults];
const newRes = convertLegacyTestResultToFixEntities(resArray, path);
results.push(...newRes);
}
stdOutSpinner.stop();
stdErrSpinner.stop();
return results;
}
4 changes: 3 additions & 1 deletion src/cli/commands/test/set-default-test-options.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import * as config from '../../../lib/config';
import { Options, ShowVulnPaths, TestOptions } from '../../../lib/types';

export function setDefaultTestOptions(options: Options): Options & TestOptions {
export function setDefaultTestOptions<CommandOptions>(
options: Options & CommandOptions,
): Options & TestOptions & CommandOptions {
const svpSupplied = (options['show-vulnerable-paths'] || '')
.toString()
.toLowerCase();
Expand Down
75 changes: 0 additions & 75 deletions test/__snapshots__/cli-fix.spec.ts.snap

This file was deleted.

37 changes: 37 additions & 0 deletions test/__snapshots__/cli-fix.system.spec.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`snyk fix (system tests) \`shows expected response when Python project was skipped because of missing remediation data --all-projects\` 1`] = `
"ℹ Running \`snyk test\` for test/acceptance/workspaces
✖ Done
✖ No successful fixes
Unresolved items:
package.json
✖ npm is not supported.
Summary:
1 items were not fixed
0 items were successfully fixed
"
`;

exports[`snyk fix (system tests) \`shows expected response when nothing could be fixed + returns exit code 2\` 1`] = `
"ℹ Running \`snyk test\` for test/acceptance/workspaces
✖ Done
✖ No successful fixes
Unresolved items:
package.json
✖ npm is not supported.
Summary:
1 items were not fixed
0 items were successfully fixed
"
`;

0 comments on commit 4ef96f5

Please sign in to comment.