diff options
author | Matthias Sohn <matthias.sohn@sap.com> | 2023-10-06 01:10:40 +0200 |
---|---|---|
committer | Matthias Sohn <matthias.sohn@sap.com> | 2023-11-09 00:08:42 +0100 |
commit | 6007371e3a21970dd34ae91ac20460922a15488e (patch) | |
tree | f4c77f590e98032641d274a8714f5ead5d0e2f42 /pom.xml | |
parent | 97afcb050b182beacd1c6913d8293d6ba0a9989e (diff) | |
download | jgit-6007371e3a21970dd34ae91ac20460922a15488e.tar.gz jgit-6007371e3a21970dd34ae91ac20460922a15488e.zip |
Enable Maven reproducible builds
- configure Maven to run build reproducibly [1]
- use UTC timestamp of checked out commit as build timestamp
- add git-describe, git-commit-id, git-commit-id, git-tags,
git-remote-origin-url to MANIFEST.MF files
- configure cyclonedx-maven-plugin to also use UTC timestamp of
checked out commit
- for packaging build use tycho-buildtimestamp-jgit [2] to ensure
version uses the timestamp of the last commit
- SBOMs are not reproducible by design [3] they should have a build
timestamp matching the time when the build was executed and a serial
number which is a unique UUID per build run. Hence exclude them from
comparison [4].
- Use gmavenplus-plugin to format build timestamps. Maven expects
build timestamp in ISO-8601 format, to replace the qualifier in
versions the timestamp format must be compatible with rules for OSGi
version numbers. Didn't find a way to read the properties set by the
git-commit-id-maven-plugin from another plugin. Hence use JGit in a
groovy script to get the commit time of the current HEAD and provide
it in these two formats.
TODO: packaging build (features and p2 repository) is not yet binary
reproducible since that's not yet supported by Tycho [5], artefacts have
reproducible version numbers but file lastModified timestamps are not
yet reproducible.
Test plan for Maven build:
- build using
mvn clean install"
- verify second build is reproducible:
mvn -T1 clean verify artifact:compare
verification seems not to be thread-safe, hence run it with a single
thread using option -T1
For packaging build (still fails due to non-reproducible file
timestamps):
- build using
mvn -f org.eclipse.jgit.packaging/pom.xml clean install
- verify second build is reproducible:
mvn -T1 -f org.eclipse.jgit.packaging/pom.xml clean verify artifact:compare
[1] https://maven.apache.org/guides/mini/guide-reproducible-builds.html
[2] https://wiki.eclipse.org/Tycho/Reproducible_Version_Qualifiers
[3] https://github.com/CycloneDX/cyclonedx-maven-plugin/issues/84
[4] https://maven.apache.org/plugins/maven-artifact-plugin/compare-mojo.html
[5] https://github.com/eclipse-tycho/tycho/issues/233
Change-Id: I0202f55a1b6ae0edd922cfef638beb39d2ce9417
Diffstat (limited to 'pom.xml')
-rw-r--r-- | pom.xml | 128 |
1 files changed, 125 insertions, 3 deletions
@@ -113,10 +113,11 @@ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> - <maven.build.timestamp.format>yyyyMMddHHmm</maven.build.timestamp.format> <java.version>11</java.version> <bundle-manifest>${project.build.directory}/META-INF/MANIFEST.MF</bundle-manifest> + <project.build.outputTimestamp>${commit.time.iso}</project.build.outputTimestamp> + <jgit-last-release-version>6.7.0.202309050840-r</jgit-last-release-version> <ant-version>1.10.14</ant-version> <apache-sshd-version>2.10.0</apache-sshd-version> @@ -191,6 +192,11 @@ <Implementation-Vendor>Eclipse.org - JGit</Implementation-Vendor> <Implementation-Vendor-Id>org.eclipse.jgit</Implementation-Vendor-Id> <Implementation-Vendor-URL>${jgit-url}</Implementation-Vendor-URL> + <git-describe>${git.commit.id.describe}</git-describe> + <git-commit-id>${git.commit.id}</git-commit-id> + <git-commit-time>${git.commit.time}</git-commit-time> + <git-tags>${git.tags}</git-tags> + <git-remote-origin-url>${git.remote.origin.url}</git-remote-origin-url> </manifestEntries> </archive> <!-- TODO: uncomment this in order to skip empty artifact of test modules as soon as bug 416299 is fixed @@ -358,6 +364,20 @@ <artifactId>license-tool-plugin</artifactId> <version>1.0.2</version> </plugin> + <plugin> + <groupId>org.cyclonedx</groupId> + <artifactId>cyclonedx-maven-plugin</artifactId> + <version>2.7.9</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-artifact-plugin</artifactId> + <version>3.5.0</version> + <configuration> + <ignore>**/*cyclonedx.json</ignore> + <reproducible>true</reproducible> + </configuration> + </plugin> </plugins> </pluginManagement> @@ -398,7 +418,7 @@ <target if="${translate-qualifier}"> <copy file="META-INF/MANIFEST.MF" tofile="${bundle-manifest}" overwrite="true"/> <replace file="${bundle-manifest}"> - <replacefilter token=".qualifier" value=".${maven.build.timestamp}"/> + <replacefilter token=".qualifier" value=".${commit.time.version}"/> </replace> </target> </configuration> @@ -570,7 +590,6 @@ <plugin> <groupId>org.cyclonedx</groupId> <artifactId>cyclonedx-maven-plugin</artifactId> - <version>2.7.9</version> <configuration> <projectType>library</projectType> <schemaVersion>1.4</schemaVersion> @@ -586,6 +605,7 @@ <outputName>cyclonedx</outputName> <outputDirectory>${project.build.directory}</outputDirectory> <verbose>false</verbose> + <detectUnusedForOptionalScope>true</detectUnusedForOptionalScope> </configuration> <executions> <execution> @@ -596,6 +616,108 @@ </execution> </executions> </plugin> + <plugin> + <groupId>io.github.git-commit-id</groupId> + <artifactId>git-commit-id-maven-plugin</artifactId> + <version>6.0.0</version> + <executions> + <execution> + <id>get-the-git-infos</id> + <goals> + <goal>revision</goal> + </goals> + <phase>initialize</phase> + </execution> + </executions> + <configuration> + <generateGitPropertiesFile>false</generateGitPropertiesFile> + <injectAllReactorProjects>true</injectAllReactorProjects> + <dateFormatTimeZone>UTC</dateFormatTimeZone> + </configuration> + </plugin> + <plugin> + <groupId>org.codehaus.gmavenplus</groupId> + <artifactId>gmavenplus-plugin</artifactId> + <version>3.0.2</version> + <dependencies> + <dependency> + <groupId>org.apache.groovy</groupId> + <artifactId>groovy</artifactId> + <version>4.0.15</version> + <scope>runtime</scope> + </dependency> + <dependency> + <groupId>org.apache.groovy</groupId> + <artifactId>groovy-ant</artifactId> + <version>4.0.15</version> + <scope>runtime</scope> + </dependency> + </dependencies> + <executions> + <execution> + <id>add-dynamic-properties</id> + <phase>initialize</phase> + <goals> + <goal>execute</goal> + </goals> + <configuration> + <bindAllProjectProperties>true</bindAllProjectProperties> + <bindAllSessionUserProperties>true</bindAllSessionUserProperties> + <scripts> + <script><![CDATA[ + @Grapes([ + @Grab(group='org.eclipse.jgit', module='org.eclipse.jgit', version='6.7.0.202309050840-r') + ]) + import java.time.Instant + import java.time.ZoneId + import java.time.format.DateTimeFormatter + import org.eclipse.jgit.lib.Constants + import org.eclipse.jgit.lib.ObjectId + import org.eclipse.jgit.lib.Repository + import org.eclipse.jgit.lib.RepositoryBuilder + import org.eclipse.jgit.revwalk.RevCommit + import org.eclipse.jgit.revwalk.RevObject + import org.eclipse.jgit.revwalk.RevTag + import org.eclipse.jgit.revwalk.RevWalk + + try { + RepositoryBuilder rb = new RepositoryBuilder().setGitDir().readEnvironment().findGitDir() + if (rb.getGitDir() == null) { + throw new Exception("Can't find .git directory") + } + Repository repo = rb.build() + ObjectId objectId = repo.resolve(Constants.HEAD) + try (RevWalk rw = new RevWalk(repo)) { + RevObject obj = rw.parseAny(objectId) + while (obj instanceof RevTag) { + obj = ((RevTag) obj).getObject() + rw.parseBody(obj) + } + + switch (obj.getType()) { + case Constants.OBJ_COMMIT: + RevCommit c = (RevCommit) obj + Instant time = c.getCommitterIdent().getWhenAsInstant() + DateTimeFormatter iso8601Fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'").withZone(ZoneId.of("UTC")) + DateTimeFormatter versionFmt = DateTimeFormatter.ofPattern("yyyyMMddHHmm").withZone(ZoneId.of("UTC")) + String isoTime = iso8601Fmt.format(time) + String versionTime = versionFmt.format(time) + project.properties.setProperty("commit.time.iso", isoTime) + project.properties.setProperty("commit.time.version", versionTime) + break + default: + throw new Exception("Didn't expect " + obj.name() + ", " + obj.getType()) + } + } + } catch (Exception e) { + e.printStackTrace() + } + ]]></script> + </scripts> + </configuration> + </execution> + </executions> + </plugin> </plugins> </build> |