diff --git a/lib/parse-sbt.ts b/lib/parse-sbt.ts index 3258af53..a6d3e361 100644 --- a/lib/parse-sbt.ts +++ b/lib/parse-sbt.ts @@ -217,14 +217,15 @@ function parseSbtPluginResults(sbtOutput: string, packageName: string, packageVe return depTree; } +const PRODUCTION_SCOPES: string[] = ['compile', 'runtime', 'provided']; + function parseSbtPluginProjectResultToDepTree( projectKey: string, sbtProjectOutput: types.SbtModulesGraph): DepTree { const pkgs = Object.keys(sbtProjectOutput.modules) .filter((module) => { - // filtering for the `compile` configuration only, otherwise, there can be multiple graph roots - return sbtProjectOutput.modules[module].configurations.includes('compile'); + return sbtProjectOutput.modules[module].configurations.some((c) => PRODUCTION_SCOPES.includes(c)); }); const getDependenciesFor = (name: string): DepTree => { @@ -236,7 +237,7 @@ function parseSbtPluginProjectResultToDepTree( } const dependencies: DepDict = {}; for (const subDepName of sbtProjectOutput.dependencies[name]) { - if (pkgs.indexOf(subDepName) > -1) { // dependency is in compile configuration + if (pkgs.indexOf(subDepName) > -1) { // dependency is in production configuration dependencies[subDepName] = getDependenciesFor(subDepName); } } diff --git a/lib/types.ts b/lib/types.ts index 11e1e5f3..2eea8627 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -32,10 +32,13 @@ export interface PluginMetadata { }; } +interface Module { + version: string; + configurations: string[]; +} + export interface SbtModulesGraph { - modules: { - string: string; - }; + modules: Record; dependencies: { string: string[]; }; diff --git a/scala/SnykSbtPlugin-0.1x.scala b/scala/SnykSbtPlugin-0.1x.scala index 01697d66..473b8916 100644 --- a/scala/SnykSbtPlugin-0.1x.scala +++ b/scala/SnykSbtPlugin-0.1x.scala @@ -31,7 +31,10 @@ object SnykSbtPlugin extends AutoPlugin { } } - val mergedDeps = dependencies ++ otherDeps + // merge maps and set values together + val mergedDeps = dependencies ++ otherDeps.map { + case (key, value) => key -> (value ++ dependencies.getOrElse(key, Set.empty)) + } SnykProjectData(projectId, mergedModules, mergedDeps) } diff --git a/scala/SnykSbtPlugin-1.2x.scala b/scala/SnykSbtPlugin-1.2x.scala index a7dcd566..366ef1c7 100644 --- a/scala/SnykSbtPlugin-1.2x.scala +++ b/scala/SnykSbtPlugin-1.2x.scala @@ -30,7 +30,10 @@ object SnykSbtPlugin extends AutoPlugin { } } - val mergedDeps = dependencies ++ otherDeps + // merge maps and set values together + val mergedDeps = dependencies ++ otherDeps.map { + case (key, value) => key -> (value ++ dependencies.getOrElse(key, Set.empty)) + } SnykProjectData(projectId, mergedModules, mergedDeps) } diff --git a/test/fixtures/proj-with-provided-1.7/build.sbt b/test/fixtures/proj-with-provided-1.7/build.sbt new file mode 100644 index 00000000..530a9829 --- /dev/null +++ b/test/fixtures/proj-with-provided-1.7/build.sbt @@ -0,0 +1,18 @@ +name := "test-snyk-scan" +organization := "org.example" + +val appScalaVersion = "2.13.8" +val apiScalaVersions = Seq(appScalaVersion) + +ThisBuild / scalaVersion := appScalaVersion + +libraryDependencies ++= Seq( + "org.jsoup" % "jsoup" % "1.14.2", + "com.softwaremill.macwire" %% "util" % "2.3.5" % "provided", + "com.softwaremill.macwire" %% "macros" % "2.3.5" % "provided", + "com.softwaremill.macwire" %% "macrosakka" % "2.3.5", + "com.softwaremill.common" %% "tagging" % "2.2.1", + "com.github.etaty" %% "rediscala" % "1.9.0", + "org.apache.santuario" % "xmlsec" % "2.2.3", + "org.apache.commons" % "commons-text" % "1.9", +) diff --git a/test/fixtures/proj-with-provided-1.7/project/build.properties b/test/fixtures/proj-with-provided-1.7/project/build.properties new file mode 100644 index 00000000..22af2628 --- /dev/null +++ b/test/fixtures/proj-with-provided-1.7/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.7.1 diff --git a/test/fixtures/proj-with-provided-1.7/project/plugins.sbt b/test/fixtures/proj-with-provided-1.7/project/plugins.sbt new file mode 100644 index 00000000..5a1274d8 --- /dev/null +++ b/test/fixtures/proj-with-provided-1.7/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.10.0-RC1") diff --git a/test/system/plugin.test.ts b/test/system/plugin.test.ts index 8d63a04a..9c998181 100644 --- a/test/system/plugin.test.ts +++ b/test/system/plugin.test.ts @@ -285,3 +285,22 @@ test('run inspect() on sbt v. 1.7.0 with new sbt dep tree plugin', async (t) => '1.5.1', 'correct version found'); }); + +test('run inspect() proj with provided 1.7', async (t) => { + const result = await plugin.inspect(path.join(__dirname, '..', 'fixtures'), + 'proj-with-provided-1.7/build.sbt', {}); + if (!result.package.dependencies) { + t.fail('project has no dependencies'); + } + else { + t.equal(Object.keys(result.package.dependencies).length, 8, '8 direct dependencies of the project'); + t.equal(result.package.dependencies['org.jsoup:jsoup']?.version, '1.14.2', 'version of jsoup is 1.14.2'); + t.equal(result.package.dependencies['com.github.etaty:rediscala_2.13']?.version, '1.9.0', 'version of rediscala_2.13 is 1.9.0'); + t.equal(result.package.dependencies['com.softwaremill.macwire:util_2.13']?.version, '2.3.5', 'version of util_2.13 is 2.3.5'); + t.equal(result.package.dependencies['com.softwaremill.macwire:macros_2.13']?.version, '2.3.5', 'version of macros_2.13 is 2.3.5'); + t.equal(result.package.dependencies['com.softwaremill.macwire:macrosakka_2.13']?.version, '2.3.5', 'version of macrosakka_2.13 is 2.3.5'); + t.equal(result.package.dependencies['com.softwaremill.common:tagging_2.13']?.version, '2.2.1', 'version of tagging is 2.2.1'); + t.equal(result.package.dependencies['org.apache.santuario:xmlsec']?.version, '2.2.3', 'version of xmlsec is 2.2.3'); + t.equal(result.package.dependencies['org.apache.commons:commons-text']?.version, '1.9', 'version of commons-text is 1.9'); + } +}); diff --git a/tsconfig.json b/tsconfig.json index 6f05da25..3be7751b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,9 +2,9 @@ "compilerOptions": { "outDir": "./dist", "pretty": true, - "target": "es2015", + "target": "es2016", "lib": [ - "es2015", + "es2016", ], "noImplicitThis": false, "module": "commonjs",