@ -17,18 +17,20 @@
@@ -17,18 +17,20 @@
package org.springframework.boot.maven ;
import java.io.File ;
import java.io.FileReader ;
import java.io.IOException ;
import java.util.ArrayList ;
import java.util.List ;
import java.util.Map ;
import java.util.concurrent.atomic.AtomicReference ;
import java.util.jar.JarFile ;
import java.util.stream.Collectors ;
import org.junit.jupiter.api.TestTemplate ;
import org.junit.jupiter.api.extension.ExtendWith ;
import org.springframework.boot.loader.tools.FileUtils ;
import org.springframework.boot.loader.tools.JarModeLibrary ;
import org.springframework.util.FileCopy Utils ;
import org.springframework.util.FileSystem Utils ;
import static org.assertj.core.api.Assertions.assertThat ;
@ -78,17 +80,34 @@ class WarIntegrationTests extends AbstractArchiveIntegrationTests {
@@ -78,17 +80,34 @@ class WarIntegrationTests extends AbstractArchiveIntegrationTests {
}
@TestTemplate
void whenWarIsRepackagedWithOutputTimestampTheBuildFailsAsItIsNotSupported ( MavenBuild mavenBuild )
void whenWarIsRepackagedWithOutputTimestampConfiguredThenWarIsReproducible ( MavenBuild mavenBuild )
throws InterruptedException {
mavenBuild . project ( "war-output-timestamp" ) . executeAndFail ( ( project ) - > {
try {
String log = FileCopyUtils . copyToString ( new FileReader ( new File ( project , "target/build.log" ) ) ) ;
assertThat ( log ) . contains ( "Reproducible repackaging is not supported with war packaging" ) ;
String firstHash = buildWarWithOutputTimestamp ( mavenBuild ) ;
Thread . sleep ( 1500 ) ;
String secondHash = buildWarWithOutputTimestamp ( mavenBuild ) ;
assertThat ( firstHash ) . isEqualTo ( secondHash ) ;
}
private String buildWarWithOutputTimestamp ( MavenBuild mavenBuild ) {
AtomicReference < String > warHash = new AtomicReference < > ( ) ;
mavenBuild . project ( "war-output-timestamp" ) . execute ( ( project ) - > {
File repackaged = new File ( project , "target/war-output-timestamp-0.0.1.BUILD-SNAPSHOT.war" ) ;
assertThat ( repackaged ) . isFile ( ) ;
assertThat ( repackaged . lastModified ( ) ) . isEqualTo ( 1584352800000L ) ;
try ( JarFile jar = new JarFile ( repackaged ) ) {
List < String > unreproducibleEntries = jar . stream ( )
. filter ( ( entry ) - > entry . getLastModifiedTime ( ) . toMillis ( ) ! = 1584352800000L )
. map ( ( entry ) - > entry . getName ( ) + ": " + entry . getLastModifiedTime ( ) )
. collect ( Collectors . toList ( ) ) ;
assertThat ( unreproducibleEntries ) . isEmpty ( ) ;
warHash . set ( FileUtils . sha1Hash ( repackaged ) ) ;
FileSystemUtils . deleteRecursively ( project ) ;
}
catch ( Exception ex ) {
catch ( IO Exception ex ) {
throw new RuntimeException ( ex ) ;
}
} ) ;
return warHash . get ( ) ;
}
@TestTemplate