Browse Source

Consider time in BuildInfo up-to-date checks and allow it to be set

Closes gh-12111
Closes gh-12266
pull/12272/head
Andy Wilkinson 8 years ago
parent
commit
fdb9a1ea8f
  1. 10
      spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/asciidoc/integrating-with-actuator.adoc
  2. 3
      spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfo.java
  3. 30
      spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoProperties.java
  4. 43
      spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoIntegrationTests.java
  5. 27
      spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoTests.java
  6. 3
      spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoIntegrationTests.gradle
  7. 25
      spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/BuildPropertiesWriter.java
  8. 4
      spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildInfoMojo.java

10
spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/asciidoc/integrating-with-actuator.adoc

@ -38,6 +38,9 @@ By default, the generated build information is derived from the project: @@ -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: @@ -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"]

3
spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfo.java

@ -61,7 +61,8 @@ public class BuildInfo extends ConventionTask { @@ -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) {

30
spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoProperties.java

@ -17,6 +17,7 @@ @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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;
}

43
spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoIntegrationTests.java

@ -1,5 +1,5 @@ @@ -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 { @@ -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);
}
@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");
.isEqualTo(TaskOutcome.SUCCESS);
}
@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() {

27
spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoTests.java

@ -1,5 +1,5 @@ @@ -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; @@ -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 { @@ -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"));

3
spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoIntegrationTests.gradle

@ -16,5 +16,8 @@ task buildInfo(type: org.springframework.boot.gradle.tasks.buildinfo.BuildInfo) @@ -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
}
}
}

25
spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/BuildPropertiesWriter.java

@ -1,5 +1,5 @@ @@ -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; @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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;
}

4
spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildInfoMojo.java

@ -17,6 +17,7 @@ @@ -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 { @@ -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) {

Loading…
Cancel
Save