Revapi Maven Plugin

Maven integration for Revapi.

Revapi Maven plugin enables API checks during the Maven build. By default, it checks the currently built project against the its latest released version (as reported by Maven). Alternatively, the two artifacts to can be set arbitrarily.

The plugin offers the following Maven goals:

The full description of all available goals is located here.

Revapi maven plugin is very simple to use. Just define what revapi extensions should be used, what artifacts to compare and off you go. See the examples section, below.

In case you still have questions regarding the plugin’s usage, please feel free to contact the user mailing list. The posts to the mailing list are archived and could already contain the answer to your question as part of an older thread. Hence, it is also worth browsing/searching the mail archive.

If you feel like the plugin is missing a feature or has a defect, you can fill a feature request or bug report in our issue tracker. When creating a new issue, please provide a comprehensive description of your concern. Especially for fixing bugs it is crucial that the developers can reproduce your problem. For this reason, entire debug logs, POMs or most preferably little demo projects attached to the issue are very much appreciated. Of course, patches are most welcome, too. Contributors can check out the project from our source repository and will find supplementary information in the guide to helping with Maven.

Examples

The list of extensions you want to use with Revapi is provided to it as plugin dependencies. Usually you will want to check the API of your java archives, so this is the minimal configuration you need to provide to revapi (note that the basic features extension is implicitly present because without it Revapi can do literally nothing).

<plugin>
  <groupId>org.revapi</groupId>
  <artifactId>revapi-maven-plugin</artifactId>
  <version>...</version>
  <dependencies>
    <dependency>
      <groupId>org.revapi</groupId>
      <artifactId>revapi-java</artifactId>
      <version>...</version>
    </dependency>
  </dependencies>
  <executions>
    <execution>
      <goals><goal>check</goal></goals>
    </execution>
  </executions>
</plugin>

Specifying Versions To Check

By default, Revapi will automagically figure out the latest released version of your project and check the code that’s been built against it.

This is assumed to be the most common usecase and as such requires no additional configuration. But it always is not exactly what you want.

Specific Old Version

You can choose to explicitly select the old version to check. This is useful in scenarios where you need tell specifically the old version and Maven rules for determining the latest release does not pick the right one.

You can use one of the following configuration parameters of Revapi maven plugin:

  • oldArtifacts - This can be used to precisely specify the GAV (or more GAVs) of the artifact(s) representing your old version.

  • oldVersion - Using this, Revapi will reuse the groupId, artifactId, type and classifier of your currently built artifact and will use the specified version. I.e. using this, you can easily specify the older version of your artifact to check against.

Both of these parameters have their command-line names, too. Please consult the check goal docs for details.

Specific New Version

This is not a very common usecase but you can also specify the new version of the API (i.e. something different than what the Maven just built). Use newArtifacts or newVersion parameters with similar meaning to the old variants.

Leaving Out Pre-releases

Frequently, you will release alpha or beta versions before you release the final version of your project. Maven will consider any non-snapshot release as the latest, but that’s possibly not what you want to check against.

After you release a beta, you still want your project to be checked against the last final release, not against the beta.

You could explicitly specify the oldVersion to be your last final release but the caveat of that is that you will have to remember to change that after you release your new final release (so that your new final release becomes the new baseline for the future development).

There is a simpler way though.

You can use the versionFormat configuration parameter to specify how the version string of the latest release must look like.

For example if you use "GA" as the suffix of your final releases and you released 1.0.GA, 2.0.Alpha and 2.0.Beta, you can configure Revapi maven plugin like this:

<configuration>
  <versionFormat>.*\.GA</versionFormat>
</configuration>

and Revapi will use the latest release that matches that regular expression (which would be 1.0.GA) instead of the latest release as reported by Maven (which would be 2.0.Beta).

Note that the version format applies to both old and new versions and is only taken into account if the version string is one of the Maven’s special version specifiers - RELEASE or LATEST (RELEASE is the default value of oldVersion configuration parameter, so the above configuration will take effect).

