Popular Gradle mistakes (and how to avoid them) - part 3
In the previous post - part 2, we covered more common Gradle mistakes and how to fix them. In the last part of this triplet, we will share our favorite Gradle plugins that can help you avoid some of the mistakes we discussed in the previous posts!
Integration Test Plugin #
https://github.com/coditory/gradle-integration-test-plugin
Separating unit tests from integration tests can lead to more explicit build logic and faster feedback cycles. The Gradle Integration Test Plugin simplifies this separation by creating a dedicated source set and task for integration tests.
Example Usage: #
plugins {
id("com.coditory.integration-test") version "2.2.5"
}
This configuration adds an integration
suite to the project, nicely separated from the default test
suite:
You can run your integration tests with:
./gradlew integrationTest
Test Logger plugin #
https://github.com/radarsh/gradle-test-logger-plugin
Readable test outputs are essential for quickly identifying issues. The Gradle Test Logger Plugin enhances test reports by providing a more detailed and visually appealing output.
Example Usage: #
plugins {
id("com.adarshr.test-logger") version "4.0.0"
}
When you run your tests, the output will be more informative and easier to read.
Axion Release Plugin #
https://github.com/allegro/axion-release-plugin
Automating versioning and release processes reduces manual errors and streamlines deployments. The Axion Release Plugin uses Git tags to manage versions, ensuring consistency between your codebase and versioning.
plugins {
id("pl.allegro.tech.build.axion-release") version "1.18.18"
}
./gradlew release
This command increments the version, creates a Git tag, and pushes it to the repository.
The plugin integrates really well with GitHub Actions:
- it can automatically unshallow your repo (by default actions/checkout makes a shallow clone)
- it produces GitHub outputs
published-version
andreleased-version
that can be referenced in the subsequent steps (e.g., to deploy the app)
Dependency Graph Generator #
https://github.com/vanniktech/gradle-dependency-graph-generator-plugin
Sometimes you have a complex multi-module gradle project. This plugin helps you to understand the dependencies between sub-projects.
Example Usage: #
plugins {
id("com.vanniktech.dependency.graph.generator") version "0.8.0"
}
Apply this plugin in the root project. It will add the task generateProjectDependencyGraph
:
Running this task:
./gradlew :generateProjectDependencyGraph
will generate a graph that shows the subproject dependencies.
For example:
Typesafe Conventions #
https://github.com/radoslaw-panuszewski/typesafe-conventions-gradle-plugin
Version catalogs are awesome! Sadly, they don’t play well with convention plugins.
Let’s say you have the following libs.versions.toml
file:
[libraries]
commons-lang3 = "org.apache.commons:commons-lang3:3.17.0"
While you can use the typesafe accessor libs.commons.lang3
in your regular build.gradle.kts
files, it’s not possible in a convention plugin. All you have is access to the non-typesafe API:
// buildSrc/src/main/kotlin/some-convention.gradle.kts
dependencies {
implementation(versionCatalogs.find("libs").get().findLibrary("commons-lang3").get())
}
To overcome this limitation, you can apply the typesafe-conventions
plugin:
// buildSrc/settings.gradle.kts
plugins {
id("dev.panuszewski.typesafe-conventions") version "0.7.3"
}
It will allow you to use the typesafe accessor from your convention plugin:
// buildSrc/src/main/kotlin/some-convention.gradle.kts
dependencies {
implementation(libs.commons.lang3)
}
Binary Compatibility Validator #
https://github.com/Kotlin/binary-compatibility-validator
⚠️ The functionality of this plugin will be moved to Kotlin Gradle Plugin starting from the 2.2.0 release.
Ensuring API stability is crucial, especially when external clients consume your library. The Binary Compatibility Validator plugin helps maintain this stability by checking for binary compatibility between versions.
Example Usage: #
plugins {
id("org.jetbrains.kotlinx.binary-compatibility-validator") version "0.17.0"
}
Generate the API dump with:
./gradlew apiDump
This creates an API dump in the api
directory, which you should commit to version control.
Subsequent runs will compare the current API against this dump to detect incompatible changes.
In one of our repositories, we have a GitHub workflow that runs when the API dump file is changed. This workflow uses an LLM to check for breaking changes,
such as new method arguments without default values or removed public methods. If breaking changes are detected, the workflow adds a breaking-change
label to
the PR. Our GitHub release configuration (via YAML) then automatically includes a section for breaking changes in the release notes. If the PR is updated and no
breaking changes are detected, the label is removed.
Summary #
This is the end of a three-part series. We hope you found it helpful and that you learned something new about Gradle (just like we did writing this post). If you have any questions or suggestions, feel free to reach out to us on GitHub or Twitter.