From 1d426364189f82398e4b3e9b53235432f1fb2cc8 Mon Sep 17 00:00:00 2001 From: Zlika Date: Fri, 20 Dec 2024 10:57:28 +0100 Subject: [PATCH] Add reproducible timestamps in archives --- .../extras/custombundle/CustomBundleMojo.java | 13 +++++++++++++ tycho-gpg-plugin/pom.xml | 5 +++++ .../tycho/gpg/SignRepositoryArtifactsMojo.java | 15 +++++++++++++++ tycho-p2-director-plugin/pom.xml | 5 +++++ .../p2/director/ProductArchiverMojo.java | 14 ++++++++++++++ tycho-p2-repository-plugin/pom.xml | 5 +++++ .../p2/repository/ArchiveRepositoryMojo.java | 14 ++++++++++++++ .../plugins/p2/repository/MavenP2SiteMojo.java | 14 ++++++++++++++ .../tycho/packaging/PackageFeatureMojo.java | 12 ++++++++++++ .../eclipse/tycho/packaging/PackageIUMojo.java | 17 +++++++++++++++++ .../tycho/packaging/PackagePluginMojo.java | 17 +++++++++++++++++ tycho-repository-plugin/pom.xml | 5 +++++ .../plugin/PackageRepositoryMojo.java | 16 ++++++++++++++++ .../tycho/source/AbstractSourceJarMojo.java | 12 ++++++++++++ .../eclipse/tycho/source/SourceFeatureMojo.java | 11 +++++++++++ 15 files changed, 175 insertions(+) diff --git a/tycho-extras/tycho-custom-bundle-plugin/src/main/java/org/eclipse/tycho/extras/custombundle/CustomBundleMojo.java b/tycho-extras/tycho-custom-bundle-plugin/src/main/java/org/eclipse/tycho/extras/custombundle/CustomBundleMojo.java index ae75b4bdcc..557851ac9a 100644 --- a/tycho-extras/tycho-custom-bundle-plugin/src/main/java/org/eclipse/tycho/extras/custombundle/CustomBundleMojo.java +++ b/tycho-extras/tycho-custom-bundle-plugin/src/main/java/org/eclipse/tycho/extras/custombundle/CustomBundleMojo.java @@ -86,6 +86,16 @@ public class CustomBundleMojo extends AbstractMojo { @Parameter private MavenArchiveConfiguration archive = new MavenArchiveConfiguration(); + /** + * Timestamp for reproducible output archive entries, either formatted as ISO + * 8601 extended offset date-time (e.g. in UTC such as '2011-12-03T10:15:30Z' or + * with an offset '2019-10-05T20:37:42+06:00'), or as an int representing + * seconds since the epoch (like SOURCE_DATE_EPOCH). + */ + @Parameter(defaultValue = "${project.build.outputTimestamp}") + private String outputTimestamp; + @Component(role = Archiver.class, hint = "jar") private JarArchiver jarArchiver; @@ -100,6 +110,9 @@ public void execute() throws MojoExecutionException, MojoFailureException { archiver.setArchiver(jarArchiver); archiver.setOutputFile(outputJarFile); + // configure for Reproducible Builds based on outputTimestamp value + archiver.configureReproducibleBuild(outputTimestamp); + try { archiver.getArchiver().setManifest(updateManifest()); diff --git a/tycho-gpg-plugin/pom.xml b/tycho-gpg-plugin/pom.xml index 77b9423d05..91ad67a4f0 100644 --- a/tycho-gpg-plugin/pom.xml +++ b/tycho-gpg-plugin/pom.xml @@ -64,6 +64,11 @@ tycho-core ${project.version} + + + org.apache.maven + maven-archiver + diff --git a/tycho-gpg-plugin/src/main/java/org/eclipse/tycho/gpg/SignRepositoryArtifactsMojo.java b/tycho-gpg-plugin/src/main/java/org/eclipse/tycho/gpg/SignRepositoryArtifactsMojo.java index 0b521c7d12..f9d7851d59 100644 --- a/tycho-gpg-plugin/src/main/java/org/eclipse/tycho/gpg/SignRepositoryArtifactsMojo.java +++ b/tycho-gpg-plugin/src/main/java/org/eclipse/tycho/gpg/SignRepositoryArtifactsMojo.java @@ -11,9 +11,11 @@ import java.io.File; import java.io.IOException; +import java.nio.file.attribute.FileTime; import java.util.Arrays; import java.util.List; +import org.apache.maven.archiver.MavenArchiver; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Component; @@ -137,6 +139,15 @@ enum PGPKeyBehavior { @Parameter private List forceSignature; + /** + * Timestamp for reproducible output archive entries, either formatted as ISO 8601 extended + * offset date-time (e.g. in UTC such as '2011-12-03T10:15:30Z' or with an offset + * '2019-10-05T20:37:42+06:00'), or as an int representing seconds since the epoch (like + * SOURCE_DATE_EPOCH). + */ + @Parameter(defaultValue = "${project.build.outputTimestamp}") + private String outputTimestamp; + @Component(role = UnArchiver.class, hint = "zip") private ZipUnArchiver zipUnArchiver; @@ -208,6 +219,10 @@ public void doExecute() throws MojoExecutionException, MojoFailureException { } } + // configure for Reproducible Builds based on outputTimestamp value + MavenArchiver.parseBuildOutputTimestamp(outputTimestamp).map(FileTime::from) + .ifPresent(modifiedTime -> xzArchiver.configureReproducibleBuild(modifiedTime)); + xzArchiver.setDestFile(artifactsXmlXz); xzArchiver.addFile(artifactsXml, artifactsXml.getName()); xzArchiver.createArchive(); diff --git a/tycho-p2-director-plugin/pom.xml b/tycho-p2-director-plugin/pom.xml index 57be865ef5..1562f389e8 100644 --- a/tycho-p2-director-plugin/pom.xml +++ b/tycho-p2-director-plugin/pom.xml @@ -96,6 +96,11 @@ tycho-p2-plugin ${project.version} + + + org.apache.maven + maven-archiver + diff --git a/tycho-p2-director-plugin/src/main/java/org/eclipse/tycho/plugins/p2/director/ProductArchiverMojo.java b/tycho-p2-director-plugin/src/main/java/org/eclipse/tycho/plugins/p2/director/ProductArchiverMojo.java index e6e2e16c10..ef3af7e585 100644 --- a/tycho-p2-director-plugin/src/main/java/org/eclipse/tycho/plugins/p2/director/ProductArchiverMojo.java +++ b/tycho-p2-director-plugin/src/main/java/org/eclipse/tycho/plugins/p2/director/ProductArchiverMojo.java @@ -16,12 +16,14 @@ import java.io.File; import java.io.IOException; +import java.nio.file.attribute.FileTime; import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import org.apache.maven.archiver.MavenArchiver; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Component; @@ -134,6 +136,15 @@ public final class ProductArchiverMojo extends AbstractProductMojo { @Parameter(defaultValue = "false") private boolean storeCreationTime; + /** + * Timestamp for reproducible output archive entries, either formatted as ISO 8601 extended + * offset date-time (e.g. in UTC such as '2011-12-03T10:15:30Z' or with an offset + * '2019-10-05T20:37:42+06:00'), or as an int representing seconds since the epoch (like + * SOURCE_DATE_EPOCH). + */ + @Parameter(defaultValue = "${project.build.outputTimestamp}") + private String outputTimestamp; + @Component private MavenProjectHelper helper; @@ -223,6 +234,9 @@ private void materialize(Product product, TargetEnvironment env) throws MojoExec createCommonsCompressTarGz(productArchive, sourceDir); } else { Archiver archiver = productArchiver.get(); + // configure for Reproducible Builds based on outputTimestamp value + MavenArchiver.parseBuildOutputTimestamp(outputTimestamp).map(FileTime::from) + .ifPresent(modifiedTime -> archiver.configureReproducibleBuild(modifiedTime)); archiver.setDestFile(productArchive); DefaultFileSet fileSet = new DefaultFileSet(sourceDir); fileSet.setUsingDefaultExcludes(false); diff --git a/tycho-p2-repository-plugin/pom.xml b/tycho-p2-repository-plugin/pom.xml index b75f097816..6096536301 100644 --- a/tycho-p2-repository-plugin/pom.xml +++ b/tycho-p2-repository-plugin/pom.xml @@ -60,6 +60,11 @@ tycho-core ${project.version} + + + org.apache.maven + maven-archiver + diff --git a/tycho-p2-repository-plugin/src/main/java/org/eclipse/tycho/plugins/p2/repository/ArchiveRepositoryMojo.java b/tycho-p2-repository-plugin/src/main/java/org/eclipse/tycho/plugins/p2/repository/ArchiveRepositoryMojo.java index 57b577d387..32cd03b63d 100644 --- a/tycho-p2-repository-plugin/src/main/java/org/eclipse/tycho/plugins/p2/repository/ArchiveRepositoryMojo.java +++ b/tycho-p2-repository-plugin/src/main/java/org/eclipse/tycho/plugins/p2/repository/ArchiveRepositoryMojo.java @@ -15,7 +15,9 @@ import java.io.File; import java.io.IOException; +import java.nio.file.attribute.FileTime; +import org.apache.maven.archiver.MavenArchiver; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Component; @@ -52,6 +54,15 @@ public final class ArchiveRepositoryMojo extends AbstractRepositoryMojo { @Parameter(defaultValue = "false") private boolean skipArchive; + /** + * Timestamp for reproducible output archive entries, either formatted as ISO 8601 extended + * offset date-time (e.g. in UTC such as '2011-12-03T10:15:30Z' or with an offset + * '2019-10-05T20:37:42+06:00'), or as an int representing seconds since the epoch (like + * SOURCE_DATE_EPOCH). + */ + @Parameter(defaultValue = "${project.build.outputTimestamp}") + private String outputTimestamp; + @Component private FileLockService fileLockService; @@ -64,6 +75,9 @@ public void execute() throws MojoExecutionException, MojoFailureException { File destFile = getBuildDirectory().getChild(finalName + ".zip"); try (var repoLock = fileLockService.lockVirtually(repositoryLocation); var destLock = fileLockService.lockVirtually(destFile);) { + // configure for Reproducible Builds based on outputTimestamp value + MavenArchiver.parseBuildOutputTimestamp(outputTimestamp).map(FileTime::from) + .ifPresent(modifiedTime -> inflater.configureReproducibleBuild(modifiedTime)); inflater.addFileSet(DefaultFileSet.fileSet(repositoryLocation).prefixed("")); inflater.setDestFile(destFile); inflater.createArchive(); diff --git a/tycho-p2-repository-plugin/src/main/java/org/eclipse/tycho/plugins/p2/repository/MavenP2SiteMojo.java b/tycho-p2-repository-plugin/src/main/java/org/eclipse/tycho/plugins/p2/repository/MavenP2SiteMojo.java index 676a74a655..32a8afb071 100644 --- a/tycho-p2-repository-plugin/src/main/java/org/eclipse/tycho/plugins/p2/repository/MavenP2SiteMojo.java +++ b/tycho-p2-repository-plugin/src/main/java/org/eclipse/tycho/plugins/p2/repository/MavenP2SiteMojo.java @@ -22,6 +22,7 @@ import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.nio.file.attribute.FileTime; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -34,6 +35,7 @@ import java.util.stream.Stream.Builder; import org.apache.commons.io.FileUtils; +import org.apache.maven.archiver.MavenArchiver; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.handler.DefaultArtifactHandler; import org.apache.maven.artifact.resolver.ArtifactResolutionRequest; @@ -175,6 +177,15 @@ public class MavenP2SiteMojo extends AbstractMojo { @Parameter(defaultValue = "${project.build.directory}/repository") private File destination; + /** + * Timestamp for reproducible output archive entries, either formatted as ISO 8601 extended + * offset date-time (e.g. in UTC such as '2011-12-03T10:15:30Z' or with an offset + * '2019-10-05T20:37:42+06:00'), or as an int representing seconds since the epoch (like + * SOURCE_DATE_EPOCH). + */ + @Parameter(defaultValue = "${project.build.outputTimestamp}") + private String outputTimestamp; + @Component private Logger logger; @Component @@ -399,6 +410,9 @@ public void execute() throws MojoExecutionException, MojoFailureException { throw new MojoFailureException("P2 publisher return code was " + result); } ZipArchiver archiver = new ZipArchiver(); + // configure for Reproducible Builds based on outputTimestamp value + MavenArchiver.parseBuildOutputTimestamp(outputTimestamp).map(FileTime::from) + .ifPresent(modifiedTime -> archiver.configureReproducibleBuild(modifiedTime)); File destFile = new File(buildDirectory, "p2-site.zip"); archiver.setDestFile(destFile); archiver.addFileSet(new DefaultFileSet(destination)); diff --git a/tycho-packaging-plugin/src/main/java/org/eclipse/tycho/packaging/PackageFeatureMojo.java b/tycho-packaging-plugin/src/main/java/org/eclipse/tycho/packaging/PackageFeatureMojo.java index 933b7f7768..98348a48c5 100644 --- a/tycho-packaging-plugin/src/main/java/org/eclipse/tycho/packaging/PackageFeatureMojo.java +++ b/tycho-packaging-plugin/src/main/java/org/eclipse/tycho/packaging/PackageFeatureMojo.java @@ -105,6 +105,16 @@ public class PackageFeatureMojo extends AbstractTychoPackagingMojo { @Parameter(defaultValue = "${project.build.directory}/site") private File target; + /** + * Timestamp for reproducible output archive entries, either formatted as ISO + * 8601 extended offset date-time (e.g. in UTC such as '2011-12-03T10:15:30Z' or + * with an offset '2019-10-05T20:37:42+06:00'), or as an int representing + * seconds since the epoch (like SOURCE_DATE_EPOCH). + */ + @Parameter(defaultValue = "${project.build.outputTimestamp}") + private String outputTimestamp; + @Component private FeatureXmlTransformer featureXmlTransformer; @@ -161,6 +171,8 @@ public void execute() throws MojoExecutionException, MojoFailureException { MavenArchiver archiver = new MavenArchiver(); JarArchiver jarArchiver = getJarArchiver(); archiver.setArchiver(jarArchiver); + // configure for Reproducible Builds based on outputTimestamp value + archiver.configureReproducibleBuild(outputTimestamp); archiver.setOutputFile(outputJar); jarArchiver.setDestFile(outputJar); diff --git a/tycho-packaging-plugin/src/main/java/org/eclipse/tycho/packaging/PackageIUMojo.java b/tycho-packaging-plugin/src/main/java/org/eclipse/tycho/packaging/PackageIUMojo.java index 9cd2d65d91..42d279f852 100644 --- a/tycho-packaging-plugin/src/main/java/org/eclipse/tycho/packaging/PackageIUMojo.java +++ b/tycho-packaging-plugin/src/main/java/org/eclipse/tycho/packaging/PackageIUMojo.java @@ -14,7 +14,9 @@ import java.io.File; import java.io.IOException; +import java.nio.file.attribute.FileTime; +import org.apache.maven.archiver.MavenArchiver; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Component; @@ -50,6 +52,16 @@ public class PackageIUMojo extends AbstractTychoPackagingMojo { @Parameter(property = "project.basedir", required = true, readonly = true) private File basedir; + /** + * Timestamp for reproducible output archive entries, either formatted as ISO + * 8601 extended offset date-time (e.g. in UTC such as '2011-12-03T10:15:30Z' or + * with an offset '2019-10-05T20:37:42+06:00'), or as an int representing + * seconds since the epoch (like SOURCE_DATE_EPOCH). + */ + @Parameter(defaultValue = "${project.build.outputTimestamp}") + private String outputTimestamp; + @Component private IUXmlTransformer iuTransformer; @@ -65,6 +77,11 @@ public void execute() throws MojoExecutionException, MojoFailureException { getLog().info("Skip packaging"); return; } + + // configure for Reproducible Builds based on outputTimestamp value + MavenArchiver.parseBuildOutputTimestamp(outputTimestamp).map(FileTime::from) + .ifPresent(modifiedTime -> zipArchiver.configureReproducibleBuild(modifiedTime)); + synchronized (LOCK) { outputDirectory.mkdirs(); diff --git a/tycho-packaging-plugin/src/main/java/org/eclipse/tycho/packaging/PackagePluginMojo.java b/tycho-packaging-plugin/src/main/java/org/eclipse/tycho/packaging/PackagePluginMojo.java index a4ee87780d..269fc83e4d 100644 --- a/tycho-packaging-plugin/src/main/java/org/eclipse/tycho/packaging/PackagePluginMojo.java +++ b/tycho-packaging-plugin/src/main/java/org/eclipse/tycho/packaging/PackagePluginMojo.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.nio.file.attribute.FileTime; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -163,6 +164,16 @@ public class PackagePluginMojo extends AbstractTychoPackagingMojo { @Parameter(defaultValue = "true") private boolean checkServiceComponentFilesExist = true; + /** + * Timestamp for reproducible output archive entries, either formatted as ISO + * 8601 extended offset date-time (e.g. in UTC such as '2011-12-03T10:15:30Z' or + * with an offset '2019-10-05T20:37:42+06:00'), or as an int representing + * seconds since the epoch (like SOURCE_DATE_EPOCH). + */ + @Parameter(defaultValue = "${project.build.outputTimestamp}") + private String outputTimestamp; + @Component private SourceReferenceComputer soureReferenceComputer; @@ -211,6 +222,9 @@ private File makeJar(BuildOutputJar jar) throws MojoExecutionException { try { File jarFile = new File(project.getBasedir(), jarName); JarArchiver archiver = new JarArchiver(); + // configure for Reproducible Builds based on outputTimestamp value + MavenArchiver.parseBuildOutputTimestamp(outputTimestamp).map(FileTime::from) + .ifPresent(modifiedTime -> archiver.configureReproducibleBuild(modifiedTime)); archiver.setDestFile(jarFile); File outputDirectory = jar.getOutputDirectory(); if (!outputDirectory.mkdirs() && !outputDirectory.exists()) { @@ -238,6 +252,9 @@ private File createPluginJar() throws MojoExecutionException { MavenArchiver archiver = new MavenArchiver(); archiver.setArchiver(jarArchiver); + // configure for Reproducible Builds based on outputTimestamp value + archiver.configureReproducibleBuild(outputTimestamp); + File pluginFile = new File(buildDirectory, finalName + ".jar"); if (pluginFile.exists()) { pluginFile.delete(); diff --git a/tycho-repository-plugin/pom.xml b/tycho-repository-plugin/pom.xml index 59b6b177e2..3f2e1dd558 100644 --- a/tycho-repository-plugin/pom.xml +++ b/tycho-repository-plugin/pom.xml @@ -62,6 +62,11 @@ tycho-spi ${project.version} + + + org.apache.maven + maven-archiver + diff --git a/tycho-repository-plugin/src/main/java/org/eclipse/tycho/repository/plugin/PackageRepositoryMojo.java b/tycho-repository-plugin/src/main/java/org/eclipse/tycho/repository/plugin/PackageRepositoryMojo.java index e80894f8ef..dde6df9824 100644 --- a/tycho-repository-plugin/src/main/java/org/eclipse/tycho/repository/plugin/PackageRepositoryMojo.java +++ b/tycho-repository-plugin/src/main/java/org/eclipse/tycho/repository/plugin/PackageRepositoryMojo.java @@ -14,11 +14,13 @@ import java.io.File; import java.io.IOException; +import java.nio.file.attribute.FileTime; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import org.apache.commons.io.FilenameUtils; +import org.apache.maven.archiver.MavenArchiver; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.handler.DefaultArtifactHandler; import org.apache.maven.execution.MavenSession; @@ -98,6 +100,16 @@ public class PackageRepositoryMojo extends AbstractMojo implements RepositoryCon @Parameter private PlexusConfiguration settings; + /** + * Timestamp for reproducible output archive entries, either formatted as ISO + * 8601 extended offset date-time (e.g. in UTC such as '2011-12-03T10:15:30Z' or + * with an offset '2019-10-05T20:37:42+06:00'), or as an int representing + * seconds since the epoch (like SOURCE_DATE_EPOCH). + */ + @Parameter(defaultValue = "${project.build.outputTimestamp}") + private String outputTimestamp; + @Component(role = Archiver.class, hint = "zip") private ZipArchiver zipArchiver; @@ -109,6 +121,10 @@ public class PackageRepositoryMojo extends AbstractMojo implements RepositoryCon @Override public void execute() throws MojoExecutionException, MojoFailureException { + // configure for Reproducible Builds based on outputTimestamp value + MavenArchiver.parseBuildOutputTimestamp(outputTimestamp).map(FileTime::from) + .ifPresent(modifiedTime -> zipArchiver.configureReproducibleBuild(modifiedTime)); + RepositoryGenerator generator = generators.get(repositoryType); if (generator == null) { throw new MojoFailureException( diff --git a/tycho-source-plugin/src/main/java/org/eclipse/tycho/source/AbstractSourceJarMojo.java b/tycho-source-plugin/src/main/java/org/eclipse/tycho/source/AbstractSourceJarMojo.java index 9e411efb15..9b46380169 100644 --- a/tycho-source-plugin/src/main/java/org/eclipse/tycho/source/AbstractSourceJarMojo.java +++ b/tycho-source-plugin/src/main/java/org/eclipse/tycho/source/AbstractSourceJarMojo.java @@ -194,6 +194,15 @@ public abstract class AbstractSourceJarMojo extends AbstractMojo { @Parameter(property = "source.forceCreation", defaultValue = "false") private boolean forceCreation; + /** + * Timestamp for reproducible output archive entries, either formatted as ISO 8601 extended + * offset date-time (e.g. in UTC such as '2011-12-03T10:15:30Z' or with an offset + * '2019-10-05T20:37:42+06:00'), or as an int representing seconds since the epoch (like + * SOURCE_DATE_EPOCH). + */ + @Parameter(defaultValue = "${project.build.outputTimestamp}") + private String outputTimestamp; + // ---------------------------------------------------------------------- // Public methods // ---------------------------------------------------------------------- @@ -349,6 +358,9 @@ protected MavenArchiver createArchiver() throws MojoExecutionException { MavenArchiver archiver = new MavenArchiver(); archiver.setArchiver(jarArchiver); + // configure for Reproducible Builds based on outputTimestamp value + archiver.configureReproducibleBuild(outputTimestamp); + if (project.getBuild() != null) { List resources = project.getBuild().getResources(); diff --git a/tycho-source-plugin/src/main/java/org/eclipse/tycho/source/SourceFeatureMojo.java b/tycho-source-plugin/src/main/java/org/eclipse/tycho/source/SourceFeatureMojo.java index 4717031d6a..c4c78a5bc8 100644 --- a/tycho-source-plugin/src/main/java/org/eclipse/tycho/source/SourceFeatureMojo.java +++ b/tycho-source-plugin/src/main/java/org/eclipse/tycho/source/SourceFeatureMojo.java @@ -193,6 +193,15 @@ public enum MissingSourcesAction { @Parameter(property = "session", readonly = true) private MavenSession session; + /** + * Timestamp for reproducible output archive entries, either formatted as ISO 8601 extended + * offset date-time (e.g. in UTC such as '2011-12-03T10:15:30Z' or with an offset + * '2019-10-05T20:37:42+06:00'), or as an int representing seconds since the epoch (like + * SOURCE_DATE_EPOCH). + */ + @Parameter(defaultValue = "${project.build.outputTimestamp}") + private String outputTimestamp; + private final Set excludedPlugins = new HashSet<>(); private final Set excludedFeatures = new HashSet<>(); @@ -243,6 +252,8 @@ public void execute() throws MojoExecutionException, MojoFailureException { writeProperties(mergedSourceFeatureProps, getMergedSourceFeaturePropertiesFile()); MavenArchiver archiver = new MavenArchiver(); archiver.setArchiver(jarArchiver); + // configure for Reproducible Builds based on outputTimestamp value + archiver.configureReproducibleBuild(outputTimestamp); File outputJarFile = getOutputJarFile(); archiver.setOutputFile(outputJarFile); File template = new File(project.getBasedir(), FEATURE_TEMPLATE_DIR);