Skip to content

Commit 5c0cffa

Browse files
committed
add git-commit-id-maven-plugin for enhanced build reproducibility
1 parent 08ad8ab commit 5c0cffa

3 files changed

Lines changed: 83 additions & 2 deletions

File tree

.github/workflows/release.yml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,17 @@ jobs:
6161
# distributionManagement points at GitHub Packages, so we override
6262
# the deploy target to the local staging directory configured in the
6363
# JReleaser <stagingRepositories> block (target/staging-deploy).
64-
run: ./mvnw -B -Pfull-build clean deploy -DaltDeploymentRepository=local::file:./target/staging-deploy
64+
#
65+
# project.build.outputTimestamp pins every archive/manifest timestamp
66+
# to the release commit's committer date (strict ISO-8601 via %cI), so
67+
# the same tag always builds byte-identical artifacts (reproducible
68+
# builds), independent of when or where the build runs.
69+
run: |
70+
BUILD_TS=$(git log -1 --format=%cI)
71+
echo "Pinning project.build.outputTimestamp to $BUILD_TS"
72+
./mvnw -B -Pfull-build clean deploy \
73+
-DaltDeploymentRepository=local::file:./target/staging-deploy \
74+
-Dproject.build.outputTimestamp="$BUILD_TS"
6575
6676
- name: Publish with JReleaser
6777
run: ./mvnw -B -Pdeploy-release jreleaser:full-release -N

.github/workflows/snapshot.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,14 @@ jobs:
5050
# artifacts to the Central Portal snapshot repo configured in pom.xml.
5151
# No GPG signing is required for snapshots.
5252
if: steps.version.outputs.is_snapshot == 'true'
53-
run: ./mvnw -B -Pfull-build clean deploy
53+
# project.build.outputTimestamp pins every archive/manifest timestamp to
54+
# the commit's committer date (strict ISO-8601 via %cI), so the same
55+
# commit always builds byte-identical artifacts (reproducible builds),
56+
# independent of when or where the build runs.
57+
run: |
58+
BUILD_TS=$(git log -1 --format=%cI)
59+
echo "Pinning project.build.outputTimestamp to $BUILD_TS"
60+
./mvnw -B -Pfull-build clean deploy -Dproject.build.outputTimestamp="$BUILD_TS"
5461
env:
5562
MAVEN_CENTRAL_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
5663
MAVEN_CENTRAL_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }}

pom.xml

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
<jreleaser-maven-plugin.version>1.24.0</jreleaser-maven-plugin.version>
6767
<versions-maven-plugin.version>2.21.0</versions-maven-plugin.version>
6868
<spotless-maven-plugin.version>3.7.0</spotless-maven-plugin.version>
69+
<git-commit-id-maven-plugin.version>10.0.0</git-commit-id-maven-plugin.version>
6970

7071
<!-- Dependency versions -->
7172
<spring-boot.version>3.5.14</spring-boot.version>
@@ -172,6 +173,11 @@
172173
<artifactId>spotless-maven-plugin</artifactId>
173174
<version>${spotless-maven-plugin.version}</version>
174175
</plugin>
176+
<plugin>
177+
<groupId>io.github.git-commit-id</groupId>
178+
<artifactId>git-commit-id-maven-plugin</artifactId>
179+
<version>${git-commit-id-maven-plugin.version}</version>
180+
</plugin>
175181
</plugins>
176182
</pluginManagement>
177183

@@ -242,6 +248,64 @@
242248
<build>
243249
<defaultGoal>package</defaultGoal>
244250
<plugins>
251+
<plugin>
252+
<groupId>io.github.git-commit-id</groupId>
253+
<artifactId>git-commit-id-maven-plugin</artifactId>
254+
<executions>
255+
<execution>
256+
<id>get-the-git-infos</id>
257+
<goals>
258+
<goal>revision</goal>
259+
</goals>
260+
<phase>initialize</phase>
261+
</execution>
262+
</executions>
263+
<configuration>
264+
<!-- No git.properties file: a shared /git.properties collides on a
265+
consumer's classpath (only the first jar's copy is ever read).
266+
The git infos are written into each jar's own MANIFEST.MF below. -->
267+
<generateGitPropertiesFile>false</generateGitPropertiesFile>
268+
<commitIdGenerationMode>full</commitIdGenerationMode>
269+
<!-- Reproducible builds: format the commit time in a fixed format and
270+
in UTC, so the rendered string does not depend on the build
271+
machine's locale or timezone. -->
272+
<dateFormat>yyyy-MM-dd'T'HH:mm:ss'Z'</dateFormat>
273+
<dateFormatTimeZone>UTC</dateFormatTimeZone>
274+
<!-- A build from a published source archive (no .git) must not fail;
275+
this also lets third parties verify reproducibility from sources. -->
276+
<failOnNoGitDirectory>false</failOnNoGitDirectory>
277+
<!-- Reproducible builds: exclude every property that varies between
278+
builds of the same commit (build time, host, the build machine's
279+
git user, and remote-tracking state). Only commit-/repo-derived
280+
values that are deterministic for a given commit are kept. -->
281+
<excludeProperties>
282+
<excludeProperty>git.build.time</excludeProperty>
283+
<excludeProperty>git.build.host</excludeProperty>
284+
<excludeProperty>git.build.user.name</excludeProperty>
285+
<excludeProperty>git.build.user.email</excludeProperty>
286+
<excludeProperty>git.local.branch.ahead</excludeProperty>
287+
<excludeProperty>git.local.branch.behind</excludeProperty>
288+
</excludeProperties>
289+
</configuration>
290+
</plugin>
291+
<plugin>
292+
<groupId>org.apache.maven.plugins</groupId>
293+
<artifactId>maven-jar-plugin</artifactId>
294+
<configuration>
295+
<archive>
296+
<!-- Git metadata lives in the per-jar manifest (no classpath
297+
collision). All values are commit-/repo-derived and thus
298+
deterministic for a given commit, keeping builds reproducible. -->
299+
<manifestEntries>
300+
<Git-Commit>${git.commit.id.abbrev}</Git-Commit>
301+
<Git-Commit-Time>${git.commit.time}</Git-Commit-Time>
302+
<Git-Branch>${git.branch}</Git-Branch>
303+
<Git-Tag>${git.tags}</Git-Tag>
304+
<Git-Dirty>${git.dirty}</Git-Dirty>
305+
</manifestEntries>
306+
</archive>
307+
</configuration>
308+
</plugin>
245309
<plugin>
246310
<groupId>org.apache.maven.plugins</groupId>
247311
<artifactId>maven-javadoc-plugin</artifactId>

0 commit comments

Comments
 (0)