How to Configure Revapi

The maven plugin itself is configured using the properties of the goals. The configuration of the API analysis is a matter of configuring different Revapi extensions that are to be run. This is done using the analysisConfiguration element in the Maven plugin’s configuration. This element contains the configuration of the individual extensions in either XML or JSON.

Specifying The Analysis Configuration Using XML

Ignoring classes

As an example, let’s configure the java extension to ignore the classes it finds missing from the API rather than reporting them and also only include the archives with com.acme groupId in the analysis::

<plugin>
  <groupId>org.revapi</groupId>
  <artifactId>revapi-maven-plugin</artifactId>
  <version>...</version>
  <configuration>
    <analysisConfiguration>
      <revapi.java>
        <missing-classes>
          <behavior>ignore</behavior>
        </missing-classes>
      </revapi.java>
      <revapi.filter>
        <archives>
          <include>
            <item>com\.acme:.*</item>
          </include>
        </archives>
      </revapi.filter>
    </analysisConfiguration>
  </configuration>

Each extension has a unique "extension id" which is used as the root tag for its configuration under the analysisConfiguration tag. Under the extension configuration’s root tag an XML representation of the configuration as specified by the extension documentation (and JSON schema - yes, the XML is validated against a JSON schema ;) ).

Failing level

By default, mvn revapi:check fails if at least one potentially breaking change is found. To fail only for breaking changes, one has to set up failSeverity as follows.

<plugin>
  <groupId>org.revapi</groupId>
  <artifactId>revapi-maven-plugin</artifactId>
  <configuration>
    <failSeverity>breaking</failSeverity>
    ...

Multiple Configurations Per Extension

There can be multiple configurations for a single extension. Optionally, each extension configuration "instance" can be assigned an ID such that it can be effectively merged (see below).

<plugin>
  <groupId>org.revapi</groupId>
  <artifactId>revapi-maven-plugin</artifactId>
  <version>...</version>
  ...
  <configuration>
    <analysisConfiguration>
      <revapi.reporter.text id="stdout">
        <output>out</output>
      </revapi.reporter.text>
      <revapi.reporter.text id="custom-report">
        <output>${project.build.directory}/revapi-custom-report.xml</output>
        <template>${custom-report.template.location}</template>
      </revapi.reporter.text>
    </analysisConfiguration>
  </configuration>

This configuration will cause the Revapi’s text reporter (if is included as a dependency of the plugin) to output the results of the analysis both to standard output and a custom file using a custom template.

Analysis Configuration And Maven Inheritance

Having the Revapi analysis configuration specified in XML enables Maven to apply its configuration inheritance logic to Revapi analysis configuration, too.

Here is a couple of tips on how to make the Maven configuration inheritance work nice with Revapi analysis configuration.

Tip
mvn help:effective-pom, combine.self and combine.children are your friends when inheriting more complex analysis configurations.

One Configuration Per Extension

Parent POM:

<plugin>
  <groupId>org.revapi</groupId>
  <artifactId>revapi-maven-plugin</artifactId>
  <configuration>
    <analysisConfiguration>
      <revapi.ignore>
        <item>
          <code>java.class.removed</code>
        </item>
        <item>
          <code>java.class.added</code>
        </item>
      </revapi.ignore>
    </analysisConfiguration>
  </configuration>
  ...

Child POM:

<plugin>
  <groupId>org.revapi</groupId>
  <artifactId>revapi-maven-plugin</artifactId>
  <configuration>
    <analysisConfiguration>
      <revapi.ignore>
        <item>
          <code>java.class.nowFinal</code>
        </item>
      </revapi.ignore>
    </analysisConfiguration>
  </configuration>
  ...

Effective Child POM:

