From c80218064fde71b991dee717166da81709558770 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 28 May 2019 16:30:36 +0100 Subject: [PATCH] Use sorted properties to make build info output repeatable Closes gh-14494 --- .../buildinfo/BuildInfoIntegrationTests.java | 19 +++++++++++++++++++ .../loader/tools/BuildPropertiesWriter.java | 6 ++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoIntegrationTests.java index 14abe9bbc7..ec67abcad2 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoIntegrationTests.java @@ -22,12 +22,15 @@ import java.io.IOException; 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; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.gradle.junit.GradleCompatibilityExtension; import org.springframework.boot.gradle.testkit.GradleBuild; +import org.springframework.boot.loader.tools.FileUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -92,6 +95,22 @@ public class BuildInfoIntegrationTests { assertThat(result.task(":buildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); } + @TestTemplate + public void reproducibleOutputWithFixedTime() throws InvalidRunnerConfigurationException, + UnexpectedBuildFailure, IOException, InterruptedException { + assertThat(this.gradleBuild.build("buildInfo", "-PnullTime").task(":buildInfo") + .getOutcome()).isEqualTo(TaskOutcome.SUCCESS); + File buildInfoProperties = new File(this.gradleBuild.getProjectDir(), + "build/build-info.properties"); + String firstHash = FileUtils.sha1Hash(buildInfoProperties); + assertThat(buildInfoProperties.delete()).isTrue(); + Thread.sleep(1500); + assertThat(this.gradleBuild.build("buildInfo", "-PnullTime") + .task(":buildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); + String secondHash = FileUtils.sha1Hash(buildInfoProperties); + assertThat(firstHash).isEqualTo(secondHash); + } + private Properties buildInfoProperties() { File file = new File(this.gradleBuild.getProjectDir(), "build/build-info.properties"); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/BuildPropertiesWriter.java b/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/BuildPropertiesWriter.java index 14614dc89c..e0435c9547 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/BuildPropertiesWriter.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/BuildPropertiesWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2018 the original author or authors. + * Copyright 2012-2019 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. @@ -24,6 +24,8 @@ import java.time.format.DateTimeFormatter; import java.util.Map; import java.util.Properties; +import org.springframework.core.CollectionFactory; + /** * A {@code BuildPropertiesWriter} writes the {@code build-info.properties} for * consumption by the Actuator. @@ -68,7 +70,7 @@ public final class BuildPropertiesWriter { } protected Properties createBuildInfo(ProjectDetails project) { - Properties properties = new Properties(); + Properties properties = CollectionFactory.createSortedProperties(true); properties.put("build.group", project.getGroup()); properties.put("build.artifact", project.getArtifact()); properties.put("build.name", project.getName());