Skip to content

Commit 047998e

Browse files
author
Konstantin Yegupov
committed
fix: reinstate --all-sub-project support for Gradle
1 parent a59786d commit 047998e

File tree

9 files changed

+72
-126
lines changed

9 files changed

+72
-126
lines changed

src/cli/commands/monitor.ts

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@ import * as detect from '../../lib/detect';
1616
import * as plugins from '../../lib/plugins';
1717
import {ModuleInfo} from '../../lib/module-info'; // TODO(kyegupov): fix import
1818
import {
19-
SingleDepRootResult,
20-
MultiDepRootsResult,
21-
isMultiResult,
2219
MonitorOptions,
2320
MonitorMeta,
2421
MonitorResult,
@@ -30,6 +27,7 @@ import {
3027
MonitorError,
3128
UnsupportedFeatureFlagError,
3229
} from '../../lib/errors';
30+
import { legacyPlugin as pluginApi } from '@snyk/cli-interface';
3331

3432
const SEPARATOR = '\n-------------------------------------------------------\n';
3533

@@ -78,7 +76,7 @@ async function monitor(...args0: MethodArgs): Promise<any> {
7876
snyk.id = options.id;
7977
}
8078

81-
if (options['all-sub-projects'] && options['project-name']) {
79+
if (options.allSubProjects && options['project-name']) {
8280
throw new Error('`--all-sub-projects` is currently not compatible with `--project-name`');
8381
}
8482

@@ -126,13 +124,12 @@ async function monitor(...args0: MethodArgs): Promise<any> {
126124

127125
// Scan the project dependencies via a plugin
128126

129-
const pluginOptions = plugins.getPluginOptions(packageManager, options);
130127
analytics.add('packageManager', packageManager);
131-
analytics.add('pluginOptions', pluginOptions);
128+
analytics.add('pluginOptions', options);
132129

133-
// TODO: the type should depend on multiDepRoots flag
134-
const inspectResult: SingleDepRootResult|MultiDepRootsResult = await promiseOrCleanup(
135-
moduleInfo.inspect(path, targetFile, { ...options, ...pluginOptions }),
130+
// TODO: the type should depend on allSubProjects flag
131+
const inspectResult: pluginApi.InspectResult = await promiseOrCleanup(
132+
moduleInfo.inspect(path, targetFile, { ...options }),
136133
spinner.clear(analyzingDepsSpinnerLabel));
137134

138135
analytics.add('pluginName', inspectResult.plugin.name);
@@ -155,30 +152,30 @@ async function monitor(...args0: MethodArgs): Promise<any> {
155152

156153
// We send results from "all-sub-projects" scanning as different Monitor objects
157154

158-
// SingleDepRootResult is a legacy format understood by Registry, so we have to convert
159-
// a MultiDepRootsResult to an array of these.
155+
// SinglePackageResult is a legacy format understood by Registry, so we have to convert
156+
// a MultiProjectResult to an array of these.
160157

161-
let perDepRootResults: SingleDepRootResult[] = [];
158+
let perSubProjectResults: pluginApi.SinglePackageResult[] = [];
162159
let advertiseSubprojectsCount: number | null = null;
163-
if (isMultiResult(inspectResult)) {
164-
perDepRootResults = inspectResult.depRoots.map(
165-
(depRoot) => ({plugin: inspectResult.plugin, package: depRoot.depTree}));
160+
if (pluginApi.isMultiResult(inspectResult)) {
161+
perSubProjectResults = inspectResult.scannedProjects.map(
162+
(scannedProject) => ({plugin: inspectResult.plugin, package: scannedProject.depTree}));
166163
} else {
167164
if (!options['gradle-sub-project']
168165
&& inspectResult.plugin.meta
169166
&& inspectResult.plugin.meta.allSubProjectNames
170167
&& inspectResult.plugin.meta.allSubProjectNames.length > 1) {
171168
advertiseSubprojectsCount = inspectResult.plugin.meta.allSubProjectNames.length;
172169
}
173-
perDepRootResults = [inspectResult];
170+
perSubProjectResults = [inspectResult];
174171
}
175172

176173
// Post the project dependencies to the Registry
177-
for (const depRootDeps of perDepRootResults) {
178-
maybePrintDeps(options, depRootDeps.package);
174+
for (const subProjDeps of perSubProjectResults) {
175+
maybePrintDeps(options, subProjDeps.package);
179176

180177
const res = await promiseOrCleanup(
181-
snykMonitor(path, meta, depRootDeps, targetFile),
178+
snykMonitor(path, meta, subProjDeps, targetFile),
182179
spinner.clear(postingMonitorSpinnerLabel));
183180

184181
await spinner.clear(postingMonitorSpinnerLabel)(res);
@@ -193,8 +190,8 @@ async function monitor(...args0: MethodArgs): Promise<any> {
193190
const manageUrl = url.format(endpoint);
194191

195192
endpoint.pathname = leader + '/monitor/' + res.id;
196-
const subProjectName = isMultiResult(inspectResult)
197-
? depRootDeps.package.name
193+
const subProjectName = pluginApi.isMultiResult(inspectResult)
194+
? subProjDeps.package.name
198195
: undefined;
199196
const monOutput = formatMonitorOutput(
200197
packageManager,

src/lib/module-info/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import * as _ from 'lodash';
22
import * as Debug from 'debug';
3-
import { SingleDepRootResult } from '../types';
3+
import { legacyPlugin as pluginApi } from '@snyk/cli-interface';
44

55
const debug = Debug('snyk-module-info');
66

77
export function ModuleInfo(plugin, policy) {
88
return {
9-
async inspect(root, targetFile, options): Promise<SingleDepRootResult> {
9+
async inspect(root, targetFile, options): Promise<pluginApi.SinglePackageResult> {
1010
const pluginOptions = _.merge({
1111
args: options._doubleDashArgs,
1212
}, options);

src/lib/monitor.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ import * as os from 'os';
88
import * as _ from 'lodash';
99
import {isCI} from './is-ci';
1010
import * as analytics from './analytics';
11-
import { SingleDepRootResult, DepTree, MonitorMeta, MonitorResult } from './types';
11+
import { DepTree, MonitorMeta, MonitorResult } from './types';
1212
import * as projectMetadata from './project-metadata';
1313
import * as path from 'path';
1414
import {MonitorError, ConnectionTimeoutError} from './errors';
1515
import { countPathsToGraphRoot, pruneGraph } from './prune';
1616
import { GRAPH_SUPPORTED_PACKAGE_MANAGERS } from './package-managers';
17+
import { legacyPlugin as pluginApi } from '@snyk/cli-interface';
1718

1819
const debug = Debug('snyk');
1920

@@ -104,7 +105,7 @@ function filterOutMissingDeps(depTree: DepTree): FilteredDepTree {
104105

105106
for (const depKey of Object.keys(depTree.dependencies)) {
106107
const dep = depTree.dependencies[depKey];
107-
if (dep.missingLockFileEntry) {
108+
if ((dep as any).missingLockFileEntry) { // TODO(kyegupov): add field to the type
108109
missingDeps.push(`${dep.name}@${dep.version}`);
109110
} else {
110111
filteredDeps[depKey] = dep;
@@ -124,7 +125,7 @@ function filterOutMissingDeps(depTree: DepTree): FilteredDepTree {
124125
export async function monitor(
125126
root: string,
126127
meta: MonitorMeta,
127-
info: SingleDepRootResult,
128+
info: pluginApi.SinglePackageResult,
128129
targetFile?: string,
129130
): Promise<MonitorResult> {
130131
apiTokenExists();
@@ -231,7 +232,7 @@ export async function monitor(
231232
export async function monitorGraph(
232233
root: string,
233234
meta: MonitorMeta,
234-
info: SingleDepRootResult,
235+
info: pluginApi.SinglePackageResult,
235236
targetFile?: string,
236237
): Promise<MonitorResult> {
237238
const packageManager = meta.packageManager;

src/lib/plugins/index.ts

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,3 @@ export function loadPlugin(packageManager: SupportedPackageManagers,
5959
}
6060
}
6161
}
62-
63-
export function getPluginOptions(packageManager: string, options: types.Options): types.Options {
64-
const pluginOptions: types.Options = {};
65-
switch (packageManager) {
66-
case 'gradle': {
67-
if (options['all-sub-projects']) {
68-
pluginOptions.multiDepRoots = true;
69-
}
70-
return pluginOptions;
71-
}
72-
default: {
73-
return pluginOptions;
74-
}
75-
}
76-
}

src/lib/plugins/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export interface InspectResult {
44
runtime?: string;
55
};
66
package?: any;
7-
depRoots?: any;
7+
scannedProjects?: any;
88
}
99

1010
export interface Options {
@@ -13,7 +13,7 @@ export interface Options {
1313
traverseNodeModules?: boolean;
1414
dev?: boolean;
1515
strictOutOfSync?: boolean | 'true' | 'false';
16-
multiDepRoots?: boolean;
16+
allSubProjects?: boolean;
1717
debug?: boolean;
1818
packageManager?: string;
1919
composerIsFine?: boolean;

src/lib/print-deps.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import { DepDict, Options, MonitorOptions, DepTree } from './types';
1+
import { DepDict, Options, MonitorOptions } from './types';
2+
import { legacyCommon as legacyApi } from '@snyk/cli-interface';
23

34
// This option is still experimental and might be deprecated.
45
// It might be a better idea to convert it to a command (i.e. do not perform test/monitor).
5-
export function maybePrintDeps(options: Options | MonitorOptions, rootPackage: DepTree) {
6+
export function maybePrintDeps(options: Options | MonitorOptions, rootPackage: legacyApi.DepTree) {
67
if (options['print-deps']) {
78
if (options.json) {
89
// Will produce 2 JSON outputs, one for the deps, one for the vuln scan.

src/lib/snyk-test/run-test.ts

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import common = require('./common');
1616
import {DepTree, TestOptions} from '../types';
1717
import gemfileLockToDependencies = require('../../lib/plugins/rubygems/gemfile-lock-to-dependencies');
1818
import {convertTestDepGraphResultToLegacy, AnnotatedIssue, LegacyVulnApiResult, TestDepGraphResponse} from './legacy';
19-
import {SingleDepRootResult, MultiDepRootsResult, isMultiResult, Options} from '../types';
19+
import {Options} from '../types';
2020
import {
2121
NoSupportedManifestsFoundError,
2222
InternalServerError,
@@ -26,6 +26,7 @@ import {
2626
import { maybePrintDeps } from '../print-deps';
2727
import { SupportedPackageManagers } from '../package-managers';
2828
import { countPathsToGraphRoot, pruneGraph } from '../prune';
29+
import { legacyPlugin as pluginApi } from '@snyk/cli-interface';
2930

3031
// tslint:disable-next-line:no-var-requires
3132
const debug = require('debug')('snyk');
@@ -207,23 +208,22 @@ function assemblePayloads(root: string, options: Options & TestOptions): Promise
207208
return assembleRemotePayloads(root, options);
208209
}
209210

210-
// Force getDepsFromPlugin to return depRoots for processing in assembleLocalPayload
211-
async function getDepsFromPlugin(root, options: Options): Promise<MultiDepRootsResult> {
211+
// Force getDepsFromPlugin to return scannedProjects for processing in assembleLocalPayload
212+
async function getDepsFromPlugin(root, options: Options): Promise<pluginApi.MultiProjectResult> {
212213
options.file = options.file || detect.detectPackageFile(root);
213214
if (!options.docker && !(options.file || options.packageManager)) {
214215
throw NoSupportedManifestsFoundError([...root]);
215216
}
216217
const plugin = plugins.loadPlugin(options.packageManager, options);
217218
const moduleInfo = ModuleInfo(plugin, options.policy);
218-
const pluginOptions = plugins.getPluginOptions(options.packageManager, options);
219-
const inspectRes: SingleDepRootResult | MultiDepRootsResult =
220-
await moduleInfo.inspect(root, options.file, { ...options, ...pluginOptions });
219+
const inspectRes: pluginApi.InspectResult =
220+
await moduleInfo.inspect(root, options.file, { ...options });
221221

222-
if (!isMultiResult(inspectRes)) {
222+
if (!pluginApi.isMultiResult(inspectRes)) {
223223
if (!inspectRes.package) {
224224
// something went wrong if both are not present...
225225
throw Error(`error getting dependencies from ${options.packageManager} ` +
226-
'plugin: neither \'package\' nor \'depRoots\' were found');
226+
'plugin: neither \'package\' nor \'scannedProjects\' were found');
227227
}
228228
if (!inspectRes.package.targetFile && inspectRes.plugin) {
229229
inspectRes.package.targetFile = inspectRes.plugin.targetFile;
@@ -238,13 +238,13 @@ async function getDepsFromPlugin(root, options: Options): Promise<MultiDepRootsR
238238
}
239239
return {
240240
plugin: inspectRes.plugin,
241-
depRoots: [{depTree: inspectRes.package}],
241+
scannedProjects: [{depTree: inspectRes.package}],
242242
};
243243
} else {
244244
// We are using "options" to store some information returned from plugin that we need to use later,
245245
// but don't want to send to Registry in the Payload.
246246
// TODO(kyegupov): decouple inspect and payload so that we don't need this hack
247-
options.subProjectNames = inspectRes.depRoots.map((depRoot) => depRoot.depTree.name);
247+
(options as any).subProjectNames = inspectRes.scannedProjects.map((scannedProject) => scannedProject.depTree.name);
248248
return inspectRes;
249249
}
250250
}
@@ -263,14 +263,14 @@ async function assembleLocalPayloads(root, options: Options & TestOptions): Prom
263263
const deps = await getDepsFromPlugin(root, options);
264264
analytics.add('pluginName', deps.plugin.name);
265265

266-
for (const depRoot of deps.depRoots) {
267-
const pkg = depRoot.depTree;
266+
for (const scannedProject of deps.scannedProjects) {
267+
const pkg = scannedProject.depTree;
268268
if (options['print-deps']) {
269269
await spinner.clear<void>(spinnerLbl)();
270270
maybePrintDeps(options, pkg);
271271
}
272272
if (deps.plugin && deps.plugin.packageManager) {
273-
options.packageManager = deps.plugin.packageManager;
273+
(options as any).packageManager = deps.plugin.packageManager;
274274
}
275275

276276
if (pkg.docker) {
@@ -332,7 +332,10 @@ async function assembleLocalPayloads(root, options: Options & TestOptions): Prom
332332
} else {
333333
// Graphs are more compact and robust representations.
334334
// Legacy parts of the code are still using trees, but will eventually be fully migrated.
335-
debug('converting dep-tree to dep-graph', {name: pkg.name, targetFile: depRoot.targetFile || options.file});
335+
debug('converting dep-tree to dep-graph', {
336+
name: pkg.name,
337+
targetFile: scannedProject.targetFile || options.file,
338+
});
336339
let depGraph = await depGraphLib.legacy.depTreeToGraph(
337340
pkg, options.packageManager);
338341

src/lib/types.ts

Lines changed: 4 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { SupportedPackageManagers } from './package-managers';
2-
3-
// TODO(kyegupov): use a shared repository snyk-cli-interface
2+
import { legacyCommon as legacyApi } from '@snyk/cli-interface';
43

54
export interface PluginMetadata {
65
name: string;
@@ -19,45 +18,7 @@ export interface DepDict {
1918
[name: string]: DepTree;
2019
}
2120

22-
export interface DepTree {
23-
name: string;
24-
version: string;
25-
dependencies?: DepDict;
26-
packageFormatVersion?: string;
27-
docker?: any;
28-
files?: any;
29-
targetFile?: string;
30-
missingLockFileEntry?: boolean;
31-
32-
labels?: {
33-
[key: string]: string;
34-
35-
// Known keys:
36-
// pruned: identical subtree already presents in the parent node.
37-
// See --prune-repeated-subdependencies flag.
38-
};
39-
}
40-
41-
export interface DepRoot {
42-
depTree: DepTree; // to be soon replaced with depGraph
43-
targetFile?: string;
44-
}
45-
46-
// Legacy result type. Will be deprecated soon.
47-
export interface SingleDepRootResult {
48-
plugin: PluginMetadata;
49-
package: DepTree;
50-
}
51-
52-
export interface MultiDepRootsResult {
53-
plugin: PluginMetadata;
54-
depRoots: DepRoot[];
55-
}
56-
57-
// https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards
58-
export function isMultiResult(pet: SingleDepRootResult | MultiDepRootsResult): pet is MultiDepRootsResult {
59-
return !!(pet as MultiDepRootsResult).depRoots;
60-
}
21+
export type DepTree = legacyApi.DepTree;
6122

6223
export interface TestOptions {
6324
traverseNodeModules: boolean;
@@ -81,7 +42,7 @@ export interface Options {
8142
'ignore-policy'?: boolean;
8243
'trust-policies'?: boolean; // used in snyk/policy lib
8344
'policy-path'?: boolean;
84-
'all-sub-projects'?: boolean; // Corresponds to multiDepRoot in plugins
45+
allSubProjects?: boolean;
8546
'project-name'?: string;
8647
'show-vulnerable-paths'?: string;
8748
showVulnPaths?: boolean;
@@ -100,7 +61,7 @@ export interface MonitorOptions {
10061
file?: string;
10162
policy?: string;
10263
json?: boolean;
103-
'all-sub-projects'?: boolean; // Corresponds to multiDepRoot in plugins
64+
allSubProjects?: boolean;
10465
'project-name'?: string;
10566
'print-deps'?: boolean;
10667
'experimental-dep-graph'?: boolean;

0 commit comments

Comments
 (0)