<plugin>
  <groupId>org.revapi</groupId>
  <artifactId>revapi-maven-plugin</artifactId>
  <configuration>
    <analysisConfiguration>
      <revapi.ignore>
        <item>
          <code>java.class.nowFinal</code>
        </item>
      </revapi.ignore>
    </analysisConfiguration>
  </configuration>
  ...

Notice that revapi.ignore doesn’t contain the items defined in the parent POM. That is the default Maven behavior. To be able to inherit the configuration of the revapi.ignore extension from the parent POM, you have to specify how to merge the `item`s in the child POM like so:

<plugin>
  <groupId>org.revapi</groupId>
  <artifactId>revapi-maven-plugin</artifactId>
  <configuration>
    <analysisConfiguration>
      <revapi.ignore combine.children="append">
        <item>
          <code>java.class.nowFinal</code>
        </item>
      </revapi.ignore>
    </analysisConfiguration>
  </configuration>
  ...

After that, the effective child POM will indeed contain configuration combined from both parent and child:

<plugin>
  <groupId>org.revapi</groupId>
  <artifactId>revapi-maven-plugin</artifactId>
  <configuration>
    <analysisConfiguration>
      <revapi.ignore>
        <item>
          <code>java.class.nowFinal</code>
        </item>
        <item>
          <code>java.class.removed</code>
        </item>
        <item>
          <code>java.class.added</code>
        </item>
      </revapi.ignore>
    </analysisConfiguration>
  </configuration>
  ...

Multiple Configurations Per Extension

As mentioned in the previous chapters, revapi supports multiple configurations per extension. This gets a little bit complicated in conjunction with inheritance. Let’s see an example.

Parent POM

<plugin>
  <groupId>org.revapi</groupId>
  <artifactId>revapi-maven-plugin</artifactId>
  <version>...</version>
  ...
  <configuration>
    <analysisConfiguration>
      <revapi.reporter.text id="stdout">
        <output>out</output>
      </revapi.reporter.text>
      <revapi.reporter.text id="custom-report">
        <output>${project.build.directory}/revapi-custom-report.xml</output>
        <template>${custom-report.template.location}</template>
      </revapi.reporter.text>
    </analysisConfiguration>
  </configuration>

Child POM

<plugin>
  <groupId>org.revapi</groupId>
  <artifactId>revapi-maven-plugin</artifactId>
  <version>...</version>
  ...
  <configuration>
    <analysisConfiguration>
      <revapi.reporter.text id="stdout">
        <output>err</output>
      </revapi.reporter.text>
    </analysisConfiguration>
  </configuration>

I.e. the child POM wants to reconfigure the "stdout" configuration of revapi text reporter to report to standard error output instead of the standard output.

If we inspect the effective child POM, we’ll see this though:

<plugin>
  <groupId>org.revapi</groupId>
  <artifactId>revapi-maven-plugin</artifactId>
  <version>...</version>
  ...
  <configuration>
    <analysisConfiguration>
      <revapi.reporter.text id="stdout">
        <output>err</output>
      </revapi.reporter.text>
    </analysisConfiguration>
  </configuration>

I.e. the configuration for the custom output is lost in the child POM (again, this is standard Maven behavior. These are just examples to save you from ripping your hair out unnecessarily ;) ). To also inherit the other reporter configuration, you have to mention it like this in the child POM

<plugin>
  <groupId>org.revapi</groupId>
  <artifactId>revapi-maven-plugin</artifactId>
  <version>...</version>
  ...
  <configuration>
    <analysisConfiguration>
      <revapi.reporter.text id="stdout">
        <output>err</output>
      </revapi.reporter.text>
      <revapi.reporter.text id="custom-report"/>
    </analysisConfiguration>
  </configuration>

Now the effective child POM contains the custom report configuration as well as the modified stdout configuration.

Specifying The Analysis Configuration Using JSON

