-
Notifications
You must be signed in to change notification settings - Fork 43
Usage With Core Gradle Locks
If you have been using tasks such as generateLock
, saveLock
, and updateLock
, then you can run add the following property to gradle.properties
:
systemProp.nebula.features.coreLockingSupport=true
and run the following:
./gradlew migrateToCoreLocks
and you will be migrated to core Gradle locks using your currently locked dependencies as well as any other unlocked dependencies. These may have been floating to lock only specific dependencies, or because they are transitive dependencies, but now they will be locked.
- By default, not all configurations are locked. The set of configurations to lock can be see here. They are based on
compileClasspath
,testCompileClasspath
,runtimeClasspath
,testRuntimeClasspath
,annotationProcessor
,testAnnotationProcessor
and configurations that contribute to these. - Lock all configurations via the property
lockAllConfigurations=true
These are not supported by core Gradle locks. You will need to delete the global lock and use project locks.
Caution
Global Locks are not recommended. While Global Locks served a purpose in the past, they are not recommended for use.
Instead of relying on in Global Locks for dependency consistency across a multi-project, we recommend using a combination of Gradle's version catalogs, consistent dependency resolution and project level locks.
You can use gradle core locks by using the flags --write-locks
and --update-locks
with a comma separated list of dependencies to update, such as group1:artifact1,group2:artifact2
along with a task to resolve all project configurations (such as those needed for a multi-project build).
./gradlew dependencies --write-locks
Note: this is used instead of the generateLock
and saveLock
tasks.
In the parent build.gradle
, add a task to resolve dependencies for all projects. One example might be:
subprojects {
task dependenciesForAll(type: DependencyReportTask) {}
}
and then invoke that task to resolve all dependencies and update locks:
./gradlew dependenciesForAll --update-locks group1:artifact1,group2:artifact2
Note: this is used instead of the updateLock
and saveLock
tasks.
With this plugin on top of Core Gradle locks, we chose not to lock all configurations by default. This means that when updating plugins, the plugin configuration is not automatically locked and the person updating plugins can continue with the workflow. Instead, we default lock configurations that directly contribute to (and include) compileClasspath
, testCompileClasspath
, runtimeClasspath
, testRuntimeClasspath
, annotationProcessor
, testAnnotationProcessor
, as mentioned above.
Opt-in to locking specific configurations that are not included in that above list via a property in gradle.properties
:
dependencyLock.additionalConfigurationsToLock=comma,separated,configurations
If you really want every project configuration locked, then add the following property to gradle.properties
, and this will lock all configurations:
lockAllConfigurations=true
Please note that with Nebula's (non-Core Gradle) locking updates, you could specify the exact requested version via the command line.
With Gradle core locking, the locked state is resolved via constraints from build.gradle.
If you'd like an exact version, please add a constraint such as the following to build.gradle and examine your updated lockfile to ensure the desired version is locked:
configurations.all {
resolutionStrategy {
force 'test.example:foo:1.0.0'
}
}
When selectively updating locks, this acts as a selective dependency upgrade. The Gradle docs state "In this mode, the existing lock state is still used as input to resolution, filtering out the modules targeted by the update."
What does this mean?
If you had locked a single direct dependency test:a:1.0.0
that brings in other:b:5.0.0
, and you update to test:a:1.1.0
that brings in a lower version of a transitive dependency other:b:4.5.0
, then your resolved dependencies will be test:a:1.1.0
and the higher version other:b:5.0.0
.
If this is problematic, we recommend either resolving all dependencies rather than performing a selective dependency upgrade or forging a new path by updating a dependency and all of its transitives by name (there is not a supported tool for this, and it is not a supported use case).
What is this plugin doing on top of core locks? A few things.
- Use a default set of configurations to lock, rather than locking every one to care foremost about the project classpaths.
- Opt-in to locking specific configurations that are not included in that above list via a property.
- Ensure all resolved configurations have done so successfully. For example, core Gradle will provide information that a dependency was not resolved, and not update the lockfiles, which can cause an unexpected state. This behavior will fail the build and require user intervention, instead.
We are prioritizing using Core Gradle locks for project dependencies before working with classpath locks. Our examples and tests are geared only towards project dependencies at this time.