Fork me on GitHub

Usage

The following examples describe the basic usage of the Reproducible Build Maven plugin.

Fix build artifacts to make them reproducible

To execute the plugin during the pre-integration-test phase (just after the package phase), add the Reproducible Build Maven plugin in the <build> section of your pom.xml.

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>io.github.zlika</groupId>
        <artifactId>reproducible-build-maven-plugin</artifactId>
        <version>0.16</version>
        <executions>
          <execution>
            <goals>
              <goal>strip-jar</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

Normalize ObjectFactory.java files generated by the JAXB xjc tool

To execute the plugin during the process-sources phase, add the Reproducible Build Maven plugin in the <build> section of your pom.xml.

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>io.github.zlika</groupId>
        <artifactId>reproducible-build-maven-plugin</artifactId>
        <version>0.16</version>
        <executions>
          <execution>
            <goals>
              <goal>strip-jaxb</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

Make reproducible archives with maven-assembly-plugin

If you use maven-assembly-plugin to create a ZIP/TAR/TAR.GZ/TAR.BZ2 archive during your build, you need to execute the strip-jar goal twice, one before the maven-assembly-plugin single goal (to strip the main artifact of the build before inclusion in the archive), and a second time after the maven-assembly-plugin single goal (to strip the non-reproducible elements of the archive format itself).

NOTE: When several plugins/goals are defined to run during the same phase, Maven runs them in their declaration order in the pom, so you must declare reproducible-build-maven-plugin BEFORE maven-assembly-plugin.

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>io.github.zlika</groupId>
        <artifactId>reproducible-build-maven-plugin</artifactId>
        <version>0.16</version>
        <executions>
          <execution>
            <id>strip-jar</id>
            <phase>package</phase>
            <goals>
              <goal>strip-jar</goal>
            </goals>
          </execution>
          <execution>
            <id>strip-archive</id>
            <phase>pre-integration-test</phase>
            <goals>
              <goal>strip-jar</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <configuration>
          <descriptors>
            <descriptor>assembly.xml</descriptor>
          </descriptors>
        </configuration>
        <executions>
          <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
      </plugin>      
    </plugins>
  </build>
  ...
</project>

Use last commit time as timestamp for zip (jar) entries (since version 0.6)

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>pl.project13.maven</groupId>
        <artifactId>git-commit-id-plugin</artifactId>
        <executions>
          <execution>
            <id>retrieve-git-info</id>
            <phase>prepare-package</phase>
            <goals>
              <goal>revision</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <injectAllReactorProjects>true</injectAllReactorProjects>
          <runOnlyOnce>true</runOnlyOnce>
          <skipPoms>false</skipPoms>
          <dateFormat>yyyyMMddHHmmss</dateFormat>
          <dateFormatTimeZone>UTC</dateFormatTimeZone>
        </configuration>
      </plugin>
      
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
          <archive>
            <manifestEntries>
              <Last-Commit-Id>${git.commit.id}</Last-Commit-Id>
              <Last-Commit-Time>${git.commit.time}</Last-Commit-Time>
              <Reproducible-Build>true</Reproducible-Build>
            </manifestEntries>
          </archive>
        </configuration>
      </plugin>
      
      <plugin>
        <groupId>io.github.zlika</groupId>
        <artifactId>reproducible-build-maven-plugin</artifactId>
        <version>0.16</version>
        <executions>
          <execution>
            <id>strip-jaxb</id>
            <goals>
              <goal>strip-jaxb</goal>
            </goals>
          </execution>
          <execution>
            <id>strip-jar</id>
            <goals>
              <goal>strip-jar</goal>
            </goals>
            <configuration>
              <zipDateTime>${git.commit.time}</zipDateTime>
              <!-- Set custom date/time format pattern, "yyyyMMddHHmmss" by default -->
              <!-- <zipDateTimeFormatPattern>yyyyMMddHHmmss</zipDateTimeFormatPattern> -->
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

Include/Exclude files (since version 0.13)

Each filename that the plugin inspects for stripping is first passed to a series of inclusion filters, and then to a series of exclusion filters. The filters are expressed as standard java.util.Pattern regular expressions. If the filename matches at least one inclusion filter, then it becomes a candidate for stripping. If the candidate filename matches at least one exclusion filter, then the file is no longer a candidate for stripping. By default, the plugin behaves as if no exclusion filter was provided, and exactly one inclusion filter was provided that matches all input (.*).

An example that will include all example-*.jar files except for example-excluded.jar:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>io.github.zlika</groupId>
        <artifactId>reproducible-build-maven-plugin</artifactId>
        <version>0.16</version>
        <executions>
          <execution>
            <id>strip-jar</id>
            <goals>
              <goal>strip-jar</goal>
            </goals>
            <configuration>
              <includes>
                <include>example-.*\.jar</include>
              </includes>
              <excludes>
                <exclude>example-excluded.jar</exclude>
              </excludes>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>