Revapi has been around for a little bit and over the time it has evolved. Originally (up until Revapi API 0.8.0), each extension was instantiated exactly once and therefore also configured exactly once. Since Revapi API 0.8.0, supported by Revapi Maven plugin 0.9.0, there can be multiple configurations for each extension (and the extension can be therefore instantiated multiple times). This brings the ability to e.g. have 2 differently configured text reporter instances, each generating a different kind of output. Unfortunately, this complicates the configuration, because it is no longer possible to have a single "configuration tree" where extensions would read their configurations from their declared locations.

Therefore, since Revapi API 0.8.0 there is a new kind of JSON format for configuration (which in turn also enables maven plugin to support XML configuration btw). To ease the migration to the new versions, the old configuration format is still supported (but mixing the two formats can lead to unresolvable situations, see the Multi-file Configuration section for more details).

The JSON Configuration Format

As explained above, each extension can be configured multiple times. To support this in JSON, the JSON configuration looks like this:

[
  {
    "extension": "revapi.reporter.text",
    "id": "optional-id",
    "configuration": {
      ... the actual configuration of the extension according to its schema ...
    }
  },
  {
    "extension": "revapi.reporter.text",
    "configuration": {
      ...
    }
  },
  {
    "extension": "revapi.ignore",
    "configuration": {
      ...
    }
  },
  ...
]

The configuration object is a list. The members of the list are individual configurations for the extensions. The extension being configured is specified by the extension key and the configuration (conforming to the schema specified by the extension) is present under the configuration key.

The optional id key is useful if there are multiple configuration sources (see multi file configuration for example) as it affects how the configurations from the different sources are merged together.

The Legacy JSON Configuration Format

Warning
This describes the obsolete JSON configuration format that cannot handle multiple configurations per extension. If you still use it, rest assured that it is still supported (with the exception of certain scenarios during merging of multiple configuration sources) but you are encouraged to start using the new configuration format.

The JSON data contains the configuration of all the extensions. Each of the extensions declares a "root" in the JSON data from which it reads its configuration (for example, ignoring specific problems found during the analysis can be done using the IgnoreDifferenceTransform extension from the basic features under the root revapi.ignore).

So, without further ado, let’s configure the java extension to report the classes it finds missing from the API rather than failing the analysis upon encountering them and also only include the archives with com.acme groupId in the analysis:

<plugin>
  <groupId>org.revapi</groupId>
  <artifactId>revapi-maven-plugin</artifactId>
  <version>...</version>
  <configuration>
    <analysisConfiguration><![CDATA[
      {
        "revapi": {
          "java": {
            "missing-classes": {
              "behavior": "report"
            }
          },
          "filter": {
            "archives": {
              "include": ["com\\.acme:.*"]
            }
          }
        }
      }
    ]]></analysisConfiguration>
  </configuration>
  <executions>
    <execution>
      <goals><goal>check</goal></goals>
    </execution>
  </executions>

The configuration options of the various extensions can be found in their respective docs: basic features documentation, java extension documentation.

Evolving The Library Using Semver Rules

By default Revapi will report all API changes of configured severity (by default "potentiallyBreaking") and the maven plugin will break the build if such differences are found since the last released version.

One then has to somehow "persuade" the plugin to let the build pass again. One way of doing it is to use the ignore extension and list all the changes and provide them with a "justification" for why such change happened.

This is very rigorous but also laborious approach that isn’t always worth the effort - especially in the early stages of development. Also one can argue that any change made to the codebase is intentional and therefore specifically listing it somewhere in a file that would justify such change to a tool is superfluous. On the other such strict policy might be required for some critical libraries that require high level of stability and any change should be vetted and approved.

There is also another way though. One can use the combination of the semver-ignore extension and the update-versions goal to (semi-)automatically increase the version of the library even during the development such that its version corresponds to the API changes it contains since the last released version. No other action like listing the and justifying the changes is necessary in this case.

For that you need to configure Revapi maven plugin to use and enable the semver-ignore extension:

