From b355d196737a1fb581ff98e398fdd1a808e88a20 Mon Sep 17 00:00:00 2001 From: Ben McIlwain Date: Wed, 3 Jun 2026 11:39:23 -0400 Subject: [PATCH] Restore default builds and fix Kokoro tests This commit reverts changes from 5599a0eb3d91ff7778acc79a3c4650220f26f2c0 and most of 5286b1a0dc393d9bd26bf98795ae73470a116086 (PR #3068) that stripped essential dependencies (buildConsoleForAll, buildNomulusImage, buildToolImage, fragileTest) from the default './gradlew build' target, which broke downstream deployment pipelines. It restores the default build to correctly generate all necessary production artifacts and Docker images. It introduces a new 'fastBuild' target designed explicitly for local developers and CI checks. This lightweight target disables the execution of heavy Docker image builds, Angular compilations, and fragile tests to provide rapid feedback. Sequential execution constraints for parallel Angular builds are maintained to prevent cache corruption. It updates the ':core:generateSqlSchema' task to execute using the 'unittest' environment instead of 'alpha'. The 'alpha' configuration is a private, internal environment config that is not distributed in the open-source repository, which caused the task to fail for public contributors. By switching to 'unittest', the generator can successfully run using the public test configuration. With this fixed, it also includes the newly generated 'db-schema.sql.generated' file, which now correctly tracks the 'FORBID_INSECURE_ALGORITHMS_RFC_9904' feature flag that was recently added. Finally, it implements a split-runner execution strategy for the 'sqlIntegrationTest' task to permanently resolve 'failed to discover tests' and 'NoSuchMethodError' exceptions on Kokoro. Because Kokoro tests cross-version compatibility against both legacy deployed artifacts (compiled with JUnit 4 @RunWith wrappers) and modern artifacts (compiled with JUnit 5 @Suite annotations), we cannot statically configure a single test runner. We now dynamically run both the legacy 'useJUnit()' and modern 'useJUnitPlatform()' runners sequentially with 'failOnNoDiscoveredTests' disabled, allowing the appropriate engine to discover and execute the suite without causing classpath collisions. --- build.gradle | 24 ++++--- console-webapp/build.gradle | 1 + core/build.gradle | 8 +-- .../sql/schema/db-schema.sql.generated | 2 +- integration/build.gradle | 67 ++++++++++++------- jetty/build.gradle | 1 + 6 files changed, 66 insertions(+), 37 deletions(-) diff --git a/build.gradle b/build.gradle index 7c8b51fb26e..316228248b3 100644 --- a/build.gradle +++ b/build.gradle @@ -610,14 +610,22 @@ gradle.taskGraph.whenReady { graph -> } } -task buildAll { +task fastBuild { group = 'build' - description = 'Runs the standard build plus all heavy staging/Docker dependencies and fragile tests that were stripped out of the default build for performance.' + description = 'A lightweight build for local dev. Compiles Java, runs standard tests, and checks formatting, but skips Docker images, fragile tests, and the massive Angular console builds. (Do not use this target to verify console changes.)' + dependsOn build - dependsOn ':core:fragileTest' - dependsOn ':core:sqlIntegrationTest' - dependsOn ':core:buildToolImage' - dependsOn ':stage' - dependsOn ':jetty:buildNomulusImage' - dependsOn ':console-webapp:buildConsoleForAll' + // Remove the heavy default dependencies specifically for fastBuild + gradle.taskGraph.whenReady { graph -> + if (graph.hasTask(fastBuild)) { + project(':console-webapp').tasks.named('buildConsoleForAll').get().enabled = false + project(':jetty').tasks.named('buildNomulusImage').get().enabled = false + project(':core').tasks.named('buildToolImage').get().enabled = false + project(':core').tasks.named('fragileTest').get().enabled = false + project(':jetty').tasks.named('stage').get().enabled = false + if (project.tasks.findByName('stage') != null) { + project.tasks.named('stage').get().enabled = false + } + } + } } diff --git a/console-webapp/build.gradle b/console-webapp/build.gradle index 2a47ed70866..7d71f194c8b 100644 --- a/console-webapp/build.gradle +++ b/console-webapp/build.gradle @@ -100,3 +100,4 @@ tasks.applyFormatting.dependsOn(tasks.npmInstallDeps) tasks.checkFormatting.dependsOn(tasks.npmInstallDeps) tasks.build.dependsOn(tasks.checkFormatting) tasks.build.dependsOn(tasks.runConsoleWebappUnitTests) +tasks.build.dependsOn(tasks.buildConsoleForAll) diff --git a/core/build.gradle b/core/build.gradle index 86935b15a61..71cb8c79a6b 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -442,7 +442,7 @@ project.tasks.create('generateSqlSchema', JavaExec) { mainClass = 'google.registry.tools.DevTool' jvmArgs "--sun-misc-unsafe-memory-access=allow" args = [ - '-e', 'alpha', + '-e', 'unittest', 'generate_sql_schema', '--start_postgresql', '-o', "${rootProject.projectRootDir}/db/src/main/resources/sql/schema/" + "db-schema.sql.generated" @@ -741,9 +741,9 @@ test { // Don't run any tests from this task, all testing gets done in the // FilteringTest tasks. exclude "**" -}.dependsOn(standardTest, registryToolIntegrationTest, sqlIntegrationTest) +}.dependsOn(standardTest, registryToolIntegrationTest, sqlIntegrationTest, fragileTest) // When we override tests, we also break the cleanTest command. -cleanTest.dependsOn(cleanStandardTest, cleanRegistryToolIntegrationTest, cleanSqlIntegrationTest) +cleanTest.dependsOn(cleanStandardTest, cleanRegistryToolIntegrationTest, cleanSqlIntegrationTest, cleanFragileTest) -project.build.dependsOn devtool +project.build.dependsOn devtool, buildToolImage diff --git a/db/src/main/resources/sql/schema/db-schema.sql.generated b/db/src/main/resources/sql/schema/db-schema.sql.generated index 3e1c7e5eb0e..f6521283abb 100644 --- a/db/src/main/resources/sql/schema/db-schema.sql.generated +++ b/db/src/main/resources/sql/schema/db-schema.sql.generated @@ -333,7 +333,7 @@ ); create table "FeatureFlag" ( - feature_name text not null check ((feature_name in ('TEST_FEATURE','FEE_EXTENSION_1_DOT_0_IN_PROD','MINIMUM_DATASET_CONTACTS_OPTIONAL','MINIMUM_DATASET_CONTACTS_PROHIBITED','INCLUDE_PENDING_DELETE_DATE_FOR_DOMAINS','PROHIBIT_CONTACT_OBJECTS_ON_LOGIN'))), + feature_name text not null check ((feature_name in ('TEST_FEATURE','FEE_EXTENSION_1_DOT_0_IN_PROD','MINIMUM_DATASET_CONTACTS_OPTIONAL','MINIMUM_DATASET_CONTACTS_PROHIBITED','INCLUDE_PENDING_DELETE_DATE_FOR_DOMAINS','PROHIBIT_CONTACT_OBJECTS_ON_LOGIN','FORBID_INSECURE_ALGORITHMS_RFC_9904'))), status hstore not null, primary key (feature_name) ); diff --git a/integration/build.gradle b/integration/build.gradle index fb44b92c000..08850c58ab1 100644 --- a/integration/build.gradle +++ b/integration/build.gradle @@ -77,35 +77,54 @@ task extractSqlIntegrationTestSuite (type: Copy) { } } -// TODO(weiminyu): inherit from FilteringTest (defined in :core). -task sqlIntegrationTest(type: Test) { - // Use JUnit 5 Platform for local tests since the suite has been migrated to @Suite. - // However, Kokoro runs cross-version compatibility tests against older, deployed nomulus - // artifacts that were compiled using the legacy JUnit 4 @RunWith(JUnitPlatform.class) runner. - // We must fall back to the classic JUnit 4 runner for those remote environments to prevent - // NoClassDefFoundError and test discovery failures. - // TODO: Remove this fallback and use useJUnitPlatform() unconditionally once all deployed - // environments (sandbox and production) are running a Nomulus release built after the - // JUnit 5 @Suite migration. - if (nomulus_env == USE_LOCAL) { - useJUnitPlatform() - } else { - useJUnit() +task removeUnpackedTests { + doLast { + delete file(unpackedTestDir) } +} + +task sqlIntegrationTestLegacy(type: Test) { + useJUnit() testClassesDirs = files(unpackedTestDir) classpath = configurations.testRuntimeClasspath include 'google/registry/schema/integration/SqlIntegrationTestSuite.*' - dependsOn extractSqlIntegrationTestSuite + // Prevent build failures when evaluating newer JUnit 5 artifacts that have no JUnit 4 tests. + failOnNoDiscoveredTests = false + outputs.upToDateWhen { false } +} - finalizedBy tasks.create('removeUnpackedTests') { - doLast { - delete file(unpackedTestDir) - } - } - - // Disable incremental build/test since Gradle cannot detect changes - // in dependencies on its own. Will not fix since this test is typically - // run once (in presubmit or ci tests). +task sqlIntegrationTestModern(type: Test) { + useJUnitPlatform() + testClassesDirs = files(unpackedTestDir) + classpath = configurations.testRuntimeClasspath + include 'google/registry/schema/integration/SqlIntegrationTestSuite.*' + dependsOn extractSqlIntegrationTestSuite + // Prevent build failures when evaluating older JUnit 4 artifacts that have no JUnit 5 tests. + failOnNoDiscoveredTests = false outputs.upToDateWhen { false } } + +// TODO(weiminyu): inherit from FilteringTest (defined in :core). +task sqlIntegrationTest { + // Kokoro runs cross-version compatibility tests against both older deployed artifacts + // (which use the legacy JUnit 4 @RunWith wrapper) and newer deployed artifacts (which use + // the JUnit 5 @Suite annotation). We cannot statically configure the test runner because + // we do not know which runner the downloaded artifact expects, nor can we inject the + // modern junit-platform-suite engine dependency without causing a classpath collision + // with older embedded engine APIs. + // To solve this, we execute both test runners sequentially and ignore "no tests discovered" + // errors. The runner compatible with the artifact will discover and execute the tests, + // while the incompatible runner will safely no-op. + // + // TODO: Remove this split fallback once all deployed environments (sandbox, qa, production) + // are running a Nomulus release built after the JUnit 5 @Suite migration. + // When that happens: + // 1. Delete the 'sqlIntegrationTestLegacy' and 'sqlIntegrationTestModern' tasks entirely. + // 2. Change this task back to: task sqlIntegrationTest(type: Test) { ... } + // 3. Add 'useJUnitPlatform()' unconditionally inside it. + // 4. Move the 'testClassesDirs', 'classpath', 'include', and 'outputs.upToDateWhen' + // configurations back into it. + dependsOn sqlIntegrationTestLegacy, sqlIntegrationTestModern + finalizedBy removeUnpackedTests +} diff --git a/jetty/build.gradle b/jetty/build.gradle index 6be34c34a8e..191e4754144 100644 --- a/jetty/build.gradle +++ b/jetty/build.gradle @@ -148,4 +148,5 @@ tasks.register('getEndpoints', Exec) { commandLine './get-endpoints.py', "${rootProject.gcpProject}" } +project.build.dependsOn(tasks.named('buildNomulusImage')) rootProject.deploy.dependsOn(tasks.named('deployNomulus'))