CI Maven Plugin
A Maven plugin for use in CI pipelines based on the patterns described in the Maven CI Friendly documentation.
Usage
<build>
<plugins>
<plugin>
<groupId>tools.bestquality</groupId>
<artifactId>ci-maven-plugin</artifactId>
<version>0.0.20</version>
<executions>
<execution>
<goals>
<goal>expand-pom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Goals
ci:expand-pom
By default, this goal is bound to the validate
phase and considers the project’s pom.xml
as a template
producing an expanded version performing the following actions on the template:
- replaces all
${revision}
,${sha1}
, and${changelist}
property references found in the project’spom.xml
file - updates the values of
revision
,sha1
, andchangelist
defined in the<properties>
element - writes the expanded pom file to
target/generated-poms/pom-ci.xml
and sets it as the project’spom.xml
file
pom.xml
files. This is critical if your POMs contain important
information in its comments.
ci:increment-pom
By default, this aggregator goal is bound to the validate
phase and will update the project’s top-level
pom.xml
ci revision
property with the next selected component to increment. Use to prepare the pom.xml
file for the next development snapshot.
Without customization, the goal will attempt to resolve the version component to increment by starting with the build
and working it’s way up to the major
component. The following standard incrementors are available:
auto
(default)major
minor
patch
build
To use a specific incrementor:
mvn ci:increment-pom -Dincrementor=minor
This goal exports the incremented version and can be configured to export to standard out (default) or a file:
Writing to stdout
# assign next version to script variable
next_version=$(mvn -q ci:increment-pom)
Writing to a file
# writes to target/ci/next-version.txt
mvn ci:increment-pom -Dscriptable=false
# customize the file location (both file properties are optional)
mvn ci:increment-pom -Dscriptable=false -Doutput-directory="." -Dfilename="next.txt"
ci:release-version
By default, this aggregator goal is bound to the validate
phase and will read the top-level project’s revision
property and output the value to a file or standard out while removing the -SNAPSHOT
qualifier. It does not make
any pom modifications and can be used if the release process is not event driven.
Writing to stdout
The goal is designed to be executed from the command line to capture and assign the output to a variable:
release_revision=$(mvn -q ci:release-version)
Writing to a file
The goal can be configured to write the output to a file:
# writes to target/ci/release-version.txt
mvn ci:release-version -Dscriptable=false
# customize the file location (both file properties are optional)
mvn ci:release-version -Dscriptable=false -Doutput-directory="." -Dfilename="release.txt"
ci:replace-content
By default, this goal is bound to the verify
phase and can be used to replace version references in documentation.
This goal can be configured with a list of documents, i.e.:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>bestquality</groupId>
<artifactId>ci-pom</artifactId>
<version>${revision}</version>
<packaging>jar</packaging>
<properties>
<revision>2.22.2-SNAPSHOT</revision>
</properties>
<build>
<plugins>
<plugin>
<groupId>tools.bestquality</groupId>
<artifactId>ci-maven-plugin</artifactId>
<version>0.0.20</version>
<configuration>
<documents>
<document>
<location>${project.basedir}/README.md</location>
<encoding>utf-8</encoding>
<pattern><![CDATA[(?sm)(<artifactId>ci-maven-plugin<\/artifactId>\s+<version>).*?(<\/version>)]]></pattern>
<replacement><![CDATA[$1${project.version}$2]]></replacement>
</document>
<document>
<location>${project.basedir}/docs/_config.yml</location>
<encoding>utf-8</encoding>
<pattern><![CDATA[(version:).*]]></pattern>
<replacement><![CDATA[$1 ${project.version}]]></replacement>
</document>
<document>
<location>${project.basedir}/pom.xml</location>
<encoding>utf-8</encoding>
<pattern><![CDATA[(<maven.ci.version>).*(<\/maven.ci.version>)]]></pattern>
<replacement><![CDATA[$1${project.version}$2]]></replacement>
</document>
</documents>
</configuration>
<executions>
<execution>
<goals>
<goal>expand-pom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Then, in a release script, the goal can be executed to update version references in the configured documents:
echo "Updating version references in documentation"
mvn ci:replace-content -Drevision="${GITHUB_REF_NAME}"
ci:clean
By default, this goal is bound to the clean
phase and will remove the expanded target/generated-poms/pom-ci.xml
file
note: This goal is only needed if the default plugin outputDirectory
configuration is changed to be outside
of ${project.build.directory}
Example Project Configuration
pom.xml
This configuration results in consistent developer and pipeline builds:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>${revision}${sha1}${changlist}</version>
<packaging>...</packaging>
<properties>
<revision>2.22.2</revision>
<sha1/>
<changelist>-SNAPSHOT</changelist>
</properties>
<build>
<plugins>
<plugin>
<groupId>tools.bestquality</groupId>
<artifactId>ci-maven-plugin</artifactId>
<version>0.0.20</version>
<executions>
<execution>
<goals>
<goal>expand-pom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Installing from workflow or pipeline
A typical workflow or pipeline step will involve building and testing the project. In this case, the
sha1
ci property can be used to namespace the branch build preventing any artifact collisions. This
is necessary if your organization captures all build artifacts:
# export BUILD_NUMBER=22
mvn clean install -Dsha1="-${BUILD_NUMBER}"
When built, the installed pom.xml
will be expanded to:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>2.22.2-22-SNAPSHOT</version>
<packaging>...</packaging>
<properties>
<revision>2.22.2</revision>
<sha1>-22</sha1>
<changelist>-SNAPSHOT</changelist>
</properties>
<build>
<plugins>
<plugin>
<groupId>tools.bestquality</groupId>
<artifactId>ci-maven-plugin</artifactId>
<version>0.0.20</version>
<executions>
<execution>
<goals>
<goal>expand-pom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Deploying
To deploy a release or non-snapshot build, such as when a tag is pushed:
# export RELEASE_VERSION=2.22.2
mvn clean deploy -Drevision="${RELEASE_VERSION}" -Dchangelist=
When deployed, the uploaded pom.xml
will be expanded to:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>2.22.2</version>
<packaging>...</packaging>
<properties>
<revision>2.22.2</revision>
<sha1/>
<changelist/>
</properties>
<build>
<plugins>
<plugin>
<groupId>tools.bestquality</groupId>
<artifactId>ci-maven-plugin</artifactId>
<version>0.0.20</version>
<executions>
<execution>
<goals>
<goal>expand-pom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>