Automating Gradle dependency updates with GitHub Actions

Friday, June 5, 2020

Using Gradle’s dependency locking feature we can create an automated process to periodically create a pull request for dependency updates.

See an example pull request using the method outlined in this article.

Configuring dependency locking

  1. Firstly, make sure the gradle wrapper is up to date. This is necessary in order to use the feature preview in the next step.

    gradle wrapper --gradle-version 6.5
    
  2. Enable the ONE_LOCKFILE_PER_PROJECT feature preview in settings.gradle.kts. You can read more about this feature here.

    rootProject.name = "example-api"
    
    enableFeaturePreview("ONE_LOCKFILE_PER_PROJECT")
    
  3. Add the following section to build.gradle.kts to version lock all configurations. See the documentation here if you would like to customise this for specific configurations.

    dependencyLocking {
        lockAllConfigurations()
    }
    
  4. Optionally, add the following if you would like to create a lockfile for the buildscript section. This can be used to version lock plugins.

    buildscript {
        repositories {
            mavenCentral()
            jcenter()
        }
        dependencies {
            classpath("com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.+")
        }
        configurations.classpath {
            resolutionStrategy.activateDependencyLocking()
        }
    }
    
    apply(plugin = "com.jfrog.bintray")
    
  5. Write a gradle.lockfile for your current dependencies. If you followed step 4, you will also have a buildscript-gradle.lockfile.

    ./gradlew dependencies --write-locks
    
  6. Check the lockfiles into source control. The lockfiles will now make sure that ./gradlew build uses strict versions from the lockfile.

  7. Specify version ranges for your dependencies. The range should include all versions that you are happy to accept version updates for. For example, 1.2.+ for just patch updates, 1.+ for minor updates, and + to include major version updates.

Automate dependency updates

Add the following GitHub Actions workflow to periodically create a pull request containing dependency updates. The following example uses the create-pull-request action and executes once a week.

Note that if you want pull requests created by this action to trigger checks then a repo scoped PAT should be used instead of the default GITHUB_TOKEN. It is highly recommended to make sure checks run and build the new pull request in CI. This will verify that the dependency versions in the new lockfile will build and pass tests.

name: Update Dependencies
on:
  schedule:
    - cron:  '0 1 * * 1'
jobs:
  update-dep:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-java@v1
        with:
          java-version: 1.8
      - name: Grant execute permission for gradlew
        run: chmod +x gradlew
      - name: Perform dependency resolution and write new lockfiles
        run: ./gradlew dependencies --write-locks
      - name: Create Pull Request
        uses: peter-evans/create-pull-request@v3
        with:
            token: ${{ secrets.PAT }}
            commit-message: Update dependencies
            title: Update dependencies
            body: |
              - Dependency updates
  
              Auto-generated by [create-pull-request][1]
  
              [1]: https://github.com/peter-evans/create-pull-request
            branch: update-dependencies

See the code in this repository for a complete example.