Use Java version and vendor from pipeline properties.

Ensure that we use always the specified Java version.

See #193
This commit is contained in:
Mark Paluch
2022-02-07 10:53:08 +01:00
parent 33f896641b
commit 2894114166
11 changed files with 171 additions and 80 deletions

View File

@@ -16,11 +16,16 @@
package org.springframework.data.release.build;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import java.io.File;
import java.io.FileInputStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
@@ -35,11 +40,12 @@ import javax.annotation.PreDestroy;
import org.apache.commons.io.IOUtils;
import org.springframework.data.release.model.JavaVersionAware;
import org.springframework.data.release.dependency.InfrastructureOperations;
import org.springframework.data.release.io.Workspace;
import org.springframework.data.release.model.JavaVersion;
import org.springframework.data.release.model.Project;
import org.springframework.data.release.model.ProjectAware;
import org.springframework.data.release.utils.ListWrapperCollector;
import org.springframework.data.release.utils.Logger;
import org.springframework.data.util.Streamable;
import org.springframework.plugin.core.PluginRegistry;
import org.springframework.stereotype.Component;
@@ -51,19 +57,13 @@ import org.springframework.util.Assert;
* @author Mark Paluch
*/
@Component
@RequiredArgsConstructor
class BuildExecutor {
private final @NonNull PluginRegistry<BuildSystem, Project> buildSystems;
private final MavenProperties mavenProperties;
private final ExecutorService executor;
public BuildExecutor(PluginRegistry<BuildSystem, Project> buildSystems, Logger logger,
MavenProperties mavenProperties, ExecutorService buildExecutor) {
this.buildSystems = buildSystems;
this.mavenProperties = mavenProperties;
this.executor = buildExecutor;
}
private final Workspace workspace;
@PreDestroy
public void shutdown() {
@@ -162,20 +162,14 @@ class BuildExecutor {
Supplier<IllegalStateException> exception = () -> new IllegalStateException(
String.format("No build system plugin found for project %s!", module.getProject()));
BuildSystem buildSystem = buildSystems.getPluginFor(module.getProject(), exception);
BuildSystem buildSystemToUse;
if (module instanceof JavaVersionAware) {
buildSystemToUse = buildSystem.withJavaVersion(((JavaVersionAware) module).getJavaVersion());
} else {
buildSystemToUse = buildSystem;
}
BuildSystem buildSystem = buildSystems.getPluginFor(module.getProject(), exception)
.withJavaVersion(detectJavaVersion(module.getProject()));
Runnable runnable = () -> {
try {
result.complete(function.apply(buildSystemToUse, module));
result.complete(function.apply(buildSystem, module));
} catch (Exception e) {
result.completeExceptionally(e);
}
@@ -186,6 +180,24 @@ class BuildExecutor {
return result;
}
@SneakyThrows
public JavaVersion detectJavaVersion(Project project) {
File ciProperties = workspace.getFile(InfrastructureOperations.CI_PROPERTIES, project);
if (!ciProperties.exists()) {
throw new IllegalStateException(String.format("Cannot find %s for project %s", ciProperties, project));
}
Properties properties = new Properties();
try (FileInputStream fis = new FileInputStream(ciProperties)) {
properties.load(fis);
}
return JavaVersion.fromDockerTag(properties.getProperty("java.main.tag"));
}
/**
* Returns a new collector to toSummaryCollector {@link ExecutionResult} as {@link Summary} using the {@link Stream}
* API.

View File

@@ -222,7 +222,7 @@ public class BuildOperations {
BuildSystem buildSystem = buildSystems.getPluginFor(module.getProject(), exception);
return function.apply(buildSystem.withJavaVersion(module.getJavaVersion()), module);
return function.apply(buildSystem.withJavaVersion(executor.detectJavaVersion(module.getProject())), module);
}
}

View File

@@ -91,6 +91,10 @@ public class JavaRuntimes {
.orElseThrow(() -> new NoSuchElementException(String.format("%s%nAvailable JDK: %s", message.get(), jdks)));
}
public static List<JdkInstallation> getJdks() {
return JDKS.get();
}
/**
* JDK detection strategy.
*/
@@ -125,7 +129,10 @@ public class JavaRuntimes {
}
public static Selector from(JavaVersion javaVersion) {
return builder().and(it -> javaVersion.getVersionDetector().test(it.getVersion()))
return builder()
.and(it -> javaVersion.getVersionDetector().test(it.getVersion())
&& javaVersion.getImplementor().test(it.getImplementor()))
.message("Cannot find Java " + javaVersion.getName());
}
@@ -184,10 +191,29 @@ public class JavaRuntimes {
version = Version.parse(candidateVersion);
}
return new JdkInstallation(version, it.getName(), it);
String implementor = normalizeImplementor(parseImplementor(it));
return new JdkInstallation(version, toDisplayName(implementor, candidateVersion), implementor, it);
}).collect(Collectors.toList());
}
@SneakyThrows
private String parseImplementor(File candidateHome) {
List<String> release = FileUtils.readLines(new File(candidateHome, "release"));
for (String line : release) {
if (line.startsWith("IMPLEMENTOR=")) {
String substring = line.substring(line.indexOf("=\""));
substring = substring.substring(2, substring.length() - 1);
return substring;
}
}
return "?";
}
}
/**
@@ -208,7 +234,8 @@ public class JavaRuntimes {
public List<JdkInstallation> detect() {
return Collections
.singletonList(new JdkInstallation(JavaVersion.parse(javaVersion), javaVendor + " " + javaVersion, javaHome));
.singletonList(new JdkInstallation(JavaVersion.parse(javaVersion), toDisplayName(javaVendor, javaVersion),
normalizeImplementor(javaVendor), javaHome));
}
}
@@ -252,6 +279,7 @@ public class JavaRuntimes {
String jvmHomePath = dict.get("JVMHomePath").toJavaObject(String.class);
String name = dict.get("JVMName").toJavaObject(String.class);
String version = dict.get("JVMVersion").toJavaObject(String.class);
String vendor = dict.get("JVMVendor").toJavaObject(String.class);
Matcher matcher = VERSION.matcher(version);
if (!matcher.find()) {
@@ -259,7 +287,9 @@ public class JavaRuntimes {
+ ". This should not happen in an ideal world, check the VERSION regex.");
}
return new JdkInstallation(JavaVersion.parse(matcher.group(1)), name, new File(jvmHomePath));
String implementor = normalizeImplementor(vendor);
return new JdkInstallation(JavaVersion.parse(matcher.group(1)), toDisplayName(implementor, version),
implementor, new File(jvmHomePath));
}).collect(Collectors.toList());
}
@@ -270,6 +300,7 @@ public class JavaRuntimes {
Version version;
String name;
String implementor;
File home;
@Override
@@ -277,4 +308,26 @@ public class JavaRuntimes {
return this.version.compareTo(o.version);
}
}
static String normalizeImplementor(String implementor) {
if (implementor.equals("Eclipse Adoptium")) {
return "Eclipse Temurin";
}
if (implementor.equals("Eclipse Foundation")) {
return "Eclipse Temurin";
}
return implementor;
}
static String toDisplayName(String implementor, String version) {
if (implementor.startsWith("Oracle")) {
implementor = "Oracle Java";
}
return implementor + " " + version;
}
}

View File

@@ -18,6 +18,8 @@ package org.springframework.data.release.model;
import lombok.Value;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Value object representing a Java version.
@@ -27,20 +29,49 @@ import java.util.function.Predicate;
@Value(staticConstructor = "of")
public class JavaVersion {
private static final Pattern DOCKER_TAG_PATTERN = Pattern.compile("((:?\\d+(:?u\\d+)?(:?\\.\\d+)*)).*");
public static final JavaVersion JAVA_8 = of("1.8.0_312");
public static final JavaVersion JAVA_17 = of("Java 17", version -> version.getMajor() == 17);
public static final JavaVersion JAVA_17 = of("Java 17", version -> version.getMajor() == 17, it -> true);
String name;
Predicate<Version> versionDetector;
Predicate<String> implementor;
public static JavaVersion of(String version) {
Version expectedVersion = parse(version);
return of("Java " + version, candidate -> candidate.is(expectedVersion));
return of("Java " + version, candidate -> candidate.is(expectedVersion), it -> true);
}
public static Version parse(String version) {
return Version.parse(version.replace('_', '.'));
}
/**
* Parse a docker tag into a Java version using {@code eclipse-temurin} conventions.
*
* @param tagName
* @return
*/
public static JavaVersion fromDockerTag(String tagName) {
Pattern versionExtractor = Pattern.compile("(:?\\d+(:?u\\d+)?(:?\\.\\d+)*).*");
Matcher matcher = versionExtractor.matcher(tagName);
if (!matcher.find()) {
throw new IllegalStateException(String.format("Cannot parse Java version '%s'", tagName));
}
String plainVersion = matcher.group(1);
if (plainVersion.startsWith("8u")) {
return of("1.8.0_" + plainVersion.substring(2));
}
return of(plainVersion).withImplementor("Temurin");
}
public JavaVersion withImplementor(String implementor) {
return of(String.format("%s (%s)", name, implementor), versionDetector, it -> it.contains(implementor));
}
}

