Update BuildInfo to support Gradle's configuration cache
See gh-22922
This commit is contained in:
parent
83cfd3b2e6
commit
d1f543fc1d
|
@ -24,6 +24,7 @@ import java.util.Map;
|
|||
import org.gradle.api.Action;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.Task;
|
||||
import org.gradle.api.file.DirectoryProperty;
|
||||
import org.gradle.api.internal.ConventionTask;
|
||||
import org.gradle.api.tasks.Nested;
|
||||
import org.gradle.api.tasks.OutputDirectory;
|
||||
|
@ -44,7 +45,12 @@ public class BuildInfo extends ConventionTask {
|
|||
|
||||
private final BuildInfoProperties properties = new BuildInfoProperties(getProject());
|
||||
|
||||
private File destinationDir;
|
||||
private final DirectoryProperty destinationDir;
|
||||
|
||||
public BuildInfo() {
|
||||
this.destinationDir = getProject().getObjects().directoryProperty()
|
||||
.convention(getProject().getLayout().getBuildDirectory());
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the {@code build-info.properties} file in the configured
|
||||
|
@ -73,7 +79,7 @@ public class BuildInfo extends ConventionTask {
|
|||
*/
|
||||
@OutputDirectory
|
||||
public File getDestinationDir() {
|
||||
return (this.destinationDir != null) ? this.destinationDir : getProject().getBuildDir();
|
||||
return this.destinationDir.getAsFile().get();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -81,7 +87,7 @@ public class BuildInfo extends ConventionTask {
|
|||
* @param destinationDir the destination directory
|
||||
*/
|
||||
public void setDestinationDir(File destinationDir) {
|
||||
this.destinationDir = destinationDir;
|
||||
this.destinationDir.set(destinationDir);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
package org.springframework.boot.gradle.tasks.buildinfo;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
|
@ -23,6 +25,7 @@ import java.util.Map;
|
|||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.provider.Provider;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.Optional;
|
||||
|
||||
|
@ -35,6 +38,8 @@ import org.gradle.api.tasks.Optional;
|
|||
@SuppressWarnings("serial")
|
||||
public class BuildInfoProperties implements Serializable {
|
||||
|
||||
private transient Instant creationTime = Instant.now();
|
||||
|
||||
private final Property<String> group;
|
||||
|
||||
private final Property<String> artifact;
|
||||
|
@ -43,22 +48,35 @@ public class BuildInfoProperties implements Serializable {
|
|||
|
||||
private final Property<String> name;
|
||||
|
||||
private final Property<Instant> time;
|
||||
private final Property<Long> time;
|
||||
|
||||
private boolean timeConfigured = false;
|
||||
|
||||
private Map<String, Object> additionalProperties = new HashMap<>();
|
||||
|
||||
BuildInfoProperties(Project project) {
|
||||
this.time = project.getObjects().property(Instant.class);
|
||||
this.time.set(Instant.now());
|
||||
this.time = project.getObjects().property(Long.class);
|
||||
this.group = project.getObjects().property(String.class);
|
||||
this.group.set(project.provider(() -> project.getGroup().toString()));
|
||||
this.artifact = project.getObjects().property(String.class);
|
||||
this.version = project.getObjects().property(String.class);
|
||||
this.version.set(project.provider(() -> project.getVersion().toString()));
|
||||
this.version.set(projectVersion(project));
|
||||
this.name = project.getObjects().property(String.class);
|
||||
this.name.set(project.provider(project::getName));
|
||||
}
|
||||
|
||||
private Provider<String> projectVersion(Project project) {
|
||||
try {
|
||||
Provider<String> externalVersionProperty = project.getProviders().gradleProperty("version")
|
||||
.forUseAtConfigurationTime();
|
||||
externalVersionProperty.getOrNull();
|
||||
}
|
||||
catch (NoSuchMethodError ex) {
|
||||
// Gradle < 6.5
|
||||
}
|
||||
return project.provider(() -> project.getVersion().toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value used for the {@code build.group} property. Defaults to the
|
||||
* {@link Project#getGroup() Project's group}.
|
||||
|
@ -142,7 +160,14 @@ public class BuildInfoProperties implements Serializable {
|
|||
@Input
|
||||
@Optional
|
||||
public Instant getTime() {
|
||||
return this.time.getOrNull();
|
||||
Long epochMillis = this.time.getOrNull();
|
||||
if (epochMillis != null) {
|
||||
return Instant.ofEpochMilli(epochMillis);
|
||||
}
|
||||
if (this.timeConfigured) {
|
||||
return null;
|
||||
}
|
||||
return this.creationTime;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -150,7 +175,8 @@ public class BuildInfoProperties implements Serializable {
|
|||
* @param time the build time
|
||||
*/
|
||||
public void setTime(Instant time) {
|
||||
this.time.set(time);
|
||||
this.timeConfigured = true;
|
||||
this.time.set((time != null) ? time.toEpochMilli() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -173,4 +199,9 @@ public class BuildInfoProperties implements Serializable {
|
|||
this.additionalProperties = additionalProperties;
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream input) throws ClassNotFoundException, IOException {
|
||||
input.defaultReadObject();
|
||||
this.creationTime = Instant.now();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,9 +19,13 @@ package org.springframework.boot.gradle.tasks.buildinfo;
|
|||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.time.Instant;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.gradle.testkit.runner.BuildResult;
|
||||
import org.gradle.testkit.runner.InvalidRunnerConfigurationException;
|
||||
import org.gradle.testkit.runner.TaskOutcome;
|
||||
import org.gradle.testkit.runner.UnexpectedBuildFailure;
|
||||
|
@ -38,7 +42,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@GradleCompatibility
|
||||
@GradleCompatibility(configurationCache = true)
|
||||
class BuildInfoIntegrationTests {
|
||||
|
||||
GradleBuild gradleBuild;
|
||||
|
@ -69,7 +73,14 @@ class BuildInfoIntegrationTests {
|
|||
@TestTemplate
|
||||
void notUpToDateWhenExecutedTwiceAsTimeChanges() {
|
||||
assertThat(this.gradleBuild.build("buildInfo").task(":buildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
Properties first = buildInfoProperties();
|
||||
String firstBuildTime = first.getProperty("build.time");
|
||||
assertThat(firstBuildTime).isNotNull();
|
||||
assertThat(this.gradleBuild.build("buildInfo").task(":buildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
Properties second = buildInfoProperties();
|
||||
String secondBuildTime = second.getProperty("build.time");
|
||||
assertThat(secondBuildTime).isNotNull();
|
||||
assertThat(Instant.parse(firstBuildTime).isBefore(Instant.parse(secondBuildTime)));
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
|
@ -81,11 +92,22 @@ class BuildInfoIntegrationTests {
|
|||
}
|
||||
|
||||
@TestTemplate
|
||||
void notUpToDateWhenExecutedTwiceWithFixedTimeAndChangedProjectVersion() {
|
||||
assertThat(this.gradleBuild.build("buildInfo", "-PnullTime").task(":buildInfo").getOutcome())
|
||||
.isEqualTo(TaskOutcome.SUCCESS);
|
||||
BuildResult result = this.gradleBuild.build("buildInfo", "-PnullTime", "-PprojectVersion=0.2.0");
|
||||
assertThat(result.task(":buildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
void notUpToDateWhenExecutedTwiceWithFixedTimeAndChangedProjectVersion() throws IOException {
|
||||
assertThat(this.gradleBuild.scriptProperty("projectVersion", "0.1.0").build("buildInfo").task(":buildInfo")
|
||||
.getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(this.gradleBuild.scriptProperty("projectVersion", "0.2.0").build("buildInfo").task(":buildInfo")
|
||||
.getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
void notUpToDateWhenExecutedTwiceWithFixedTimeAndChangedGradlePropertiesProjectVersion() throws IOException {
|
||||
Path gradleProperties = new File(this.gradleBuild.getProjectDir(), "gradle.properties").toPath();
|
||||
Files.write(gradleProperties, "version=0.1.0".getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE,
|
||||
StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);
|
||||
assertThat(this.gradleBuild.build("buildInfo").task(":buildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
Files.write(gradleProperties, "version=0.2.0".getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE,
|
||||
StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);
|
||||
assertThat(this.gradleBuild.build("buildInfo").task(":buildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
|
|
|
@ -24,6 +24,8 @@ import java.time.format.DateTimeFormatter;
|
|||
import java.util.Properties;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.internal.project.ProjectInternal;
|
||||
import org.gradle.initialization.GradlePropertiesController;
|
||||
import org.gradle.testfixtures.ProjectBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
@ -125,7 +127,10 @@ class BuildInfoTests {
|
|||
|
||||
private Project createProject(String projectName) {
|
||||
File projectDir = new File(this.temp, projectName);
|
||||
return ProjectBuilder.builder().withProjectDir(projectDir).withName(projectName).build();
|
||||
Project project = ProjectBuilder.builder().withProjectDir(projectDir).withName(projectName).build();
|
||||
((ProjectInternal) project).getServices().get(GradlePropertiesController.class)
|
||||
.loadGradlePropertiesFrom(projectDir);
|
||||
return project;
|
||||
}
|
||||
|
||||
private BuildInfo createTask(Project project) {
|
||||
|
|
|
@ -176,7 +176,7 @@ public class GradleBuild {
|
|||
new File(this.projectDir, "repository"));
|
||||
GradleRunner gradleRunner = GradleRunner.create().withProjectDir(this.projectDir)
|
||||
.withPluginClasspath(pluginClasspath());
|
||||
if (this.dsl != Dsl.KOTLIN) {
|
||||
if (this.dsl != Dsl.KOTLIN && !this.configurationCache) {
|
||||
// see https://github.com/gradle/gradle/issues/6862
|
||||
gradleRunner.withDebug(true);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
plugins {
|
||||
id 'org.springframework.boot' version '{version}' apply false
|
||||
}
|
||||
|
||||
version = '0.1.0'
|
||||
|
||||
task buildInfo(type: org.springframework.boot.gradle.tasks.buildinfo.BuildInfo) {
|
||||
destinationDir project.buildDir
|
||||
properties {
|
||||
artifact = 'foo'
|
||||
group = 'foo'
|
||||
name = 'foo'
|
||||
additional = ['additional': 'foo']
|
||||
}
|
||||
}
|
|
@ -2,8 +2,4 @@ plugins {
|
|||
id 'org.springframework.boot' version '{version}' apply false
|
||||
}
|
||||
|
||||
def property(String name, Object defaultValue) {
|
||||
project.hasProperty(name) ? project.getProperty(name) : defaultValue
|
||||
}
|
||||
|
||||
task buildInfo(type: org.springframework.boot.gradle.tasks.buildinfo.BuildInfo)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
plugins {
|
||||
id 'org.springframework.boot' version '{version}' apply false
|
||||
}
|
||||
|
||||
task buildInfo(type: org.springframework.boot.gradle.tasks.buildinfo.BuildInfo)
|
|
@ -0,0 +1,13 @@
|
|||
plugins {
|
||||
id 'org.springframework.boot' version '{version}' apply false
|
||||
}
|
||||
|
||||
task buildInfo(type: org.springframework.boot.gradle.tasks.buildinfo.BuildInfo) {
|
||||
properties {
|
||||
artifact = 'example'
|
||||
group = 'com.example'
|
||||
name = 'example'
|
||||
additional = ['additional': 'alpha']
|
||||
time = null
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
plugins {
|
||||
id 'org.springframework.boot' version '{version}' apply false
|
||||
}
|
||||
|
||||
version = '{projectVersion}'
|
||||
|
||||
task buildInfo(type: org.springframework.boot.gradle.tasks.buildinfo.BuildInfo) {
|
||||
properties {
|
||||
artifact = 'example'
|
||||
group = 'com.example'
|
||||
name = 'example'
|
||||
additional = ['additional': 'alpha']
|
||||
time = null
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
plugins {
|
||||
id 'org.springframework.boot' version '{version}' apply false
|
||||
}
|
||||
|
||||
task buildInfo(type: org.springframework.boot.gradle.tasks.buildinfo.BuildInfo) {
|
||||
properties {
|
||||
time = null
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
plugins {
|
||||
id 'org.springframework.boot' version '{version}' apply false
|
||||
}
|
||||
|
||||
task buildInfo(type: org.springframework.boot.gradle.tasks.buildinfo.BuildInfo) {
|
||||
properties {
|
||||
time = null
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
plugins {
|
||||
id 'org.springframework.boot' version '{version}' apply false
|
||||
}
|
||||
|
||||
def property(String name, Object defaultValue) {
|
||||
project.hasProperty(name) ? project.getProperty(name) : defaultValue
|
||||
}
|
||||
|
||||
version = property('projectVersion', '0.1.0')
|
||||
|
||||
task buildInfo(type: org.springframework.boot.gradle.tasks.buildinfo.BuildInfo) {
|
||||
destinationDir file(property('buildInfoDestinationDir', project.buildDir))
|
||||
properties {
|
||||
artifact = property('buildInfoArtifact', 'foo')
|
||||
group = property('buildInfoGroup', 'foo')
|
||||
name = property('buildInfoName', 'foo')
|
||||
additional = ['additional': property('buildInfoAdditional', 'foo')]
|
||||
if (project.hasProperty('nullTime')) {
|
||||
time = null
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue