Fork me on GitHub

Usage

This plugin works in one of 3 ways: with an SCM, with a sequential build number, or with a timestamp.

No matter which method you choose, you must include it in your pom:

  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>buildnumber-maven-plugin</artifactId>
        <version>3.1.0</version>
        <executions>
          <execution>
            <phase>validate</phase>
            <goals>
              <goal>create</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <doCheck>true</doCheck>
          <doUpdate>true</doUpdate>
        </configuration>
      </plugin>
    </plugins>
  </build>

This will cause the create goal of the buildNumber plugin to be executed during the validate phase. It will first check to see if you have locally modified files, and will fail if there are any. You can suppress this behaviour with -Dmaven.buildNumber.doCheck=false (or remove/change the configuration info).

The buildNumber plugin will then update your local repository. This is done because local revision might not be the same locally as the last one on some remote server (example for svn: 'svn info' grabs the revision out of your local repository, and is not necessarily the same as the revision in the remote repository). You should probably deal with these changes before creating a build in any case. Again, this behaviour can be suppressed with -Dmaven.buildNumber.doUpdate=false.

You then need to do something with the revision provided by the plugin. The revision number is available using ${buildNumber} in your pom. For example:

  <build>
    <finalName>$\{project.artifactId}-$\{project.version}-r$\{buildNumber}</finalName>
  </build>

or to place in the manifest (META-INF/MANIFEST.mf) of your jar:

  <build>
    ...
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <version>3.0.2</version>
        <configuration>
          <archive>
            <manifest>
              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
            </manifest>
            <manifestEntries>
              <Implementation-Build>${buildNumber}</Implementation-Build>
            </manifestEntries>
          </archive>
        </configuration>
      </plugin>
    </plugins>
  </build>

or war:

  <build>
    ...
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>3.0.0</version>
        <configuration>
          <archive>
            <manifest>
              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
            </manifest>
            <manifestEntries>
              <Implementation-Build>${buildNumber}</Implementation-Build>
            </manifestEntries>
          </archive>
        </configuration>
      </plugin>
    </plugins>
  </build>

The ${scmBranch} property is also populated to provide the SCM branch.

Note: Older version of the jar and war plugin don't require the manifest/addDefaultImplementationEntries element, and in fact will fail if present. The new versions require this element.

You can also configure the plugin to be more flexible.

  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>buildnumber-maven-plugin</artifactId>
        <version>3.1.0</version>
        <configuration>
          <format>At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.</format>
          <items>
            <item implementation="java.lang.Integer">7</item>
            <item>timestamp</item>
            <item>a disturbance in the Force</item>
          </items>
        </configuration>
        <executions>
          <execution>
            <phase>validate</phase>
            <goals>
              <goal>create</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

Other more useful configurations might be:

    <configuration>
      <format>{0,number}.{1,number}.{2,number}</format>
      <items>
        <item>buildNumber0</item>
        <item>buildNumber1</item>
        <item>buildNumber2</item>
      </items>
    </configuration>

or:

    <configuration>
      <format>yyyy-MM-dd HH:mm:ss</format>
      <items>
        <item>timestamp</item>
      </items>
    </configuration>

The plugin simply uses the MessageFormat class to produce ${buildNumber}, and thus the above configurations would produce:

    At 12:30 PM on Jul 3, 2053, there was a disturbance in the Force on planet 7.

and

    2.0.3

and

    2005-10-06 2:22:55

respectively.

When you specify the special items of "buildNumber\d*" or "timestamp", then some magic is performed. For each unique buildNumber, a properties file ( see buildNumberPropertiesFileLocation ) will be created (or read if it exists) which holds an integer, starting at 1. That number will be incremented on each access. Of course, the given example is somewhat non-sensical, since it will increment all 3 numbers on each build, but it shows the type of flexibility available. For each timestamp, you simply get the current date and time.

Here is some additional writeup on how to version your projects with this plugin. It even details how to access the version number in your code.

Git short revision ID

From the version 1.1 you can specify the length for the Git revision. To enable this feature you have to specify the new tag <shortRevisionLength> in the <configuration> section. For exemple:

    <configuration>
       <shortRevisionLength>5</shortRevisionLength>
    </configuration>

the output of the found git revision will have only 5 characters:

    instead of b0c1c69be579175e63eeb1c056d607f01ab61e96 you will have only b0c1c

Note: this feature uses internally the git rev-parse --short command and the revision length is set to minimum 4 characters. So you can't have the revision id shorter then 4 characters. Even if you specify the length between 0 and 4, the plugin will inform you about this situation and the minimum value (4) will be used.

Using svnjava provider

If you need to execute the plugin on machine without any svn in the path you can configure the mojo to use the svnjava provider.

NOTE the svnjava provider use the svnjava scm provider implementation maven-scm-provider-svnjava which rely on svnkit version.

  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>buildnumber-maven-plugin</artifactId>
        <version>3.1.0</version>
        <executions>
          <execution>
            <phase>validate</phase>
            <goals>
              <goal>create</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <doCheck>true</doCheck>
          <doUpdate>true</doUpdate>
          <providerImplementations>
            <svn>javasvn</svn>
          </providerImplementations>
        </configuration>
      </plugin>
    </plugins>
  </build>

Using Perforce P4Maven provider

To use this plugin with Perforce P4Maven Provider, add p4maven-provider to dependencies list.

  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>buildnumber-maven-plugin</artifactId>
        <version>3.1.0</version>
        <dependencies>
          <dependency>
            <groupId>com.perforce.p4maven</groupId>
            <artifactId>p4maven-provider</artifactId>
            <version>${p4maven.version}</version>
          </dependency>
        </dependencies>
        [...]
      </plugin>
    </plugins>
  </build>

Create Build Metadata

For quick quick discovery of a SCM revision of an snapshot/release artifact available at maven repository, use buildnumber:create-metadata to deploy a build metadata file associate with a specific artifact of the same project.

  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>buildnumber-maven-plugin</artifactId>
        <version>3.1.0</version>
        <executions>
          <execution>
            <phase>generate-resources</phase>
            <goals>
              <goal>create-metadata</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <attach>true</attach>
          <!--make it available for jar/war classpath resource -->
          <addOutputDirectoryToResources>true</addOutputDirectoryToResources>
        </configuration>
      </plugin>
    </plugins>
  </build>