<build>
    <plugin>
        <groupId>org.revapi</groupId>
        <artifactId>revapi-maven-plugin</artifactId>
        <configuration>
            <analysisConfiguration><![CDATA[
                {
                  "revapi": {
                    "semver": {
                      "ignore": {
                        "enabled": true
                      }
                    }
                  }
                }
            ]]></analysisConfiguration>
        </configuration>
    </plugin>
</build>

Then, when you try to build your project, revapi might find a change that is incompatible with the current version increase (like an API breaking change when you only increased a micro version since the last release) and fail your build. At that moment, it is enough to invoke:

mvn revapi:update-versions

and the version will be updated to reflect the API changes made. When you build the project again, the build should pass.

Note
You can even embed the update-versions goal in your regular build and have the versions increase automagically (at the cost of having to run the build twice when an incompatible change is made).

Multi-file Configuration

Sometimes it can be handy to split the configuration of Revapi analysis in separate files - this can be done for various reasons - you might want to keep the config of different extensions separate or you want to compose the config from various contributing locations, etc.

For Revapi, this can be achieved by using the analysisConfigurationFiles configuration element instead of (or in addition to) the analysisConfiguration element which provides the in-POM way of configuring Revapi.

<plugin>
    <groupId>org.revapi</groupId>
    <artifactId>revapi-maven-plugin</artifactId>
    <version>...</version>
    ...
    <configuration>
        <analysisConfigurationFiles>
            <file>${project.basedir}/config/filter.json</file>
            <file>${project.basedir}/config/ignore.xml</file>
        </analysisConfigurationFiles>
    </configuration>
    <executions>
        <execution>
            <goals><goal>check</goal></goals>
        </execution>
    </executions>
</plugin>

Each of the configuration files (e.g. filter.json and ignore.xml in the above example) is a JSON or XML document with the configuration. The maven plugin then merges the files together (in an unspecified order) and uses the result as the final configuration for the analysis.

Using Configuration Defined In Other Modules

It is possible to define a JAR artifact that contains "common" configuration of the Revapi analysis shared by many modules. To reference it, simply add the artifact as a dependency of the revapi maven plugin and reference the configuration file inside that artifact like:

<plugin>
    <groupId>org.revapi</groupId>
    <artifactId>revapi-maven-plugin</artifactId>
    <version>...</version>
    <dependencies>
      ...
      <dependency>
        <groupId>my.group.id</groupId>
        <artifactId>artifact-with-common-config</artifact>
        <version>...</version>
      </dependency>
    </dependencies>
    <configuration>
        <analysisConfigurationFiles>
          <configurationFile>
            <resource>path/to/the/config/file/in/the/shared/artifact</resource>
          </configurationFile>
          ...
        </analysisConfigurationFiles>
        ...
    </configuration>
    ...
</plugin>

Merging Configuration From Multiple Files

When the analysis configuration is split amongst several files, it needs to be merged together before it is applied to the Revapi extensions. This process is slightly complex with the ability for a single extension to be configured multiple times but in the end is somewhat similar to the way Maven merges the executions of a plugin - as long as the executions are defined once in the effective POM, they don’t need to be assigned IDs. If there are multiple executions and you override them in child POMs, they need to have the IDs assigned so that it is clear what executions in child POM need to be merged with what executions in the parent POM.

In Revapi, too, an extension configuration can optionally have an ID. In JSON this is expressed like this:

...
    {
      "extension": "my.extension",
      "id": "id",
      "configuration": ...
    }
...

and in XML like so:

...
    <my.extension id="myid">
      ...
    </my.extension>
...

When merging configurations without an explicit ID, everything works as long as there is at most a single configuration for each extension in each configuration file to be merged. As soon as there is more than one configuration for some extension in one of the configuration files, you need to assign IDs to the configurations of that extension so that it is clear what configs should be merged with what.

Custom Root Element of Configuration

