Wrap VersionPropertiesLoader in a BuildService to decouple build logic projects (#78704)

By using a BuildService we can decouple the configuration of projects but keep making
expensive operations (e.g. parsing properties file or reading minimumJavaCompiler from file) only once
per build.

This bring us closer to decouple projects and get ultimatively configuration cache compliant. In
general we will bring in more BuildServices for the main build to follow along that Pattern and
ultimatevely remove usages of allprojects and subprojects in our build.
This commit is contained in:
Rene Groeschke 2021-10-07 18:00:21 +02:00 committed by GitHub
parent 5823ad695d
commit f16a6990bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 141 additions and 30 deletions

View File

@ -45,6 +45,10 @@ gradlePlugin {
id = 'elasticsearch.build-tools'
implementationClass = 'org.elasticsearch.gradle.internal.conventions.BuildToolsConventionsPlugin'
}
versions {
id = 'elasticsearch.versions'
implementationClass = 'org.elasticsearch.gradle.internal.conventions.VersionPropertiesPlugin'
}
}
}

View File

@ -0,0 +1,67 @@
/*
* 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 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 or the Server
* Side Public License, v 1.
*/
package org.elasticsearch.gradle.internal.conventions;
import org.apache.commons.io.FileUtils;
import org.gradle.api.GradleException;
import org.gradle.api.JavaVersion;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.ProviderFactory;
import org.gradle.api.services.BuildService;
import org.gradle.api.services.BuildServiceParameters;
import org.gradle.initialization.layout.BuildLayout;
import org.gradle.initialization.layout.BuildLayoutFactory;
import javax.inject.Inject;
import java.io.File;
import java.io.IOException;
import java.util.Properties;
import java.util.function.Function;
abstract class VersionPropertiesBuildService implements BuildService<VersionPropertiesBuildService.Params>, AutoCloseable {
private final Properties properties;
@Inject
public VersionPropertiesBuildService(ProviderFactory providerFactory) {
File infoPath = getParameters().getInfoPath().getAsFile().get();
try {
File propertiesInputFile = new File(infoPath, "version.properties");
properties = VersionPropertiesLoader.loadBuildSrcVersion(propertiesInputFile, providerFactory);
properties.computeIfAbsent("minimumJava", s -> resolveMinimumJavaVersion(infoPath));
} catch (IOException e) {
throw new GradleException("Cannot load VersionPropertiesBuildService", e);
}
}
private JavaVersion resolveMinimumJavaVersion(File infoPath) {
final JavaVersion minimumJavaVersion;
File minimumJavaInfoSource = new File(infoPath, "src/main/resources/minimumCompilerVersion");
try {
String versionString = FileUtils.readFileToString(minimumJavaInfoSource);
minimumJavaVersion = JavaVersion.toVersion(versionString);
} catch (IOException e) {
throw new GradleException("Cannot resolve minimum compiler version via VersionPropertiesBuildService", e);
}
return minimumJavaVersion;
}
public Properties getProperties() {
return properties;
}
@Override
public void close() throws Exception {
}
public interface Params extends BuildServiceParameters {
RegularFileProperty getInfoPath();
}
}

View File

@ -0,0 +1,38 @@
/*
* 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 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 or the Server
* Side Public License, v 1.
*/
package org.elasticsearch.gradle.internal.conventions;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.provider.Provider;
import org.gradle.initialization.layout.BuildLayout;
import javax.inject.Inject;
import java.io.File;
public class VersionPropertiesPlugin implements Plugin<Project> {
private BuildLayout buildLayout;
@Inject
VersionPropertiesPlugin(BuildLayout buildLayout) {
this.buildLayout = buildLayout;
}
@Override
public void apply(Project project) {
// Register the service if not done yet
File infoPath = new File(buildLayout.getRootDirectory(), "build-tools-internal");
Provider<VersionPropertiesBuildService> serviceProvider = project.getGradle().getSharedServices()
.registerIfAbsent("versions", VersionPropertiesBuildService.class, spec -> {
spec.getParameters().getInfoPath().set(infoPath);
});
project.getExtensions().add("versions", serviceProvider.forUseAtConfigurationTime().get().getProperties());
}
}

View File

