Skip to content

Commit 510e451

Browse files
Update build to use gradle wrapper 6.8 (7.x backport) (#67327)
- Updates our build to use the latest Gradle 6.8 release which is the last release before the major 7.0 release. - Resolve available gradle versions using built-in toolchain support - Fixes deprecated usage of JavaInstallationRegistry - We replace jdk handling in our build to rely on jvm detection provided by the gradle build tool itself. As we rely on environment variables pointing to jdks we wire this into the gradle jdk detection mechanism - Fix runtime jdk vendor detection used in fips.gradle (#67417) - Allow Current JDK as valid installation without requiring ENV setup (#67411) Co-authored-by: Mark Vieira <[email protected]>
1 parent e289a6e commit 510e451

File tree

23 files changed

+201
-164
lines changed

23 files changed

+201
-164
lines changed

buildSrc/src/integTest/groovy/org/elasticsearch/gradle/DistributionDownloadPluginFuncTest.groovy

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
package org.elasticsearch.gradle
2121

2222
import org.elasticsearch.gradle.fixtures.AbstractGradleFuncTest
23-
import org.elasticsearch.gradle.transform.SymbolicLinkPreservingUntarTransform
2423
import org.gradle.testkit.runner.TaskOutcome
2524
import spock.lang.Unroll
2625

@@ -61,17 +60,21 @@ class DistributionDownloadPluginFuncTest extends AbstractGradleFuncTest {
6160
"""
6261

6362
when:
64-
def runner = gradleRunner('clean', 'setupDistro', '-i')
63+
def guh = new File(testProjectDir.getRoot(), "gradle-user-home").absolutePath;
64+
def runner = gradleRunner('clean', 'setupDistro', '-i', '-g', guh)
6565
def result = withMockedDistributionDownload(version, platform, runner) {
6666
// initial run
67-
build()
67+
def firstRun = build()
68+
assertOutputContains(firstRun.output, "Unpacking elasticsearch-${version}-linux-x86_64.tar.gz " +
69+
"using SymbolicLinkPreservingUntarTransform")
6870
// 2nd invocation
6971
build()
7072
}
7173

7274
then:
7375
result.task(":setupDistro").outcome == TaskOutcome.SUCCESS
74-
assertOutputContains(result.output, "Skipping ${SymbolicLinkPreservingUntarTransform.class.simpleName}")
76+
assertOutputMissing(result.output, "Unpacking elasticsearch-${version}-linux-x86_64.tar.gz " +
77+
"using SymbolicLinkPreservingUntarTransform")
7578
}
7679

7780
def "transforms are reused across projects"() {
@@ -109,7 +112,7 @@ class DistributionDownloadPluginFuncTest extends AbstractGradleFuncTest {
109112
then:
110113
result.tasks.size() == 3
111114
result.output.count("Unpacking elasticsearch-${version}-linux-x86_64.tar.gz " +
112-
"using SymbolicLinkPreservingUntarTransform.") == 1
115+
"using SymbolicLinkPreservingUntarTransform") == 1
113116
}
114117

115118
private boolean assertExtractedDistroCreated(String relativePath) {

buildSrc/src/integTest/groovy/org/elasticsearch/gradle/ElasticsearchJavaPluginFuncTest.groovy

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,4 @@ class ElasticsearchJavaPluginFuncTest extends AbstractGradleFuncTest {
5858
then:
5959
gradleRunner("help").build()
6060
}
61-
62-
private File someJavaSource() {
63-
file("src/main/java/org/acme/SomeClass.java") << """
64-
package org.acme;
65-
public class SomeClass {}
66-
"""
67-
}
6861
}

buildSrc/src/integTest/groovy/org/elasticsearch/gradle/JdkDownloadPluginFuncTest.groovy

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ class JdkDownloadPluginFuncTest extends AbstractGradleFuncTest {
135135

136136
then:
137137
result.tasks.size() == 3
138-
result.output.count("Unpacking linux-12.0.2-x64.tar.gz using ${SymbolicLinkPreservingUntarTransform.simpleName}.") == 1
138+
result.output.count("Unpacking linux-12.0.2-x64.tar.gz using ${SymbolicLinkPreservingUntarTransform.simpleName}") == 1
139139

140140
where:
141141
platform | jdkVendor | jdkVersion | expectedJavaBin
@@ -177,18 +177,20 @@ class JdkDownloadPluginFuncTest extends AbstractGradleFuncTest {
177177

178178
def commonGradleUserHome = testProjectDir.newFolder().toString()
179179
// initial run
180-
gradleRunner('clean', 'getJdk', '-g', commonGradleUserHome).build()
180+
def firstResult = gradleRunner('clean', 'getJdk', '-i', '--warning-mode', 'all', '-g', commonGradleUserHome).build()
181+
// assert the output of an executed transform is shown
182+
assertOutputContains(firstResult.output, "Unpacking $expectedArchiveName using $transformType")
181183
// run against up-to-date transformations
182-
gradleRunner('clean', 'getJdk', '-i', '-g', commonGradleUserHome).build()
184+
gradleRunner('clean', 'getJdk', '-i', '--warning-mode', 'all', '-g', commonGradleUserHome).build()
183185
}
184186

185187
then:
186-
assertOutputContains(result.output, "Skipping $transformType")
188+
normalized(result.output).contains("Unpacking $expectedArchiveName using $transformType") == false
187189

188190
where:
189-
platform | transformType
190-
"linux" | SymbolicLinkPreservingUntarTransform.class.simpleName
191-
"windows" | UnzipTransform.class.simpleName
191+
platform | expectedArchiveName | transformType
192+
"linux" | "linux-12.0.2-x64.tar.gz" | SymbolicLinkPreservingUntarTransform.class.simpleName
193+
"windows" | "windows-12.0.2-x64.zip" | UnzipTransform.class.simpleName
192194
}
193195

194196
static boolean assertExtraction(String output, String javaBin) {
@@ -237,6 +239,7 @@ class JdkDownloadPluginFuncTest extends AbstractGradleFuncTest {
237239
if(repo.name == "jdk_repo_${jdkVendor}_${jdkVersion}") {
238240
repo.setUrl('${server.baseUrl()}')
239241
}
242+
allowInsecureProtocol = true
240243
}
241244
}"""
242245
}

buildSrc/src/integTest/groovy/org/elasticsearch/gradle/fixtures/AbstractGradleFuncTest.groovy

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,14 @@ abstract class AbstractGradleFuncTest extends Specification {
3535

3636
File settingsFile
3737
File buildFile
38+
File propertiesFile
3839

3940
def setup() {
4041
settingsFile = testProjectDir.newFile('settings.gradle')
4142
settingsFile << "rootProject.name = 'hello-world'\n"
4243
buildFile = testProjectDir.newFile('build.gradle')
44+
propertiesFile = testProjectDir.newFile('gradle.properties')
45+
propertiesFile << "org.gradle.java.installations.fromEnv=JAVA_HOME,RUNTIME_JAVA_HOME,JAVA15_HOME,JAVA14_HOME,JAVA13_HOME,JAVA12_HOME,JAVA11_HOME,JAVA8_HOME"
4346
}
4447

4548
GradleRunner gradleRunner(String... arguments) {
@@ -60,6 +63,10 @@ abstract class AbstractGradleFuncTest extends Specification {
6063
true
6164
}
6265

66+
def assertOutputMissing(String givenOutput, String expected) {
67+
assert normalized(givenOutput).contains(normalized(expected)) == false
68+
true
69+
}
6370
String normalized(String input) {
6471
String normalizedPathPrefix = testProjectDir.root.canonicalPath.replace('\\', '/')
6572
return input.readLines()

buildSrc/src/integTest/java/org/elasticsearch/gradle/BuildPluginIT.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,9 @@ private void runInsecureArtifactRepositoryTest(final String name, final String u
105105
.withProjectDir(tmpDir.getRoot())
106106
.withArguments("clean", "hello", "-s", "-i", "--warning-mode=all", "--scan")
107107
.withPluginClasspath()
108+
.forwardOutput()
108109
.buildAndFail();
110+
109111
assertOutputContains(
110112
result.getOutput(),
111113
"repository [" + name + "] on project with path [:] is not using a secure protocol for artifacts on [" + url + "]"

buildSrc/src/integTest/java/org/elasticsearch/gradle/precommit/TestingConventionsTasksIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public void testNamingConvention() {
6262
" * org.elasticsearch.gradle.testkit.LooksLikeATestWithoutNamingConvention2",
6363
" * org.elasticsearch.gradle.testkit.LooksLikeATestWithoutNamingConvention3"
6464
);
65-
assertOutputDoesNotContain(result.getOutput(), "LooksLikeTestsButAbstract");
65+
assertOutputMissing(result.getOutput(), "LooksLikeTestsButAbstract");
6666
}
6767

6868
public void testNoEmptyTasks() {

buildSrc/src/integTest/java/org/elasticsearch/gradle/precommit/ThirdPartyAuditTaskIT.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public void testViolationFoundAndCompileOnlyIgnored() {
6262

6363
assertTaskFailed(result, ":absurd");
6464
assertOutputContains(result.getOutput(), "Classes with violations:", " * TestingIO", "> Audit of third party dependencies failed");
65-
assertOutputDoesNotContain(result.getOutput(), "Missing classes:");
65+
assertOutputMissing(result.getOutput(), "Missing classes:");
6666
assertNoDeprecationWarning(result);
6767
}
6868

@@ -84,7 +84,7 @@ public void testClassNotFoundAndCompileOnlyIgnored() {
8484
" * org.apache.logging.log4j.LogManager",
8585
"> Audit of third party dependencies failed"
8686
);
87-
assertOutputDoesNotContain(result.getOutput(), "Classes with violations:");
87+
assertOutputMissing(result.getOutput(), "Classes with violations:");
8888
assertNoDeprecationWarning(result);
8989
}
9090

@@ -106,7 +106,7 @@ public void testJarHellWithJDK() {
106106
" Jar Hell with the JDK:",
107107
" * java.lang.String"
108108
);
109-
assertOutputDoesNotContain(result.getOutput(), "Classes with violations:");
109+
assertOutputMissing(result.getOutput(), "Classes with violations:");
110110
assertNoDeprecationWarning(result);
111111
}
112112

buildSrc/src/integTest/resources/org/elasticsearch/gradle/internal/fake_git/remote/gradle.properties

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,7 @@
1919

2020
# forcing to use TLS1.2 to avoid failure in vault
2121
# see https://github.com/hashicorp/vault/issues/8750#issuecomment-631236121
22-
systemProp.jdk.tls.client.protocols=TLSv1.2
22+
systemProp.jdk.tls.client.protocols=TLSv1.2
23+
24+
# java homes resolved by environment variables
25+
org.gradle.java.installations.fromEnv=JAVA_HOME,RUNTIME_JAVA_HOME,JAVA15_HOME,JAVA14_HOME,JAVA13_HOME,JAVA12_HOME,JAVA11_HOME,JAVA8_HOME

buildSrc/src/main/java/org/elasticsearch/gradle/info/BuildParams.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ public void setRuntimeJavaHome(File runtimeJavaHome) {
209209
BuildParams.runtimeJavaHome = requireNonNull(runtimeJavaHome);
210210
}
211211

212-
public void setIsRutimeJavaHomeSet(boolean isRutimeJavaHomeSet) {
212+
public void setIsRuntimeJavaHomeSet(boolean isRutimeJavaHomeSet) {
213213
BuildParams.isRuntimeJavaHomeSet = isRutimeJavaHomeSet;
214214
}
215215

buildSrc/src/main/java/org/elasticsearch/gradle/info/GlobalBuildInfoPlugin.java

Lines changed: 59 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,13 @@
2828
import org.gradle.api.Project;
2929
import org.gradle.api.logging.Logger;
3030
import org.gradle.api.logging.Logging;
31-
import org.gradle.api.model.ObjectFactory;
32-
import org.gradle.api.provider.Provider;
3331
import org.gradle.api.provider.ProviderFactory;
3432
import org.gradle.internal.jvm.Jvm;
35-
import org.gradle.jvm.toolchain.JavaInstallation;
36-
import org.gradle.jvm.toolchain.JavaInstallationRegistry;
33+
import org.gradle.internal.jvm.inspection.JvmInstallationMetadata;
34+
import org.gradle.internal.jvm.inspection.JvmMetadataDetector;
35+
import org.gradle.internal.jvm.inspection.JvmVendor;
36+
import org.gradle.jvm.toolchain.internal.InstallationLocation;
37+
import org.gradle.jvm.toolchain.internal.SharedJavaInstallationRegistry;
3738
import org.gradle.util.GradleVersion;
3839

3940
import javax.inject.Inject;
@@ -50,7 +51,6 @@
5051
import java.nio.file.Paths;
5152
import java.time.ZoneOffset;
5253
import java.time.ZonedDateTime;
53-
import java.util.ArrayList;
5454
import java.util.Arrays;
5555
import java.util.HashMap;
5656
import java.util.Iterator;
@@ -69,14 +69,18 @@ public class GlobalBuildInfoPlugin implements Plugin<Project> {
6969
private static Integer _defaultParallel = null;
7070
private static Boolean _isBundledJdkSupported = null;
7171

72-
private final JavaInstallationRegistry javaInstallationRegistry;
73-
private final ObjectFactory objects;
72+
private final SharedJavaInstallationRegistry javaInstallationRegistry;
73+
private final JvmMetadataDetector metadataDetector;
7474
private final ProviderFactory providers;
7575

7676
@Inject
77-
public GlobalBuildInfoPlugin(JavaInstallationRegistry javaInstallationRegistry, ObjectFactory objects, ProviderFactory providers) {
77+
public GlobalBuildInfoPlugin(
78+
SharedJavaInstallationRegistry javaInstallationRegistry,
79+
JvmMetadataDetector metadataDetector,
80+
ProviderFactory providers
81+
) {
7882
this.javaInstallationRegistry = javaInstallationRegistry;
79-
this.objects = objects;
83+
this.metadataDetector = metadataDetector;
8084
this.providers = providers;
8185
}
8286

@@ -105,9 +109,10 @@ public void apply(Project project) {
105109
params.reset();
106110
params.setRuntimeJavaHome(runtimeJavaHome);
107111
params.setRuntimeJavaVersion(determineJavaVersion("runtime java.home", runtimeJavaHome, minimumRuntimeVersion));
108-
params.setIsRutimeJavaHomeSet(Jvm.current().getJavaHome().equals(runtimeJavaHome) == false);
109-
params.setRuntimeJavaDetails(getJavaInstallation(runtimeJavaHome).getImplementationName());
110-
params.setJavaVersions(getAvailableJavaVersions(minimumCompilerVersion));
112+
params.setIsRuntimeJavaHomeSet(Jvm.current().getJavaHome().equals(runtimeJavaHome) == false);
113+
JvmInstallationMetadata runtimeJdkMetaData = metadataDetector.getMetadata(getJavaInstallation(runtimeJavaHome).getLocation());
114+
params.setRuntimeJavaDetails(formatJavaVendorDetails(runtimeJdkMetaData));
115+
params.setJavaVersions(getAvailableJavaVersions());
111116
params.setMinimumCompilerVersion(minimumCompilerVersion);
112117
params.setMinimumRuntimeVersion(minimumRuntimeVersion);
113118
params.setGradleJavaVersion(Jvm.current().getJavaVersion());
@@ -129,6 +134,11 @@ public void apply(Project project) {
129134
project.getGradle().getTaskGraph().whenReady(graph -> logGlobalBuildInfo());
130135
}
131136

137+
private String formatJavaVendorDetails(JvmInstallationMetadata runtimeJdkMetaData) {
138+
JvmVendor vendor = runtimeJdkMetaData.getVendor();
139+
return runtimeJdkMetaData.getVendor().getKnownVendor().name() + "/" + vendor.getRawVendor();
140+
}
141+
132142
/* Introspect all versions of ES that may be tested against for backwards
133143
* compatibility. It is *super* important that this logic is the same as the
134144
* logic in VersionUtils.java. */
@@ -147,20 +157,22 @@ private void logGlobalBuildInfo() {
147157
final String osVersion = System.getProperty("os.version");
148158
final String osArch = System.getProperty("os.arch");
149159
final Jvm gradleJvm = Jvm.current();
150-
final String gradleJvmDetails = getJavaInstallation(gradleJvm.getJavaHome()).getImplementationName();
151-
160+
JvmInstallationMetadata gradleJvmMetadata = metadataDetector.getMetadata(gradleJvm.getJavaHome());
161+
final String gradleJvmVendorDetails = gradleJvmMetadata.getVendor().getDisplayName();
152162
LOGGER.quiet("=======================================");
153163
LOGGER.quiet("Elasticsearch Build Hamster says Hello!");
154164
LOGGER.quiet(" Gradle Version : " + GradleVersion.current().getVersion());
155165
LOGGER.quiet(" OS Info : " + osName + " " + osVersion + " (" + osArch + ")");
156166
if (BuildParams.getIsRuntimeJavaHomeSet()) {
157-
String runtimeJvmDetails = getJavaInstallation(BuildParams.getRuntimeJavaHome()).getImplementationName();
158-
LOGGER.quiet(" Runtime JDK Version : " + BuildParams.getRuntimeJavaVersion() + " (" + runtimeJvmDetails + ")");
167+
final String runtimeJvmVendorDetails = metadataDetector.getMetadata(BuildParams.getRuntimeJavaHome())
168+
.getVendor()
169+
.getDisplayName();
170+
LOGGER.quiet(" Runtime JDK Version : " + BuildParams.getRuntimeJavaVersion() + " (" + runtimeJvmVendorDetails + ")");
159171
LOGGER.quiet(" Runtime java.home : " + BuildParams.getRuntimeJavaHome());
160-
LOGGER.quiet(" Gradle JDK Version : " + gradleJvm.getJavaVersion() + " (" + gradleJvmDetails + ")");
172+
LOGGER.quiet(" Gradle JDK Version : " + gradleJvm.getJavaVersion() + " (" + gradleJvmVendorDetails + ")");
161173
LOGGER.quiet(" Gradle java.home : " + gradleJvm.getJavaHome());
162174
} else {
163-
LOGGER.quiet(" JDK Version : " + gradleJvm.getJavaVersion() + " (" + gradleJvmDetails + ")");
175+
LOGGER.quiet(" JDK Version : " + gradleJvm.getJavaVersion() + " (" + gradleJvmVendorDetails + ")");
164176
LOGGER.quiet(" JAVA_HOME : " + gradleJvm.getJavaHome());
165177
}
166178
LOGGER.quiet(" Random Testing Seed : " + BuildParams.getTestSeed());
@@ -169,8 +181,8 @@ private void logGlobalBuildInfo() {
169181
}
170182

171183
private JavaVersion determineJavaVersion(String description, File javaHome, JavaVersion requiredVersion) {
172-
JavaInstallation installation = getJavaInstallation(javaHome);
173-
JavaVersion actualVersion = installation.getJavaVersion();
184+
InstallationLocation installation = getJavaInstallation(javaHome);
185+
JavaVersion actualVersion = metadataDetector.getMetadata(installation.getLocation()).getLanguageVersion();
174186
if (actualVersion.isCompatibleWith(requiredVersion) == false) {
175187
throwInvalidJavaHomeException(
176188
description,
@@ -183,46 +195,38 @@ private JavaVersion determineJavaVersion(String description, File javaHome, Java
183195
return actualVersion;
184196
}
185197

186-
private JavaInstallation getJavaInstallation(File javaHome) {
187-
JavaInstallation installation;
188-
if (isCurrentJavaHome(javaHome)) {
189-
installation = javaInstallationRegistry.getInstallationForCurrentVirtualMachine().get();
190-
} else {
191-
installation = javaInstallationRegistry.installationForDirectory(objects.directoryProperty().fileValue(javaHome)).get();
192-
}
193-
194-
return installation;
198+
private InstallationLocation getJavaInstallation(File javaHome) {
199+
return getAvailableJavaInstallationLocationSteam().filter(installationLocation -> isSameFile(javaHome, installationLocation))
200+
.findFirst()
201+
.get();
195202
}
196203

197-
private List<JavaHome> getAvailableJavaVersions(JavaVersion minimumCompilerVersion) {
198-
final List<JavaHome> javaVersions = new ArrayList<>();
199-
for (int v = 8; v <= Integer.parseInt(minimumCompilerVersion.getMajorVersion()); v++) {
200-
int version = v;
201-
String javaHomeEnvVarName = getJavaHomeEnvVarName(Integer.toString(version));
202-
if (System.getenv(javaHomeEnvVarName) != null) {
203-
File javaHomeDirectory = new File(findJavaHome(Integer.toString(version)));
204-
Provider<JavaInstallation> javaInstallationProvider = javaInstallationRegistry.installationForDirectory(
205-
objects.directoryProperty().fileValue(javaHomeDirectory)
206-
);
207-
JavaHome javaHome = JavaHome.of(version, providers.provider(() -> {
208-
int actualVersion = Integer.parseInt(javaInstallationProvider.get().getJavaVersion().getMajorVersion());
209-
if (actualVersion != version) {
210-
throwInvalidJavaHomeException("env variable " + javaHomeEnvVarName, javaHomeDirectory, version, actualVersion);
211-
}
212-
return javaHomeDirectory;
213-
}));
214-
javaVersions.add(javaHome);
215-
}
204+
private boolean isSameFile(File javaHome, InstallationLocation installationLocation) {
205+
try {
206+
return Files.isSameFile(installationLocation.getLocation().toPath(), javaHome.toPath());
207+
} catch (IOException ioException) {
208+
throw new UncheckedIOException(ioException);
216209
}
217-
return javaVersions;
218210
}
219211

220-
private static boolean isCurrentJavaHome(File javaHome) {
221-
try {
222-
return Files.isSameFile(javaHome.toPath(), Jvm.current().getJavaHome().toPath());
223-
} catch (IOException e) {
224-
throw new UncheckedIOException(e);
225-
}
212+
/**
213+
* We resolve all available java versions using auto detected by gradles tool chain
214+
* To make transition more reliable we only take env var provided installations into account for now
215+
*/
216+
private List<JavaHome> getAvailableJavaVersions() {
217+
return getAvailableJavaInstallationLocationSteam().map(installationLocation -> {
218+
File installationDir = installationLocation.getLocation();
219+
JvmInstallationMetadata metadata = metadataDetector.getMetadata(installationDir);
220+
int actualVersion = Integer.parseInt(metadata.getLanguageVersion().getMajorVersion());
221+
return JavaHome.of(actualVersion, providers.provider(() -> installationDir));
222+
}).collect(Collectors.toList());
223+
}
224+
225+
private Stream<InstallationLocation> getAvailableJavaInstallationLocationSteam() {
226+
return Stream.concat(
227+
javaInstallationRegistry.listInstallations().stream(),
228+
Stream.of(new InstallationLocation(Jvm.current().getJavaHome(), "Current JVM"))
229+
);
226230
}
227231

228232
private static String getTestSeed() {

buildSrc/src/main/java/org/elasticsearch/gradle/precommit/JarHellPrecommitPlugin.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ public class JarHellPrecommitPlugin extends PrecommitPlugin {
3232
public TaskProvider<? extends Task> createTask(Project project) {
3333
Configuration jarHellConfig = project.getConfigurations().create("jarHell");
3434
if (BuildParams.isInternal() && project.getPath().equals(":libs:elasticsearch-core") == false) {
35+
// ideally we would configure this as a default dependency. But Default dependencies do not work correctly
36+
// with gradle project dependencies as they're resolved to late in the build and don't setup according task
37+
// dependencies properly
3538
project.getDependencies().add("jarHell", project.project(":libs:elasticsearch-core"));
3639
}
3740
TaskProvider<JarHellTask> jarHell = project.getTasks().register("jarHell", JarHellTask.class);

0 commit comments

Comments
 (0)