As the project grows, the number of dependencies used in the project grows too. It’s very crucial to maintain them to have a state-of-the-art product. There is no way in Android Studio that can manage these updates for us. You have to do it manually. Usually, the process involves checking if a new dependency version is available, checking what’s new or reading changelogs, and then bumping the version and creating a PR.

We were doing exactly the same. It was a tedious task for us. That’s when I decided to automate this process. During research I got to know about Dependabot - version update system. This article is about how to automate dependency updates using Dependabot and how to handle its limitations.

What is dependency?

Dependencies allow us to include external libraries, local jar files, or other library modules into our project. No need to add actual code files or jar files into your project. For example, to handle network calls, there’s no need to write your network layer, instead one can use Retrofit to enrich your app’s network layer. The Gradle build system makes it easy to add such external binaries or other library modules into the project as dependencies

Dependency management

Managing dependencies is crucial for any project. Dependencies can vary depending on the size of the project, especially those with a large number of them spread in various modules. The important part here is to keep them up to date to avoid outdated usage or technical debts. These technical debts are easily neglected which costs a lot later.

How to keep dependencies up to date?

The traditional way to keep them up to date is to keep track of each dependency manually and update them whenever needed. You have to be very careful before updating the dependency. It’s critical to read changelogs and then update them to avoid unwanted results. Doing it manually is a tedious job.

The best way is to automate this process so that whenever there is an update available it will get updated automatically providing all the required information developers need to know to update the dependency. Github recently announced Dependabot - version update system, which does this.

What is a Dependabot?

Dependabot is a version update system that provides a brilliant way to keep your dependencies up to date. Dependabot does the following things,

  • Checks for updates of Gradle dependencies, including Android plugins.
  • Check updates of Actions in project workflows if you use Github Actions for CI
  • Open PR’s which can be then reviewed and merged if an update is required

Configuring Dependabot with Gradle

Configuring Dependabot is super easy.

  • Go to repository settings,
  • Open the “Security & analysis” section,
  • Click “Enable” on both Dependabot alerts and security updates

That’s it. No further set up required. However, it won’t work until a configuration file is added to the repository. Create a dependabot.yml and place it in the .github folder at the root of your repository (.github/dependabot.yml)

version: 2
updates:
  # Maintain dependencies for GitHub Actions
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "daily"
    open-pull-requests-limit: 5
    labels:
      - "Github Actions"

  # Maintain App gradle dependencies
  - package-ecosystem: "gradle"
    directory: "/"
    schedule:
      interval: "daily"
    open-pull-requests-limit: 5
    labels:
      - "Dependencies"

How it works

Dependabot scans for build.gradle or a settings.gradle files inside a repo, then scans outdated dependencies and creates PR. However, Dependabot isn’t that smart. Dependabot’s Gradle support is limited and is still in beta.

Issue

If the multi-module project is maintaining shared dependencies that are defined in Gradle files other than build.gradle, then Dependabot has difficulties detecting these dependencies. Dependabot looks only build.gradle and settings.gradle and scans dependencies in those files. This is a standard way of defining dependencies and most of the projects follow it, but projects having multiple modules that are following different versioning approaches won’t work at all. Even the approach to create versions.gradle to store dependency versions and then define dependencies in build.gradle by applying versions.gradle, is also not supported.

Solution

This is a workaround that is not properly documented anywhere in official documentation but this is provided by the developers as a part of this Github issue. Follow these steps to fix the issue:

  • Create a dependencies.gradle file to extract all the dependencies you have in your module. If you have a modular project then you can create dependencies.gradle for each module to extract your dependencies. It’s very critical to name the file as “dependencies” otherwise, this solution will not work.
ext.dependency = [:]
def dependency = [:]
ext.dependency = dependency

dependency.firebase = [:]
dependency.androidX = [:]
dependency.androidX.room = [:]
dependency.androidX.camera = [:]
dependency.androidX.lifecycle = [:]

dependency.gradle = 'com.android.tools.build:gradle:7.0.4'
dependency.sonarqube = 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.3'
dependency.salesforceMarketingCloud = 'com.salesforce.marketingcloud:marketingcloudsdk:8.0.4'
dependency.desugarJdkLibs = 'com.android.tools:desugar_jdk_libs:1.1.5'
dependency.eventbus = 'org.greenrobot:eventbus:3.3.1'

dependency.androidX.lifecycle.runTime = 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0'
dependency.androidX.lifecycle.viewModel = 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0'
dependency.androidX.material = 'com.google.android.material:material:1.4.0'
dependency.androidX.appcompat = 'androidx.appcompat:appcompat:1.4.1'
dependency.androidX.viewpager2 = 'androidx.viewpager2:viewpager2:1.0.0'
......
  • Modify build.gradle to use dependencies.gradle
buildscript {
    apply from: 'dependencies.gradle'
    repositories {
        google()
        mavenCentral()
        maven { url "https://jitpack.io" }
        maven { url 'https://developer.huawei.com/repo/' }
    }
    dependencies {
        classpath dependency.gradle
        classpath dependency.gms.services
        classpath dependency.kotlin.gradlePlugin
        classpath dependency.firebase.crashlyticsGradlePlugin
        classpath dependency.huawei.appGalleryConnect
        classpath dependency.sonarqube
        classpath dependency.huawei.publishGradlePlugin
    }
}
.......
  • Add Dependabot support by providing the configuration file .github/dependabot.yml as described above

dependabot_config

  • That’s it. On the next dependency check, if there are any outdated dependencies, you should expect PR’s opened by Dependabot

dependabot_pr

dependabot_pr_description

Conclusion

To automate dependency updates, Dependabot is an amazing tool and I believe that Dependabot will become an essential tool in the Android developer’s community. However, the Gradle support by Dependabot is limited as compared to Maven when dependencies are not maintained in build.gradle or settings.gradle. If the dependency versions are not maintained in these two files, you can tweak your gradle files in a way that dependabot can parse them and fetch the dependencies. Don’t hesitate to give it a try and leave feedback so we could see it coming out of beta sooner.

Special thanks to Sameer Kulkarni