For a build to be reproducible the project.build.outputTimestamp needs to be set to a valid value for the spring-boot-maven-plugin.

This can be either a number (indicating the epoch seconds) or an ISO 8601 timestamp.

These example values all work as expected (plugin version 3.1.3): - '2023-09-17T12:34:56Z' --> Valid timestamp - '1694946896' --> Valid timestamp - 'a' --> Valid (= null, no timestamp) - '' --> Valid (= null, no timestamp) - 'aa' --> Invalid (parse error, build fails)

This merge request fixes the edge case of having a single character numerical timestamp which has been implemented differently from what Maven does.

Maven accepts a '0' as a valid timestamp. See for example https://github.com/apache/maven-archiver/blob/master/src/main/java/org/apache/maven/archiver/MavenArchiver.java#L762

The Spring Boot maven plugin currently sees the '0' as a null instead (i.e. no timestamp set instead of epoch=0).

Comment From: vy

I can confirm @nielsbasjes finding that setting project.build.outputTimestamp to 0 causes spring-boot:repackage to generate a different artifact (i.e., not reproducible) at each run, whereas the rest of the Maven ecosystem [supporting reproducible builds] works just fine.

Comment From: nielsbasjes

I went through the build logs to see why it failed.

I found this. Please assist in helping me understand how (and if) I can fix this problem. At this time I do not see the relation between my changes and this failure.

Caused by: java.nio.file.AccessDeniedException: /tmp/junit-image-cache-wkkvnpipvv-build/committed/io.buildpacks.lifecycle.cache.metadata
    at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:90)
    at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:106)
    at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)
    at java.base/sun.nio.fs.UnixFileSystemProvider.implDelete(UnixFileSystemProvider.java:248)
    at java.base/sun.nio.fs.AbstractFileSystemProvider.delete(AbstractFileSystemProvider.java:105)
    at java.base/java.nio.file.Files.delete(Files.java:1152)
    at org.springframework.util.FileSystemUtils$1.visitFile(FileSystemUtils.java:90)
    at org.springframework.util.FileSystemUtils$1.visitFile(FileSystemUtils.java:87)
    at java.base/java.nio.file.Files.walkFileTree(Files.java:2811)
    at java.base/java.nio.file.Files.walkFileTree(Files.java:2882)
    at org.springframework.util.FileSystemUtils.deleteRecursively(FileSystemUtils.java:87)
    at org.springframework.boot.maven.BuildImageTests.lambda$whenBuildImageIsInvokedWithBindCaches$19(BuildImageTests.java:422)
    at org.springframework.boot.maven.MavenBuild.execute(MavenBuild.java:190)
    ... 124 more

Comment From: wilkinsona

@nielsbasjes there's no connection. It's an unfortunate intermittent failure that we, as far as I can recall, have only seen on GitHub actions. Please ignore it for now. We will build your changes locally prior to merging them.

Comment From: mhalbritter

When merging this, polish the contribution so that the parsing of the timestamp matches the implementation in https://github.com/nielsbasjes/maven-archiver/blob/master/src/main/java/org/apache/maven/archiver/MavenArchiver.java#L768C37-L801

A dependency for just one method feels unjustified.

Comment From: nielsbasjes

@mhalbritter Would you like me to update the pull request in this way? Or are you going to pick this up?

Comment From: hgschmie

When merging this, polish the contribution so that the parsing of the timestamp matches the implementation in https://github.com/nielsbasjes/maven-archiver/blob/master/src/main/java/org/apache/maven/archiver/MavenArchiver.java#L768C37-L801

A dependency for just one method feels unjustified.

then you just set yourself up for another breakage some time in the future. The maven-archiver artifact is available anyway, declaring a dependency is not a big deal and it allows you to write less code but call code that is maintained by the maven project.

Not sure why you consider this unjustified. Anyway, your call.

Comment From: mhalbritter

@mhalbritter Would you like me to update the pull request in this way? Or are you going to pick this up?

If you like, you can do it, i'd be happy. If you don't find the time, I'll do it on the merge.

Comment From: nielsbasjes

Working on it.

Comment From: nielsbasjes

I have now copied part of the maven archiver code as I understood this is what you wanted (instead of adding the maven-archiver dependency). Correct?

Comment From: mhalbritter

Thanks a lot!