Browse Source

Allow configuring snyk target reference and lifecycle properties (#88220)

We will use target reference to distinguish between different versions or branches of our elasticsearch project
to be able to trace vulnerable dependencies down to the version.

snyk lifecycle property allows filtering the project overview by `production` or `development`. When version
is ending with SNAPSHOT we configure the lifecycle as development. Otherwise its production.

Related to #87620
Rene Groeschke 3 years ago
parent
commit
d5a60f2665

+ 18 - 7
build-tools-internal/src/integTest/groovy/org/elasticsearch/gradle/internal/snyk/SnykDependencyMonitoringGradlePluginFuncTest.groovy

@@ -31,7 +31,7 @@ class SnykDependencyMonitoringGradlePluginFuncTest extends AbstractGradleInterna
         given:
         given:
         buildFile << """
         buildFile << """
             apply plugin:'java'
             apply plugin:'java'
-            version = "1.0-SNAPSHOT"
+            version = "$version"
 
 
             repositories {
             repositories {
                 mavenCentral() 
                 mavenCentral() 
@@ -45,7 +45,7 @@ class SnykDependencyMonitoringGradlePluginFuncTest extends AbstractGradleInterna
         def build = gradleRunner("generateSnykDependencyGraph").build()
         def build = gradleRunner("generateSnykDependencyGraph").build()
         then:
         then:
         build.task(":generateSnykDependencyGraph").outcome == TaskOutcome.SUCCESS
         build.task(":generateSnykDependencyGraph").outcome == TaskOutcome.SUCCESS
-        JSONAssert.assertEquals(file( "build/snyk/dependencies.json").text, """{
+        JSONAssert.assertEquals(file("build/snyk/dependencies.json").text, """{
             "meta": {
             "meta": {
                 "method": "custom gradle",
                 "method": "custom gradle",
                 "id": "gradle",
                 "id": "gradle",
@@ -71,7 +71,7 @@ class SnykDependencyMonitoringGradlePluginFuncTest extends AbstractGradleInterna
                                     "nodeId": "org.apache.lucene:lucene-monitor@9.2.0"
                                     "nodeId": "org.apache.lucene:lucene-monitor@9.2.0"
                                 }
                                 }
                             ],
                             ],
-                            "pkgId": "hello-world@1.0-SNAPSHOT"
+                            "pkgId": "hello-world@$version"
                         },
                         },
                         {
                         {
                             "nodeId": "org.apache.lucene:lucene-monitor@9.2.0",
                             "nodeId": "org.apache.lucene:lucene-monitor@9.2.0",
@@ -117,10 +117,10 @@ class SnykDependencyMonitoringGradlePluginFuncTest extends AbstractGradleInterna
                 },
                 },
                 "pkgs": [
                 "pkgs": [
                     {
                     {
-                        "id": "hello-world@1.0-SNAPSHOT",
+                        "id": "hello-world@$version",
                         "info": {
                         "info": {
                             "name": "hello-world",
                             "name": "hello-world",
-                            "version": "1.0-SNAPSHOT"
+                            "version": "$version"
                         }
                         }
                     },
                     },
                     {
                     {
@@ -156,8 +156,19 @@ class SnykDependencyMonitoringGradlePluginFuncTest extends AbstractGradleInterna
             "target": {
             "target": {
                 "remoteUrl": "http://github.com/elastic/elasticsearch.git",
                 "remoteUrl": "http://github.com/elastic/elasticsearch.git",
                 "branch": "unknown"
                 "branch": "unknown"
+            },
+            "targetReference": "$version",
+            "projectAttributes": {
+                "lifecycle": [
+                  "$expectedLifecycle"
+                ]
             }
             }
         }""", true)
         }""", true)
+
+        where:
+        version        | expectedLifecycle
+        '1.0-SNAPSHOT' | 'development'
+        '1.0'          | 'production'
     }
     }
 
 
     def "upload fails with reasonable error message"() {
     def "upload fails with reasonable error message"() {
@@ -167,7 +178,7 @@ class SnykDependencyMonitoringGradlePluginFuncTest extends AbstractGradleInterna
         """
         """
         when:
         when:
         def result = withWireMock(PUT, "/api/v1/monitor/gradle/graph", "OK", HTTP_CREATED) { server ->
         def result = withWireMock(PUT, "/api/v1/monitor/gradle/graph", "OK", HTTP_CREATED) { server ->
-            buildFile <<  """
+            buildFile << """
             tasks.named('uploadSnykDependencyGraph').configure {
             tasks.named('uploadSnykDependencyGraph').configure {
                 getUrl().set('${server.baseUrl()}/api/v1/monitor/gradle/graph')
                 getUrl().set('${server.baseUrl()}/api/v1/monitor/gradle/graph')
                 getToken().set("myToken")
                 getToken().set("myToken")
@@ -181,7 +192,7 @@ class SnykDependencyMonitoringGradlePluginFuncTest extends AbstractGradleInterna
 
 
         when:
         when:
         result = withWireMock(PUT, GRADLE_GRAPH_ENDPOINT, "Internal Error", HTTP_INTERNAL_ERROR) { server ->
         result = withWireMock(PUT, GRADLE_GRAPH_ENDPOINT, "Internal Error", HTTP_INTERNAL_ERROR) { server ->
-            buildFile <<  """
+            buildFile << """
             tasks.named('uploadSnykDependencyGraph').configure {
             tasks.named('uploadSnykDependencyGraph').configure {
                 getUrl().set('${server.baseUrl()}/api/v1/monitor/gradle/graph')
                 getUrl().set('${server.baseUrl()}/api/v1/monitor/gradle/graph')
             }
             }

+ 28 - 9
build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/snyk/GenerateSnykDependencyGraph.java

@@ -22,11 +22,11 @@ import org.gradle.api.tasks.Input;
 import org.gradle.api.tasks.InputFiles;
 import org.gradle.api.tasks.InputFiles;
 import org.gradle.api.tasks.OutputFile;
 import org.gradle.api.tasks.OutputFile;
 import org.gradle.api.tasks.TaskAction;
 import org.gradle.api.tasks.TaskAction;
-import org.gradle.initialization.layout.BuildLayout;
 
 
 import java.io.IOException;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Files;
 import java.nio.file.StandardOpenOption;
 import java.nio.file.StandardOpenOption;
+import java.util.List;
 import java.util.Map;
 import java.util.Map;
 import java.util.Set;
 import java.util.Set;
 
 
@@ -51,22 +51,22 @@ public class GenerateSnykDependencyGraph extends DefaultTask {
         true
         true
     );
     );
     private final Property<Configuration> configuration;
     private final Property<Configuration> configuration;
+    private final Property<String> gradleVersion;
+    private final RegularFileProperty outputFile;
     private final Property<String> projectName;
     private final Property<String> projectName;
     private final Property<String> projectPath;
     private final Property<String> projectPath;
+    private final Property<String> targetReference;
     private final Property<String> version;
     private final Property<String> version;
-    private final Property<String> gradleVersion;
-    private final RegularFileProperty outputFile;
-    private final BuildLayout buildLayout;
 
 
     @Inject
     @Inject
-    public GenerateSnykDependencyGraph(ObjectFactory objectFactory, BuildLayout buildLayout) {
+    public GenerateSnykDependencyGraph(ObjectFactory objectFactory) {
         configuration = objectFactory.property(Configuration.class);
         configuration = objectFactory.property(Configuration.class);
+        gradleVersion = objectFactory.property(String.class);
+        outputFile = objectFactory.fileProperty();
         projectName = objectFactory.property(String.class);
         projectName = objectFactory.property(String.class);
         projectPath = objectFactory.property(String.class);
         projectPath = objectFactory.property(String.class);
         version = objectFactory.property(String.class);
         version = objectFactory.property(String.class);
-        gradleVersion = objectFactory.property(String.class);
-        outputFile = objectFactory.fileProperty();
-        this.buildLayout = buildLayout;
+        targetReference = objectFactory.property(String.class);
     }
     }
 
 
     @TaskAction
     @TaskAction
@@ -96,7 +96,22 @@ public class GenerateSnykDependencyGraph extends DefaultTask {
             version.get(),
             version.get(),
             firstLevelModuleDependencies
             firstLevelModuleDependencies
         );
         );
-        return Map.of("meta", FIXED_META_DATA, "depGraphJSON", builder.build(), "target", buildTargetData());
+        return Map.of(
+            "meta",
+            FIXED_META_DATA,
+            "depGraphJSON",
+            builder.build(),
+            "target",
+            buildTargetData(),
+            "targetReference",
+            targetReference.get(),
+            "projectAttributes",
+            projectAttributesData()
+        );
+    }
+
+    private Map<String, List<String>> projectAttributesData() {
+        return Map.of("lifecycle", List.of(version.map(v -> v.endsWith("SNAPSHOT") ? "development" : "production").get()));
     }
     }
 
 
     private Object buildTargetData() {
     private Object buildTargetData() {
@@ -133,4 +148,8 @@ public class GenerateSnykDependencyGraph extends DefaultTask {
         return gradleVersion;
         return gradleVersion;
     }
     }
 
 
+    @Input
+    public Property<String> getTargetReference() {
+        return targetReference;
+    }
 }
 }

+ 4 - 1
build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/snyk/SnykDependencyMonitoringGradlePlugin.java

@@ -37,8 +37,11 @@ public class SnykDependencyMonitoringGradlePlugin implements Plugin<Project> {
             .register("generateSnykDependencyGraph", GenerateSnykDependencyGraph.class, generateSnykDependencyGraph -> {
             .register("generateSnykDependencyGraph", GenerateSnykDependencyGraph.class, generateSnykDependencyGraph -> {
                 generateSnykDependencyGraph.getProjectPath().set(project.getPath());
                 generateSnykDependencyGraph.getProjectPath().set(project.getPath());
                 generateSnykDependencyGraph.getProjectName().set(project.getName());
                 generateSnykDependencyGraph.getProjectName().set(project.getName());
-                generateSnykDependencyGraph.getVersion().set(project.getVersion().toString());
+                String projectVersion = project.getVersion().toString();
+                generateSnykDependencyGraph.getVersion().set(projectVersion);
                 generateSnykDependencyGraph.getGradleVersion().set(project.getGradle().getGradleVersion());
                 generateSnykDependencyGraph.getGradleVersion().set(project.getGradle().getGradleVersion());
+                generateSnykDependencyGraph.getTargetReference()
+                    .set(providerFactory.gradleProperty("snykTargetReference").orElse(projectVersion));
                 generateSnykDependencyGraph.getOutputFile().set(projectLayout.getBuildDirectory().file("snyk/dependencies.json"));
                 generateSnykDependencyGraph.getOutputFile().set(projectLayout.getBuildDirectory().file("snyk/dependencies.json"));
             });
             });