Add initial support for DS_EXPERIMENTAL_GRADLE_BUILTIN_PARSER to gemnasium-maven

Implementation plan

  1. Add a new DS_EXPERIMENTAL_GRADLE_BUILTIN_PARSER environment variable to the gradle.Flags:

    Click to expand
    diff --git a/builder/gradle/gradle.go b/builder/gradle/gradle.go
    index 4cdf166..cb20920 100644
    --- a/builder/gradle/gradle.go
    +++ b/builder/gradle/gradle.go
    @@ -17,16 +17,18 @@ import (
     const (
            pathDefaultGradleBinary = "/opt/asdf/shims/gradle"
    
    -       flagGradleOpts       = "gradle-opts"
    -       flagGradleInitScript = "gradle-init-script"
    +       flagGradleOpts               = "gradle-opts"
    +       flagGradleInitScript         = "gradle-init-script"
    +       flagExperimentalGradleParser = "experimental-gradle-parser"
     )
    
     var errNoGradleWrapper = errors.New("cannot access gradle wrapper")
    
     // Builder generates dependency lists for gradle projects
     type Builder struct {
    -       GradleOpts       string
    -       GradleInitScript string
    +       GradleOpts               string
    +       GradleInitScript         string
    +       ExperimentalGradleParser bool
     }
    
     // Flags returns the CLI flags that configure the gradle command
    @@ -44,6 +46,12 @@ func (b Builder) Flags() []cli.Flag {
                            Value:   "gemnasium-gradle-plugin-init.gradle",
                            EnvVars: []string{"GRADLE_PLUGIN_INIT_PATH"},
                    },
    +               &cli.BoolFlag{
    +                       Name:    flagExperimentalGradleParser,
    +                       Usage:   "Enable experimental gradle parser",
    +                       Value:   false,
    +                       EnvVars: []string{"DS_EXPERIMENTAL_GRADLE_BUILTIN_PARSER"},
    +               },
            }
     }
    
    @@ -51,6 +59,7 @@ func (b Builder) Flags() []cli.Flag {
     func (b *Builder) Configure(c *cli.Context) error {
            b.GradleOpts = c.String(flagGradleOpts)
            b.GradleInitScript = c.String(flagGradleInitScript)
    +       b.ExperimentalGradleParser = c.Bool(flagExperimentalGradleParser)
            return nil
     }
  2. Add a new init.gradle file to gemnasium-maven, and update the Dockerfile to copy this file to the / directory in the Docker image. This file must contain the following:

    allprojects { apply plugin: 'project-report' }

    This will enable the Project Report Plugin and allow us to export a JSON dependency list.

  3. Add conditional logic to the --init-script argument to use the new DS_EXPERIMENTAL_GRADLE_BUILTIN_PARSER environment variable added in step 1. above.

    If the DS_EXPERIMENTAL_GRADLE_BUILTIN_PARSER environment variable is set to true, refer to the init.gradle initialization script added in step 2., and use the htmlDependencyReport task instead of the gemnasiumDumpDependencies task:

    Click to expand
    diff --git a/builder/gradle/gradle.go b/builder/gradle/gradle.go
    index 4cdf166..a7c8597 100644
    --- a/builder/gradle/gradle.go
    +++ b/builder/gradle/gradle.go
    @@ -77,7 +77,14 @@ func (b Builder) listDeps(input string) ([]string, error) {
    
            // run gemnasiumDumpDependencies gradle task
            args := strings.Fields(b.GradleOpts)
    -       args = append(args, "--init-script", b.GradleInitScript, "gemnasiumDumpDependencies")
    +       if b.ExperimentalGradleParser {
    +               initScript := "init.gradle"
    +               taskName := "htmlDependencyReport"
    +               args = []string{"--init-script", initScript, taskName}
    +       } else {
    +               args = append(args, "--init-script", b.GradleInitScript, "gemnasiumDumpDependencies")
    +       }
    +
            cmd := exec.Command(gradlewPath, args...)
            cmd.Dir = dir
            cmd.Env = os.Environ()
  4. Create a new extractor in the gemnasium-maven exportpath package to parse the output of the htmlDependencyReport task executed above, to extract the paths to the JSON files for each sub-project. For example, assuming the output is the following:

    root@d04f6cdbcf81:/src# gradle --init-script init.gradle htmlDependencyReport
    
    > Task :htmlDependencyReport
    See the report at: file:///src/build/reports/project/dependencies/index.html
    
    > Task :mail:protocols:pop3:htmlDependencyReport
    See the report at: file:///src/mail/protocols/pop3/build/reports/project/dependencies/index.html
    
    > Task :plugins:openpgp-api-lib:openpgp-api:htmlDependencyReport
    See the report at: file:///src/plugins/openpgp-api-lib/openpgp-api/build/reports/project/dependencies/index.html

    We should obtain the following list of JSON files for the sub-projects:

    • build/reports/project/dependencies/root.js
    • mail/protocols/pop3/build/reports/project/dependencies/root.mail.protocols.pop3.js
    • plugins/openpgp-api-lib/openpgp-api/build/reports/project/dependencies/root.plugins.openpgp-api-lib.openpgp-api.js
  5. Create a unit test for the extractor added in step 4. above.

/cc @thiagocsf @johncrowley

Edited by Philip Cunningham