@ -19,6 +19,7 @@ plugins {
id 'groovy'
id 'elasticsearch.build-tools'
id 'elasticsearch.eclipse'
id 'elasticsearch.versions'
}
group = 'org.elasticsearch.gradle'
@ -26,8 +27,7 @@ group = 'org.elasticsearch.gradle'
// we update the version property to reflect if we are building a snapshot or a release build
// we write this back out below to load it in the Build.java which will be shown in rest main action
// to indicate this being a snapshot build or a release build.
Properties props = VersionPropertiesLoader.loadBuildSrcVersion(project.file('version.properties'), project.getProviders())
version = props.getProperty("elasticsearch")
version = versions.getProperty("elasticsearch")
gradlePlugin {
// We already configure publication and we don't need or want the one that comes
@ -169,7 +169,7 @@ gradlePlugin {
* Java version *
*****************************************************************************/
def minCompilerJava = JavaVersion.toVersion(file('src/main/resources/minimumCompilerVersion').text)
def minCompilerJava = versions.get("minimumJava")
targetCompatibility = minCompilerJava
sourceCompatibility = minCompilerJava
@ -226,22 +226,22 @@ dependencies {
api 'com.avast.gradle:gradle-docker-compose-plugin:0.14.0'
api 'org.apache.maven:maven-model:3.6.2'
api 'com.networknt:json-schema-validator:1.0.36'
api "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:${props.getProperty('jackson')}"
api "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:${versions.getProperty('jackson')}"
api 'org.ow2.asm:asm:9.0'
api 'org.ow2.asm:asm-tree:9.0'
api "org.apache.httpcomponents:httpclient:${props.getProperty('httpclient')}"
api "org.apache.httpcomponents:httpcore:${props.getProperty('httpcore')}"
compileOnly "com.puppycrawl.tools:checkstyle:${props.getProperty('checkstyle')}"
api "org.apache.httpcomponents:httpclient:${versions.getProperty('httpclient')}"
api "org.apache.httpcomponents:httpcore:${versions.getProperty('httpcore')}"
compileOnly "com.puppycrawl.tools:checkstyle:${versions.getProperty('checkstyle')}"
runtimeOnly "org.elasticsearch.gradle:reaper:$version"
testImplementation "com.puppycrawl.tools:checkstyle:${props.getProperty('checkstyle')}"
testImplementation "junit:junit:${props.getProperty('junit')}"
testImplementation "com.puppycrawl.tools:checkstyle:${versions.getProperty('checkstyle')}"
testImplementation "junit:junit:${versions.getProperty('junit')}"
testImplementation 'com.github.tomakehurst:wiremock-jre8-standalone:2.23.2'
testImplementation 'org.mockito:mockito-core:1.9.5'
testImplementation "org.hamcrest:hamcrest:${props.getProperty('hamcrest')}"
testImplementation "org.hamcrest:hamcrest:${versions.getProperty('hamcrest')}"
testImplementation testFixtures("org.elasticsearch.gradle:build-tools:$version")
integTestImplementation(platform("org.junit:junit-bom:${props.getProperty('junit5')}"))
integTestImplementation(platform("org.junit:junit-bom:${versions.getProperty('junit5')}"))
integTestImplementation("org.junit.jupiter:junit-jupiter") {
because 'allows to write and run Jupiter tests'
}

View File

@ -13,25 +13,16 @@ plugins {
id 'java-test-fixtures'
id 'elasticsearch.publish'
id 'elasticsearch.build-tools'
id 'elasticsearch.eclipse'
id 'elasticsearch.versions'
}
description = "The elasticsearch build tools"
// we update the version property to reflect if we are building a snapshot or a release build
// we write this back out below to load it in the Build.java which will be shown in rest main action
// to indicate this being a snapshot build or a release build.
Properties props = VersionPropertiesLoader.loadBuildSrcVersion(project.file('../build-tools-internal/version.properties'), project.getProviders())
def minRuntimeJava = JavaVersion.toVersion(file('../build-tools-internal/src/main/resources/minimumRuntimeVersion').text)
allprojects {
group = "org.elasticsearch.gradle"
version = props.getProperty("elasticsearch")
apply plugin: 'java'
apply plugin: 'elasticsearch.eclipse'
targetCompatibility = minRuntimeJava
sourceCompatibility = minRuntimeJava
}
version = versions.getProperty("elasticsearch")
targetCompatibility = versions.get("minimumJava")
sourceCompatibility = versions.get("minimumJava")
gradlePlugin {
// We already configure publication and we don't need or want the one that comes
@ -69,10 +60,13 @@ gradlePlugin {
}
}
// we update the version property to reflect if we are building a snapshot or a release build
// we write this back out below to load it in the Build.java which will be shown in rest main action
// to indicate this being a snapshot build or a release build.
def generateVersionProperties = tasks.register("generateVersionProperties", WriteProperties) {
outputFile = "${buildDir}/version.properties"
comment = 'Generated version properties'
properties(props)
properties(versions)
}
tasks.named("processResources").configure {
@ -118,8 +112,8 @@ dependencies {
api 'org.apache.ant:ant:1.10.8'
api 'commons-io:commons-io:2.2'
testFixturesApi "junit:junit:${props.getProperty('junit')}"
testFixturesApi "com.carrotsearch.randomizedtesting:randomizedtesting-runner:${props.getProperty('randomizedrunner')}"
testFixturesApi "junit:junit:${versions.getProperty('junit')}"
testFixturesApi "com.carrotsearch.randomizedtesting:randomizedtesting-runner:${versions.getProperty('randomizedrunner')}"
testFixturesApi gradleApi()
testFixturesApi gradleTestKit()
testFixturesApi 'com.github.tomakehurst:wiremock-jre8-standalone:2.23.2'
@ -132,7 +126,7 @@ dependencies {
because 'required as we rely on junit4 rules'
}
integTestImplementation(platform("org.junit:junit-bom:${props.getProperty('junit5')}"))
integTestImplementation(platform("org.junit:junit-bom:${versions.getProperty('junit5')}"))
integTestImplementation("org.junit.jupiter:junit-jupiter") {
because 'allows to write and run Jupiter tests'
}

View File

@ -1,7 +1,14 @@
plugins {
id 'java'
id 'elasticsearch.eclipse'
id 'elasticsearch.versions'
}
group = "org.elasticsearch.gradle"
version = versions.getProperty("elasticsearch")
targetCompatibility = versions.get("minimumJava")
sourceCompatibility = versions.get("minimumJava")
tasks.named("jar").configure {
archiveFileName = "${project.name}.jar"
manifest {

View File

@ -46,6 +46,7 @@ plugins {
id 'elasticsearch.internal-testclusters'
id 'elasticsearch.run'
id 'elasticsearch.release-tools'
id 'elasticsearch.versions'
id "com.diffplug.spotless" version "5.15.1" apply false
}