From 0a8c2dcd642c942a9de0a5fb90db4abf5a97546b Mon Sep 17 00:00:00 2001 From: ghe Date: Thu, 13 Aug 2020 11:15:11 +0100 Subject: [PATCH 1/5] test: gradle kts fixture --- test/find-files.test.ts | 2 ++ .../find-files/gradle-kts/build.gradle.kts | 33 +++++++++++++++++++ .../gradle-kts/subproj/build.gradle.kts | 33 +++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 test/fixtures/find-files/gradle-kts/build.gradle.kts create mode 100644 test/fixtures/find-files/gradle-kts/subproj/build.gradle.kts diff --git a/test/find-files.test.ts b/test/find-files.test.ts index fc5c3de70ca..156e43fd0ed 100644 --- a/test/find-files.test.ts +++ b/test/find-files.test.ts @@ -20,6 +20,7 @@ test('find all files in test fixture', async (t) => { path.join(testFixture, 'golang', 'golang-app', 'Gopkg.toml'), path.join(testFixture, 'golang', 'golang-gomodules', 'go.mod'), path.join(testFixture, 'gradle', 'build.gradle'), + path.join(testFixture, 'gradle-kts', 'build.gradle.kts'), path.join(testFixture, 'gradle-multiple', 'gradle/build.gradle'), path.join(testFixture, 'gradle-multiple', 'gradle-another/build.gradle'), path.join(testFixture, 'maven', 'pom.xml'), @@ -53,6 +54,7 @@ test('find all files in test fixture ignoring node_modules', async (t) => { path.join(testFixture, 'golang', 'golang-gomodules', 'go.mod'), path.join(testFixture, 'gradle', 'build.gradle'), path.join(testFixture, 'gradle-multiple', 'gradle/build.gradle'), + path.join(testFixture, 'gradle-multiple', 'gradle/build.gradle'), path.join(testFixture, 'gradle-multiple', 'gradle-another/build.gradle'), path.join(testFixture, 'maven', 'pom.xml'), path.join(testFixture, 'maven', 'test.txt'), diff --git a/test/fixtures/find-files/gradle-kts/build.gradle.kts b/test/fixtures/find-files/gradle-kts/build.gradle.kts new file mode 100644 index 00000000000..545523eb6cc --- /dev/null +++ b/test/fixtures/find-files/gradle-kts/build.gradle.kts @@ -0,0 +1,33 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + val kotlinVersion = "1.3.21" + id("org.jetbrains.kotlin.jvm") version kotlinVersion + id("org.jetbrains.kotlin.plugin.spring") version kotlinVersion + id("org.jetbrains.kotlin.plugin.jpa") version kotlinVersion +} + +version = "1.0.0-SNAPSHOT" + +tasks.withType { + kotlinOptions { + jvmTarget = "1.8" + freeCompilerArgs = listOf("-Xjsr305=strict") + } +} + +tasks.withType { + useJUnitPlatform() +} + +repositories { + mavenCentral() +} + +dependencies { + // Removed Spring because too heavy + compile("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + testCompile("org.jetbrains.kotlin:kotlin-reflect") { + exclude(module = "junit") + } +} diff --git a/test/fixtures/find-files/gradle-kts/subproj/build.gradle.kts b/test/fixtures/find-files/gradle-kts/subproj/build.gradle.kts new file mode 100644 index 00000000000..545523eb6cc --- /dev/null +++ b/test/fixtures/find-files/gradle-kts/subproj/build.gradle.kts @@ -0,0 +1,33 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + val kotlinVersion = "1.3.21" + id("org.jetbrains.kotlin.jvm") version kotlinVersion + id("org.jetbrains.kotlin.plugin.spring") version kotlinVersion + id("org.jetbrains.kotlin.plugin.jpa") version kotlinVersion +} + +version = "1.0.0-SNAPSHOT" + +tasks.withType { + kotlinOptions { + jvmTarget = "1.8" + freeCompilerArgs = listOf("-Xjsr305=strict") + } +} + +tasks.withType { + useJUnitPlatform() +} + +repositories { + mavenCentral() +} + +dependencies { + // Removed Spring because too heavy + compile("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + testCompile("org.jetbrains.kotlin:kotlin-reflect") { + exclude(module = "junit") + } +} From f386147178c55275dd86e6d39374bfa677a624e1 Mon Sep 17 00:00:00 2001 From: ghe Date: Thu, 13 Aug 2020 11:16:51 +0100 Subject: [PATCH 2/5] test: failing test for gradle kts auto detect --- test/find-files.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/find-files.test.ts b/test/find-files.test.ts index 156e43fd0ed..ca6e2877ec5 100644 --- a/test/find-files.test.ts +++ b/test/find-files.test.ts @@ -53,7 +53,7 @@ test('find all files in test fixture ignoring node_modules', async (t) => { path.join(testFixture, 'golang', 'golang-app', 'Gopkg.toml'), path.join(testFixture, 'golang', 'golang-gomodules', 'go.mod'), path.join(testFixture, 'gradle', 'build.gradle'), - path.join(testFixture, 'gradle-multiple', 'gradle/build.gradle'), + path.join(testFixture, 'gradle-kts', 'build.gradle.kts'), path.join(testFixture, 'gradle-multiple', 'gradle/build.gradle'), path.join(testFixture, 'gradle-multiple', 'gradle-another/build.gradle'), path.join(testFixture, 'maven', 'pom.xml'), From 57d8d02f88ce0e041fd164fa8998dbbfaa7de25c Mon Sep 17 00:00:00 2001 From: ghe Date: Thu, 13 Aug 2020 11:24:58 +0100 Subject: [PATCH 3/5] feat: detect gradle.kts files --- src/lib/detect.ts | 1 + src/lib/find-files.ts | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/lib/detect.ts b/src/lib/detect.ts index f467a31e2ca..376753c9c8e 100644 --- a/src/lib/detect.ts +++ b/src/lib/detect.ts @@ -57,6 +57,7 @@ export const AUTO_DETECTABLE_FILES: string[] = [ 'requirements.txt', 'build.sbt', 'build.gradle', + 'build.gradle.kts', ]; // 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 810a00c0a16..1f66b65b373 100644 --- a/src/lib/find-files.ts +++ b/src/lib/find-files.ts @@ -193,7 +193,11 @@ function shouldSkipAddingFile( ): boolean { if (['gradle'].includes(packageManager) && filePath) { const rootGradleFile = filteredFiles - .filter((targetFile) => targetFile.endsWith('build.gradle')) + .filter( + (targetFile) => + targetFile.endsWith('build.gradle') || + targetFile.endsWith('build.gradle.kts'), + ) .filter((targetFile) => { const parsedPath = pathLib.parse(targetFile); const relativePath = pathLib.relative(parsedPath.dir, filePath); @@ -238,7 +242,7 @@ function chooseBestManifest( } case 'cocoapods': { debug( - 'Encountered multiple cocoapod manifest files, defaulting to Podfile', + 'Encountered multiple cocoapods manifest files, defaulting to Podfile', ); const defaultManifest = files.filter((path) => ['Podfile'].includes(path.base), From 6e806fb1f2971f564befc2db8d18dd380e4787e1 Mon Sep 17 00:00:00 2001 From: ghe Date: Thu, 13 Aug 2020 11:27:36 +0100 Subject: [PATCH 4/5] feat: prefer build.gradle if kotlin also found --- src/lib/find-files.ts | 9 +++++ test/find-files.test.ts | 15 +++++++++ .../find-files/gradle-and-kotlin/build.gradle | 0 .../gradle-and-kotlin/build.gradle.kts | 33 +++++++++++++++++++ 4 files changed, 57 insertions(+) create mode 100644 test/fixtures/find-files/gradle-and-kotlin/build.gradle create mode 100644 test/fixtures/find-files/gradle-and-kotlin/build.gradle.kts diff --git a/src/lib/find-files.ts b/src/lib/find-files.ts index 1f66b65b373..01bf502834f 100644 --- a/src/lib/find-files.ts +++ b/src/lib/find-files.ts @@ -256,6 +256,15 @@ function chooseBestManifest( )[0]; return defaultManifest.path; } + case 'gradle': { + debug( + 'Encountered multiple gradle manifest files, defaulting to build.gradle', + ); + const defaultManifest = files.filter((path) => + ['build.gradle'].includes(path.base), + )[0]; + return defaultManifest.path; + } default: { return null; } diff --git a/test/find-files.test.ts b/test/find-files.test.ts index ca6e2877ec5..052f30db080 100644 --- a/test/find-files.test.ts +++ b/test/find-files.test.ts @@ -21,6 +21,7 @@ test('find all files in test fixture', async (t) => { path.join(testFixture, 'golang', 'golang-gomodules', 'go.mod'), path.join(testFixture, 'gradle', 'build.gradle'), path.join(testFixture, 'gradle-kts', 'build.gradle.kts'), + path.join(testFixture, 'gradle-and-kotlin', 'build.gradle'), path.join(testFixture, 'gradle-multiple', 'gradle/build.gradle'), path.join(testFixture, 'gradle-multiple', 'gradle-another/build.gradle'), path.join(testFixture, 'maven', 'pom.xml'), @@ -54,6 +55,7 @@ test('find all files in test fixture ignoring node_modules', async (t) => { path.join(testFixture, 'golang', 'golang-gomodules', 'go.mod'), path.join(testFixture, 'gradle', 'build.gradle'), path.join(testFixture, 'gradle-kts', 'build.gradle.kts'), + path.join(testFixture, 'gradle-and-kotlin', 'build.gradle'), path.join(testFixture, 'gradle-multiple', 'gradle/build.gradle'), path.join(testFixture, 'gradle-multiple', 'gradle-another/build.gradle'), path.join(testFixture, 'maven', 'pom.xml'), @@ -102,6 +104,19 @@ test('find package-lock.json file in test fixture (ignore package.json in the sa t.same(result, expected, 'should return expected file'); }); +test('find build.gradle file in test fixture (ignore build.gradle in the same folder)', async (t) => { + const buildGradle = path.join(testFixture, 'gradle-and-kotlin'); + + const result = await find( + buildGradle, + [], + ['build.gradle.kts', 'build.gradle'], + 1, + ); + const expected = [path.join(buildGradle, 'build.gradle')]; + t.same(result, expected, 'should return expected file'); +}); + test('find Gemfile.lock file in test fixture (ignore Gemfile in the same folder)', async (t) => { const npmLockfilePath = path.join(testFixture, 'ruby'); diff --git a/test/fixtures/find-files/gradle-and-kotlin/build.gradle b/test/fixtures/find-files/gradle-and-kotlin/build.gradle new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/fixtures/find-files/gradle-and-kotlin/build.gradle.kts b/test/fixtures/find-files/gradle-and-kotlin/build.gradle.kts new file mode 100644 index 00000000000..545523eb6cc --- /dev/null +++ b/test/fixtures/find-files/gradle-and-kotlin/build.gradle.kts @@ -0,0 +1,33 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + val kotlinVersion = "1.3.21" + id("org.jetbrains.kotlin.jvm") version kotlinVersion + id("org.jetbrains.kotlin.plugin.spring") version kotlinVersion + id("org.jetbrains.kotlin.plugin.jpa") version kotlinVersion +} + +version = "1.0.0-SNAPSHOT" + +tasks.withType { + kotlinOptions { + jvmTarget = "1.8" + freeCompilerArgs = listOf("-Xjsr305=strict") + } +} + +tasks.withType { + useJUnitPlatform() +} + +repositories { + mavenCentral() +} + +dependencies { + // Removed Spring because too heavy + compile("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + testCompile("org.jetbrains.kotlin:kotlin-reflect") { + exclude(module = "junit") + } +} From 7dfc02784f23424d219e581587d53d32fa1e5265 Mon Sep 17 00:00:00 2001 From: ghe Date: Thu, 13 Aug 2020 14:35:13 +0100 Subject: [PATCH 5/5] test: kotlin monorepo --all-projects --- .../cli-monitor.all-projects.spec.ts | 104 ++++++++++++++- .../cli-test/cli-test.all-projects.spec.ts | 119 +++++++++++++++++- .../workspaces/kotlin-monorepo/Gemfile | 4 + .../workspaces/kotlin-monorepo/Gemfile.lock | 15 +++ .../kotlin-monorepo/build.gradle.kts | 1 + .../kotlin-monorepo/subproj/build.gradle.kts | 1 + 6 files changed, 241 insertions(+), 3 deletions(-) create mode 100644 test/acceptance/workspaces/kotlin-monorepo/Gemfile create mode 100644 test/acceptance/workspaces/kotlin-monorepo/Gemfile.lock create mode 100644 test/acceptance/workspaces/kotlin-monorepo/build.gradle.kts create mode 100644 test/acceptance/workspaces/kotlin-monorepo/subproj/build.gradle.kts 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 97603ca3488..00bd0affe5b 100644 --- a/test/acceptance/cli-monitor/cli-monitor.all-projects.spec.ts +++ b/test/acceptance/cli-monitor/cli-monitor.all-projects.spec.ts @@ -801,7 +801,6 @@ export const AllProjectsTests: AcceptanceTests = { }; }, }; - const spyPlugin = sinon.spy(plugin, 'inspect'); const loadPlugin = sinon.stub(params.plugins, 'loadPlugin'); t.teardown(loadPlugin.restore); loadPlugin.withArgs('gradle').returns(plugin); @@ -842,5 +841,108 @@ export const AllProjectsTests: AcceptanceTests = { ); }); }, + '`monitor kotlin-monorepo --all-projects` scans kotlin files': ( + params, + utils, + ) => async (t) => { + utils.chdirWorkspaces(); + const simpleGradleGraph = depGraphLib.createFromJSON({ + schemaVersion: '1.2.0', + pkgManager: { + name: 'gradle', + }, + pkgs: [ + { + id: 'gradle-monorepo@0.0.0', + info: { + name: 'gradle-monorepo', + version: '0.0.0', + }, + }, + ], + graph: { + rootNodeId: 'root-node', + nodes: [ + { + nodeId: 'root-node', + pkgId: 'gradle-monorepo@0.0.0', + deps: [], + }, + ], + }, + }); + const plugin = { + async inspect() { + return { + plugin: { + name: 'bundled:gradle', + runtime: 'unknown', + meta: {}, + }, + scannedProjects: [ + { + meta: { + gradleProjectName: 'root-proj', + versionBuildInfo: { + gradleVersion: '6.5', + }, + }, + depGraph: simpleGradleGraph, + }, + { + meta: { + gradleProjectName: 'root-proj/subproj', + versionBuildInfo: { + gradleVersion: '6.5', + }, + }, + depGraph: simpleGradleGraph, + }, + ], + }; + }, + }; + const loadPlugin = sinon.stub(params.plugins, 'loadPlugin'); + t.teardown(loadPlugin.restore); + loadPlugin.withArgs('gradle').returns(plugin); + loadPlugin.callThrough(); + + const result = await params.cli.monitor('kotlin-monorepo', { + allProjects: true, + detectionDepth: 3, + }); + t.ok(loadPlugin.withArgs('rubygems').calledOnce, 'calls rubygems plugin'); + t.ok(loadPlugin.withArgs('gradle').calledOnce, 'calls gradle plugin'); + + t.match( + result, + 'gradle/graph/some/project-id', + 'gradle project was monitored', + ); + t.match( + result, + 'rubygems/graph/some/project-id', + 'rubygems project was monitored', + ); + // Pop one extra call to server and filter out call to `featureFlag` endpoint + const requests = params.server + .popRequests(4) + .filter((req) => req.url.includes('/monitor/')); + t.equal(requests.length, 3, 'correct amount of monitor requests'); + requests.forEach((req) => { + t.match( + req.url, + /\/api\/v1\/monitor\/(rubygems\/graph|gradle\/graph)/, + 'puts at correct url', + ); + t.notOk(req.body.targetFile, "doesn't send the targetFile"); + t.equal(req.method, 'PUT', 'makes PUT request'); + t.equal( + req.headers['x-snyk-cli-version'], + params.versionNumber, + 'sends version number', + ); + }); + }, }, }; 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 6a71a1372f0..90862be8034 100644 --- a/test/acceptance/cli-test/cli-test.all-projects.spec.ts +++ b/test/acceptance/cli-test/cli-test.all-projects.spec.ts @@ -1,12 +1,127 @@ -import { AcceptanceTests } from './cli-test.acceptance.test'; -import { getWorkspaceJSON } from '../workspace-helper'; import * as path from 'path'; import * as sinon from 'sinon'; +import * as depGraphLib from '@snyk/dep-graph'; import { CommandResult } from '../../../src/cli/commands/types'; +import { AcceptanceTests } from './cli-test.acceptance.test'; +import { getWorkspaceJSON } from '../workspace-helper'; export const AllProjectsTests: AcceptanceTests = { language: 'Mixed', tests: { + '`test kotlin-monorepo --all-projects` scans kotlin files': ( + params, + utils, + ) => async (t) => { + utils.chdirWorkspaces(); + const simpleGradleGraph = depGraphLib.createFromJSON({ + schemaVersion: '1.2.0', + pkgManager: { + name: 'gradle', + }, + pkgs: [ + { + id: 'gradle-monorepo@0.0.0', + info: { + name: 'gradle-monorepo', + version: '0.0.0', + }, + }, + ], + graph: { + rootNodeId: 'root-node', + nodes: [ + { + nodeId: 'root-node', + pkgId: 'gradle-monorepo@0.0.0', + deps: [], + }, + ], + }, + }); + const plugin = { + async inspect() { + return { + plugin: { + name: 'bundled:gradle', + runtime: 'unknown', + meta: {}, + }, + scannedProjects: [ + { + meta: { + gradleProjectName: 'root-proj', + versionBuildInfo: { + gradleVersion: '6.5', + }, + }, + depGraph: simpleGradleGraph, + }, + { + meta: { + gradleProjectName: 'root-proj/subproj', + versionBuildInfo: { + gradleVersion: '6.5', + }, + }, + depGraph: simpleGradleGraph, + }, + ], + }; + }, + }; + const loadPlugin = sinon.stub(params.plugins, 'loadPlugin'); + t.teardown(loadPlugin.restore); + loadPlugin.withArgs('gradle').returns(plugin); + loadPlugin.callThrough(); + + const result: CommandResult = await params.cli.test('kotlin-monorepo', { + allProjects: true, + detectionDepth: 3, + }); + t.ok(loadPlugin.withArgs('rubygems').calledOnce, 'calls rubygems plugin'); + t.ok(loadPlugin.withArgs('gradle').calledOnce, 'calls gradle plugin'); + + params.server.popRequests(2).forEach((req) => { + t.equal(req.method, 'POST', 'makes POST request'); + t.equal( + req.headers['x-snyk-cli-version'], + params.versionNumber, + 'sends version number', + ); + t.match(req.url, '/api/v1/test-dep-graph', 'posts to correct url'); + t.ok(req.body.depGraph, 'body contains depGraph'); + t.match( + req.body.depGraph.pkgManager.name, + /(gradle|rubygems)/, + 'depGraph has package manager', + ); + }); + t.match( + result.getDisplayResults(), + 'Tested 3 projects', + 'Detected 3 projects', + ); + t.match( + result.getDisplayResults(), + 'Package manager: rubygems', + 'contains package manager rubygems', + ); + t.match( + result.getDisplayResults(), + 'Package manager: gradle', + 'contains package manager gradle', + ); + t.match( + result.getDisplayResults(), + 'Target file: Gemfile.lock', + 'contains target file Gemfile.lock', + ); + t.match( + result.getDisplayResults(), + 'Target file: build.gradle.kts', + 'contains target file build.gradle.kts', + ); + }, '`test yarn-out-of-sync` out of sync fails': (params, utils) => async ( t, ) => { diff --git a/test/acceptance/workspaces/kotlin-monorepo/Gemfile b/test/acceptance/workspaces/kotlin-monorepo/Gemfile new file mode 100644 index 00000000000..e0f77a325fc --- /dev/null +++ b/test/acceptance/workspaces/kotlin-monorepo/Gemfile @@ -0,0 +1,4 @@ +source :rubygems + +gem "json" +gem "lynx", "0.4.0" diff --git a/test/acceptance/workspaces/kotlin-monorepo/Gemfile.lock b/test/acceptance/workspaces/kotlin-monorepo/Gemfile.lock new file mode 100644 index 00000000000..1664b0b0b57 --- /dev/null +++ b/test/acceptance/workspaces/kotlin-monorepo/Gemfile.lock @@ -0,0 +1,15 @@ +GEM + remote: http://rubygems.org/ + specs: + json (2.0.2) + lynx (0.4.0) + +PLATFORMS + ruby + +DEPENDENCIES + json + lynx (= 0.4.0) + +BUNDLED WITH + 1.13.5 diff --git a/test/acceptance/workspaces/kotlin-monorepo/build.gradle.kts b/test/acceptance/workspaces/kotlin-monorepo/build.gradle.kts new file mode 100644 index 00000000000..17189e77e6e --- /dev/null +++ b/test/acceptance/workspaces/kotlin-monorepo/build.gradle.kts @@ -0,0 +1 @@ +// I will be mocked diff --git a/test/acceptance/workspaces/kotlin-monorepo/subproj/build.gradle.kts b/test/acceptance/workspaces/kotlin-monorepo/subproj/build.gradle.kts new file mode 100644 index 00000000000..17189e77e6e --- /dev/null +++ b/test/acceptance/workspaces/kotlin-monorepo/subproj/build.gradle.kts @@ -0,0 +1 @@ +// I will be mocked