Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Gradle JDK Automanagement] Install only used JDKs #479

Open
wants to merge 16 commits into
base: develop
Choose a base branch
from
5 changes: 5 additions & 0 deletions changelog/@unreleased/pr-472.v2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type: fix
fix:
description: Add `daemonJdkOnly ` property for gradle jdk directory generation
links:
- https://github.com/palantir/gradle-jdks/pull/472
20 changes: 19 additions & 1 deletion gradle-jdks-setup/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ jdks {
jdks {
daemonTarget = <version eg. 11/17/21>
daemonJdkOnly() # optional, only installs & configures the daemon JDK version
jdkVersionsToUse = [11, 17, 21, 23] # optional, the set of java versions to install, by default it will contain all the major versions configured in step 3.
jdkMajorVersionsToUse = [11, 17, 21, 23] # optional, the set of java versions to install, by default it will contain all the major versions configured in step 3.
}
```
5. Enable the jdk setup by adding the following to `gradle.properties`:
Expand Down Expand Up @@ -211,6 +211,24 @@ The plugin registers the following tasks:
- `checkGradleJdkConfigs` - checks that all the `gradle/` configurations are up-to-date. E.g. if the `jdks-latest` plugin is updated, we need to make sure the `gradle/jdks` files reflect the jdk versions.
- `setupJdks` - task that triggers `wrapperJdkPatcher` and `generateGradleJdkConfigs` and runs the patched `./gradlew` script.


## Using a new java version

We are only generating the jdk configuration files for the jdk versions that are used see: [jdkMajorVersionsToUse](https://github.com/palantir/gradle-jdks/blob/26d54605b7827b232024ec7e0c34a87983804492/gradle-jdks/src/main/java/com/palantir/gradle/jdks/JdksExtension.java#L44)
Using a new java version is a 2-step process:
1. Firstly, we need to generate the gradle jdk configuration files for the new java version that we are going to use
2. Secondly, once the new files are generated, the javaVersion can be configured in the gradle build configuration.

### Palantir specific, if using `baseline-java-version` through excavators
1. Run `./gradlew generateGradleJdkConfigs --includeAllJdks`. The command will generate the Gradle jdk configuration files for all jdks.
2. Update the javaVersion(s)/jdks extension values with the desired java major version.
3. Run `./gradlew setupJdks` to only keep the Gradle jdk configuration files for the used Gradle JDKs.

### Gradle Toolchains workflow
1. Update `jdkMajorVersionsToUse` with the required jdk versions
2. Run `./gradlew setupJdks`


## Unsupported

- This workflow is disabled on `Windows` at the moment.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Nested;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.options.Option;
import org.gradle.jvm.toolchain.JavaLanguageVersion;

/**
Expand All @@ -43,6 +44,15 @@ public abstract class GradleJdksConfigs extends DefaultTask {
public static final String GRADLE_JDKS_SETUP_SCRIPT = "gradle-jdks-setup.sh";
public static final String GRADLE_JDKS_FUNCTIONS_SCRIPT = "gradle-jdks-functions.sh";

/**
* Option to include a specific java major version when generating/checking the gradle jdk configuration files.
*/
@Input
@Option(
option = "includeAllJdks",
description = "Generates the configuration directories for all configured Java major versions.")
public abstract Property<Boolean> getIncludeAllJdks();

@Nested
public abstract MapProperty<JavaLanguageVersion, List<JdkDistributionConfig>> getJavaVersionToJdkDistros();

Expand All @@ -65,6 +75,10 @@ protected abstract void applyGradleJdkFileAction(

protected abstract void maybePrepareForAction(List<Path> targetPaths);

public GradleJdksConfigs() {
getIncludeAllJdks().convention(false);
}

@TaskAction
public final void action() {
Path gradleJdksDir = gradleDirectory().dir("jdks").getAsFile().toPath();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.gradle.api.JavaVersion;
import org.gradle.api.Project;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
Expand All @@ -36,8 +37,11 @@ public final class JdkDistributionConfigurator {
private static final JavaLanguageVersion MINIMUM_SUPPORTED_JAVA_VERSION = JavaLanguageVersion.of(11);

public static Map<JavaLanguageVersion, List<JdkDistributionConfig>> getJavaVersionToJdkDistros(
Project project, JdkDistributions jdkDistributions, JdksExtension jdksExtension) {
Set<JavaLanguageVersion> javaVersions = jdksExtension.getJdkMajorVersionsToUse().get().stream()
Project project, JdkDistributions jdkDistributions, JdksExtension jdksExtension, Boolean includeAllJdks) {
Set<JavaLanguageVersion> javaVersions = (includeAllJdks
? Arrays.stream(JavaVersion.values())
.map(javaVersion -> JavaLanguageVersion.of(javaVersion.getMajorVersion()))
: jdksExtension.jdkMajorVersionsToUse().get().stream())
.filter(javaLanguageVersion -> javaLanguageVersion.canCompileOrRun(MINIMUM_SUPPORTED_JAVA_VERSION))
.collect(Collectors.toSet());
return javaVersions.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,13 @@ public final void setDaemonTarget(int value) {
getDaemonTarget().set(JavaLanguageVersion.of(value));
}

public final SetProperty<JavaLanguageVersion> getJdkMajorVersionsToUse() {
public final SetProperty<JavaLanguageVersion> jdkMajorVersionsToUse() {
return this.jdkMajorVersionsToUse;
}

public final void setJdkMajorVersionsToUse(Set<JavaLanguageVersion> javaLanguageVersions) {
this.jdkMajorVersionsToUse.set(javaLanguageVersions);
public final void setJdkMajorVersionsToUse(Set<String> jdkMajorVersions) {
jdkMajorVersionsToUse()
.set(jdkMajorVersions.stream().map(JavaLanguageVersion::of).collect(Collectors.toSet()));
}

public final void daemonJdkOnly() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,19 @@

package com.palantir.gradle.jdks;

import com.palantir.baseline.plugins.javaversions.BaselineJavaVersionExtension;
import com.palantir.baseline.plugins.javaversions.BaselineJavaVersionsExtension;
import com.palantir.baseline.plugins.javaversions.ChosenJavaVersion;
import com.palantir.gradle.jdks.GradleWrapperPatcher.GradleWrapperPatcherTask;
import com.palantir.gradle.jdks.enablement.GradleJdksEnablement;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.TaskProvider;
import org.gradle.api.tasks.wrapper.Wrapper;
import org.gradle.language.base.plugins.LifecycleBasePlugin;
Expand Down Expand Up @@ -58,12 +63,32 @@ public void apply(Project rootProject) {
JdksExtension jdksExtension = JdksPlugin.extension(rootProject, jdkDistributions);

rootProject.getPluginManager().withPlugin("com.palantir.baseline-java-versions", unused -> {
rootProject
.getExtensions()
.getByType(BaselineJavaVersionsExtension.class)
.getSetupJdkToolchains()
.set(false);
BaselineJavaVersionsExtension baselineJavaVersionsExtension =
rootProject.getExtensions().getByType(BaselineJavaVersionsExtension.class);
baselineJavaVersionsExtension.getSetupJdkToolchains().set(false);

jdksExtension.jdkMajorVersionsToUse().set(rootProject.provider(() -> Stream.of(
jdksExtension.getDaemonTarget(),
baselineJavaVersionsExtension.libraryTarget(),
baselineJavaVersionsExtension.runtime().map(ChosenJavaVersion::javaLanguageVersion),
baselineJavaVersionsExtension
.distributionTarget()
.map(ChosenJavaVersion::javaLanguageVersion))
.map(Provider::get)
.collect(Collectors.toSet())));
});

rootProject.subprojects(
proj -> proj.getPluginManager().withPlugin("com.palantir.baseline-java-version", unused -> {
BaselineJavaVersionExtension projectVersions =
proj.getExtensions().getByType(BaselineJavaVersionExtension.class);

jdksExtension.jdkMajorVersionsToUse().addAll(rootProject.provider(() -> Stream.of(
projectVersions.target(), projectVersions.runtime())
.map(Provider::get)
.map(ChosenJavaVersion::javaLanguageVersion)
.collect(Collectors.toSet())));
}));
TaskProvider<Wrapper> wrapperTask = rootProject.getTasks().named("wrapper", Wrapper.class);

TaskProvider<GenerateGradleJdksConfigsTask> generateGradleJdkConfigs = rootProject
Expand All @@ -89,7 +114,10 @@ public void apply(Project rootProject) {
task.getDaemonJavaVersion().set(jdksExtension.getDaemonTarget());
task.getJavaVersionToJdkDistros()
.putAll(rootProject.provider(() -> JdkDistributionConfigurator.getJavaVersionToJdkDistros(
rootProject, jdkDistributions, jdksExtension)));
rootProject,
jdkDistributions,
jdksExtension,
task.getIncludeAllJdks().get())));
task.getCaCerts().putAll(jdksExtension.getCaCerts());
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,108 @@ class GradleJdkToolchainsIntegrationTest extends GradleJdkIntegrationSpec {

where:
gradleVersionNumber << GRADLE_TEST_VERSIONS

}

def '#gradleVersionNumber: can bump java major version when baseline-java is applied'() {
gradleVersion = gradleVersionNumber
setupJdksHardcodedVersions('11')
applyBaselineJavaVersions()
applyApplicationPlugin()

// language=groovy
buildFile << """
javaVersions {
libraryTarget = '11'
}
""".stripIndent(true)

file('gradle.properties') << 'palantir.jdk.setup.enabled=true'
file('src/main/java/Main.java') << java17PreviewCode
runTasksSuccessfully('wrapper')

when:
runTasksSuccessfully('generateGradleJdkConfigs', '--includeAllJdks')

then: 'generates directories for all jdk versions'
Files.list(projectDir.toPath().resolve("gradle/jdks"))
.map { it -> it.getFileName().toString() }
.collect(Collectors.toList())
.containsAll(List.of("11", "17", "21"))

when:
runTasksSuccessfully('setupJdks')

then: 'only jdk 11 is generated'
Files.list(projectDir.toPath().resolve("gradle/jdks"))
.allMatch { it -> it.endsWith("gradle/jdks/11")}

where:
gradleVersionNumber << GRADLE_TEST_VERSIONS
}

def '#gradleVersionNumber: only jdkVersionsToUse jdks are generated'() {
gradleVersion = gradleVersionNumber
setupJdksHardcodedVersions('11')
applyApplicationPlugin()

file('gradle.properties') << 'palantir.jdk.setup.enabled=true'
file('src/main/java/Main.java') << java17PreviewCode
runTasksSuccessfully('wrapper')

when:
buildFile << """
jdks {
jdkMajorVersionsToUse = ["11", "21"]
}
""".stripIndent(true)

runTasksSuccessfully('setupJdks')

then: 'only jdkVersionsToUse files are generated'
Files.list(projectDir.toPath().resolve("gradle/jdks"))
.map { it -> it.getFileName().toString() }
.collect(Collectors.toList())
.containsAll(List.of("11", "21"))

where:
gradleVersionNumber << GRADLE_TEST_VERSIONS
}

def '#gradleVersionNumber: only required java versions are configured'() {
gradleVersion = gradleVersionNumber
setupJdksHardcodedVersions('17')
applyBaselineJavaVersions()
applyApplicationPlugin()

file('gradle.properties') << 'palantir.jdk.setup.enabled=true'
file('src/main/java/Main.java') << java17PreviewCode

// language=Groovy
buildFile << """
javaVersions {
libraryTarget = '17'
}
""".stripIndent(true)

//language=groovy
def subprojectLib21 = addSubproject 'subproject-lib-21', '''
apply plugin: 'java-library'
javaVersion {
target = 17
runtime = 21
}
'''.stripIndent(true)
writeJavaSourceFile(getMainJavaCode(), subprojectLib21)

when:
runTasksSuccessfully('wrapper')

then: 'generates directories for all jdk versions'
Files.list(projectDir.toPath().resolve("gradle/jdks")).map { it -> it.getFileName().toString() }.collect(Collectors.toList()).containsAll(List.of("17", "21"))

where:
gradleVersionNumber << GRADLE_TEST_VERSIONS
}

def '#gradleVersionNumber: fails if the jdk version is not configured'() {
Expand All @@ -219,7 +321,7 @@ class GradleJdkToolchainsIntegrationTest extends GradleJdkIntegrationSpec {

buildFile << '''
javaVersions {
distributionTarget = '15'
libraryTarget = 15
}
'''.stripIndent(true)
writeHelloWorld(projectDir)
Expand Down