Skip to content

Commit a04a1a9

Browse files
committedMay 5, 2021
feat: exit code 0 if nothing is vulnerable
Improve exit code to help action `snyk fix` output. If `snyk test` failed => error If `snyk test` returned no vulnerable results => success If `snyk fix` had some errors and nothing was fixed => error If `snyk fix` fixed anyrying at all => success
1 parent 8e4862d commit a04a1a9

File tree

3 files changed

+86
-4
lines changed

3 files changed

+86
-4
lines changed
 

‎src/cli/commands/fix/index.ts

+17-2
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,29 @@ async function fix(...args: MethodArgs): Promise<string> {
3737
validateCredentials(options);
3838
const results: snykFix.EntityToFix[] = [];
3939
results.push(...(await runSnykTestLegacy(options, paths)));
40-
4140
// fix
4241
debug(
4342
`Organization has ${snykFixFeatureFlag} feature flag enabled for experimental Snyk fix functionality`,
4443
);
44+
const vulnerableResults = results.filter(
45+
(res) => Object.keys(res.testResult.issues).length,
46+
);
4547
const { dryRun, quiet } = options;
4648
const { fixSummary, meta } = await snykFix.fix(results, { dryRun, quiet });
47-
if (meta.fixed === 0) {
49+
50+
// `snyk test` did not return any test results
51+
if (results.length === 0) {
52+
throw new Error(fixSummary);
53+
}
54+
// `snyk test` returned no vulnerable results, so nothing to fix
55+
if (vulnerableResults.length === 0) {
56+
return fixSummary;
57+
}
58+
// `snyk test` returned vulnerable results
59+
// however some errors occurred during `snyk fix` and nothing was fixed in the end
60+
const anyFailed = meta.failed > 0;
61+
const noneFixed = meta.fixed === 0;
62+
if (anyFailed && noneFixed) {
4863
throw new Error(fixSummary);
4964
}
5065
return fixSummary;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"vulnerabilities": [],
3+
"ok": true,
4+
"dependencyCount": 2,
5+
"org": "bananaq",
6+
"policy": "# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.\nversion: v1.19.0\nignore: {}\npatch: {}\n",
7+
"isPrivate": true,
8+
"licensesPolicy": {},
9+
"packageManager": "pip",
10+
"ignoreSettings": null,
11+
"summary": "Tested 1 project, no vulnerable paths were found.",
12+
"filesystemPolicy": false,
13+
"filtered": {
14+
"ignore": [],
15+
"patch": []
16+
},
17+
"uniqueCount": 4,
18+
"projectName": "pip-app",
19+
"foundProjectCount": 23
20+
}

‎test/jest/unit/lib/commands/fix/fix.spec.ts

+49-2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,19 @@ const pipWithRemediation = JSON.parse(
5050
),
5151
);
5252

53+
const pipNoIssues = JSON.parse(
54+
fs.readFileSync(
55+
pathLib.resolve(
56+
__dirname,
57+
'../../../../../',
58+
'fixtures',
59+
'snyk-fix',
60+
'test-result-pip-no-vulns.json',
61+
),
62+
'utf8',
63+
),
64+
);
65+
5366
describe('snyk fix (functional tests)', () => {
5467
let origStdWrite;
5568
let snykFixSpy: jest.SpyInstance;
@@ -167,7 +180,7 @@ describe('snyk fix (functional tests)', () => {
167180
);
168181

169182
it(
170-
'snyk fix continues to fix when 1 path fails to test with `snyk fix path1 path2`',
183+
'snyk fix continues to fix when 1 path fails to test with `snyk fix path1 path2` (exit code 0)',
171184
async () => {
172185
// read data from console.log
173186
let stdoutMessages = '';
@@ -205,7 +218,7 @@ describe('snyk fix (functional tests)', () => {
205218
);
206219

207220
it(
208-
'snyk fails to fix when all path fails to test with `snyk fix path1 path2`',
221+
'snyk fails to fix when all path fails to test with `snyk fix path1 path2` (non 0 error code)',
209222
async () => {
210223
// read data from console.log
211224
let stdoutMessages = '';
@@ -241,4 +254,38 @@ describe('snyk fix (functional tests)', () => {
241254
},
242255
testTimeout,
243256
);
257+
258+
it(
259+
'snyk succeeds to fix when no vulns `snyk fix path1` (exit code 0)',
260+
async () => {
261+
// read data from console.log
262+
let stdoutMessages = '';
263+
let stderrMessages = '';
264+
jest
265+
.spyOn(console, 'log')
266+
.mockImplementation((msg: string) => (stdoutMessages += msg));
267+
jest
268+
.spyOn(console, 'error')
269+
.mockImplementation((msg: string) => (stderrMessages += msg));
270+
271+
jest.spyOn(snyk, 'test').mockResolvedValue({
272+
...pipNoIssues,
273+
// pip plugin does not return targetFile, instead fix will fallback to displayTargetFile
274+
displayTargetFile: pipRequirementsTxt,
275+
});
276+
const res = await cli.fix(pipAppWorkspace, {
277+
dryRun: true, // prevents write to disc
278+
quiet: true,
279+
});
280+
expect(snykFixSpy).toHaveBeenCalledTimes(1);
281+
expect(snykFixSpy.mock.calls[0][1]).toEqual({
282+
dryRun: true,
283+
quiet: true,
284+
});
285+
expect(stripAnsi(res)).toMatch('No successful fixes');
286+
expect(stdoutMessages).toEqual('');
287+
expect(stderrMessages).toEqual('');
288+
},
289+
testTimeout,
290+
);
244291
});

0 commit comments

Comments
 (0)
Please sign in to comment.