Automated Pull Requests with Gradle

Gradle

NEW IN IQ SERVER RELEASE 103

Nexus IQ for SCM supports updates to build.gradle files. During policy evaluations, Lifecycle scans your build.gradle  files for matching components and create a Pull Request for every match that has a remediation available.

All build.gradle files that exist in the repository will be examined, except build.gradle files in src/test directories, which are ignored. These are considered test files or build artifacts and not relevant project manifest files.

Only Groovy based build files are supported. 

NEW IN IQ SERVER RELEASE 120

Additionally, if a gradle.properties file is found in the root directory, it will be considered as well.

Dependencies

Nexus IQ for SCM supports:

  • Component defined directly inside a dependencies block with a literal version.

    dependencies {
    
      // string dependency notation
      implementation "org.apache.struts:struts2-core:2.2.1"
    
      // map dependency notation
      smokeTest group: 'org.springframework', name: 'spring-api', version: '2.5'
    }
  • Component defined inside a constraints block of a dependencies block with a literal version.

    dependencies {
    
      constraints {
        // string dependency notation
        implementation "org.apache.struts:struts2-core:2.2.1"
    
        // map dependency notation
        smokeTest group: 'org.springframework', name: 'spring-api', version: '2.5'
      }
    }
  • Component defined inside a dependencies block with a property or variable version. Component versions are also looked up in the gradle.properties file, if one exists. 

    // Project property
    ext {
      slf4jSimpleVersion = '1.7.30'
    }
    
    // Groovy variable - dynamic typed
    def jerseyVersion = '2.29.1'
    
    // Groovy variable - static typed
    String jerseyVersionStr = '2.29.1'
    
    dependencies {
    
      implementation group: 'org.glassfish.jersey.core', name: 'jersey-core', version: jerseyVersion
    
      implementation group: 'org.glassfish.jersey.core', name: 'jersey-common', version: jerseyVersionStr
    
      implementation "org.slf4j:slf4j-simple:$slf4jSimpleVersion"
    }
  • Component defined inside a dependencies block with version constraints.

    // project-level inline declaration
    ext.slf4jVersion = '1.7.30'
    
    dependencies {
    
      implementation('org.slf4j:slf4j-api') {
        version {
          strictly '[1.7, 1.8['
          prefer "$slf4jVersion"
        }
      }
    }
  • Gradle version ranges are supported for all the above mentioned cases.

    ext {
      asmVersion = '[7.1,['
    }
    
    dependencies {
    
      implementation "org.apache.struts:struts2-core:[2.2.1 , 2.2.10)"
    
      implementation group: 'org.slf4j', name: 'slf4j-core', version: ']1.20,1.30['
    
      implementation('org.ow2.asm:asm')
    
      constraints {
        implementation("org.ow2.asm:asm:$asmVersion") {
          because 'we require a JDK 9 compatible bytecode generator'
        }
      }
    
      implementation('org.slf4j:slf4j-simple') {
        version {
          require '[1.7, 1.8['
          prefer '1.7.25'
          reject '1.7.20', '1.7.21'
        }
      }
    }

Version Pinning and Best Practices

It is important to note that Nexus IQ for SCM will always bump to a specific version, therefore pinning it in your manifest. In the below range syntax example, this means that a build.gradle containing:

dependencies {
  implementation "org.apache.struts:struts2-core:[2.2.1 , 2.2.10)"
}


Will result in a pull request to replace the contents with (assuming that version 2.2.8 passes the policy check):

dependencies {
  implementation "org.apache.struts:struts2-core:2.2.8"
}

Important: Pinning your dependency version is a best practice. Only a pinned version allows you to control remediation through security and quality policies. For the above example, version 2.2.8 might pass policy check, but version 2.2.9 might not. A version range does not allow this type of control.