Skip to content

Commit 3d7c9ec

Browse files
committed
feat: dep-graph json output
Changes dependency JSON output for snyk test and snyk container test. When using either `--json` or `--json-file-output` together with `--print-deps` attached a `depGraph` property to the output JSON. Previously using `--json` and `--print-deps` together would produce invalid JSON. Prevent any warning logs from invalidating JSON output when `--json` is being used.
1 parent cf671cd commit 3d7c9ec

File tree

4 files changed

+90
-20
lines changed

4 files changed

+90
-20
lines changed

src/lib/print-deps.ts

+9-20
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import * as depGraphLib from '@snyk/dep-graph';
33
import { DepDict, Options, MonitorOptions } from './types';
44
import { legacyCommon as legacyApi } from '@snyk/cli-interface';
55
import { countPathsToGraphRoot } from './utils';
6-
import { jsonStringifyLargeObject } from './json';
76

87
export async function maybePrintDepGraph(
98
options: Options | MonitorOptions,
@@ -20,18 +19,11 @@ export async function maybePrintDepGraph(
2019
)) as legacyApi.DepTree;
2120
maybePrintDepTree(options, depTree);
2221
} else {
23-
if (options['print-deps']) {
24-
if (options.json) {
25-
console.warn(
26-
'--print-deps --json option not yet supported for large projects. Displaying graph json output instead',
27-
);
28-
// TODO @boost: add as output graphviz 'dot' file to visualize?
29-
console.log(jsonStringifyLargeObject(depGraph.toJSON()));
30-
} else {
31-
console.warn(
32-
'--print-deps option not yet supported for large projects. Try with --json.',
33-
);
34-
}
22+
if (options['print-deps'] && !options.json) {
23+
// don't print a warning when --json is being used, it can invalidate the JSON output
24+
console.warn(
25+
'--print-deps option not yet supported for large projects. Try with --json.',
26+
);
3527
}
3628
}
3729
}
@@ -42,13 +34,10 @@ export function maybePrintDepTree(
4234
options: Options | MonitorOptions,
4335
rootPackage: legacyApi.DepTree,
4436
) {
45-
if (options['print-deps']) {
46-
if (options.json) {
47-
// Will produce 2 JSON outputs, one for the deps, one for the vuln scan.
48-
console.log(jsonStringifyLargeObject(rootPackage));
49-
} else {
50-
printDepsForTree({ [rootPackage.name!]: rootPackage });
51-
}
37+
if (options['print-deps'] && !options.json) {
38+
// only print human readable output tree if NOT using --json
39+
// to ensure this output does not invalidate JSON output
40+
printDepsForTree({ [rootPackage.name!]: rootPackage });
5241
}
5342
}
5443

src/lib/snyk-test/legacy.ts

+4
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ export interface LegacyVulnApiResult extends BasicResultData {
165165
filesystemPolicy?: boolean;
166166
uniqueCount?: any;
167167
remediation?: RemediationChanges;
168+
depGraph?: depGraphLib.DepGraphData;
168169
}
169170

170171
export interface BaseImageRemediation {
@@ -451,6 +452,9 @@ function convertTestDepGraphResultToLegacy(
451452
severityThreshold,
452453
remediation: result.remediation,
453454
};
455+
if (options['print-deps']) {
456+
legacyRes.depGraph = depGraph.toJSON();
457+
}
454458

455459
return legacyRes;
456460
}

test/jest/acceptance/cli-json-file-output.spec.ts

+42
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { createProjectFromWorkspace } from '../util/createProject';
44
import { runSnykCLI } from '../util/runSnykCLI';
55
import { humanFileSize } from '../../utils';
66
import { getServerPort } from '../util/getServerPort';
7+
import * as depGraphLib from '@snyk/dep-graph';
78

89
jest.setTimeout(1000 * 60);
910

@@ -112,4 +113,45 @@ describe('test --json-file-output', () => {
112113
expect(fileExists).toBeFalsy();
113114
expect(code).toEqual(0);
114115
});
116+
117+
describe('print-deps', () => {
118+
it('saves JSON output to file with depGraph when --print-deps is used', async () => {
119+
const project = await createProjectFromWorkspace('maven-app');
120+
const outputPath = 'json-file-output.json';
121+
122+
const { code } = await runSnykCLI(
123+
`test --print-deps --json-file-output=${outputPath}`,
124+
{
125+
cwd: project.path(),
126+
env,
127+
},
128+
);
129+
130+
expect(code).toEqual(0);
131+
const json = await project.readJSON(outputPath);
132+
expect(json.depGraph).toBeTruthy();
133+
const depGraph = depGraphLib.createFromJSON(json.depGraph);
134+
expect(depGraph.getPkgs()).toContainEqual({
135+
name: 'axis:axis',
136+
version: '1.4',
137+
});
138+
});
139+
140+
it('saves JSON output to file without a depGraph when --print-deps is not used', async () => {
141+
const project = await createProjectFromWorkspace('maven-app');
142+
const outputPath = 'json-file-output.json';
143+
144+
const { code } = await runSnykCLI(
145+
`test --json-file-output=${outputPath}`,
146+
{
147+
cwd: project.path(),
148+
env,
149+
},
150+
);
151+
152+
expect(code).toEqual(0);
153+
const json = await project.readJSON(outputPath);
154+
expect(json.depGraph).toBeUndefined();
155+
});
156+
});
115157
});

test/jest/acceptance/cli-json-output.spec.ts

+35
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { getServerPort } from '../util/getServerPort';
44
import { runSnykCLI } from '../util/runSnykCLI';
55
import { AppliedPolicyRules } from '../../../src/lib/formatters/types';
66
import * as Parser from 'jsonparse';
7+
import * as depGraphLib from '@snyk/dep-graph';
78

89
jest.setTimeout(1000 * 60);
910

@@ -193,4 +194,38 @@ describe('test --json', () => {
193194
}
194195
});
195196
});
197+
198+
describe('print-deps', () => {
199+
it('JSON output contains depGraph when --print-deps is used', async () => {
200+
const project = await createProjectFromWorkspace('maven-app');
201+
202+
const { code, stdout } = await runSnykCLI(`test --print-deps --json`, {
203+
cwd: project.path(),
204+
env,
205+
});
206+
207+
expect(code).toEqual(0);
208+
console.log(stdout);
209+
210+
const json = JSON.parse(stdout);
211+
const depGraph = depGraphLib.createFromJSON(json.depGraph);
212+
expect(depGraph.getPkgs()).toContainEqual({
213+
name: 'axis:axis',
214+
version: '1.4',
215+
});
216+
});
217+
218+
it('JSON output has no depGraph when --print-deps is not used', async () => {
219+
const project = await createProjectFromWorkspace('maven-app');
220+
221+
const { code, stdout } = await runSnykCLI(`test --json`, {
222+
cwd: project.path(),
223+
env,
224+
});
225+
226+
expect(code).toEqual(0);
227+
const json = JSON.parse(stdout);
228+
expect(json.depGraph).toBeUndefined();
229+
});
230+
});
196231
});

0 commit comments

Comments
 (0)