It might sometimes be useful to be able to only use a part of a JSON document as configuration for Revapi. This might be because the same file might be used for holding other data, too, or because the file(s) contain(s) multiple Revapi configurations. Note that the custom root is only applicable to configuration files, not the in-POM configuration.

The below example illustrates the usage of the custom configuration root.

<plugin>
    <groupId>org.revapi</groupId>
    <artifactId>revapi-maven-plugin</artifactId>
    <version>...</version>
    ...
    <configuration>
        <analysisConfigurationFiles>
            <file>${project.basedir}/config/filter.json</file>
            <file>${project.basedir}/config/ignore.json</file>
            <file>
              <path>${project.basedir}/config/json-data-for-many-things.json</path>
              <roots>
                <root>configuration/revapi</root>
              </roots>
            </file>
            <file>
              <path>${project.basedir}/config/xml-data-for-many-things.xml</path>
              <roots>
                <root>configuration/revapi</root>
              </roots>
            </file>
        </analysisConfigurationFiles>
    </configuration>
    <executions>
        <execution>
            <goals><goal>check</goal></goals>
        </execution>
    </executions>
</plugin>

The above would read the configuration from the filter.json and ignore.json files. In addition it would also read the configuration from the json-data-for-many-things.json and xml-data-for-many-things.xml files but would only consider the data from the "configuration/revapi" subpath in those file. E.g. if the files looked like:

{
  "itest-setup": {...},
  "configuration": {
    "our-custom-tool": {
    },
    "revapi": {
      ... HERE WE ARE ...
    }
  }
}
<configuration>
  <ci>...</ci>
  <revapi>
     ... HERE WE ARE ...
  </revapi>
</configuration>

The Revapi configurations would only be read from the "…​ HERE WE ARE …​" part of the documents.

Revapi itself uses this approach to track the changes made to its API across the versions using a single file. Each Revapi module can have a "api-changes.json" file in its base directory. The contents of this file follow this pattern:

{
  "version1": {
    "revapi": {
      "ignore": [
        ...
      ]
    }
  },
  "version2": {
    "revapi": {
      "ignore": [
        ...
      ]
    }
  },
  ...
}

I.e. in that file, the root elements are the released versions of revapi and under them there are configurations for revapi for the particular version to pass the build. Usually, this is just a list of ignored API changes - i.e. the API changes made in that release that are to be purposefully ignored by the tool so that the build passes. To make this work, revapi build contains this profile:

<profile>
    <id>api-check</id>
    <activation>
        <activeByDefault>true</activeByDefault>
    </activation>

    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <id>parse-version</id>
                        <goals>
                            <goal>parse-version</goal>
                        </goals>
                        <phase>validate</phase>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <groupId>org.revapi</groupId>
                <artifactId>revapi-maven-plugin</artifactId>
                <version>${self-api-check.maven-version}</version>
                <dependencies>
                    <dependency>
                        <groupId>org.revapi</groupId>
                        <artifactId>revapi-java</artifactId>
                        <version>${self-api-check.java-extension-version}</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <failOnMissingConfigurationFiles>false</failOnMissingConfigurationFiles>
                    <analysisConfigurationFiles>
                        <configurationFile>
                            <path>api-changes.json</path>
                            <roots>
                                <root>${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}</root>
                            </roots>
                        </configurationFile>
                    </analysisConfigurationFiles>
                </configuration>
                <executions>
                    <execution>
                        <id>api-check</id>
                        <goals><goal>check</goal></goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</profile>

Reporting With Revapi

Report Per Module

Note
Goal details page: here

The Revapi Maven plugin offers the possibility to create simple reports of the API changes found in the analysis. The report goal offers the same configuration properties as the analysis itself. Just include the following snippet in reporting/plugins of your POM:

