LoremIpsum-42
10/10/2025, 12:37 PMproject.tasks.register("checkDependencies") {
val configurationsToCheck = mutableSetOf<Configuration>()
listOf("compileClasspath", extension.configuration.get()).forEach { configToCheck: String ->
configurationsToCheck += project.configurations[configToCheck]
}
doLast {
val snapshotDeps = mutableListOf<String>()
val resolvedDependencies = mutableSetOf<ResolvedDependency>()
configurationsToCheck.forEach { configToCheck: Configuration ->
configToCheck
.resolvedConfiguration.firstLevelModuleDependencies
.forEach { resolvedDependencies += it }
}
val sortedValues = resolvedDependencies.toMutableList()
sortedValues.sortWith(compareBy({ it.moduleGroup }, { it.moduleName }))
sortedValues.forEach { dep: ResolvedDependency ->
if (dep.moduleGroup.startsWith("com.example")) {
// body work
Logging.getLogger("com.example").quiet("Found $dep")
}
}
if (!snapshotDeps.isEmpty()) {
throw GradleException("Found snapshot dependency: ${snapshotDeps.joinToString(separator = "\n")}")
}
}
}
Which does look over the 1st level declared deps on the given configurations and searches for patterns which I don't want there - this fails with CC enabled and Gradle 9.
Anyone have some pointers (to the docs) / ideas how to get those info / task / work done in a CC compatible way? Thanks.Jonathing
10/10/2025, 12:48 PMJonathing
10/10/2025, 12:48 PMVampire
10/10/2025, 1:20 PMLoremIpsum-42
10/10/2025, 1:25 PMLoremIpsum-42
10/10/2025, 2:21 PMval configurationsToCheck = mutableSetOf<Configuration>()
listOf("compileClasspath", extension.configuration.get()).forEach { configToCheck: String ->
configurationsToCheck += project.configurations[configToCheck]
}
val preRelease = providers.gradleProperty("preRelease").orElse("")
val snapshotDeps = mutableListOf<String>()
val ids = mutableListOf<ComponentArtifactIdentifier>()
configurationsToCheck.forEach { conf ->
val artifacts: Provider<Set<ResolvedArtifactResult>> =
conf.incoming
.artifactView {
componentFilter {
when (it) {
is ModuleComponentIdentifier ->
it.group.startsWith("com.example") && !it.group.startsWith("<http://com.example.org|com.example.org>")
else -> false
}
}
}.artifacts.resolvedArtifacts
ids.addAll(
artifacts.get().map { artifact ->
artifact.id
},
)
}
doLast {
ids.sortBy { it.componentIdentifier.displayName }
ids.forEach { artifact ->
Logging.getLogger("com.example").quiet("Checking artifact => $artifact")
val componentId: ModuleComponentIdentifier = artifact.componentIdentifier as ModuleComponentIdentifier
if (!Utils.isValidDependency(componentId.version, preRelease.get().isNotBlank())) {
snapshotDeps += "$artifact"
}
}
if (!snapshotDeps.isEmpty()) {
throw GradleException("Found snapshot dependency: ${snapshotDeps.joinToString(separator = "\n")}")
}
}Vampire
10/10/2025, 2:26 PMget() on a Provider curing configuration phase is practically always a bad idea.
That introduces the same race conditions you earned from using afterEvaluate.LoremIpsum-42
10/10/2025, 2:26 PMLoremIpsum-42
10/10/2025, 2:28 PM.get() .LoremIpsum-42
10/10/2025, 2:30 PMLoremIpsum-42
10/10/2025, 2:39 PMval componentProviders = mutableListOf<Provider<List<ComponentArtifactIdentifier>>>()
...
componentProviders.add(artifacts.map { it.map { it.id } })
doLast {
val ids = mutableListOf<ComponentArtifactIdentifier>()
componentProviders.forEach {
ids.addAll(it.get())
}
...
}
That way I retain the provider to the execution phase, would that be ok?LoremIpsum-42
10/10/2025, 2:43 PMVampire
10/10/2025, 3:14 PMprovider.gradleProperty provider is fine, as its value cannot change, at lest as of today.
Once you are able to programmatically change Project Properties, it becomes not-ok if it could be avoided.