From f21c7c27cb66e2110c4d5a666e123280259ed4d4 Mon Sep 17 00:00:00 2001 From: Weimin Yu Date: Thu, 19 Mar 2026 19:44:03 +0000 Subject: [PATCH] Prepare for Gradle 9 upgrade Refactor Gradle scripts to replace usages incompatible with Gradle 9. PR prepared mostly with gemini-cli, with one issue (project.exec) researched with gemini web and manually applied. The actual upgrade to Gradle 9 will be in another PR. Verified: none of the issues reported in build/reports/problems/problems-report.html is related to Gradle 9. --- build.gradle | 23 ++++++++++++------- core/build.gradle | 51 ++++++++++++++++++++++++++--------------- dependency_lic.gradle | 2 +- networking/build.gradle | 12 ++++++---- prober/build.gradle | 2 +- proxy/build.gradle | 2 +- utils.gradle | 8 +++---- 7 files changed, 61 insertions(+), 39 deletions(-) diff --git a/build.gradle b/build.gradle index c3629696e03..eb8cb36eaa1 100644 --- a/build.gradle +++ b/build.gradle @@ -153,7 +153,7 @@ allprojects { if (!mavenUrl.isEmpty()) { maven { println "Java dependencies: Using repo ${mavenUrl}..." - url mavenUrl + url = mavenUrl allowInsecureProtocol = allowInsecure == "true" } } else { @@ -161,7 +161,7 @@ allprojects { mavenCentral() google() maven { - url "https://packages.confluent.io/maven/" + url = "https://packages.confluent.io/maven/" content { includeGroup "io.confluent" } @@ -291,7 +291,7 @@ subprojects { // We do seem to get duplicates when constructing uber-jars, either // this is a product of something in gradle 7 or a product of gradle 7 // now giving an error about them when it didn't previously. - duplicatesStrategy DuplicatesStrategy.WARN + duplicatesStrategy = DuplicatesStrategy.WARN } } @@ -341,8 +341,10 @@ subprojects { // search for `flex-template-base-image` and update the parameter value. // There are at least two instances, one in core/build.gradle, one in // release/stage_beam_pipeline.sh - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 + java { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 + } project.tasks.test.dependsOn runPresubmits @@ -369,11 +371,16 @@ subprojects { // No need to produce javadoc for the jetty subproject, which has no APIs to // expose to users. - if (project.name != 'jetty') { + if (project.name != 'jetty' && !services.contains(project.path)) { javadocSource << project.sourceSets.main.allJava - javadocClasspath << project.sourceSets.main.runtimeClasspath + javadocClasspath << { project.sourceSets.main.runtimeClasspath.files } javadocClasspath << "${buildDir}/generated/sources/annotationProcessor/java/main" - javadocDependentTasks << project.tasks.compileJava + if (project.tasks.findByName('compileJava')) { + javadocDependentTasks << project.tasks.compileJava + } + if (project.tasks.findByName('processResources')) { + javadocDependentTasks << project.tasks.processResources + } } } diff --git a/core/build.gradle b/core/build.gradle index fcfab8b461a..50547549223 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -108,7 +108,15 @@ configurations { // Published jars that are used for server/schema compatibility tests. // See the integration project // for details. - nomulus_test + nomulus_test { + canBeConsumed = true + canBeResolved = false + } + testRuntimeElements { + canBeConsumed = true + canBeResolved = false + extendsFrom testRuntimeOnly + } // Exclude non-canonical servlet-api jars. Our deployment uses // javax.servlet:servlet-api:2.5 @@ -339,7 +347,7 @@ task jaxbToJava { destdir: "${generatedDir}", binding: "${xjcTempSourceDir}/bindings.xjb", removeOldOutput: 'yes', extension: 'true') { - project.fileTree( + fileTree( dir: new File("$xjcTempSourceDir"), include: ['**/*.xsd']) .addToAntBuilder(ant, 'schema', FileCollection.AntType.FileSet) @@ -377,13 +385,13 @@ task soyToJava { } ext.soyToJava = { javaPackage, outputDirectory, soyFiles -> - javaexec { - main = "com.google.template.soy.SoyParseInfoGenerator" - classpath configurations.soy - args "--javaPackage", "${javaPackage}", + project.services.get(ExecOperations).javaexec { + mainClass = "com.google.template.soy.SoyParseInfoGenerator" + classpath = configurations.soy + args = ["--javaPackage", "${javaPackage}", "--outputDirectory", "${outputDirectory}", "--javaClassNameSource", "filename", - "--srcs", "${soyFiles.join(',')}" + "--srcs", "${soyFiles.join(',')}"] } // Replace the "@link" tags after the "@deprecated" tags in the generated @@ -397,8 +405,8 @@ task soyToJava { } outputs.each { file -> - exec { - commandLine 'sed', '-i""', '-e', 's/@link/LINK/g', file.getCanonicalPath() + project.services.get(ExecOperations).exec { + commandLine = ['sed', '-i""', '-e', 's/@link/LINK/g', file.getCanonicalPath()] } } } @@ -429,12 +437,12 @@ task testJar(type: Jar) { } artifacts { - testRuntimeOnly testJar + add('testRuntimeElements', testJar) } task findGoldenImages(type: JavaExec) { classpath = sourceSets.test.runtimeClasspath - main = 'google.registry.webdriver.GoldenImageFinder' + mainClass = 'google.registry.webdriver.GoldenImageFinder' def arguments = [] arguments << "--screenshots_for_goldens_dir=${screenshotsForGoldensDir}" @@ -481,11 +489,11 @@ Optional> getToolArgsList() { // parameter. ext.createToolTask = { taskName, - mainClass, + mainClassName, sourceSet = sourceSets.main -> project.tasks.create(taskName, JavaExec) { classpath = sourceSet.runtimeClasspath - main = mainClass + mainClass = mainClassName doFirst { getToolArgsList().ifPresent { @@ -502,7 +510,7 @@ createToolTask( project.tasks.create('generateSqlSchema', JavaExec) { classpath = sourceSets.nonprod.runtimeClasspath - main = 'google.registry.tools.DevTool' + mainClass = 'google.registry.tools.DevTool' args = [ '-e', 'alpha', 'generate_sql_schema', '--start_postgresql', '-o', @@ -515,7 +523,7 @@ task generateGoldenImages(type: FilteringTest) { tests = ["**/webdriver/*"] // Sets the maximum number of test executors that may exist at the same time. - maxParallelForks 5 + maxParallelForks = 5 systemProperty 'test.screenshot.dir', screenshotsForGoldensDir systemProperty 'test.screenshot.runAllAttempts', 'true' @@ -659,7 +667,7 @@ artifacts { } task runTestServer(type: JavaExec) { - main = 'google.registry.server.RegistryTestServerMain' + mainClass = 'google.registry.server.RegistryTestServerMain' classpath = sourceSets.test.runtimeClasspath dependsOn(rootProject.project('console-webapp').tasks.named('buildConsoleWebapp')) } @@ -685,6 +693,8 @@ abstract class FilteringTest extends Test { FilteringTest() { useJUnitPlatform(); + testClassesDirs = project.sourceSets.test.output.classesDirs + classpath = project.sourceSets.test.runtimeClasspath } private void applyTestFilter() { @@ -739,7 +749,7 @@ task fragileTest(type: FilteringTest) { } // Run every test class in a freshly started process. - forkEvery 1 + forkEvery = 1 doFirst { new File(screenshotsDir).deleteDir() @@ -754,6 +764,9 @@ task sqlIntegrationTest(type: FilteringTest) { useJUnit() excludeTestCases = false tests = ['google/registry/schema/integration/SqlIntegrationTestSuite.*'] + + testClassesDirs = sourceSets.test.output.classesDirs + classpath = sourceSets.test.runtimeClasspath } // Verifies that RegistryTool can be instantiated: @@ -779,13 +792,13 @@ task standardTest(type: FilteringTest) { // Run every test class in its own process. // Uncomment to unblock build while troubleshooting inexplicable test errors. // This setting makes the build take 35 minutes, without it it takes about 10. - // forkEvery 1 + // forkEvery = 1 // Sets the maximum number of test executors that may exist at the same time. // Also, Gradle executes tests in 1 thread and some of our test infrastructures // depend on that, e.g. DualDatabaseTestInvocationContextProvider injects // different implementation of TransactionManager into TransactionManagerFactory. - maxParallelForks 64 + maxParallelForks = 64 systemProperty 'test.projectRoot', rootProject.projectRootDir systemProperty 'test.resourcesDir', resourcesDir diff --git a/dependency_lic.gradle b/dependency_lic.gradle index 306227da322..8b1cc37d9f2 100644 --- a/dependency_lic.gradle +++ b/dependency_lic.gradle @@ -19,7 +19,7 @@ buildscript { repositories { maven { - url 'https://plugins.gradle.org/m2/' + url = 'https://plugins.gradle.org/m2/' } } dependencies { diff --git a/networking/build.gradle b/networking/build.gradle index 4958df029bd..db16fa59db6 100644 --- a/networking/build.gradle +++ b/networking/build.gradle @@ -56,12 +56,14 @@ task testJar(type: Jar) { from sourceSets.test.output } -artifacts { - testRuntimeOnly testJar -} - configurations { - testRuntimeOnly { + testRuntimeElements { canBeConsumed = true + canBeResolved = false + extendsFrom testRuntimeOnly } } + +artifacts { + add('testRuntimeElements', testJar) +} diff --git a/prober/build.gradle b/prober/build.gradle index 8bbd49f804f..dee2c2d91ca 100644 --- a/prober/build.gradle +++ b/prober/build.gradle @@ -55,7 +55,7 @@ dependencies { testImplementation deps['org.mockito:mockito-core'] testImplementation deps['org.testcontainers:junit-jupiter'] testImplementation project(path: ':common', configuration: 'testing') - testImplementation project(path: ':networking', configuration: 'testRuntimeOnly') + testImplementation project(path: ':networking', configuration: 'testRuntimeElements') // Include auto-value in compile until nebula-lint understands // annotationProcessor diff --git a/proxy/build.gradle b/proxy/build.gradle index 2652358059d..3bddd072d22 100644 --- a/proxy/build.gradle +++ b/proxy/build.gradle @@ -83,7 +83,7 @@ dependencies { testImplementation deps['org.testcontainers:junit-jupiter'] testImplementation deps['org.yaml:snakeyaml'] testImplementation project(path: ':common', configuration: 'testing') - testImplementation project(path: ':networking', configuration: 'testRuntimeOnly') + testImplementation project(path: ':networking', configuration: 'testRuntimeElements') // Include auto-value in compile until nebula-lint understands // annotationProcessor diff --git a/utils.gradle b/utils.gradle index 940edd01252..7dd830eaf94 100644 --- a/utils.gradle +++ b/utils.gradle @@ -18,10 +18,10 @@ rootProject.ext { // to stdout as a string. This method allows pipes in shell command. execInBash = { shellCommand, bashWorkingDir -> return new ByteArrayOutputStream().withStream { os -> - exec { - workingDir bashWorkingDir - commandLine 'bash', '-c', "${shellCommand}" - standardOutput os + project.services.get(ExecOperations).exec { + workingDir = bashWorkingDir + commandLine = ['bash', '-c', "${shellCommand}"] + standardOutput = os }.assertNormalExitValue() return os }.toString().trim()