Consider time in BuildInfo up-to-date checks and allow it to be set
Closes gh-12111 Closes gh-12266
This commit is contained in:
@@ -38,6 +38,9 @@ By default, the generated build information is derived from the project:
|
||||
| `build.version`
|
||||
| The version of the project
|
||||
|
||||
| `build.time`
|
||||
| The time at which the project is being built
|
||||
|
||||
|===
|
||||
|
||||
The properties can be customized using the DSL:
|
||||
@@ -47,6 +50,13 @@ The properties can be customized using the DSL:
|
||||
include::../gradle/integrating-with-actuator/build-info-custom-values.gradle[tags=custom-values]
|
||||
----
|
||||
|
||||
The default value for `build.time` is the instant at which the project is being built. A
|
||||
side-effect of this is that the task will never be up-to-date and, therefore, builds will
|
||||
take slighly longer as more tasks will have to be executed. Another side-effect is that
|
||||
the task's output will always change and, therefore, the build will not be truly
|
||||
repeatable. If you value build performance or repeatability more highly than the accuracy
|
||||
of the `build.time` property, set `time` to `null` or a fixed value.
|
||||
|
||||
Additional properties can also be added to the build information:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim"]
|
||||
|
||||
@@ -61,7 +61,8 @@ public class BuildInfo extends ConventionTask {
|
||||
? "unspecified"
|
||||
: this.properties.getArtifact(),
|
||||
this.properties.getVersion(),
|
||||
this.properties.getName(), coerceToStringValues(
|
||||
this.properties.getName(), this.properties.getTime(),
|
||||
coerceToStringValues(
|
||||
this.properties.getAdditional())));
|
||||
}
|
||||
catch (IOException ex) {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.boot.gradle.tasks.buildinfo;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -40,10 +41,13 @@ public class BuildInfoProperties implements Serializable {
|
||||
|
||||
private String name;
|
||||
|
||||
private Instant time;
|
||||
|
||||
private Map<String, Object> additionalProperties = new HashMap<>();
|
||||
|
||||
BuildInfoProperties(Project project) {
|
||||
this.project = project;
|
||||
this.time = Instant.now();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,6 +125,23 @@ public class BuildInfoProperties implements Serializable {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value used for the {@code build.time} property. Defaults to
|
||||
* {@link Instant#now} when the {@code BuildInfoProperties} instance was created.
|
||||
* @return the time
|
||||
*/
|
||||
public Instant getTime() {
|
||||
return this.time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value used for the {@code build.time} property.
|
||||
* @param time the build time
|
||||
*/
|
||||
public void setTime(Instant time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the additional properties that will be included. When written, the name of
|
||||
* each additional property is prefixed with {@code build.}.
|
||||
@@ -152,6 +173,7 @@ public class BuildInfoProperties implements Serializable {
|
||||
result = prime * result + ((this.group == null) ? 0 : this.group.hashCode());
|
||||
result = prime * result + ((this.name == null) ? 0 : this.name.hashCode());
|
||||
result = prime * result + ((this.version == null) ? 0 : this.version.hashCode());
|
||||
result = prime * result + ((this.time == null) ? 0 : this.time.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -207,6 +229,14 @@ public class BuildInfoProperties implements Serializable {
|
||||
else if (!this.version.equals(other.version)) {
|
||||
return false;
|
||||
}
|
||||
if (this.time == null) {
|
||||
if (other.time != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!this.time.equals(other.time)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@@ -69,48 +69,19 @@ public class BuildInfoIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void upToDateWhenExecutedTwice() {
|
||||
public void notUpToDateWhenExecutedTwiceAsTimeChanges() {
|
||||
assertThat(this.gradleBuild.build("buildInfo").task(":buildInfo").getOutcome())
|
||||
.isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(this.gradleBuild.build("buildInfo").task(":buildInfo").getOutcome())
|
||||
.isEqualTo(TaskOutcome.UP_TO_DATE);
|
||||
.isEqualTo(TaskOutcome.SUCCESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notUpToDateWhenDestinationDirChanges() {
|
||||
notUpToDateWithChangeToProperty("buildInfoDestinationDir");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notUpToDateWhenProjectArtifactChanges() {
|
||||
notUpToDateWithChangeToProperty("buildInfoArtifact");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notUpToDateWhenProjectGroupChanges() {
|
||||
notUpToDateWithChangeToProperty("buildInfoGroup");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notUpToDateWhenProjectVersionChanges() {
|
||||
notUpToDateWithChangeToProperty("buildInfoVersion");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notUpToDateWhenProjectNameChanges() {
|
||||
notUpToDateWithChangeToProperty("buildInfoName");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notUpToDateWhenAdditionalPropertyChanges() {
|
||||
notUpToDateWithChangeToProperty("buildInfoAdditional");
|
||||
}
|
||||
|
||||
private void notUpToDateWithChangeToProperty(String name) {
|
||||
assertThat(this.gradleBuild.build("buildInfo", "--stacktrace").task(":buildInfo")
|
||||
public void upToDateWhenExecutedTwiceWithFixedTime() {
|
||||
assertThat(this.gradleBuild.build("buildInfo", "-PnullTime").task(":buildInfo")
|
||||
.getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(this.gradleBuild.build("buildInfo", "-P" + name + "=changed")
|
||||
.task(":buildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(this.gradleBuild.build("buildInfo", "-PnullTime").task(":buildInfo")
|
||||
.getOutcome()).isEqualTo(TaskOutcome.UP_TO_DATE);
|
||||
}
|
||||
|
||||
private Properties buildInfoProperties() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@@ -19,6 +19,8 @@ package org.springframework.boot.gradle.tasks.buildinfo;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
@@ -91,6 +93,29 @@ public class BuildInfoTests {
|
||||
assertThat(buildInfoProperties(task)).containsEntry("build.version", "2.3.4");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void timeIsSetInProperties() {
|
||||
BuildInfo task = createTask(createProject("test"));
|
||||
assertThat(buildInfoProperties(task)).containsEntry("build.time",
|
||||
DateTimeFormatter.ISO_INSTANT.format(task.getProperties().getTime()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void timeCanBeRemovedFromProperties() {
|
||||
BuildInfo task = createTask(createProject("test"));
|
||||
task.getProperties().setTime(null);
|
||||
assertThat(buildInfoProperties(task)).doesNotContainKey("build.time");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void timeCanBeCustomizedInProperties() {
|
||||
Instant now = Instant.now();
|
||||
BuildInfo task = createTask(createProject("test"));
|
||||
task.getProperties().setTime(now);
|
||||
assertThat(buildInfoProperties(task)).containsEntry("build.time",
|
||||
DateTimeFormatter.ISO_INSTANT.format(now));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalPropertiesAreReflectedInProperties() {
|
||||
BuildInfo task = createTask(createProject("test"));
|
||||
|
||||
@@ -16,5 +16,8 @@ task buildInfo(type: org.springframework.boot.gradle.tasks.buildinfo.BuildInfo)
|
||||
group = property('buildInfoGroup', 'foo')
|
||||
name = property('buildInfoName', 'foo')
|
||||
additional = ['additional': property('buildInfoAdditional', 'foo')]
|
||||
if (project.hasProperty('nullTime')) {
|
||||
time = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@@ -19,8 +19,8 @@ package org.springframework.boot.loader.tools;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.time.Instant;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Properties;
|
||||
@@ -74,7 +74,10 @@ public final class BuildPropertiesWriter {
|
||||
properties.put("build.artifact", project.getArtifact());
|
||||
properties.put("build.name", project.getName());
|
||||
properties.put("build.version", project.getVersion());
|
||||
properties.put("build.time", formatDate(new Date()));
|
||||
if (project.getTime() != null) {
|
||||
properties.put("build.time",
|
||||
DateTimeFormatter.ISO_INSTANT.format(project.getTime()));
|
||||
}
|
||||
if (project.getAdditionalProperties() != null) {
|
||||
for (Map.Entry<String, String> entry : project.getAdditionalProperties()
|
||||
.entrySet()) {
|
||||
@@ -84,11 +87,6 @@ public final class BuildPropertiesWriter {
|
||||
return properties;
|
||||
}
|
||||
|
||||
private String formatDate(Date date) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
|
||||
return sdf.format(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build-system agnostic details of a project.
|
||||
*/
|
||||
@@ -102,14 +100,17 @@ public final class BuildPropertiesWriter {
|
||||
|
||||
private final String version;
|
||||
|
||||
private final Instant time;
|
||||
|
||||
private final Map<String, String> additionalProperties;
|
||||
|
||||
public ProjectDetails(String group, String artifact, String version, String name,
|
||||
Map<String, String> additionalProperties) {
|
||||
Instant time, Map<String, String> additionalProperties) {
|
||||
this.group = group;
|
||||
this.artifact = artifact;
|
||||
this.name = name;
|
||||
this.version = version;
|
||||
this.time = time;
|
||||
validateAdditionalProperties(additionalProperties);
|
||||
this.additionalProperties = additionalProperties;
|
||||
}
|
||||
@@ -141,6 +142,10 @@ public final class BuildPropertiesWriter {
|
||||
return this.version;
|
||||
}
|
||||
|
||||
public Instant getTime() {
|
||||
return this.time;
|
||||
}
|
||||
|
||||
public Map<String, String> getAdditionalProperties() {
|
||||
return this.additionalProperties;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.boot.maven;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.maven.plugin.AbstractMojo;
|
||||
@@ -71,7 +72,8 @@ public class BuildInfoMojo extends AbstractMojo {
|
||||
new BuildPropertiesWriter(this.outputFile)
|
||||
.writeBuildProperties(new ProjectDetails(this.project.getGroupId(),
|
||||
this.project.getArtifactId(), this.project.getVersion(),
|
||||
this.project.getName(), this.additionalProperties));
|
||||
this.project.getName(), Instant.now(),
|
||||
this.additionalProperties));
|
||||
this.buildContext.refresh(this.outputFile);
|
||||
}
|
||||
catch (NullAdditionalPropertyValueException ex) {
|
||||
|
||||
Reference in New Issue
Block a user