From 2a8237c81c28c487f57a490d66a7866286a7d2ec Mon Sep 17 00:00:00 2001 From: Brandon Schmitt Date: Thu, 18 Dec 2025 21:49:04 +0100 Subject: [PATCH] [FELIX-6814] Improve Reproducible Build Support Use the value of Maven's project.build.outputTimestamp property as the value for the -reproducible instruction. Timestamps, formatted in ISO-8601 or in number of seconds since the epoch, are both supported by bnd tools. The value is also already sanitized by MavenArchiver::parseOutputTimestamp which also allows only numeric timestamps or timestamps in ISO-8601 format. --- .../src/it/reproducible-manifest/pom.xml | 2 +- .../src/it/reproducible-manifest/verify.groovy | 17 +++++++++++++++++ .../src/it/reproducible/pom.xml | 2 +- .../src/it/reproducible/verify.groovy | 17 +++++++++++++++++ .../apache/felix/bundleplugin/BundlePlugin.java | 2 +- 5 files changed, 37 insertions(+), 3 deletions(-) diff --git a/tools/maven-bundle-plugin/src/it/reproducible-manifest/pom.xml b/tools/maven-bundle-plugin/src/it/reproducible-manifest/pom.xml index 38f3ae2444..2afe809438 100644 --- a/tools/maven-bundle-plugin/src/it/reproducible-manifest/pom.xml +++ b/tools/maven-bundle-plugin/src/it/reproducible-manifest/pom.xml @@ -26,7 +26,7 @@ under the License. - 1 + 2000-01-01T00:00:00Z diff --git a/tools/maven-bundle-plugin/src/it/reproducible-manifest/verify.groovy b/tools/maven-bundle-plugin/src/it/reproducible-manifest/verify.groovy index 08c1c4b8b8..f85d3acada 100644 --- a/tools/maven-bundle-plugin/src/it/reproducible-manifest/verify.groovy +++ b/tools/maven-bundle-plugin/src/it/reproducible-manifest/verify.groovy @@ -17,6 +17,12 @@ * under the License. */ +import java.time.LocalDateTime +import java.time.ZoneId +import java.util.zip.ZipEntry +import java.util.zip.ZipFile + + String manifest = new File( basedir, "target/classes/META-INF/MANIFEST.MF" ).text; assert !manifest.contains( "Build-Jdk:" ) @@ -25,3 +31,14 @@ assert manifest.contains( "Build-Jdk-Spec:" ) assert !manifest.contains( "Build-By:" ) assert !manifest.contains( "Bnd-LastModified:" ) + + +Enumeration bundleEntries = new ZipFile(new File( basedir, "target/reproducible-1-SNAPSHOT.jar" )).entries() + +// ZipEntry::getTime() interprets the time information in the local timezone. +long expectedTime = LocalDateTime.of(2000, 1, 1, 0, 0, 0).atZone(ZoneId.systemDefault()).toEpochSecond() * 1000 + +while(bundleEntries.hasMoreElements()) { + ZipEntry entry = bundleEntries.nextElement() + assert entry.getTime() == expectedTime +} diff --git a/tools/maven-bundle-plugin/src/it/reproducible/pom.xml b/tools/maven-bundle-plugin/src/it/reproducible/pom.xml index d0ae17c502..c3fbcbdf89 100644 --- a/tools/maven-bundle-plugin/src/it/reproducible/pom.xml +++ b/tools/maven-bundle-plugin/src/it/reproducible/pom.xml @@ -25,7 +25,7 @@ under the License. 1-SNAPSHOT bundle - 1 + 946684800 diff --git a/tools/maven-bundle-plugin/src/it/reproducible/verify.groovy b/tools/maven-bundle-plugin/src/it/reproducible/verify.groovy index 08c1c4b8b8..f85d3acada 100644 --- a/tools/maven-bundle-plugin/src/it/reproducible/verify.groovy +++ b/tools/maven-bundle-plugin/src/it/reproducible/verify.groovy @@ -17,6 +17,12 @@ * under the License. */ +import java.time.LocalDateTime +import java.time.ZoneId +import java.util.zip.ZipEntry +import java.util.zip.ZipFile + + String manifest = new File( basedir, "target/classes/META-INF/MANIFEST.MF" ).text; assert !manifest.contains( "Build-Jdk:" ) @@ -25,3 +31,14 @@ assert manifest.contains( "Build-Jdk-Spec:" ) assert !manifest.contains( "Build-By:" ) assert !manifest.contains( "Bnd-LastModified:" ) + + +Enumeration bundleEntries = new ZipFile(new File( basedir, "target/reproducible-1-SNAPSHOT.jar" )).entries() + +// ZipEntry::getTime() interprets the time information in the local timezone. +long expectedTime = LocalDateTime.of(2000, 1, 1, 0, 0, 0).atZone(ZoneId.systemDefault()).toEpochSecond() * 1000 + +while(bundleEntries.hasMoreElements()) { + ZipEntry entry = bundleEntries.nextElement() + assert entry.getTime() == expectedTime +} diff --git a/tools/maven-bundle-plugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java b/tools/maven-bundle-plugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java index 7c54ba1b75..295530f8d7 100644 --- a/tools/maven-bundle-plugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java +++ b/tools/maven-bundle-plugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java @@ -553,7 +553,7 @@ protected Builder getOSGiBuilder( MavenProject currentProject, Map