Skip to content

Commit fdb9a1e

Browse files
committed
Consider time in BuildInfo up-to-date checks and allow it to be set
Closes spring-projectsgh-12111 Closes spring-projectsgh-12266
1 parent 6b3b790 commit fdb9a1e

File tree

8 files changed

+96
-49
lines changed

8 files changed

+96
-49
lines changed

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

+10
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ By default, the generated build information is derived from the project:
3838
| `build.version`
3939
| The version of the project
4040

41+
| `build.time`
42+
| The time at which the project is being built
43+
4144
|===
4245

4346
The properties can be customized using the DSL:
@@ -47,6 +50,13 @@ The properties can be customized using the DSL:
4750
include::../gradle/integrating-with-actuator/build-info-custom-values.gradle[tags=custom-values]
4851
----
4952

53+
The default value for `build.time` is the instant at which the project is being built. A
54+
side-effect of this is that the task will never be up-to-date and, therefore, builds will
55+
take slighly longer as more tasks will have to be executed. Another side-effect is that
56+
the task's output will always change and, therefore, the build will not be truly
57+
repeatable. If you value build performance or repeatability more highly than the accuracy
58+
of the `build.time` property, set `time` to `null` or a fixed value.
59+
5060
Additional properties can also be added to the build information:
5161

5262
[source,groovy,indent=0,subs="verbatim"]

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ public void generateBuildProperties() {
6161
? "unspecified"
6262
: this.properties.getArtifact(),
6363
this.properties.getVersion(),
64-
this.properties.getName(), coerceToStringValues(
64+
this.properties.getName(), this.properties.getTime(),
65+
coerceToStringValues(
6566
this.properties.getAdditional())));
6667
}
6768
catch (IOException ex) {

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

+30
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.boot.gradle.tasks.buildinfo;
1818

1919
import java.io.Serializable;
20+
import java.time.Instant;
2021
import java.util.HashMap;
2122
import java.util.Map;
2223

@@ -40,10 +41,13 @@ public class BuildInfoProperties implements Serializable {
4041

4142
private String name;
4243

44+
private Instant time;
45+
4346
private Map<String, Object> additionalProperties = new HashMap<>();
4447

4548
BuildInfoProperties(Project project) {
4649
this.project = project;
50+
this.time = Instant.now();
4751
}
4852

4953
/**
@@ -121,6 +125,23 @@ public void setName(String name) {
121125
this.name = name;
122126
}
123127

128+
/**
129+
* Returns the value used for the {@code build.time} property. Defaults to
130+
* {@link Instant#now} when the {@code BuildInfoProperties} instance was created.
131+
* @return the time
132+
*/
133+
public Instant getTime() {
134+
return this.time;
135+
}
136+
137+
/**
138+
* Sets the value used for the {@code build.time} property.
139+
* @param time the build time
140+
*/
141+
public void setTime(Instant time) {
142+
this.time = time;
143+
}
144+
124145
/**
125146
* Returns the additional properties that will be included. When written, the name of
126147
* each additional property is prefixed with {@code build.}.
@@ -152,6 +173,7 @@ public int hashCode() {
152173
result = prime * result + ((this.group == null) ? 0 : this.group.hashCode());
153174
result = prime * result + ((this.name == null) ? 0 : this.name.hashCode());
154175
result = prime * result + ((this.version == null) ? 0 : this.version.hashCode());
176+
result = prime * result + ((this.time == null) ? 0 : this.time.hashCode());
155177
return result;
156178
}
157179

@@ -207,6 +229,14 @@ else if (!this.name.equals(other.name)) {
207229
else if (!this.version.equals(other.version)) {
208230
return false;
209231
}
232+
if (this.time == null) {
233+
if (other.time != null) {
234+
return false;
235+
}
236+
}
237+
else if (!this.time.equals(other.time)) {
238+
return false;
239+
}
210240
return true;
211241
}
212242

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

+7-36
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2017 the original author or authors.
2+
* Copyright 2012-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -69,48 +69,19 @@ public void basicExecution() {
6969
}
7070

7171
@Test
72-
public void upToDateWhenExecutedTwice() {
72+
public void notUpToDateWhenExecutedTwiceAsTimeChanges() {
7373
assertThat(this.gradleBuild.build("buildInfo").task(":buildInfo").getOutcome())
7474
.isEqualTo(TaskOutcome.SUCCESS);
7575
assertThat(this.gradleBuild.build("buildInfo").task(":buildInfo").getOutcome())
76-
.isEqualTo(TaskOutcome.UP_TO_DATE);
77-
}
78-
79-
@Test
80-
public void notUpToDateWhenDestinationDirChanges() {
81-
notUpToDateWithChangeToProperty("buildInfoDestinationDir");
82-
}
83-
84-
@Test
85-
public void notUpToDateWhenProjectArtifactChanges() {
86-
notUpToDateWithChangeToProperty("buildInfoArtifact");
87-
}
88-
89-
@Test
90-
public void notUpToDateWhenProjectGroupChanges() {
91-
notUpToDateWithChangeToProperty("buildInfoGroup");
92-
}
93-
94-
@Test
95-
public void notUpToDateWhenProjectVersionChanges() {
96-
notUpToDateWithChangeToProperty("buildInfoVersion");
97-
}
98-
99-
@Test
100-
public void notUpToDateWhenProjectNameChanges() {
101-
notUpToDateWithChangeToProperty("buildInfoName");
76+
.isEqualTo(TaskOutcome.SUCCESS);
10277
}
10378

10479
@Test
105-
public void notUpToDateWhenAdditionalPropertyChanges() {
106-
notUpToDateWithChangeToProperty("buildInfoAdditional");
107-
}
108-
109-
private void notUpToDateWithChangeToProperty(String name) {
110-
assertThat(this.gradleBuild.build("buildInfo", "--stacktrace").task(":buildInfo")
80+
public void upToDateWhenExecutedTwiceWithFixedTime() {
81+
assertThat(this.gradleBuild.build("buildInfo", "-PnullTime").task(":buildInfo")
11182
.getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
112-
assertThat(this.gradleBuild.build("buildInfo", "-P" + name + "=changed")
113-
.task(":buildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
83+
assertThat(this.gradleBuild.build("buildInfo", "-PnullTime").task(":buildInfo")
84+
.getOutcome()).isEqualTo(TaskOutcome.UP_TO_DATE);
11485
}
11586

11687
private Properties buildInfoProperties() {

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

+26-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2017 the original author or authors.
2+
* Copyright 2012-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,6 +19,8 @@
1919
import java.io.File;
2020
import java.io.FileReader;
2121
import java.io.IOException;
22+
import java.time.Instant;
23+
import java.time.format.DateTimeFormatter;
2224
import java.util.Properties;
2325

2426
import org.gradle.api.Project;
@@ -91,6 +93,29 @@ public void customVersionIsReflectedInProperties() {
9193
assertThat(buildInfoProperties(task)).containsEntry("build.version", "2.3.4");
9294
}
9395

96+
@Test
97+
public void timeIsSetInProperties() {
98+
BuildInfo task = createTask(createProject("test"));
99+
assertThat(buildInfoProperties(task)).containsEntry("build.time",
100+
DateTimeFormatter.ISO_INSTANT.format(task.getProperties().getTime()));
101+
}
102+
103+
@Test
104+
public void timeCanBeRemovedFromProperties() {
105+
BuildInfo task = createTask(createProject("test"));
106+
task.getProperties().setTime(null);
107+
assertThat(buildInfoProperties(task)).doesNotContainKey("build.time");
108+
}
109+
110+
@Test
111+
public void timeCanBeCustomizedInProperties() {
112+
Instant now = Instant.now();
113+
BuildInfo task = createTask(createProject("test"));
114+
task.getProperties().setTime(now);
115+
assertThat(buildInfoProperties(task)).containsEntry("build.time",
116+
DateTimeFormatter.ISO_INSTANT.format(now));
117+
}
118+
94119
@Test
95120
public void additionalPropertiesAreReflectedInProperties() {
96121
BuildInfo task = createTask(createProject("test"));

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

+3
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,8 @@ task buildInfo(type: org.springframework.boot.gradle.tasks.buildinfo.BuildInfo)
1616
group = property('buildInfoGroup', 'foo')
1717
name = property('buildInfoName', 'foo')
1818
additional = ['additional': property('buildInfoAdditional', 'foo')]
19+
if (project.hasProperty('nullTime')) {
20+
time = null
21+
}
1922
}
2023
}

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

+15-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2017 the original author or authors.
2+
* Copyright 2012-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,8 +19,8 @@
1919
import java.io.File;
2020
import java.io.FileOutputStream;
2121
import java.io.IOException;
22-
import java.text.SimpleDateFormat;
23-
import java.util.Date;
22+
import java.time.Instant;
23+
import java.time.format.DateTimeFormatter;
2424
import java.util.Map;
2525
import java.util.Map.Entry;
2626
import java.util.Properties;
@@ -74,7 +74,10 @@ protected Properties createBuildInfo(ProjectDetails project) {
7474
properties.put("build.artifact", project.getArtifact());
7575
properties.put("build.name", project.getName());
7676
properties.put("build.version", project.getVersion());
77-
properties.put("build.time", formatDate(new Date()));
77+
if (project.getTime() != null) {
78+
properties.put("build.time",
79+
DateTimeFormatter.ISO_INSTANT.format(project.getTime()));
80+
}
7881
if (project.getAdditionalProperties() != null) {
7982
for (Map.Entry<String, String> entry : project.getAdditionalProperties()
8083
.entrySet()) {
@@ -84,11 +87,6 @@ protected Properties createBuildInfo(ProjectDetails project) {
8487
return properties;
8588
}
8689

87-
private String formatDate(Date date) {
88-
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
89-
return sdf.format(date);
90-
}
91-
9290
/**
9391
* Build-system agnostic details of a project.
9492
*/
@@ -102,14 +100,17 @@ public static final class ProjectDetails {
102100

103101
private final String version;
104102

103+
private final Instant time;
104+
105105
private final Map<String, String> additionalProperties;
106106

107107
public ProjectDetails(String group, String artifact, String version, String name,
108-
Map<String, String> additionalProperties) {
108+
Instant time, Map<String, String> additionalProperties) {
109109
this.group = group;
110110
this.artifact = artifact;
111111
this.name = name;
112112
this.version = version;
113+
this.time = time;
113114
validateAdditionalProperties(additionalProperties);
114115
this.additionalProperties = additionalProperties;
115116
}
@@ -141,6 +142,10 @@ public String getVersion() {
141142
return this.version;
142143
}
143144

145+
public Instant getTime() {
146+
return this.time;
147+
}
148+
144149
public Map<String, String> getAdditionalProperties() {
145150
return this.additionalProperties;
146151
}

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

+3-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.boot.maven;
1818

1919
import java.io.File;
20+
import java.time.Instant;
2021
import java.util.Map;
2122

2223
import org.apache.maven.plugin.AbstractMojo;
@@ -71,7 +72,8 @@ public void execute() throws MojoExecutionException, MojoFailureException {
7172
new BuildPropertiesWriter(this.outputFile)
7273
.writeBuildProperties(new ProjectDetails(this.project.getGroupId(),
7374
this.project.getArtifactId(), this.project.getVersion(),
74-
this.project.getName(), this.additionalProperties));
75+
this.project.getName(), Instant.now(),
76+
this.additionalProperties));
7577
this.buildContext.refresh(this.outputFile);
7678
}
7779
catch (NullAdditionalPropertyValueException ex) {

0 commit comments

Comments
 (0)