From c7ac7087f79ff5a23c625fe7838f7167006acf7b Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Thu, 25 Jun 2026 14:48:08 -0400 Subject: [PATCH] Fix updateVerificationMetadata task to account for IDE tooling. --- build-logic/plugins/build.gradle.kts | 46 +++++++ .../java/UpdateVerificationMetadataTask.kt | 3 + gradle/verification-metadata.xml | 128 ++++++++++++++++++ 3 files changed, 177 insertions(+) diff --git a/build-logic/plugins/build.gradle.kts b/build-logic/plugins/build.gradle.kts index f1da4be921..2853f16804 100644 --- a/build-logic/plugins/build.gradle.kts +++ b/build-logic/plugins/build.gradle.kts @@ -37,3 +37,49 @@ ktlint { } } } + +// The IDE's KotlinDslScriptsModel resolves the Groovy modules bundled with this Gradle distribution (via the +// localGroovy() dependency that groovy-gradle-plugin adds) during sync. That resolution happens in the Tooling +// API model-building phase, which no task graph -- and therefore no updateVerificationMetadata pass -- ever +// reaches, so their checksums never get written and a fresh sync fails verification. This task resolves that +// same module graph from a task so --write-verification-metadata can capture it. +run { + val syncGroovyTaskName = "syncGroovyVerification" + + val syncTask = tasks.register(syncGroovyTaskName) { + group = "Verification" + description = "Resolves the Groovy modules bundled with this Gradle distribution so their checksums can be written to verification-metadata.xml. The IDE's KotlinDslScriptsModel resolves these (via localGroovy) during sync, but no task graph does, so the cross-platform/qa passes never capture them." + } + + // Only wire up the resolvable configuration when the task is actually requested. This build is included by the + // root, so the requested task names live on the parent build's start parameters, not this one's. + val requested = (gradle.parent ?: gradle).startParameter.taskNames.any { it.substringAfterLast(':') == syncGroovyTaskName } + if (requested) { + val groovyVersion = groovy.lang.GroovySystem.getVersion() + val suffix = "-$groovyVersion.jar" + // localGroovy() puts the whole bundled Groovy runtime on the classpath, not just the umbrella module. Derive the + // module names from the jars it actually resolves to (rather than every groovy jar in the distribution) so the + // set matches what the IDE resolves and adapts automatically across Gradle versions. + val modules = configurations.detachedConfiguration(dependencies.localGroovy()).files + .map { it.name } + .filter { it.startsWith("groovy") && it.endsWith(suffix) } + .map { it.removeSuffix(suffix) } + .sorted() + .ifEmpty { listOf("groovy") } + + val configuration = configurations.create("groovyVerification") { + isCanBeConsumed = false + isCanBeResolved = true + } + modules.forEach { module -> + dependencies.add(configuration.name, "org.apache.groovy:$module:$groovyVersion") + } + + syncTask.configure { + inputs.files(configuration.incoming.files) + doLast { + println("Resolved Groovy $groovyVersion module graph for verification.") + } + } + } +} diff --git a/build-logic/plugins/src/main/java/UpdateVerificationMetadataTask.kt b/build-logic/plugins/src/main/java/UpdateVerificationMetadataTask.kt index 405e905df7..ce6109a40c 100644 --- a/build-logic/plugins/src/main/java/UpdateVerificationMetadataTask.kt +++ b/build-logic/plugins/src/main/java/UpdateVerificationMetadataTask.kt @@ -63,6 +63,9 @@ constructor( // nested builds, which resolve plugin dependencies (e.g. junit BOMs) that no configuration walk or qa build // ever sees. Forcing a refresh re-downloads them through the verifier so their checksums get written. runGradle("--write-verification-metadata", "sha256", ":build-logic:plugins:generatePrecompiledScriptPluginAccessors", "--rerun-tasks", "--no-build-cache", "--refresh-dependencies") + // The IDE resolves the bundled Groovy module graph (via localGroovy) during sync's model-building phase, which + // no task graph reaches, so resolve it explicitly to capture those checksums. + runGradle("--write-verification-metadata", "sha256", ":build-logic:plugins:syncGroovyVerification", "--rerun-tasks", "--refresh-dependencies") runGradle("--write-verification-metadata", "sha256", "syncCrossPlatformVerification", "--rerun-tasks") } catch (failure: Throwable) { file.writeBytes(original) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index ad60bed1c4..43fd73f80b 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -4186,6 +4186,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + @@ -5365,6 +5370,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + @@ -6134,6 +6144,26 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + + + + + + + + + + + + + + + + @@ -6149,6 +6179,99 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -7611,6 +7734,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + +