Rishi Goomar

Using Gradle Composite Builds for Plugin Development & Debugging

Published on

Gradle has recently released a feature called Composite Builds starting from version 3.1. It allows you to combine multiple different Gradle builds from different projects together. Essentially, it is a build that includes other builds. I found it useful for debugging and developing plugins and testing it against the consumer that wants the feature or reported a bug.

The Old Way: Publishing Locally

Before composite builds, in order to test out if your new fixes on the Gradle plugin you are developing works for a specific consumer, you had to use the maven-publish plugin and publish a release locally.

You can follow these steps to publish and test locally:

Step 1 — Add the maven-publish plugin to the plugin you are going to publish:

plugins {
  id 'maven-publish'
}

Step 2 — Publish your plugin changes to your local Maven repository:

./gradlew publishToMavenLocal

Step 3 — Add your local Maven repository to the top of the project’s settings.gradle file:

pluginRepositories {
  maven {
    url 'file:///Users/YOUR_USERNAME/.m2/repository'
  }
}

Step 4 — Add the plugin with the version you published to your local Maven repository to your project:

// Put your plugin id and locally published version
plugins {
  id 'your.plugin.id' version 'x.x.x'
}

Step 5 — Test the project that is consuming the locally published plugin:

./gradlew build

After doing all of that, then you are able to test your new changes on your plugin against a specific project. This is usually done to make sure a bug is resolved or a feature works the way you want it to before officially publishing the plugin. It’s a lot of steps in order to test your changes locally and can be a pain if you have to test out multiple plugins at once against a project.

The New Way: Composite Builds

With composite builds, you can follow these steps:

Step 1 — Use Gradle 3.1+ wrapper for the project that will consume the plugin:

You can either run the wrapper command and go to Step 3

./gradlew wrapper --gradle-version=3.1

or modify the build.gradle and move to Step 2

build.gradle with component model

model {
  tasks {
    wrapper {
      gradleVersion = '3.1'
    }
  }
}

build.gradle without component model

task wrapper(type: Wrapper) {
  gradleVersion = '3.1'
}

Step 2 — Regenerate the wrapper and confirm the version:

./gradlew wrapper
./gradlew --version

Step 3 — Test your plugin changes in the project:

./gradlew build --include-build /path/to/plugin

If you want to test it against multiple different plugins that you are changing at once, you can do that as well:

./gradlew build --include-build /path/to/plugin-one --include-build /path/to/plugin-two

Step 4 — Develop and enjoy!

You should now be able to see that your local plugin was pulled in and overrides the version that was defined in the past. This makes debugging and developing Gradle plugins easy. No need to publish locally anymore, you can just point to the local directory that you are developing your plugin at.

There are a number of improvements that they are making on component builds. I’m excited for when they make it work in continuous build mode so that I can get fast feedback while debugging an issue for a plugin i’m developing.