View File

@@ -1,24 +0,0 @@
/*
* Copyright 2022-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.release.model;
/**
* @author Mark Paluch
*/
public interface JavaVersionAware {
JavaVersion getJavaVersion();
}

View File

@@ -18,7 +18,6 @@ package org.springframework.data.release.model;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Value;
import lombok.With;
import org.springframework.util.Assert;
@@ -28,31 +27,25 @@ import org.springframework.util.Assert;
*/
@Value
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class Module implements VersionAware, ProjectAware, JavaVersionAware, Comparable<Module> {
public class Module implements VersionAware, ProjectAware, Comparable<Module> {
Project project;
Version version;
Iteration customFirstIteration;
@With JavaVersion javaVersion;
public Module(Project project, String version) {
this(project, version, null, JavaVersion.JAVA_8);
this(project, version, null);
}
Module(Project project, String version, String customFirstIteration) {
this(project, version, customFirstIteration, JavaVersion.JAVA_8);
}
Module(Project project, String version, String customFirstIteration, JavaVersion javaVersion) {
Assert.notNull(project, "Project must not be null!");
Assert.notNull(javaVersion, "JavaVersion must not be null!");
this.project = project;
this.version = Version.parse(version);
this.customFirstIteration = customFirstIteration == null ? null
: new Iteration(customFirstIteration, Iteration.RC1);
this.javaVersion = javaVersion;
}
public boolean hasName(String name) {
@@ -97,8 +90,4 @@ public class Module implements VersionAware, ProjectAware, JavaVersionAware, Com
return String.format("Spring Data %s %s - %s", project.getName(), version, project.getKey());
}
public Module withJavaVersion(JavaVersion javaVersion) {
return this.javaVersion == javaVersion ? this
: new Module(this.project, this.version, this.customFirstIteration, javaVersion);
}
}

View File

@@ -25,7 +25,7 @@ import lombok.RequiredArgsConstructor;
*/
@RequiredArgsConstructor
@EqualsAndHashCode
public class ModuleIteration implements IterationVersion, ProjectAware, JavaVersionAware {
public class ModuleIteration implements IterationVersion, ProjectAware {
private final @Getter Module module;
private final @Getter TrainIteration trainIteration;
@@ -46,11 +46,6 @@ public class ModuleIteration implements IterationVersion, ProjectAware, JavaVers
return module.getProject();
}
@Override
public JavaVersion getJavaVersion() {
return trainIteration.getTrain().getJavaVersion();
}
/*
* (non-Javadoc)
* @see org.springframework.data.release.model.IterationVersion#getVersion()

View File

@@ -77,7 +77,6 @@ public class ReleaseTrains {
TURING = PASCAL.next("Turing", Transition.MAJOR, //
new Module(R2DBC, "3.0")) //
.withCalver("2022.0") //
.withJavaVersion(JavaVersion.JAVA_17)
.filterModules(module -> !module.getProject().equals(ENVERS))
.withAlwaysUseBranch(true)
.withIterations(new Train.Iterations(M1, M2, M3, M4, M5, RC1, RC2, GA, SR1, SR2, SR3, SR4, SR5));

View File

@@ -185,15 +185,6 @@ public class Train implements Streamable<Module> {
return new Train(name, Modules.of(modules), calver, iterations, alwaysUseBranch, javaVersion);
}
public Train withJavaVersion(JavaVersion javaVersion) {
Set<Module> modules = this.modules.stream().map(it -> {
return it.withJavaVersion(javaVersion);
}).collect(Collectors.toSet());
return new Train(name, Modules.of(modules), calver, iterations, alwaysUseBranch, javaVersion);
}
/**
* Check whether this train comes before {@link Train other}.
*

View File

@@ -37,4 +37,5 @@ class JavaRuntimesUnitTests {
assertThat(jdk).isNotNull();
assertThat(System.getProperty("java.home")).contains(jdk.getHome().getPath());
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.release.model;
import static org.assertj.core.api.Assertions.*;
import org.junit.jupiter.api.Test;
/**
* Unit tests for {@link JavaVersion}.
*
* @author Mark Paluch
*/
class JavaVersionUnitTests {
@Test
void shouldParseDockerTag() {
assertThat(JavaVersion.fromDockerTag("8u312-b07-jdk").getName()).isEqualTo("Java 1.8.0_312");
assertThat(JavaVersion.fromDockerTag("8u322-b06-jre-focal").getName()).isEqualTo("Java 1.8.0_322");
assertThat(JavaVersion.fromDockerTag("11.0.13_8-jdk").getName()).isEqualTo("Java 11.0.13");
assertThat(JavaVersion.fromDockerTag("17.0.1_12").getName()).isEqualTo("Java 17.0.1");
}
@Test
void shouldConsiderImplementor() {
assertThat(JavaVersion.fromDockerTag("8u312-b07-jdk").withImplementor("Temurin").getName())
.isEqualTo("Java 1.8.0_312 (Temurin)");
}
}