Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use reproducible version qualifiers #4569

Merged
merged 1 commit into from
Jan 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>reproducible.archive.timestamps</groupId>
<artifactId>reproducible.archive.timestamps.parent</artifactId>
<groupId>reproducible.build</groupId>
<artifactId>reproducible.build.parent</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>

<modules>
<module>reproducible.buildqualifier</module>
<module>reproducible.bundle</module>
<module>reproducible.bundle.feature</module>
<module>reproducible.iu</module>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Reproducible-buildqualifier
Bundle-SymbolicName: reproducible.buildqualifier
Bundle-Version: 1.0.0.qualifier
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>reproducible.build</groupId>
<artifactId>reproducible.build.parent</artifactId>
<version>1.0.0</version>
</parent>

<artifactId>reproducible.buildqualifier</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package reproducible.buildqualifier;

public class PublicClass
{

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>reproducible.archive.timestamps</groupId>
<artifactId>reproducible.archive.timestamps.parent</artifactId>
<groupId>reproducible.build</groupId>
<artifactId>reproducible.build.parent</artifactId>
<version>1.0.0</version>
</parent>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>reproducible.archive.timestamps</groupId>
<artifactId>reproducible.archive.timestamps.parent</artifactId>
<groupId>reproducible.build</groupId>
<artifactId>reproducible.build.parent</artifactId>
<version>1.0.0</version>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>reproducible.archive.timestamps</groupId>
<artifactId>reproducible.archive.timestamps.parent</artifactId>
<groupId>reproducible.build</groupId>
<artifactId>reproducible.build.parent</artifactId>
<version>1.0.0</version>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>reproducible.archive.timestamps</groupId>
<artifactId>reproducible.archive.timestamps.parent</artifactId>
<groupId>reproducible.build</groupId>
<artifactId>reproducible.build.parent</artifactId>
<version>1.0.0</version>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
package org.eclipse.tycho.test.reproducible;

import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
Expand All @@ -21,7 +25,7 @@
import org.junit.Assert;
import org.junit.Test;

public class ReproducibleArchiveTimestampsTest extends AbstractTychoIntegrationTest {
public class ReproducibleBuildTest extends AbstractTychoIntegrationTest {
// The ZipEntry.getLastModifiedTime() method uses the default timezone to
// convert date and time fields to Instant, so we also use the default timezone
// for the expected timestamp here.
Expand All @@ -30,17 +34,17 @@ public class ReproducibleArchiveTimestampsTest extends AbstractTychoIntegrationT
.toInstant(OffsetDateTime.now().getOffset());

/**
* Check that the timestamp of the files inside the produced archives is equal
* to the one specified in the "project.build.outputTimestamp" property of the
* pom file.
* Check that the build is reproducible.
*/
@Test
public void test() throws Exception {
Verifier verifier = getVerifier("reproducible-archive-timestamps");
Verifier verifier = getVerifier("reproducible-build");
verifier.executeGoals(List.of("clean", "verify"));
verifier.verifyErrorFreeLog();

// Check timestamps of files in archives
// Check that the timestamp of the files inside the produced archives is equal
// to the one specified in the "project.build.outputTimestamp" property of the
// pom file.
checkTimestamps(verifier.getBasedir() + "/reproducible.bundle/target/reproducible.bundle-1.0.0.jar");
checkTimestamps(verifier.getBasedir() + "/reproducible.bundle/target/reproducible.bundle-1.0.0-attached.jar");
checkTimestamps(verifier.getBasedir() + "/reproducible.bundle/target/reproducible.bundle-1.0.0-sources.jar");
Expand All @@ -51,6 +55,11 @@ public void test() throws Exception {
checkTimestamps(verifier.getBasedir() + "/reproducible.iu/target/reproducible.iu-1.0.0.zip");
checkTimestamps(verifier.getBasedir() + "/reproducible.repository/target/reproducible.repository-1.0.0.zip");
checkTimestamps(verifier.getBasedir() + "/reproducible.repository/target/p2-site.zip");

// Check that the build qualifier uses the timestamp specified in the
// "project.build.outputTimestamp" property of the pom file.
checkBuildQualifier(verifier.getBasedir()
+ "/reproducible.buildqualifier/target/reproducible.buildqualifier-1.0.0-SNAPSHOT.jar");
}

private void checkTimestamps(String file) throws IOException {
Expand All @@ -62,4 +71,12 @@ private void checkTimestamps(String file) throws IOException {
}
}
}

private void checkBuildQualifier(String file) throws IOException {
try (FileSystem fileSystem = FileSystems.newFileSystem(Path.of(file))) {
Path manifest = fileSystem.getPath("META-INF/MANIFEST.MF");
List<String> lines = Files.readAllLines(manifest);
Assert.assertTrue(lines.stream().anyMatch(l -> l.equals("Bundle-Version: 1.0.0.202301010000")));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,22 @@
*******************************************************************************/
package org.eclipse.tycho.buildversion;

import java.time.Instant;
import java.util.Date;
import java.util.Optional;

import org.apache.maven.archiver.MavenArchiver;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.component.annotations.Component;
import org.eclipse.tycho.build.BuildTimestampProvider;

/**
* Build timestamp provider that returns the same timestamp for all projects, the
* ${maven.build.timestamp}.
* Build timestamp provider that returns the same timestamp for all projects. If
* the standard Maven property ${project.build.outputTimestamp} exists, its
* value is used for the timestamp. If it does not exist (or cannot be parsed),
* the ${maven.build.timestamp} timestamp is used instead.
*/
@Component(role = BuildTimestampProvider.class, hint = DefaultBuildTimestampProvider.ROLE_HINT)
public class DefaultBuildTimestampProvider implements BuildTimestampProvider {
Expand All @@ -31,7 +36,14 @@ public class DefaultBuildTimestampProvider implements BuildTimestampProvider {

@Override
public Date getTimestamp(MavenSession session, MavenProject project, MojoExecution execution) {
return session.getStartTime();
// Use the outputTimestamp property value if available for reproducible builds
final String outputTimestamp = (String) project.getProperties().get("project.build.outputTimestamp");
Optional<Instant> reproducibleTimestamp = MavenArchiver.parseBuildOutputTimestamp(outputTimestamp);
if (reproducibleTimestamp.isPresent()) {
return Date.from(reproducibleTimestamp.get());
} else {
return session.getStartTime();
}
}

@Override
Expand Down
Loading