From 22f9ccd89d02cc335ea280591bed094b0ad6721d Mon Sep 17 00:00:00 2001 From: Rene Groeschke Date: Fri, 15 Aug 2025 13:38:00 +0200 Subject: [PATCH 1/2] Fix reproducability of builds against Java EA versions (#132847) * Introduce dedicated toolchain resolver for EA java versions * Fix reproducability of builds against Java EA versions This fixes a reproducability issue when using the gradle javaToolChain api. There is no way to test toolchain candidates reliable against the build number in use. This meant that ones you e.g. have resolved some version of java 25, gradle toolchain detection does not detect the difference between certain builds (or even ea vs. released version) Therefore we fallback to rely on our custom JDKDownloadPlugin for now here. Syncing with the gradle team, they want to fix this somewhen in 9.x. We will revisit our solution ones something is available. Ultimately we want to get rid of usages of the JDK download plugin. * Minor cleanup and fixing non set distribution type in jdk * Fix ea jdk selection not just based on major version explicitly requires to add a ea postfix to the runtime sys property * Fix test reproduce linies when using java ea version * Apply review feedback * Use runtime jdk when patching * More cleanup (cherry picked from commit 16fe7db13720c19bbe48f5882706f16ed751f972) # Conflicts: # BUILDING.md # build-tools-internal/src/integTest/groovy/org/elasticsearch/gradle/internal/JdkDownloadPluginFuncTest.groovy --- BUILDING.md | 40 +++-- .../AbstractGitAwareGradleFuncTest.groovy | 1 - .../internal/JdkDownloadPluginFuncTest.groovy | 60 ++++--- .../elasticsearch/gradle/internal/Jdk.java | 19 ++- .../gradle/internal/JdkDownloadPlugin.java | 9 + .../internal/info/GlobalBuildInfoPlugin.java | 38 ++++- ...arlyAccessCatalogJdkToolchainResolver.java | 160 ++++++++++++++++++ .../JavaToolChainResolverPlugin.java | 1 + .../OracleOpenJdkToolchainResolver.java | 37 +--- .../gradle/internal/JdkSpec.groovy | 46 +++++ .../AbstractToolchainResolverSpec.groovy | 1 + .../AdoptiumJdkToolchainResolverSpec.groovy | 2 +- ...cessCatalogJdkToolchainResolverSpec.groovy | 62 +++++++ .../OracleOpenJdkToolchainResolverSpec.groovy | 51 +----- .../elasticsearch/gradle/Architecture.java | 8 +- .../gradle/DistributionDownloadPlugin.java | 10 +- .../java/org/elasticsearch/gradle/OS.java | 13 +- build.gradle | 4 +- gradle/verification-metadata.xml | 1 + settings.gradle | 1 + .../junit/listeners/ReproduceInfoPrinter.java | 4 +- 21 files changed, 427 insertions(+), 141 deletions(-) create mode 100644 build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/toolchain/EarlyAccessCatalogJdkToolchainResolver.java create mode 100644 build-tools-internal/src/test/groovy/org/elasticsearch/gradle/internal/JdkSpec.groovy create mode 100644 build-tools-internal/src/test/groovy/org/elasticsearch/gradle/internal/toolchain/EarlyAccessCatalogJdkToolchainResolverSpec.groovy diff --git a/BUILDING.md b/BUILDING.md index 127d422fad089..623babc06e3b0 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -92,10 +92,10 @@ uses the changed dependencies. In most cases, `precommit` or `check` are good ca We prefer sha256 checksums as md5 and sha1 are not considered safe anymore these days. The generated entry will have the `origin` attribute been set to `Generated by Gradle`. ->A manual confirmation of the Gradle generated checksums is currently not mandatory. ->If you want to add a level of verification you can manually confirm the checksum (e.g. by looking it up on the website of the library) ->Please replace the content of the `origin` attribute by `official site` in that case. -> +> [!Tip] +> A manual confirmation of the Gradle generated checksums is currently not mandatory. +> If you want to add a level of verification you can manually confirm the checksum (e.g. by looking it up on the website of the library) +> Please replace the content of the `origin` attribute by `official site` in that case. #### Custom plugin and task implementations @@ -186,6 +186,25 @@ dependencies { To test an unreleased development version of a third party dependency you have several options. +### How do I test against java early access (ea) versions? + +Currently only openjdk EA builds by oracle are supported. +To test against an early access version java version you can pass the major +java version appended with `-ea` as a system property (e.g. -Druntime.java=26-ea) to the Gradle build: + +``` +./gradlew clean test -Druntime.java=26-ea +``` + +This will run the tests using the JDK 26 EA version and pick the latest available build of the matching JDK EA version we expose +in our custom jdk catalogue at `https://storage.googleapis.com/elasticsearch-jdk-archive/jdks/openjdk/latest.json`. + +To run against a specific build number of the EA build you can pass a second system property (e.g. `-Druntime.java.build=6`): + +``` +./gradlew clean test -Druntime.java=26-ea -Druntime.java.build=6 +``` + #### How to use a Maven based third party dependency via `mavenlocal`? 1. Clone the third party repository locally @@ -229,11 +248,8 @@ In addition to snapshot builds JitPack supports building Pull Requests. Simply u 3. Run the Gradle build as needed. Keep in mind the initial resolution might take a bit longer as this needs to be built by JitPack in the background before we can resolve the adhoc built dependency. ---- - -**NOTE** - -You should only use that approach locally or on a developer branch for production dependencies as we do +> [!Note] +> You should only use that approach locally or on a developer branch for production dependencies as we do not want to ship unreleased libraries into our releases. --- @@ -265,10 +281,8 @@ allprojects { ``` 4. Run the Gradle build as needed with `--write-verification-metadata` to ensure the Gradle dependency verification does not fail on your custom dependency. ---- -**NOTE** - -As Gradle prefers to use modules whose descriptor has been created from real meta-data rather than being generated, +> [!Note] +> As Gradle prefers to use modules whose descriptor has been created from real meta-data rather than being generated, flat directory repositories cannot be used to override artifacts with real meta-data from other repositories declared in the build. For example, if Gradle finds only `jmxri-1.2.1.jar` in a flat directory repository, but `jmxri-1.2.1.pom` in another repository that supports meta-data, it will use the second repository to provide the module. diff --git a/build-tools-internal/src/integTest/groovy/org/elasticsearch/gradle/fixtures/AbstractGitAwareGradleFuncTest.groovy b/build-tools-internal/src/integTest/groovy/org/elasticsearch/gradle/fixtures/AbstractGitAwareGradleFuncTest.groovy index f7c05894d3e95..d8cb55fc0373f 100644 --- a/build-tools-internal/src/integTest/groovy/org/elasticsearch/gradle/fixtures/AbstractGitAwareGradleFuncTest.groovy +++ b/build-tools-internal/src/integTest/groovy/org/elasticsearch/gradle/fixtures/AbstractGitAwareGradleFuncTest.groovy @@ -10,7 +10,6 @@ package org.elasticsearch.gradle.fixtures import org.apache.commons.io.FileUtils -import org.elasticsearch.gradle.internal.test.InternalAwareGradleRunner import org.gradle.testkit.runner.GradleRunner import org.junit.Rule import org.junit.rules.TemporaryFolder diff --git a/build-tools-internal/src/integTest/groovy/org/elasticsearch/gradle/internal/JdkDownloadPluginFuncTest.groovy b/build-tools-internal/src/integTest/groovy/org/elasticsearch/gradle/internal/JdkDownloadPluginFuncTest.groovy index 94df02b280ca6..d1fedef1afb54 100644 --- a/build-tools-internal/src/integTest/groovy/org/elasticsearch/gradle/internal/JdkDownloadPluginFuncTest.groovy +++ b/build-tools-internal/src/integTest/groovy/org/elasticsearch/gradle/internal/JdkDownloadPluginFuncTest.groovy @@ -26,6 +26,7 @@ import java.util.regex.Pattern import static org.elasticsearch.gradle.internal.JdkDownloadPlugin.VENDOR_ADOPTIUM import static org.elasticsearch.gradle.internal.JdkDownloadPlugin.VENDOR_OPENJDK +import static org.elasticsearch.gradle.internal.JdkDownloadPlugin.VENDOR_ZULU class JdkDownloadPluginFuncTest extends AbstractGradleFuncTest { @@ -33,17 +34,20 @@ class JdkDownloadPluginFuncTest extends AbstractGradleFuncTest { private static final String ADOPT_JDK_VERSION = "12.0.2+10" private static final String ADOPT_JDK_VERSION_11 = "11.0.10+9" private static final String ADOPT_JDK_VERSION_15 = "15.0.2+7" + private static final String AZUL_JDK_VERSION_8 = "8u302+b08" + private static final String AZUL_8_DISTRO_VERSION = "8.56.0.23" + private static final String CATALOG_EA_VERSION = "25-ea+30" private static final String OPEN_JDK_VERSION = "12.0.1+99@123456789123456789123456789abcde" private static final Pattern JDK_HOME_LOGLINE = Pattern.compile("JDK HOME: (.*)") def setup() { - configurationCacheCompatible = false + configurationCacheCompatible = false // JDK class references configurations which break configuration cache } @Unroll - def "jdk #jdkVendor for #platform#suffix are downloaded and extracted"() { + def "jdk #distributionVersion #jdkVendor for #platform#suffix are downloaded and extracted"() { given: - def mockRepoUrl = urlPath(jdkVendor, jdkVersion, platform, arch); + def mockRepoUrl = urlPath(jdkVendor, jdkVersion, platform, arch, distributionVersion); def mockedContent = filebytes(jdkVendor, platform) buildFile.text = """ plugins { @@ -78,22 +82,28 @@ class JdkDownloadPluginFuncTest extends AbstractGradleFuncTest { assertExtraction(result.output, expectedJavaBin); where: - platform | arch | jdkVendor | jdkVersion | expectedJavaBin | suffix - "linux" | "x64" | VENDOR_ADOPTIUM | ADOPT_JDK_VERSION | "bin/java" | "" - "linux" | "x64" | VENDOR_OPENJDK | OPEN_JDK_VERSION | "bin/java" | "" - "linux" | "x64" | VENDOR_OPENJDK | OPENJDK_VERSION_OLD | "bin/java" | "(old version)" - "windows" | "x64" | VENDOR_ADOPTIUM | ADOPT_JDK_VERSION | "bin/java" | "" - "windows" | "x64" | VENDOR_OPENJDK | OPEN_JDK_VERSION | "bin/java" | "" - "windows" | "x64" | VENDOR_OPENJDK | OPENJDK_VERSION_OLD | "bin/java" | "(old version)" - "darwin" | "x64" | VENDOR_ADOPTIUM | ADOPT_JDK_VERSION | "Contents/Home/bin/java" | "" - "darwin" | "x64" | VENDOR_OPENJDK | OPEN_JDK_VERSION | "Contents/Home/bin/java" | "" - "darwin" | "x64" | VENDOR_OPENJDK | OPENJDK_VERSION_OLD | "Contents/Home/bin/java" | "(old version)" - "mac" | "x64" | VENDOR_OPENJDK | OPEN_JDK_VERSION | "Contents/Home/bin/java" | "" - "mac" | "x64" | VENDOR_OPENJDK | OPENJDK_VERSION_OLD | "Contents/Home/bin/java" | "(old version)" - "darwin" | "aarch64" | VENDOR_ADOPTIUM | ADOPT_JDK_VERSION | "Contents/Home/bin/java" | "" - "linux" | "aarch64" | VENDOR_ADOPTIUM | ADOPT_JDK_VERSION | "bin/java" | "" - "linux" | "aarch64" | VENDOR_ADOPTIUM | ADOPT_JDK_VERSION_11 | "bin/java" | "(jdk 11)" - "linux" | "aarch64" | VENDOR_ADOPTIUM | ADOPT_JDK_VERSION_15 | "bin/java" | "(jdk 15)" + platform | arch | jdkVendor | jdkVersion | distributionVersion | expectedJavaBin | suffix + "linux" | "aarch64" | VENDOR_OPENJDK | CATALOG_EA_VERSION | "ea" | "bin/java" | "" + "linux" | "x64" | VENDOR_OPENJDK | CATALOG_EA_VERSION | "ea" | "bin/java" | "" + "darwin" | "aarch64" | VENDOR_OPENJDK | CATALOG_EA_VERSION | "ea" | "Contents/Home/bin/java" | "" + "darwin" | "x64" | VENDOR_OPENJDK | CATALOG_EA_VERSION | "ea" | "Contents/Home/bin/java" | "" + "windows" | "x64" | VENDOR_OPENJDK | CATALOG_EA_VERSION | "ea" | "bin/java" | "" + "linux" | "x64" | VENDOR_ADOPTIUM | ADOPT_JDK_VERSION | "" | "bin/java" | "" + "linux" | "x64" | VENDOR_OPENJDK | OPEN_JDK_VERSION | "" | "bin/java" | "" + "linux" | "x64" | VENDOR_OPENJDK | OPENJDK_VERSION_OLD | "" | "bin/java" | "(old version)" + "windows" | "x64" | VENDOR_ADOPTIUM | ADOPT_JDK_VERSION | "" | "bin/java" | "" + "windows" | "x64" | VENDOR_OPENJDK | OPEN_JDK_VERSION | "" | "bin/java" | "" + "windows" | "x64" | VENDOR_OPENJDK | OPENJDK_VERSION_OLD | "" | "bin/java" | "(old version)" + "darwin" | "x64" | VENDOR_ADOPTIUM | ADOPT_JDK_VERSION | "" | "Contents/Home/bin/java" | "" + "darwin" | "x64" | VENDOR_OPENJDK | OPEN_JDK_VERSION | "" | "Contents/Home/bin/java" | "" + "darwin" | "x64" | VENDOR_OPENJDK | OPENJDK_VERSION_OLD | "" | "Contents/Home/bin/java" | "(old version)" + "mac" | "x64" | VENDOR_OPENJDK | OPEN_JDK_VERSION | "" | "Contents/Home/bin/java" | "" + "mac" | "x64" | VENDOR_OPENJDK | OPENJDK_VERSION_OLD | "" | "Contents/Home/bin/java" | "(old version)" + "darwin" | "aarch64" | VENDOR_ADOPTIUM | ADOPT_JDK_VERSION | "" | "Contents/Home/bin/java" | "" + "linux" | "aarch64" | VENDOR_ADOPTIUM | ADOPT_JDK_VERSION | "" | "bin/java" | "" + "linux" | "aarch64" | VENDOR_ADOPTIUM | ADOPT_JDK_VERSION_11 | "" | "bin/java" | "(jdk 11)" + "linux" | "aarch64" | VENDOR_ADOPTIUM | ADOPT_JDK_VERSION_15 | "" | "bin/java" | "(jdk 15)" + "darwin" | "aarch64" | VENDOR_ZULU | AZUL_JDK_VERSION_8 | AZUL_8_DISTRO_VERSION | "Contents/Home/bin/java" | "(jdk 8)" } def "transforms are reused across projects"() { @@ -211,13 +221,19 @@ class JdkDownloadPluginFuncTest extends AbstractGradleFuncTest { private static String urlPath(final String vendor, final String version, final String platform, - final String arch = 'x64') { - if (vendor.equals(VENDOR_ADOPTIUM)) { + final String arch = 'x64', + final String distributedVersion = '') { + final boolean isOld = version.equals(OPENJDK_VERSION_OLD); + + if (distributedVersion.equals("ea")) { + def effectivePlatform = isMac(platform) ? "macos" : platform; + def fileExtension = platform.toLowerCase().equals("windows") ? "zip" : "tar.gz"; + return "/jdks/openjdk/25/openjdk-${version}/openjdk-${version}_$effectivePlatform-${arch}_bin.$fileExtension"; + } else if (vendor.equals(VENDOR_ADOPTIUM)) { final String module = isMac(platform) ? "mac" : platform; return "/jdk-" + version + "/" + module + "/${arch}/jdk/hotspot/normal/adoptium"; } else if (vendor.equals(VENDOR_OPENJDK)) { final String effectivePlatform = isMac(platform) ? "macos" : platform; - final boolean isOld = version.equals(OPENJDK_VERSION_OLD); final String versionPath = isOld ? "jdk1/99" : "jdk12.0.1/123456789123456789123456789abcde/99"; final String filename = "openjdk-" + (isOld ? "1" : "12.0.1") + "_" + effectivePlatform + "-x64_bin." + extension(platform); return "/java/GA/" + versionPath + "/GPL/" + filename; diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/Jdk.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/Jdk.java index c70d421939d6d..8abdf011135b2 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/Jdk.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/Jdk.java @@ -31,6 +31,7 @@ public class Jdk implements Buildable, Iterable { "(\\d+)(\\.\\d+\\.\\d+(?:\\.\\d+)?)?\\+(\\d+(?:\\.\\d+)?)(@([a-f0-9]{32}))?" ); private static final Pattern LEGACY_VERSION_PATTERN = Pattern.compile("(\\d)(u\\d+)\\+(b\\d+?)(@([a-f0-9]{32}))?"); + private static final Pattern EA_VERSION_PATTERN = Pattern.compile("(\\d+)-ea\\+(\\d+)(@([a-f0-9]{32}))?"); private final String name; private final Configuration configuration; @@ -75,7 +76,9 @@ public String getVersion() { } public void setVersion(String version) { - if (VERSION_PATTERN.matcher(version).matches() == false && LEGACY_VERSION_PATTERN.matcher(version).matches() == false) { + if (VERSION_PATTERN.matcher(version).matches() == false + && LEGACY_VERSION_PATTERN.matcher(version).matches() == false + && EA_VERSION_PATTERN.matcher(version).matches() == false) { throw new IllegalArgumentException("malformed version [" + version + "] for jdk [" + name + "]"); } parseVersion(version); @@ -109,7 +112,7 @@ public void setArchitecture(final String architecture) { } public String getDistributionVersion() { - return distributionVersion.get(); + return distributionVersion.getOrNull(); } public void setDistributionVersion(String distributionVersion) { @@ -215,9 +218,17 @@ private void parseVersion(String version) { if (jdkVersionMatcher.matches() == false) { // Try again with the pre-Java9 version format jdkVersionMatcher = LEGACY_VERSION_PATTERN.matcher(version); - if (jdkVersionMatcher.matches() == false) { - throw new IllegalArgumentException("Malformed jdk version [" + version + "]"); + // Try again with the pre-Java9 version format + jdkVersionMatcher = EA_VERSION_PATTERN.matcher(version); + if (jdkVersionMatcher.matches() == false) { + throw new IllegalArgumentException("Malformed jdk version [" + version + "]"); + } + baseVersion = version; + major = jdkVersionMatcher.group(1); + build = jdkVersionMatcher.group(2); + hash = null; + return; } } diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/JdkDownloadPlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/JdkDownloadPlugin.java index 5b195cad3388f..b4f84f4aac979 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/JdkDownloadPlugin.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/JdkDownloadPlugin.java @@ -115,6 +115,15 @@ private void setupRepository(Project project, Jdk jdk) { + jdk.getBuild() + "/[module]/[classifier]/jdk/hotspot/normal/adoptium"; } + } else if (jdk.getVendor().equals(VENDOR_OPENJDK) && "ea".equals(jdk.getDistributionVersion())) { + repoUrl = "https://builds.es-jdk-archive.com/"; + // current pattern since 12.0.1 + artifactPattern = "jdks/openjdk/" + + jdk.getMajor() + + "/openjdk-" + + jdk.getBaseVersion() + + "/" + + "openjdk-[revision]_[module]-[classifier]_bin.[ext]"; } else if (jdk.getVendor().equals(VENDOR_OPENJDK)) { repoUrl = "https://download.oracle.com"; if (jdk.getHash() != null) { diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/info/GlobalBuildInfoPlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/info/GlobalBuildInfoPlugin.java index c680d65955873..ff7baf7310194 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/info/GlobalBuildInfoPlugin.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/info/GlobalBuildInfoPlugin.java @@ -12,8 +12,12 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.io.IOUtils; +import org.elasticsearch.gradle.Architecture; +import org.elasticsearch.gradle.OS; import org.elasticsearch.gradle.VersionProperties; import org.elasticsearch.gradle.internal.BwcVersions; +import org.elasticsearch.gradle.internal.Jdk; +import org.elasticsearch.gradle.internal.JdkDownloadPlugin; import org.elasticsearch.gradle.internal.conventions.GitInfoPlugin; import org.elasticsearch.gradle.internal.conventions.info.GitInfo; import org.elasticsearch.gradle.internal.conventions.info.ParallelDetector; @@ -22,6 +26,7 @@ import org.gradle.api.Action; import org.gradle.api.GradleException; import org.gradle.api.JavaVersion; +import org.gradle.api.NamedDomainObjectContainer; import org.gradle.api.Plugin; import org.gradle.api.Project; import org.gradle.api.logging.Logger; @@ -63,6 +68,7 @@ import javax.inject.Inject; import static org.elasticsearch.gradle.internal.conventions.GUtils.elvis; +import static org.elasticsearch.gradle.internal.toolchain.EarlyAccessCatalogJdkToolchainResolver.findLatestEABuildNumber; public class GlobalBuildInfoPlugin implements Plugin { private static final Logger LOGGER = Logging.getLogger(GlobalBuildInfoPlugin.class); @@ -92,11 +98,13 @@ public GlobalBuildInfoPlugin( @Override public void apply(Project project) { + if (project != project.getRootProject()) { throw new IllegalStateException(this.getClass().getName() + " can only be applied to the root project."); } this.project = project; project.getPlugins().apply(JvmToolchainsPlugin.class); + project.getPlugins().apply(JdkDownloadPlugin.class); Provider gitInfo = project.getPlugins().apply(GitInfoPlugin.class).getGitInfo(); toolChainService = project.getExtensions().getByType(JavaToolchainService.class); @@ -277,7 +285,9 @@ private JavaVersion determineJavaVersion(String description, File javaHome, Java private InstallationLocation getJavaInstallation(File javaHome) { return getAvailableJavaInstallationLocationSteam().filter(installationLocation -> isSameFile(javaHome, installationLocation)) .findFirst() - .orElseThrow(() -> new GradleException("Could not locate available Java installation in Gradle registry at: " + javaHome)); + .orElse( + InstallationLocation.userDefined(javaHome, "Manually resolved JavaHome (not auto-detected by Gradle toolchain service)") + ); } private boolean isSameFile(File javaHome, InstallationLocation installationLocation) { @@ -345,7 +355,14 @@ private Provider findRuntimeJavaHome() { String runtimeJavaProperty = System.getProperty("runtime.java"); if (runtimeJavaProperty != null) { - return resolveJavaHomeFromToolChainService(runtimeJavaProperty); + if (runtimeJavaProperty.toLowerCase().endsWith("-ea")) { + // handle EA builds differently due to lack of support in Gradle toolchain service + // we resolve them using JdkDownloadPlugin for now. + Integer major = Integer.parseInt(runtimeJavaProperty.substring(0, runtimeJavaProperty.length() - 3)); + return resolveEarlyAccessJavaHome(major); + } else { + return resolveJavaHomeFromToolChainService(runtimeJavaProperty); + } } if (System.getenv("RUNTIME_JAVA_HOME") != null) { return providers.provider(() -> new File(System.getenv("RUNTIME_JAVA_HOME"))); @@ -360,6 +377,23 @@ private Provider findRuntimeJavaHome() { }); } + private Provider resolveEarlyAccessJavaHome(Integer runtimeJavaProperty) { + NamedDomainObjectContainer container = (NamedDomainObjectContainer) project.getExtensions().getByName("jdks"); + Integer buildNumber = Integer.getInteger("runtime.java.build"); + if (buildNumber == null) { + buildNumber = findLatestEABuildNumber(runtimeJavaProperty); + } + String eaVersionString = String.format("%d-ea+%d", runtimeJavaProperty, buildNumber); + Jdk jdk = container.create("ea_jdk_" + runtimeJavaProperty, j -> { + j.setVersion(eaVersionString); + j.setVendor("openjdk"); + j.setPlatform(OS.current().javaOsReference); + j.setArchitecture(Architecture.current().javaClassifier); + j.setDistributionVersion("ea"); + }); + return providers.provider(() -> new File(jdk.getJavaHomePath().toString())); + } + @NotNull private Provider resolveJavaHomeFromToolChainService(String version) { Property value = objectFactory.property(JavaLanguageVersion.class).value(JavaLanguageVersion.of(version)); diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/toolchain/EarlyAccessCatalogJdkToolchainResolver.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/toolchain/EarlyAccessCatalogJdkToolchainResolver.java new file mode 100644 index 0000000000000..dace087b05842 --- /dev/null +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/toolchain/EarlyAccessCatalogJdkToolchainResolver.java @@ -0,0 +1,160 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.gradle.internal.toolchain; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; + +import org.elasticsearch.gradle.VersionProperties; +import org.gradle.jvm.toolchain.JavaLanguageVersion; +import org.gradle.jvm.toolchain.JavaToolchainDownload; +import org.gradle.jvm.toolchain.JavaToolchainRequest; +import org.gradle.jvm.toolchain.JavaToolchainSpec; +import org.gradle.platform.Architecture; +import org.gradle.platform.BuildPlatform; +import org.gradle.platform.OperatingSystem; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +/** + * A toolchain resolver that resolves early access JDKs from the Elasticsearch JDK archive. + *

+ * This resolver can used to resolve JDKs that are not bundled with Elasticsearch but are available in the early access catalog. + * It supports resolving JDKs based on their language version and build number. + * + * Currently the gradle toolchain support does not support querying specific versions (e.g. 26-ea+6) so. For now + * this only supports resolving the latest early access build for a given language version. + *

+ */ +public abstract class EarlyAccessCatalogJdkToolchainResolver extends AbstractCustomJavaToolchainResolver { + + interface JdkBuild { + JavaLanguageVersion languageVersion(); + + String url(String os, String arch, String extension); + } + + @FunctionalInterface + interface EarlyAccessJdkBuildResolver { + Optional findLatestEABuild(JavaLanguageVersion languageVersion); + } + + // allow overriding for testing + EarlyAccessJdkBuildResolver earlyAccessJdkBuildResolver = (languageVersion) -> findLatestEABuild(languageVersion); + + record EarlyAccessJdkBuild(JavaLanguageVersion languageVersion, int buildNumber) implements JdkBuild { + @Override + public String url(String os, String arch, String extension) { + // example: + // https://builds.es-jdk-archive.com/jdks/openjdk/26/openjdk-26-ea+6/openjdk-26-ea+6_linux-aarch64_bin.tar.gz + return "https://builds.es-jdk-archive.com/jdks/openjdk/" + + languageVersion.asInt() + + "/" + + "openjdk-" + + languageVersion.asInt() + + "-ea+" + + buildNumber + + "/" + + "openjdk-" + + languageVersion.asInt() + + "-ea+" + + buildNumber + + "_" + + os + + "-" + + arch + + "_bin." + + extension; + } + } + + private static final List supportedOperatingSystems = List.of( + OperatingSystem.MAC_OS, + OperatingSystem.LINUX, + OperatingSystem.WINDOWS + ); + + /** + * We need some place to map JavaLanguageVersion to buildNumber, minor version etc. + * */ + @Override + public Optional resolve(JavaToolchainRequest request) { + if (Integer.parseInt(VersionProperties.getBundledJdkMajorVersion()) >= request.getJavaToolchainSpec() + .getLanguageVersion() + .get() + .asInt()) { + // This resolver only handles early access builds, that are beyond the last bundled jdk version + } + return findSupportedBuild(request).map(build -> { + OperatingSystem operatingSystem = request.getBuildPlatform().getOperatingSystem(); + String extension = operatingSystem.equals(OperatingSystem.WINDOWS) ? "zip" : "tar.gz"; + String arch = toArchString(request.getBuildPlatform().getArchitecture()); + String os = toOsString(operatingSystem); + return (JavaToolchainDownload) () -> URI.create(build.url(os, arch, extension)); + }); + } + + /** + * Check if request can be full-filled by this resolver: + * 1. Aarch64 windows images are not supported + */ + private Optional findSupportedBuild(JavaToolchainRequest request) { + JavaToolchainSpec javaToolchainSpec = request.getJavaToolchainSpec(); + BuildPlatform buildPlatform = request.getBuildPlatform(); + Architecture architecture = buildPlatform.getArchitecture(); + OperatingSystem operatingSystem = buildPlatform.getOperatingSystem(); + + if (supportedOperatingSystems.contains(operatingSystem) == false + || Architecture.AARCH64 == architecture && OperatingSystem.WINDOWS == operatingSystem) { + return Optional.empty(); + } + + JavaLanguageVersion languageVersion = javaToolchainSpec.getLanguageVersion().get(); + return earlyAccessJdkBuildResolver.findLatestEABuild(languageVersion); + } + + private static Optional findLatestEABuild(JavaLanguageVersion languageVersion) { + try { + URL url = new URL("https://storage.googleapis.com/elasticsearch-jdk-archive/jdks/openjdk/latest.json"); + try (InputStream is = url.openStream()) { + ObjectMapper mapper = new ObjectMapper(); + JsonNode node = mapper.readTree(is); + ArrayNode buildsNode = (ArrayNode) node.get("builds"); + List buildsList = new ArrayList<>(); + buildsNode.forEach(buildsList::add); + List eaBuilds = buildsList.stream() + .map( + n -> new EarlyAccessJdkBuild( + JavaLanguageVersion.of(n.get("major").asText()), + Integer.parseInt(n.get("build").asText()) + ) + ) + .toList(); + return eaBuilds.stream().filter(ea -> ea.languageVersion().equals(languageVersion)).findFirst(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } catch (MalformedURLException e) { + return Optional.empty(); + } + } + + public static int findLatestEABuildNumber(int languageVersion) { + return findLatestEABuild(JavaLanguageVersion.of(languageVersion)).map(ea -> ea.buildNumber()).get(); + } +} diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/toolchain/JavaToolChainResolverPlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/toolchain/JavaToolChainResolverPlugin.java index b89eb87325754..1cacbb38fdd5d 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/toolchain/JavaToolChainResolverPlugin.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/toolchain/JavaToolChainResolverPlugin.java @@ -23,6 +23,7 @@ public void apply(Settings settings) { settings.getPlugins().apply("jvm-toolchain-management"); JavaToolchainResolverRegistry registry = getToolchainResolverRegistry(); registry.register(OracleOpenJdkToolchainResolver.class); + registry.register(EarlyAccessCatalogJdkToolchainResolver.class); registry.register(AdoptiumJdkToolchainResolver.class); registry.register(ArchivedOracleJdkToolchainResolver.class); } diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/toolchain/OracleOpenJdkToolchainResolver.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/toolchain/OracleOpenJdkToolchainResolver.java index dbf60e1b4f4d8..a0036529ad6fe 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/toolchain/OracleOpenJdkToolchainResolver.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/toolchain/OracleOpenJdkToolchainResolver.java @@ -58,32 +58,6 @@ public String url(String os, String arch, String extension) { } } - record EarlyAccessJdkBuild(JavaLanguageVersion languageVersion, String buildNumber) implements JdkBuild { - @Override - public String url(String os, String arch, String extension) { - // example: - // https://builds.es-jdk-archive.com/jdks/openjdk/26/openjdk-26-ea+6/openjdk-26-ea+6_linux-aarch64_bin.tar.gz - return "https://builds.es-jdk-archive.com/jdks/openjdk/" - + languageVersion.asInt() - + "/" - + "openjdk-" - + languageVersion.asInt() - + "-ea+" - + buildNumber - + "/" - + "openjdk-" - + languageVersion.asInt() - + "-ea+" - + buildNumber - + "_" - + os - + "-" - + arch - + "_bin." - + extension; - } - } - private static final Pattern VERSION_PATTERN = Pattern.compile( "(\\d+)(\\.\\d+\\.\\d+(?:\\.\\d+)?)?\\+(\\d+(?:\\.\\d+)?)(@([a-f0-9]{32}))?" ); @@ -96,18 +70,9 @@ public String url(String os, String arch, String extension) { // package private so it can be replaced by tests List builds = List.of( - getBundledJdkBuild(VersionProperties.getBundledJdkVersion(), VersionProperties.getBundledJdkMajorVersion()), - getEarlyAccessBuild(JavaLanguageVersion.of(25), "3") + getBundledJdkBuild(VersionProperties.getBundledJdkVersion(), VersionProperties.getBundledJdkMajorVersion()) ); - static EarlyAccessJdkBuild getEarlyAccessBuild(JavaLanguageVersion languageVersion, String buildNumber) { - // first try the unversioned override, then the versioned override which has higher precedence - buildNumber = System.getProperty("runtime.java.build", buildNumber); - buildNumber = System.getProperty("runtime.java." + languageVersion.asInt() + ".build", buildNumber); - - return new EarlyAccessJdkBuild(languageVersion, buildNumber); - } - static JdkBuild getBundledJdkBuild(String bundledJdkVersion, String bundledJkdMajorVersionString) { JavaLanguageVersion bundledJdkMajorVersion = JavaLanguageVersion.of(bundledJkdMajorVersionString); Matcher jdkVersionMatcher = VERSION_PATTERN.matcher(bundledJdkVersion); diff --git a/build-tools-internal/src/test/groovy/org/elasticsearch/gradle/internal/JdkSpec.groovy b/build-tools-internal/src/test/groovy/org/elasticsearch/gradle/internal/JdkSpec.groovy new file mode 100644 index 0000000000000..72aebda2e0b80 --- /dev/null +++ b/build-tools-internal/src/test/groovy/org/elasticsearch/gradle/internal/JdkSpec.groovy @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.gradle.internal + +import spock.lang.Specification + +import org.gradle.api.artifacts.Configuration +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property + +class JdkSpec extends Specification { + + def "jdk version is parsed correctly"() { + given: + Jdk jdk = newJdk() + + when: + jdk.setVersion(version) + then: + jdk.getBaseVersion() == baseVersion + jdk.getBuild() == buildNumber + + where: + version | baseVersion | major | buildNumber + "25-ea+30" | "25-ea+30" | "25" | "30" + "26-ea+6" | "26-ea+6" | "26" | "6" + } + + Object newJdk(String name = "jdk") { + Configuration configuration = Mock() + _ * configuration.getName() >> name + "Config" + + ObjectFactory objectFactory = Mock() + Property stringProperty = Mock() + _ * objectFactory.property(String.class) >> stringProperty + + return new Jdk(name, configuration, objectFactory) + } +} diff --git a/build-tools-internal/src/test/groovy/org/elasticsearch/gradle/internal/toolchain/AbstractToolchainResolverSpec.groovy b/build-tools-internal/src/test/groovy/org/elasticsearch/gradle/internal/toolchain/AbstractToolchainResolverSpec.groovy index cea96437129a6..05372f25a4981 100644 --- a/build-tools-internal/src/test/groovy/org/elasticsearch/gradle/internal/toolchain/AbstractToolchainResolverSpec.groovy +++ b/build-tools-internal/src/test/groovy/org/elasticsearch/gradle/internal/toolchain/AbstractToolchainResolverSpec.groovy @@ -73,6 +73,7 @@ abstract class AbstractToolchainResolverSpec extends Specification { _ * languageVersionProperty.get() >> languageVersion Property vendorSpecProperty = Mock() + _ * vendorSpecProperty.isPresent() >> true _ * vendorSpecProperty.get() >> vendorSpec _ * toolchainSpec.getVendor() >> vendorSpecProperty diff --git a/build-tools-internal/src/test/groovy/org/elasticsearch/gradle/internal/toolchain/AdoptiumJdkToolchainResolverSpec.groovy b/build-tools-internal/src/test/groovy/org/elasticsearch/gradle/internal/toolchain/AdoptiumJdkToolchainResolverSpec.groovy index 5abb78b062c39..f26c9c46d52b3 100644 --- a/build-tools-internal/src/test/groovy/org/elasticsearch/gradle/internal/toolchain/AdoptiumJdkToolchainResolverSpec.groovy +++ b/build-tools-internal/src/test/groovy/org/elasticsearch/gradle/internal/toolchain/AdoptiumJdkToolchainResolverSpec.groovy @@ -47,7 +47,7 @@ class AdoptiumJdkToolchainResolverSpec extends AbstractToolchainResolverSpec { @Override def supportedRequests() { return [ - [19, ADOPTIUM, MAC_OS, X86_64, "https://api.adoptium.net/v3/binary/version/jdk-19.1.1.1+37.1/mac/x64/jdk/hotspot/normal/eclipse?project=jdk"], + [19, ADOPTIUM, LINUX, X86_64, "https://api.adoptium.net/v3/binary/version/jdk-19.1.1.1+37.1/linux/x64/jdk/hotspot/normal/eclipse?project=jdk"], [19, ADOPTIUM, WINDOWS, X86_64, "https://api.adoptium.net/v3/binary/version/jdk-19.1.1.1+37.1/windows/x64/jdk/hotspot/normal/eclipse?project=jdk"], [19, ADOPTIUM, MAC_OS, AARCH64, "https://api.adoptium.net/v3/binary/version/jdk-19.1.1.1+37.1/mac/aarch64/jdk/hotspot/normal/eclipse?project=jdk"], diff --git a/build-tools-internal/src/test/groovy/org/elasticsearch/gradle/internal/toolchain/EarlyAccessCatalogJdkToolchainResolverSpec.groovy b/build-tools-internal/src/test/groovy/org/elasticsearch/gradle/internal/toolchain/EarlyAccessCatalogJdkToolchainResolverSpec.groovy new file mode 100644 index 0000000000000..aaf71c41e5087 --- /dev/null +++ b/build-tools-internal/src/test/groovy/org/elasticsearch/gradle/internal/toolchain/EarlyAccessCatalogJdkToolchainResolverSpec.groovy @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.gradle.internal.toolchain + +import org.elasticsearch.gradle.VersionProperties +import org.gradle.api.services.BuildServiceParameters +import org.gradle.jvm.toolchain.JavaLanguageVersion +import org.gradle.jvm.toolchain.JavaToolchainResolver +import org.gradle.jvm.toolchain.JvmVendorSpec + +import static org.gradle.platform.Architecture.AARCH64 +import static org.gradle.platform.Architecture.X86_64 +import static org.gradle.platform.OperatingSystem.* + +class EarlyAccessCatalogJdkToolchainResolverSpec extends AbstractToolchainResolverSpec { + @Override + JavaToolchainResolver resolverImplementation() { + def resolver = new EarlyAccessCatalogJdkToolchainResolver() { + @Override + BuildServiceParameters.None getParameters() { + return null + } + } + resolver.earlyAccessJdkBuildResolver = (JavaLanguageVersion version) -> { + return Optional.of( + new EarlyAccessCatalogJdkToolchainResolver.EarlyAccessJdkBuild(version, 30) + ) + } + return resolver + } + + @Override + def supportedRequests() { + return [ + [25, anyVendor(), LINUX, X86_64, "https://builds.es-jdk-archive.com/jdks/openjdk/25/openjdk-25-ea+30/openjdk-25-ea+30_linux-x64_bin.tar.gz"], + [25, anyVendor(), LINUX, AARCH64, "https://builds.es-jdk-archive.com/jdks/openjdk/25/openjdk-25-ea+30/openjdk-25-ea+30_linux-aarch64_bin.tar.gz"], + [25, anyVendor(), MAC_OS, X86_64, "https://builds.es-jdk-archive.com/jdks/openjdk/25/openjdk-25-ea+30/openjdk-25-ea+30_macos-x64_bin.tar.gz"], + [25, anyVendor(), MAC_OS, AARCH64, "https://builds.es-jdk-archive.com/jdks/openjdk/25/openjdk-25-ea+30/openjdk-25-ea+30_macos-aarch64_bin.tar.gz"], + [25, anyVendor(), WINDOWS, X86_64, "https://builds.es-jdk-archive.com/jdks/openjdk/25/openjdk-25-ea+30/openjdk-25-ea+30_windows-x64_bin.zip"], + + [26, anyVendor(), LINUX, X86_64, "https://builds.es-jdk-archive.com/jdks/openjdk/26/openjdk-26-ea+30/openjdk-26-ea+30_linux-x64_bin.tar.gz"], + [26, anyVendor(), LINUX, AARCH64, "https://builds.es-jdk-archive.com/jdks/openjdk/26/openjdk-26-ea+30/openjdk-26-ea+30_linux-aarch64_bin.tar.gz"], + [26, anyVendor(), MAC_OS, X86_64, "https://builds.es-jdk-archive.com/jdks/openjdk/26/openjdk-26-ea+30/openjdk-26-ea+30_macos-x64_bin.tar.gz"], + [26, anyVendor(), MAC_OS, AARCH64, "https://builds.es-jdk-archive.com/jdks/openjdk/26/openjdk-26-ea+30/openjdk-26-ea+30_macos-aarch64_bin.tar.gz"], + [26, anyVendor(), WINDOWS, X86_64, "https://builds.es-jdk-archive.com/jdks/openjdk/26/openjdk-26-ea+30/openjdk-26-ea+30_windows-x64_bin.zip"] + ] + } + + @Override + def unsupportedRequests() { + [ + [Integer.parseInt(VersionProperties.bundledJdkMajorVersion) + 1, anyVendor(), WINDOWS, AARCH64], + ] + } +} diff --git a/build-tools-internal/src/test/groovy/org/elasticsearch/gradle/internal/toolchain/OracleOpenJdkToolchainResolverSpec.groovy b/build-tools-internal/src/test/groovy/org/elasticsearch/gradle/internal/toolchain/OracleOpenJdkToolchainResolverSpec.groovy index df9f70d0a47f6..5520358631e04 100644 --- a/build-tools-internal/src/test/groovy/org/elasticsearch/gradle/internal/toolchain/OracleOpenJdkToolchainResolverSpec.groovy +++ b/build-tools-internal/src/test/groovy/org/elasticsearch/gradle/internal/toolchain/OracleOpenJdkToolchainResolverSpec.groovy @@ -9,11 +9,9 @@ package org.elasticsearch.gradle.internal.toolchain -import spock.util.environment.RestoreSystemProperties import org.gradle.api.services.BuildServiceParameters import org.gradle.jvm.toolchain.JavaLanguageVersion -import org.gradle.jvm.toolchain.JavaToolchainDownload import static org.gradle.jvm.toolchain.JvmVendorSpec.ORACLE import static org.gradle.platform.Architecture.AARCH64 @@ -22,7 +20,6 @@ import static org.gradle.platform.OperatingSystem.* class OracleOpenJdkToolchainResolverSpec extends AbstractToolchainResolverSpec { - OracleOpenJdkToolchainResolver resolverImplementation() { var toolChain = new OracleOpenJdkToolchainResolver() { @Override @@ -39,7 +36,6 @@ class OracleOpenJdkToolchainResolverSpec extends AbstractToolchainResolverSpec { "bdc68b4b9cbc4ebcb30745c85038d91d" ), OracleOpenJdkToolchainResolver.getBundledJdkBuild("24+36@1f9ff9062db4449d8ca828c504ffae90", "24"), - OracleOpenJdkToolchainResolver.getEarlyAccessBuild(JavaLanguageVersion.of(25), "3") ] toolChain } @@ -65,51 +61,8 @@ class OracleOpenJdkToolchainResolverSpec extends AbstractToolchainResolverSpec { [24, anyVendor(), MAC_OS, AARCH64, "https://download.oracle.com/java/GA/jdk24/1f9ff9062db4449d8ca828c504ffae90/36/GPL/openjdk-24_macos-aarch64_bin.tar.gz"], [24, anyVendor(), LINUX, X86_64, "https://download.oracle.com/java/GA/jdk24/1f9ff9062db4449d8ca828c504ffae90/36/GPL/openjdk-24_linux-x64_bin.tar.gz"], [24, anyVendor(), LINUX, AARCH64, "https://download.oracle.com/java/GA/jdk24/1f9ff9062db4449d8ca828c504ffae90/36/GPL/openjdk-24_linux-aarch64_bin.tar.gz"], - [24, anyVendor(), WINDOWS, X86_64, "https://download.oracle.com/java/GA/jdk24/1f9ff9062db4449d8ca828c504ffae90/36/GPL/openjdk-24_windows-x64_bin.zip"], - // EA build - [25, ORACLE, MAC_OS, X86_64, "https://builds.es-jdk-archive.com/jdks/openjdk/25/openjdk-25-ea+3/openjdk-25-ea+3_macos-x64_bin.tar.gz"], - [25, ORACLE, MAC_OS, AARCH64, "https://builds.es-jdk-archive.com/jdks/openjdk/25/openjdk-25-ea+3/openjdk-25-ea+3_macos-aarch64_bin.tar.gz"], - [25, ORACLE, LINUX, X86_64, "https://builds.es-jdk-archive.com/jdks/openjdk/25/openjdk-25-ea+3/openjdk-25-ea+3_linux-x64_bin.tar.gz"], - [25, ORACLE, LINUX, AARCH64, "https://builds.es-jdk-archive.com/jdks/openjdk/25/openjdk-25-ea+3/openjdk-25-ea+3_linux-aarch64_bin.tar.gz"], - [25, ORACLE, WINDOWS, X86_64, "https://builds.es-jdk-archive.com/jdks/openjdk/25/openjdk-25-ea+3/openjdk-25-ea+3_windows-x64_bin.zip"], - [25, anyVendor(), MAC_OS, X86_64, "https://builds.es-jdk-archive.com/jdks/openjdk/25/openjdk-25-ea+3/openjdk-25-ea+3_macos-x64_bin.tar.gz"], - [25, anyVendor(), MAC_OS, AARCH64, "https://builds.es-jdk-archive.com/jdks/openjdk/25/openjdk-25-ea+3/openjdk-25-ea+3_macos-aarch64_bin.tar.gz"], - [25, anyVendor(), LINUX, X86_64, "https://builds.es-jdk-archive.com/jdks/openjdk/25/openjdk-25-ea+3/openjdk-25-ea+3_linux-x64_bin.tar.gz"], - [25, anyVendor(), LINUX, AARCH64, "https://builds.es-jdk-archive.com/jdks/openjdk/25/openjdk-25-ea+3/openjdk-25-ea+3_linux-aarch64_bin.tar.gz"], - [25, anyVendor(), WINDOWS, X86_64, "https://builds.es-jdk-archive.com/jdks/openjdk/25/openjdk-25-ea+3/openjdk-25-ea+3_windows-x64_bin.zip"]] - } - - @RestoreSystemProperties - def "can provide build number for ea versions"() { - given: - System.setProperty('runtime.java.build', "42") - System.setProperty('runtime.java.25.build', "13") - def resolver = resolverImplementation() - - when: - Optional download = resolver.resolve( - request( - JavaLanguageVersion.of(version), - vendor, - platform(os, arch) - ) - ) - - then: - download.get().uri == URI.create(expectedUrl) - - where: - version | vendor | os | arch | expectedUrl - 25 | ORACLE | MAC_OS | X86_64 | urlPrefix(25) + "openjdk-25-ea+13/openjdk-25-ea+13_macos-x64_bin.tar.gz" - 25 | ORACLE | MAC_OS | AARCH64 | urlPrefix(25) + "openjdk-25-ea+13/openjdk-25-ea+13_macos-aarch64_bin.tar.gz" - 25 | ORACLE | LINUX | X86_64 | urlPrefix(25) + "openjdk-25-ea+13/openjdk-25-ea+13_linux-x64_bin.tar.gz" - 25 | ORACLE | LINUX | AARCH64 | urlPrefix(25) + "openjdk-25-ea+13/openjdk-25-ea+13_linux-aarch64_bin.tar.gz" - 25 | ORACLE | WINDOWS | X86_64 | urlPrefix(25) + "openjdk-25-ea+13/openjdk-25-ea+13_windows-x64_bin.zip" - 25 | anyVendor() | MAC_OS | X86_64 | urlPrefix(25) + "openjdk-25-ea+13/openjdk-25-ea+13_macos-x64_bin.tar.gz" - 25 | anyVendor() | MAC_OS | AARCH64 | urlPrefix(25) + "openjdk-25-ea+13/openjdk-25-ea+13_macos-aarch64_bin.tar.gz" - 25 | anyVendor() | LINUX | X86_64 | urlPrefix(25) + "openjdk-25-ea+13/openjdk-25-ea+13_linux-x64_bin.tar.gz" - 25 | anyVendor() | LINUX | AARCH64 | urlPrefix(25) + "openjdk-25-ea+13/openjdk-25-ea+13_linux-aarch64_bin.tar.gz" - 25 | anyVendor() | WINDOWS | X86_64 | urlPrefix(25) + "openjdk-25-ea+13/openjdk-25-ea+13_windows-x64_bin.zip" + [24, anyVendor(), WINDOWS, X86_64, "https://download.oracle.com/java/GA/jdk24/1f9ff9062db4449d8ca828c504ffae90/36/GPL/openjdk-24_windows-x64_bin.zip"] + ] } private static String urlPrefix(int i) { diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/Architecture.java b/build-tools/src/main/java/org/elasticsearch/gradle/Architecture.java index ae47f934b0dc3..c2654f9ae851f 100644 --- a/build-tools/src/main/java/org/elasticsearch/gradle/Architecture.java +++ b/build-tools/src/main/java/org/elasticsearch/gradle/Architecture.java @@ -11,17 +11,19 @@ public enum Architecture { - X64("x86_64", "linux/amd64", "amd64"), - AARCH64("aarch64", "linux/arm64", "arm64"); + X64("x86_64", "linux/amd64", "amd64", "x64"), + AARCH64("aarch64", "linux/arm64", "arm64", "aarch64"); public final String classifier; public final String dockerPlatform; public final String dockerClassifier; + public final String javaClassifier; - Architecture(String classifier, String dockerPlatform, String dockerClassifier) { + Architecture(String classifier, String dockerPlatform, String dockerClassifier, String javaClassifier) { this.classifier = classifier; this.dockerPlatform = dockerPlatform; this.dockerClassifier = dockerClassifier; + this.javaClassifier = javaClassifier; } public static Architecture current() { diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/DistributionDownloadPlugin.java b/build-tools/src/main/java/org/elasticsearch/gradle/DistributionDownloadPlugin.java index 4c7290457e7df..3e9b42995a9c8 100644 --- a/build-tools/src/main/java/org/elasticsearch/gradle/DistributionDownloadPlugin.java +++ b/build-tools/src/main/java/org/elasticsearch/gradle/DistributionDownloadPlugin.java @@ -188,10 +188,12 @@ private static void addIvyRepo(Project project, String name, String url, String repo.metadataSources(IvyArtifactRepository.MetadataSources::artifact); repo.patternLayout(layout -> layout.artifact("/downloads/elasticsearch/[module]-[revision](-[classifier]).[ext]")); }); - project.getRepositories().exclusiveContent(exclusiveContentRepository -> { - exclusiveContentRepository.filter(config -> config.includeGroup(group)); - exclusiveContentRepository.forRepositories(ivyRepo); - }); + if (project != project.getRootProject()) { + project.getRepositories().exclusiveContent(exclusiveContentRepository -> { + exclusiveContentRepository.filter(config -> config.includeGroup(group)); + exclusiveContentRepository.forRepositories(ivyRepo); + }); + } } private static void setupDownloadServiceRepo(Project project) { diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/OS.java b/build-tools/src/main/java/org/elasticsearch/gradle/OS.java index d5649f94cf1a4..fda24687ad4e8 100644 --- a/build-tools/src/main/java/org/elasticsearch/gradle/OS.java +++ b/build-tools/src/main/java/org/elasticsearch/gradle/OS.java @@ -15,9 +15,16 @@ import java.util.function.Supplier; public enum OS { - WINDOWS, - MAC, - LINUX; + WINDOWS("windows"), + MAC("darwin"), + LINUX("linux"); + + public final String javaOsReference; + + OS(String javaOsReference) { + // This constructor is intentionally empty, but it can be used to set up any necessary state. + this.javaOsReference = javaOsReference; + } public static OS current() { String os = System.getProperty("os.name", ""); diff --git a/build.gradle b/build.gradle index f971cad29cc19..e5c4f9b263b60 100644 --- a/build.gradle +++ b/build.gradle @@ -36,11 +36,11 @@ buildscript { plugins { id 'lifecycle-base' id 'elasticsearch.docker-support' + id 'elasticsearch.internal-distribution-download' + id 'elasticsearch.jdk-download' id 'elasticsearch.global-build-info' id 'elasticsearch.build-complete' id 'elasticsearch.build-scan' - id 'elasticsearch.jdk-download' - id 'elasticsearch.internal-distribution-download' id 'elasticsearch.runtime-jdk-provision' id 'elasticsearch.ide' id 'elasticsearch.forbidden-dependencies' diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 24b2bedc5eb7c..b83f0b5cec106 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -9,6 +9,7 @@ + diff --git a/settings.gradle b/settings.gradle index af3d5cbc3c550..52f437c56d4f2 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,6 +1,7 @@ import org.elasticsearch.gradle.internal.toolchain.OracleOpenJdkToolchainResolver import org.elasticsearch.gradle.internal.toolchain.ArchivedOracleJdkToolchainResolver import org.elasticsearch.gradle.internal.toolchain.AdoptiumJdkToolchainResolver +import org.elasticsearch.gradle.internal.toolchain.EarlyAccessCatalogJdkToolchainResolver pluginManagement { repositories { diff --git a/test/framework/src/main/java/org/elasticsearch/test/junit/listeners/ReproduceInfoPrinter.java b/test/framework/src/main/java/org/elasticsearch/test/junit/listeners/ReproduceInfoPrinter.java index 1aba9670d0b9b..fbd31201b41da 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/junit/listeners/ReproduceInfoPrinter.java +++ b/test/framework/src/main/java/org/elasticsearch/test/junit/listeners/ReproduceInfoPrinter.java @@ -185,9 +185,11 @@ private ReproduceErrorMessageBuilder appendESProperties() { appendOpt("tests.locale", Locale.getDefault().toLanguageTag()); appendOpt("tests.timezone", TimeZone.getDefault().getID()); appendOpt("tests.distribution", System.getProperty("tests.distribution")); - appendOpt("runtime.java", Integer.toString(Runtime.version().feature())); if (Runtime.version().build().isPresent() && "ea".equalsIgnoreCase(Runtime.version().pre().orElse(""))) { + appendOpt("runtime.java", Runtime.version().feature() + "-ea"); appendOpt("runtime.java.build", Integer.toString(Runtime.version().build().get())); + } else { + appendOpt("runtime.java", Integer.toString(Runtime.version().feature())); } appendOpt(ESTestCase.FIPS_SYSPROP, System.getProperty(ESTestCase.FIPS_SYSPROP)); return this; From ad30b37f45c85eca6cfb48561570cad10d159c01 Mon Sep 17 00:00:00 2001 From: Rene Groeschke Date: Fri, 15 Aug 2025 16:35:50 +0200 Subject: [PATCH 2/2] Fix jdkdownload tests --- .../gradle/internal/JdkDownloadPluginFuncTest.groovy | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/build-tools-internal/src/integTest/groovy/org/elasticsearch/gradle/internal/JdkDownloadPluginFuncTest.groovy b/build-tools-internal/src/integTest/groovy/org/elasticsearch/gradle/internal/JdkDownloadPluginFuncTest.groovy index d1fedef1afb54..2c08ffa6dc360 100644 --- a/build-tools-internal/src/integTest/groovy/org/elasticsearch/gradle/internal/JdkDownloadPluginFuncTest.groovy +++ b/build-tools-internal/src/integTest/groovy/org/elasticsearch/gradle/internal/JdkDownloadPluginFuncTest.groovy @@ -26,7 +26,6 @@ import java.util.regex.Pattern import static org.elasticsearch.gradle.internal.JdkDownloadPlugin.VENDOR_ADOPTIUM import static org.elasticsearch.gradle.internal.JdkDownloadPlugin.VENDOR_OPENJDK -import static org.elasticsearch.gradle.internal.JdkDownloadPlugin.VENDOR_ZULU class JdkDownloadPluginFuncTest extends AbstractGradleFuncTest { @@ -60,6 +59,7 @@ class JdkDownloadPluginFuncTest extends AbstractGradleFuncTest { version = '$jdkVersion' platform = "$platform" architecture = '$arch' + distributionVersion = '$distributionVersion' } } @@ -103,7 +103,6 @@ class JdkDownloadPluginFuncTest extends AbstractGradleFuncTest { "linux" | "aarch64" | VENDOR_ADOPTIUM | ADOPT_JDK_VERSION | "" | "bin/java" | "" "linux" | "aarch64" | VENDOR_ADOPTIUM | ADOPT_JDK_VERSION_11 | "" | "bin/java" | "(jdk 11)" "linux" | "aarch64" | VENDOR_ADOPTIUM | ADOPT_JDK_VERSION_15 | "" | "bin/java" | "(jdk 15)" - "darwin" | "aarch64" | VENDOR_ZULU | AZUL_JDK_VERSION_8 | AZUL_8_DISTRO_VERSION | "Contents/Home/bin/java" | "(jdk 8)" } def "transforms are reused across projects"() { @@ -223,7 +222,7 @@ class JdkDownloadPluginFuncTest extends AbstractGradleFuncTest { final String platform, final String arch = 'x64', final String distributedVersion = '') { - final boolean isOld = version.equals(OPENJDK_VERSION_OLD); + final boolean isOld = version.equals(OPENJDK_VERSION_OLD) if (distributedVersion.equals("ea")) { def effectivePlatform = isMac(platform) ? "macos" : platform;