Skip to content

Commit

Permalink
Add reproducible timestamps in archives
Browse files Browse the repository at this point in the history
  • Loading branch information
Zlika committed Dec 20, 2024
1 parent edb9113 commit 1d42636
Show file tree
Hide file tree
Showing 15 changed files with 175 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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 <a href=
* "https://reproducible-builds.org/docs/source-date-epoch/">SOURCE_DATE_EPOCH</a>).
*/
@Parameter(defaultValue = "${project.build.outputTimestamp}")
private String outputTimestamp;

@Component(role = Archiver.class, hint = "jar")
private JarArchiver jarArchiver;

Expand All @@ -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());

Expand Down
5 changes: 5 additions & 0 deletions tycho-gpg-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@
<artifactId>tycho-core</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-archiver</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -137,6 +139,15 @@ enum PGPKeyBehavior {
@Parameter
private List<String> 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
* <a href="https://reproducible-builds.org/docs/source-date-epoch/">SOURCE_DATE_EPOCH</a>).
*/
@Parameter(defaultValue = "${project.build.outputTimestamp}")
private String outputTimestamp;

@Component(role = UnArchiver.class, hint = "zip")
private ZipUnArchiver zipUnArchiver;

Expand Down Expand Up @@ -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();
Expand Down
5 changes: 5 additions & 0 deletions tycho-p2-director-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@
<artifactId>tycho-p2-plugin</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-archiver</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
* <a href="https://reproducible-builds.org/docs/source-date-epoch/">SOURCE_DATE_EPOCH</a>).
*/
@Parameter(defaultValue = "${project.build.outputTimestamp}")
private String outputTimestamp;

@Component
private MavenProjectHelper helper;

Expand Down Expand Up @@ -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);
Expand Down
5 changes: 5 additions & 0 deletions tycho-p2-repository-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@
<artifactId>tycho-core</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-archiver</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
* <a href="https://reproducible-builds.org/docs/source-date-epoch/">SOURCE_DATE_EPOCH</a>).
*/
@Parameter(defaultValue = "${project.build.outputTimestamp}")
private String outputTimestamp;

@Component
private FileLockService fileLockService;

Expand All @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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
* <a href="https://reproducible-builds.org/docs/source-date-epoch/">SOURCE_DATE_EPOCH</a>).
*/
@Parameter(defaultValue = "${project.build.outputTimestamp}")
private String outputTimestamp;

@Component
private Logger logger;
@Component
Expand Down Expand Up @@ -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));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 <a href=
* "https://reproducible-builds.org/docs/source-date-epoch/">SOURCE_DATE_EPOCH</a>).
*/
@Parameter(defaultValue = "${project.build.outputTimestamp}")
private String outputTimestamp;

@Component
private FeatureXmlTransformer featureXmlTransformer;

Expand Down Expand Up @@ -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);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 <a href=
* "https://reproducible-builds.org/docs/source-date-epoch/">SOURCE_DATE_EPOCH</a>).
*/
@Parameter(defaultValue = "${project.build.outputTimestamp}")
private String outputTimestamp;

@Component
private IUXmlTransformer iuTransformer;

Expand All @@ -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();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 <a href=
* "https://reproducible-builds.org/docs/source-date-epoch/">SOURCE_DATE_EPOCH</a>).
*/
@Parameter(defaultValue = "${project.build.outputTimestamp}")
private String outputTimestamp;

@Component
private SourceReferenceComputer soureReferenceComputer;

Expand Down Expand Up @@ -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()) {
Expand Down Expand Up @@ -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();
Expand Down
5 changes: 5 additions & 0 deletions tycho-repository-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@
<artifactId>tycho-spi</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-archiver</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 <a href=
* "https://reproducible-builds.org/docs/source-date-epoch/">SOURCE_DATE_EPOCH</a>).
*/
@Parameter(defaultValue = "${project.build.outputTimestamp}")
private String outputTimestamp;

@Component(role = Archiver.class, hint = "zip")
private ZipArchiver zipArchiver;

Expand All @@ -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(
Expand Down
Loading

0 comments on commit 1d42636

Please sign in to comment.