The Gradle team is excited to announce Gradle 8.6.
This release features support for custom encryption keys for the configuration cache, several improvements to build init, and updated build authoring APIs.
Additionally, this release provides more helpful error and warning messages and a new API for IDE integrators.
We would like to thank the following community members for their contributions to this release of Gradle: Baptiste Decroix, Björn Kautler, Daniel Lacasse, Danny Thomas, Hyeonmin Park, jeffalder, Jendrik Johannes, John Jiang, Kaiyao Ke, Kevin Mark, king-tyler, Marcin Dąbrowski, Marcin Laskowski, Markus Gaisbauer, Mel Arthurs, Ryan Schmitt, Surya K N, Vladislav Golubtsov, Yanshun Li, Andrzej Ressel
Be sure to check out the public roadmap for insight into what's planned for future releases.
Switch your build to use Gradle 8.6 by updating your wrapper:
./gradlew wrapper --gradle-version=8.6
See the Gradle 8.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading to Gradle 8.6.
For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.
The configuration cache improves build time by caching the result of the configuration phase and reusing it for subsequent builds. This feature can significantly improve build performance.
The configuration cache is encrypted to mitigate the risk of accidental exposure of sensitive data. By default, Gradle automatically creates and manages the key, storing it in a keystore in the Gradle User Home directory. While convenient, this may be inappropriate in some environments.
You may now provide Gradle with the key used to encrypt cached configuration data via the GRADLE_ENCRYPTION_KEY
environment variable.
More details can be found in the configuration cache section of the Gradle User Manual.
The build init plugin allows users to easily create a new Gradle build, supporting various types of projects.
You no longer have to answer an interactive question about the source package. Instead, a default value of org.example
will be used. You can override it using an existing option --package
flag for the init
task. Additionally, you can set the default value by adding a new org.gradle.buildinit.source.package
property in gradle.properties
in the Gradle User Home.
// ~/.gradle/gradle.properties
org.gradle.buildinit.source.package=my.corp.domain
Names of the generated convention plugins now start with buildlogic
instead of the package name, making them shorter and cleaner.
A new --use-defaults
option applies default values for options that were not explicitly configured. It also ensures the init command can be completed without interactive user input. This is handy in shell scripts to ensure they do not accidentally hang.
For example, here is how you can generate a Kotlin library without answering any questions:
gradle init --use-defaults --type kotlin-library
Projects generated with Kotlin DSL scripts now use simple property assignment syntax with the =
operator.
For instance, setting mainClass
of an application looks like this:
application {
mainClass = "org.example.AppKt"
}
Gradle provides rich APIs for plugin authors and build engineers to develop custom build logic. The task configuration avoidance API avoids configuring tasks if they are not needed for the execution of a build.
Previously, filtering tasks by name required using the matching
method using the following pattern:
tasks.matching { it.name.contains("pack") }.configureEach {
// configure details of all '*pack*' tasks that are part of the task graph
}
The problem was that calling matching
triggered the creation of all tasks, even when the task was not part of the build execution.
Starting from this release, you can use:
tasks.named { it.contains("pack") }.configureEach {
// lazily configure details of all '*pack*' tasks that are part of the task graph
}
Using named
will not cause the registered tasks to be eagerly created.
This new method is available on all Gradle containers that extend NamedDomainObjectSet
.
Gradle supports declaring capabilities for components to better manage dependencies by allowing Gradle to detect and resolve conflicts between dependencies at build time.
Previously, capability methods only accepted inputs as strings using with the capability notation:
dependencies {
implementation("org.foo:bar:1.0") {
capabilities {
requireCapability("org.foo:module-variant") // capability notation
}
}
}
Providers
can now be passed to capability methods ConfigurationPublications#capability(Object)
, ModuleDependencyCapabilitiesHandler#requireCapability(Object)
, and CapabilitiesResolution#withCapability(Object, Action)
. This allows computing the capability coordinates using values that may change after calling these methods, for example:
dependencies {
implementation("org.foo:bar:1.0") {
capabilities {
// Values in the interpolated String below are lazily evaluated, allowing them to be set after this block
requireCapability(project.provider(() -> "${project.group}:${project.name}-platform:${project.version}"))
}
}
}
// Later, the version of the project is set.
// Without the provider above, this change would not be reflected in the capability.
project.version = "1.0.0"
Gradle provides a rich set of error and warning messages to help you understand and resolve problems in your build.
This release improves error messages in dependency locking by separating the error from the possible action to fix the issue in the console output. Errors from invalid lock file format or missing lock state when strict mode is enabled are now displayed as illustrated below:
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':dependencies'.
> Could not resolve all dependencies for configuration ':lockedConf'.
> Invalid lock state for lock file specified in '<project>/lock.file'. Line: '<<<<<<< HEAD'
* Try:
> Verify the lockfile content. For more information on lock file format, please refer to https://docs.gradle.org/8.6/userguide/dependency_locking.html#lock_state_location_and_format in the Gradle documentation.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.
Before this release, evaluating a provider with a cycle in its value assignment would lead to a StackOverflowError
. With this release, circular references are properly detected and reported.
For instance, the following code:
def property = objects.property(String)
property.set("some value")
// wrong, self-references only supported via #update()
property.set(property.map { "$it and more" })
println(property.get()) // error when evaluating
Previously failed with a StackOverflowError
and limited details:
FAILURE: Build failed with an exception.
* What went wrong:
A problem occurred evaluating root project 'test'.
> java.lang.StackOverflowError (no error message)
Starting with this release, you get a more helpful error message indicating the source of the cycle and a list of the providers in the chain that led to it:
FAILURE: Build failed with an exception.
* Where:
Build file '<project>/build.gradle' line: 7
* What went wrong:
A problem occurred evaluating root project 'test'.
> Circular evaluation detected: property(java.lang.String, map(java.lang.String map(<CIRCULAR REFERENCE>) check-type()))
-> map(java.lang.String map(property(java.lang.String, <CIRCULAR REFERENCE>)) check-type())
-> map(property(java.lang.String, map(java.lang.String <CIRCULAR REFERENCE> check-type())))
-> property(java.lang.String, map(java.lang.String map(<CIRCULAR REFERENCE>) check-type()))
Gradle is integrated into many IDEs using the Tooling API.
The following improvements are for IDE integrators. They will become available to end-users in future IDE releases once IDE vendors adopt them.
The new Problems API has entered a public incubation phase and is ready for integration.
The Problems API enables plugin and build engineers to report rich, structured information about problems that may occur during a build. This information can be received by Tooling API clients, such as IDEs or CI systems, and can be represented in a way that best suits the platform. Tooling API clients are encouraged to begin integrating with the API and provide additional feedback.
The integration process for established Tooling API clients should be straightforward. Problems can be received using the same ProgressListener
interface used for other progress messages. The new template showcases a self-functioning Tooling API client that can receive and present problems. Additionally, a new sample has been introduced to demonstrate various use cases of the API.
Known issues are problems that were discovered post release that are directly related to changes made in this release.
We love getting contributions from the Gradle community. For information on contributing, please see gradle.org/contribute.
If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.
We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.