<plugin>
    <groupId>org.revapi</groupId>
    <artifactId>revapi-maven-plugin</artifactId>
    <version>...</version>
    <reportSets>
        <reportSet>
            <reports>
                <report>report</report>
            </reports>
        </reportSet>
    </reportSets>
    ...
</plugin>

The report can be configured in a very much the same way as the build-time API check and provides virtually the same configuration properties.

Aggregate Report

Note
Goal details page: here

For POM-packaged modules, one can create an aggregate report consisting of the individual reports of the modules that are (indirectly) referenced by the POM module. Again this can be configured the same way the rest of the Revapi goals. Please consult the details page of the goal for the individual configuration properties.

<plugin>
    <groupId>org.revapi</groupId>
    <artifactId>revapi-maven-plugin</artifactId>
    <version>...</version>
    <reportSets>
        <reportSet>
            <reports>
                <report>report-aggregate</report>
            </reports>
        </reportSet>
    </reportSets>
    ...
</plugin>

Comparing Specific Artifacts

By default Revapi checks the currently built artifact against the latest released version of it. This actually is equivalent to running the maven plugin with the following set up:

<plugin>
  <groupId>org.revapi</groupId>
  <artifactId>revapi-maven-plugin</artifactId>
  <version>...</version>
  <configuration>
    <oldArtifacts>
        <artifact>${project.groupId}:${project.artifactId}:RELEASE</artifact>
    </oldArtifacts>
    <newArtifacts>
        <artifact>${project.groupId}:${project.artifactId}:${project.version}</artifact>
    </newArtifacts>
  </configuration>
  <executions>
    <execution>
      <goals><goal>check</goal></goals>
    </execution>
  </executions>

I.e. the oldArtifacts are set up to include the current project with the RELEASE version, which is Maven’s way of saying "this project in the latest released version". The newArtifacts specifies the currently built project.

The above example implies a couple of things:

  • you can include more than one artifact to be included in the analysis

  • you don’t have to specify the "supplementary archives" - the dependencies of the artifacts are automatically obtained from Maven and used during the analysis so that the complete classpath is used

  • you’re not constrained to check the artifacts of the current project - in fact you could have a separate "check" module that would perform API checks completely separately from other modules in the project.

Updating Version In pom.xml

Note
Goal details page: here

Revapi needs two artifacts to compare against each other to determine the API differences and therefore the required version changes. By default the new artifact is the project being built so the artifacts need to be actually produced prior to running revapi. This is usually done in the package phase, which is therefore run prior to any Revapi goal.

When updating the version, the plugin takes into consideration the configuration of Revapi as declared in the pom.xml but does not use certain extensions that would make some of the differences disappear (like the semver-ignore extension). This list of extensions is configurable using the disallowedExtensions configuration property, see the goal’s detail page for further info.

For a single-module project, updating the versions is very simple:

mvn revapi:update-versions

The version in pom.xml will be updated according to the API changes and the semantic versioning rules.

For multi-module project, one has more options. If each of the modules in the project is independently versioned, then the invocation is the same as for the single-module project, but if you version the child modules uniformly with the parent (i.e. you set autoVersionSubmodules to true when releasing using the maven release plugin), you should set the singleVersionForAllModules of revapi to true, too. Generally, autoVersionSubmodules and singleVersionForAllModules should be set to the same value.

mvn revapi:update-versions -Drevapi.singleVersionForAllModules=true

This will check the API differences in all the child modules and will determine the version of the whole based on the "biggest" change. I.e. if one child module breaks the API then the major version will be increased in all modules even though the rest of the child modules might not have changed at all.

Updating Versions In release.properties

Note
Goal details page: here

This works identically to the update versions goal but instead of updating the version directly in the pom.xml files, it creates or updates the release.properties file. This will then be read by the maven release plugin during the release process.

Thus, running:

mvn revapi:update-release-properties && mvn release:prepare

will automatically set the release and development versions for you according to the semver versioning rules.

Back to top

Msb3 Maven skin by Marek Romanowski.