diff --git a/src/cli/commands/monitor/index.ts b/src/cli/commands/monitor/index.ts index 7c3c2f6f6e..7504cb2a77 100644 --- a/src/cli/commands/monitor/index.ts +++ b/src/cli/commands/monitor/index.ts @@ -56,7 +56,6 @@ async function monitor(...args0: MethodArgs): Promise { if (typeof args[args.length - 1] === 'object') { options = (args.pop() as ArgsOptions) as MonitorOptions; } - args = args.filter(Boolean); // populate with default path (cwd) if no path given @@ -85,9 +84,15 @@ async function monitor(...args0: MethodArgs): Promise { debug(`Processing ${path}...`); try { await validateMonitorPath(path, options.docker); - const guessedPackageManager = detect.detectPackageManager(path, options); - const analysisType = - (options.docker ? 'docker' : guessedPackageManager) || 'all'; + let analysisType = 'all'; + let packageManager; + if (options.allProjects) { + analysisType = 'all'; + } else if (options.docker) { + analysisType = 'docker'; + } else { + packageManager = detect.detectPackageManager(path, options); + } const targetFile = !options.scanAllUnmanaged && options.docker && !options.file // snyk monitor --docker (without --file) @@ -100,7 +105,10 @@ async function monitor(...args0: MethodArgs): Promise { ); const analyzingDepsSpinnerLabel = - 'Analyzing ' + analysisType + ' dependencies for ' + displayPath; + 'Analyzing ' + + (packageManager ? packageManager : analysisType) + + ' dependencies for ' + + displayPath; await spinner(analyzingDepsSpinnerLabel); @@ -115,7 +123,7 @@ async function monitor(...args0: MethodArgs): Promise { getDepsFromPlugin(path, { ...options, path, - packageManager: guessedPackageManager, + packageManager, }), spinner.clear(analyzingDepsSpinnerLabel), ); diff --git a/src/lib/detect.ts b/src/lib/detect.ts index 40374483b3..f8a03ec0a2 100644 --- a/src/lib/detect.ts +++ b/src/lib/detect.ts @@ -41,6 +41,8 @@ export const AUTO_DETECTABLE_FILES: string[] = [ 'packages.config', 'project.json', 'project.assets.json', + 'Podfile', + 'Podfile.lock', ]; // when file is specified with --file, we look it up here diff --git a/src/lib/find-files.ts b/src/lib/find-files.ts index 7619d041c2..1a279fb2cd 100644 --- a/src/lib/find-files.ts +++ b/src/lib/find-files.ts @@ -193,6 +193,12 @@ function chooseBestManifest( )[0]; return defaultManifest.path; } + case 'cocoapods': { + const defaultManifest = files.filter((path) => + ['Podfile'].includes(path.base), + )[0]; + return defaultManifest.path; + } default: { return null; } diff --git a/src/lib/types.ts b/src/lib/types.ts index 181e6261c0..1269274c18 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -80,6 +80,7 @@ export interface MonitorOptions { 'print-deps'?: boolean; 'experimental-dep-graph'?: boolean; scanAllUnmanaged?: boolean; + allProjects?: boolean; // An experimental flag to allow monitoring of bigtrees (with degraded deps info and remediation advice). 'prune-repeated-subdependencies'?: boolean; } diff --git a/test/acceptance/cli-monitor/cli-monitor.all-projects.spec.ts b/test/acceptance/cli-monitor/cli-monitor.all-projects.spec.ts index a6594b62cf..890c77ca2f 100644 --- a/test/acceptance/cli-monitor/cli-monitor.all-projects.spec.ts +++ b/test/acceptance/cli-monitor/cli-monitor.all-projects.spec.ts @@ -269,5 +269,35 @@ export const AllProjectsTests: AcceptanceTests = { 'sends version number', ); }, + '`monitor monorepo-with-nuget with Cocoapods --all-projects and without same meta`': ( + params, + utils, + ) => async (t) => { + utils.chdirWorkspaces(); + const spyPlugin = sinon.spy(params.plugins, 'loadPlugin'); + t.teardown(spyPlugin.restore); + + await params.cli.monitor('monorepo-with-nuget/src/cocoapods-app', { + allProjects: true, + }); + // Pop all calls to server and filter out calls to `featureFlag` endpoint + const [cocoapodsAll] = params.server + .popRequests(1) + .filter((req) => req.url.includes('/monitor/')); + + // Cocoapods + await params.cli.monitor('monorepo-with-nuget/src/cocoapods-app', { + file: 'Podfile', + }); + const [requestsCocoapods] = params.server + .popRequests(1) + .filter((req) => req.url.includes('/monitor/')); + + t.deepEqual( + cocoapodsAll.body, + requestsCocoapods.body, + 'Same body for --all-projects and --file=src/cocoapods-app/Podfile', + ); + }, }, }; diff --git a/test/acceptance/cli-test/cli-test.all-projects.spec.ts b/test/acceptance/cli-test/cli-test.all-projects.spec.ts index c3a9de4eec..c15ca205d0 100644 --- a/test/acceptance/cli-test/cli-test.all-projects.spec.ts +++ b/test/acceptance/cli-test/cli-test.all-projects.spec.ts @@ -396,11 +396,16 @@ export const AllProjectsTests: AcceptanceTests = { allProjects: true, detectionDepth: 4, }); + t.ok( + spyPlugin.withArgs('cocoapods').callCount, + 1, + 'calls cocoapods plugin', + ); t.ok(spyPlugin.withArgs('nuget').callCount, 2, 'calls nuget plugin'); t.ok(spyPlugin.withArgs('npm').calledOnce, 'calls npm plugin'); t.match( res, - /Tested 3 projects, no vulnerable paths were found./, + /Tested 4 projects, no vulnerable paths were found./, 'Two projects tested', ); t.match( @@ -420,6 +425,17 @@ export const AllProjectsTests: AcceptanceTests = { 'Nuget project targetFile is as expected', ); t.match(res, 'Package manager: nuget', 'Nuget package manager'); + + t.match( + res, + `Target file: src${path.sep}cocoapods-app${path.sep}Podfile`, + 'Cocoapods project targetFile is as expected', + ); + t.match( + res, + 'Package manager: cocoapods', + 'cocoapods package manager', + ); } catch (err) { t.fail('expected to pass'); } diff --git a/test/acceptance/workspaces/monorepo-with-nuget/src/cocoapods-app/Podfile b/test/acceptance/workspaces/monorepo-with-nuget/src/cocoapods-app/Podfile new file mode 100644 index 0000000000..06d5477fb8 --- /dev/null +++ b/test/acceptance/workspaces/monorepo-with-nuget/src/cocoapods-app/Podfile @@ -0,0 +1,4 @@ +target 'SampleApp' do + platform :ios, '6.0' + pod 'Reachability', '3.1.0' +end diff --git a/test/acceptance/workspaces/monorepo-with-nuget/src/cocoapods-app/Podfile.lock b/test/acceptance/workspaces/monorepo-with-nuget/src/cocoapods-app/Podfile.lock new file mode 100644 index 0000000000..6e2e737317 --- /dev/null +++ b/test/acceptance/workspaces/monorepo-with-nuget/src/cocoapods-app/Podfile.lock @@ -0,0 +1,14 @@ +PODS: + - Reachability (3.1.0) + +DEPENDENCIES: + - Reachability (= 3.1.0) + +SPEC REPOS: + trunk: + - Reachability + +SPEC CHECKSUMS: + Reachability: 3c8fe9643e52184d17f207e781cd84158da8c02b + +PODFILE CHECKSUM: eef52b2296b88c87f94cf0f232f010176b9f11cd diff --git a/test/acceptance/workspaces/monorepo-with-nuget/src/emailservice/requirements.in b/test/acceptance/workspaces/monorepo-with-nuget/src/emailservice/requirements.in deleted file mode 100644 index bb60d5a0f2..0000000000 --- a/test/acceptance/workspaces/monorepo-with-nuget/src/emailservice/requirements.in +++ /dev/null @@ -1,7 +0,0 @@ -google-api-core==1.6.0 -grpcio-health-checking==1.12.1 -grpcio==1.16.1 -jinja2==2.10 -opencensus[stackdriver]==0.1.10 -python-json-logger==0.1.9 -google-cloud-profiler==1.0.8 diff --git a/test/acceptance/workspaces/monorepo-with-nuget/src/emailservice/requirements.txt b/test/acceptance/workspaces/monorepo-with-nuget/src/emailservice/requirements.txt deleted file mode 100644 index c0d5346746..0000000000 --- a/test/acceptance/workspaces/monorepo-with-nuget/src/emailservice/requirements.txt +++ /dev/null @@ -1,34 +0,0 @@ -# -# This file is autogenerated by pip-compile -# To update, run: -# -# pip-compile --output-file requirements.txt requirements.in -# -cachetools==3.0.0 # via google-auth -certifi==2018.11.29 # via requests -chardet==3.0.4 # via requests -google-api-core[grpc]==1.6.0 -google-api-python-client==1.7.8 # via google-cloud-profiler -google-auth-httplib2==0.0.3 # via google-api-python-client, google-cloud-profiler -google-auth==1.6.2 # via google-api-core, google-api-python-client, google-auth-httplib2, google-cloud-profiler -google-cloud-core==0.29.1 # via google-cloud-trace -google-cloud-profiler==1.0.8 -google-cloud-trace==0.20.2 # via opencensus -googleapis-common-protos==1.5.5 # via google-api-core -grpcio-health-checking==1.12.1 -grpcio==1.16.1 -httplib2==0.12.1 # via google-api-python-client, google-auth-httplib2 -idna==2.8 # via requests -jinja2==2.10 -markupsafe==1.1.0 # via jinja2 -opencensus[stackdriver]==0.1.10 -protobuf==3.6.1 # via google-api-core, google-cloud-profiler, googleapis-common-protos, grpcio-health-checking -pyasn1-modules==0.2.3 # via google-auth -pyasn1==0.4.5 # via pyasn1-modules, rsa -python-json-logger==0.1.9 -pytz==2018.9 # via google-api-core -requests==2.21.0 # via google-api-core, google-cloud-profiler -rsa==4.0 # via google-auth -six==1.12.0 # via google-api-core, google-api-python-client, google-auth, grpcio, protobuf -uritemplate==3.0.0 # via google-api-python-client -urllib3==1.24.1 # via requests