Allow build info properties to be excluded

Update Maven and Gradle plugins to allow build info properties to be
excluded.

Prior to this commit, the `BuildPropertiesWriter` would fail with an
NPE if the group, artifact, name or version properties were `null`.

This was specifically problematic with the Gradle plugin, since its
DSL allows `null` properties which would either be passed to the writer
or, in the case of `artifact`, converted into a string value of
"unspecified".

See gh-27412
This commit is contained in:
Vedran Pavic
2021-07-16 21:57:57 +02:00
committed by Phillip Webb
parent 2034ad4827
commit ea9faf8690
13 changed files with 355 additions and 26 deletions

View File

@@ -30,8 +30,7 @@ By default, the generated build information is derived from the project:
| Property | Default value
| `build.artifact`
| The base name of the `bootJar` or `bootWar` task, or `unspecified` if no such task
exists
| The base name of the `bootJar` or `bootWar` task
| `build.group`
| The group of the project
@@ -61,6 +60,8 @@ include::../gradle/integrating-with-actuator/build-info-custom-values.gradle[tag
include::../gradle/integrating-with-actuator/build-info-custom-values.gradle.kts[tags=custom-values]
----
NOTE: To omit any of the default properties from the generated build information, set its value to `null`.
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.
As a result, builds will take longer as more tasks, including the project's tests, will have to be executed.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2021 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.
@@ -60,12 +60,9 @@ public class BuildInfo extends ConventionTask {
public void generateBuildProperties() {
try {
new BuildPropertiesWriter(new File(getDestinationDir(), "build-info.properties"))
.writeBuildProperties(
new ProjectDetails(this.properties.getGroup(),
(this.properties.getArtifact() != null) ? this.properties.getArtifact()
: "unspecified",
this.properties.getVersion(), this.properties.getName(), this.properties.getTime(),
coerceToStringValues(this.properties.getAdditional())));
.writeBuildProperties(new ProjectDetails(this.properties.getGroup(), this.properties.getArtifact(),
this.properties.getVersion(), this.properties.getName(), this.properties.getTime(),
coerceToStringValues(this.properties.getAdditional())));
}
catch (IOException ex) {
throw new TaskExecutionException(this, ex);

View File

@@ -39,6 +39,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* Integration tests for the {@link BuildInfo} task.
*
* @author Andy Wilkinson
* @author Vedran Pavic
*/
@GradleCompatibility(configurationCache = true)
class BuildInfoIntegrationTests {
@@ -50,8 +51,8 @@ class BuildInfoIntegrationTests {
assertThat(this.gradleBuild.build("buildInfo").task(":buildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
Properties buildInfoProperties = buildInfoProperties();
assertThat(buildInfoProperties).containsKey("build.time");
assertThat(buildInfoProperties).containsEntry("build.artifact", "unspecified");
assertThat(buildInfoProperties).containsEntry("build.group", "");
assertThat(buildInfoProperties).doesNotContainKey("build.artifact");
assertThat(buildInfoProperties).doesNotContainKey("build.group");
assertThat(buildInfoProperties).containsEntry("build.name", this.gradleBuild.getProjectDir().getName());
assertThat(buildInfoProperties).containsEntry("build.version", "unspecified");
}
@@ -122,6 +123,26 @@ class BuildInfoIntegrationTests {
assertThat(firstHash).isEqualTo(secondHash);
}
@TestTemplate
void removePropertiesUsingNulls() {
assertThat(this.gradleBuild.build("buildInfo").task(":buildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
Properties buildInfoProperties = buildInfoProperties();
assertThat(buildInfoProperties).doesNotContainKey("build.group");
assertThat(buildInfoProperties).doesNotContainKey("build.artifact");
assertThat(buildInfoProperties).doesNotContainKey("build.version");
assertThat(buildInfoProperties).doesNotContainKey("build.name");
}
@TestTemplate
void removePropertiesUsingEmptyStrings() {
assertThat(this.gradleBuild.build("buildInfo").task(":buildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
Properties buildInfoProperties = buildInfoProperties();
assertThat(buildInfoProperties).doesNotContainKey("build.group");
assertThat(buildInfoProperties).doesNotContainKey("build.artifact");
assertThat(buildInfoProperties).doesNotContainKey("build.version");
assertThat(buildInfoProperties).doesNotContainKey("build.name");
}
private Properties buildInfoProperties() {
File file = new File(this.gradleBuild.getProjectDir(), "build/build-info.properties");
assertThat(file).isFile();

View File

@@ -38,6 +38,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* Tests for {@link BuildInfo}.
*
* @author Andy Wilkinson
* @author Vedran Pavic
*/
@ClassPathExclusions("kotlin-daemon-client-*")
class BuildInfoTests {
@@ -49,8 +50,8 @@ class BuildInfoTests {
void basicExecution() {
Properties properties = buildInfoProperties(createTask(createProject("test")));
assertThat(properties).containsKey("build.time");
assertThat(properties).containsEntry("build.artifact", "unspecified");
assertThat(properties).containsEntry("build.group", "");
assertThat(properties).doesNotContainKey("build.artifact");
assertThat(properties).doesNotContainKey("build.group");
assertThat(properties).containsEntry("build.name", "test");
assertThat(properties).containsEntry("build.version", "unspecified");
}
@@ -62,6 +63,20 @@ class BuildInfoTests {
assertThat(buildInfoProperties(task)).containsEntry("build.artifact", "custom");
}
@Test
void artifactCanBeRemovedFromPropertiesUsingNull() {
BuildInfo task = createTask(createProject("test"));
task.getProperties().setArtifact(null);
assertThat(buildInfoProperties(task)).doesNotContainKey("build.artifact");
}
@Test
void artifactCanBeRemovedFromPropertiesUsingEmptyString() {
BuildInfo task = createTask(createProject("test"));
task.getProperties().setArtifact("");
assertThat(buildInfoProperties(task)).doesNotContainKey("build.artifact");
}
@Test
void projectGroupIsReflectedInProperties() {
BuildInfo task = createTask(createProject("test"));
@@ -76,6 +91,20 @@ class BuildInfoTests {
assertThat(buildInfoProperties(task)).containsEntry("build.group", "com.example");
}
@Test
void groupCanBeRemovedFromPropertiesUsingNull() {
BuildInfo task = createTask(createProject("test"));
task.getProperties().setGroup(null);
assertThat(buildInfoProperties(task)).doesNotContainKey("build.group");
}
@Test
void groupCanBeRemovedFromPropertiesUsingEmptyString() {
BuildInfo task = createTask(createProject("test"));
task.getProperties().setGroup("");
assertThat(buildInfoProperties(task)).doesNotContainKey("build.group");
}
@Test
void customNameIsReflectedInProperties() {
BuildInfo task = createTask(createProject("test"));
@@ -83,6 +112,20 @@ class BuildInfoTests {
assertThat(buildInfoProperties(task)).containsEntry("build.name", "Example");
}
@Test
void nameCanBeRemovedFromPropertiesUsingNull() {
BuildInfo task = createTask(createProject("test"));
task.getProperties().setName(null);
assertThat(buildInfoProperties(task)).doesNotContainKey("build.name");
}
@Test
void nameCanBeRemovedFromPropertiesUsingEmptyString() {
BuildInfo task = createTask(createProject("test"));
task.getProperties().setName("");
assertThat(buildInfoProperties(task)).doesNotContainKey("build.name");
}
@Test
void projectVersionIsReflectedInProperties() {
BuildInfo task = createTask(createProject("test"));
@@ -97,6 +140,20 @@ class BuildInfoTests {
assertThat(buildInfoProperties(task)).containsEntry("build.version", "2.3.4");
}
@Test
void versionCanBeRemovedFromPropertiesUsingNull() {
BuildInfo task = createTask(createProject("test"));
task.getProperties().setVersion(null);
assertThat(buildInfoProperties(task)).doesNotContainKey("build.version");
}
@Test
void versionCanBeRemovedFromPropertiesUsingEmptyString() {
BuildInfo task = createTask(createProject("test"));
task.getProperties().setVersion("");
assertThat(buildInfoProperties(task)).doesNotContainKey("build.version");
}
@Test
void timeIsSetInProperties() {
BuildInfo task = createTask(createProject("test"));

View File

@@ -0,0 +1,16 @@
plugins {
id 'org.springframework.boot' version '{version}' apply false
}
group = 'foo'
version = '0.1.0'
task buildInfo(type: org.springframework.boot.gradle.tasks.buildinfo.BuildInfo) {
destinationDir project.buildDir
properties {
group = ''
artifact = ''
version = ''
name = ''
}
}

View File

@@ -0,0 +1,16 @@
plugins {
id 'org.springframework.boot' version '{version}' apply false
}
group = 'foo'
version = '0.1.0'
task buildInfo(type: org.springframework.boot.gradle.tasks.buildinfo.BuildInfo) {
destinationDir project.buildDir
properties {
group = null
artifact = null
version = null
name = null
}
}