A Maven Plugin to update the project version in the local pom.xml
file according to the Semantic Versioning 2.0.0 specification
As a user of this Maven Plugin, I want to update my project’s version in the local pom.xml
file according
to the Semantic Versioning 2.0.0 specifications, by issuing Maven commands from CLI or build script/code.
Notes:
pom.xml
file.Maven 3.5.4 or better
Include this plugin in pom.xml
:
<build>
<plugins>
<plugin>
<groupId>io.github.q3769</groupId>
<artifactId>semver-maven-plugin</artifactId>
<version>${latest.version}</version>
</plugin>
Note: By default, only the parent project’s version is processed, module versions are not. Use
the -DprocessModule
command flag if you also wish to process modules.
From CLI, assuming you are in the Maven project’s default root directory where the pom.xml
file is located:
mvn semver:set-current -Dsemver=blah
errors out because blah
is not a valid SemVer
mvn semver:set-current -Dsemver=1.2.3-beta
sets the new value of the version element of the pom.xml
file to be 1.2.3-beta
, regardless of the original value in
POM
mvn semver:increment-major
increments 1.2.3-beta.1
into 2.0.0
, where 1.2.3-beta.1
is the original POM value
mvn semver:increment-minor -Dsnapshot=true
increments 1.2.3 into 1.3.0-SNAPSHOT
. Note that snapshot
is a convenience flag to set the target pre-release label
as SNAPSHOT
with no build meta label. This labeling shorthand only works with a normal version increment - major,
minor, or patch. To set the labels other ways, see examples in the Pre-release and Build Metadata labels section.
mvn semver:increment-patch
increments 1.2.3-beta.1
into 1.2.4
Assuming now is 1PM on Jan 31, 2021 in UTC time zone, then:
mvn semver:calendar-major
increments 1.2.3
into 2021.0.0
; 20201225.2.3-beta.1
into 20210131.0.0
; 2021.2.3
into 202101.0.0
; 20210131.2.3
into 2021013113.0.0
, etc…
This goal uses the current calendar datetime as the target major
number: It tries to increase the precision
of the current time stamp until the value is larger than the original major
version number; then uses that
time stamp value as the replacement. If the original major
number is too large to replace even when increasing
the current time precision to milliseconds, then the goal errors out and no update will be performed to the POM.
mvn semver:calendar-minor
applies similar manipulations as with semver:calendar-major
, to the minor
normal version number of the original
semver.
mvn semver:calendar-patch
applies similar manipulations as with semver:calendar-major
, to the patch
normal version number of the original
semver.
mvn semver:update-pre-release
increments 1.2.3-beta
into 1.2.3-beta.1
mvn semver:update-build-metadata
increments 1.2.3-beta.1+build.10
into 1.2.3-beta.1+build.11
.
Using this goal alone, without the Dset=...
parameter (mentioned later), is deprecated as SemVer spec
excludes using build metadata for precedence or equavalance comparison; thus, there is no definitive way
to increment build metadata.
mvn semver:update-pre-release -Dset=beta
updates/sets 1.2.3-alpha+build.7
into 1.2.3-beta
mvn semver:update-build-metadata -Dset=build.reno
updates/sets 1.2.3-alpha
into 1.2.3-alpha+build.reno
mvn semver:pick-newer -Dsemver=1.3.0-HOTFIX
updates the original POM version 1.2.3
to 1.3.0-HOTFIX
because 1.3.0-HOTFIX
is a newer version than 1.2.3
.
However, if the original version were 1.3.0
, then no change would have been made because, according to the SemVer
precedence, the original 1.3.0
is newer than the given 1.3.0-HOTFIX
. (Note that a final SemVer is always newer
than any labeled counterpart, regardless the label’s semantics. That is, the final/stable “hot fix” SemVer of 1.3.0
would be 1.3.1
, not 1.3.0-HOTFIX
or 1.3.1-HOTFIX
.)
mvn semver:merge -Dsemver=1.3.10-HOTFIX
updates 1.2.0-SNAPSHOT+chi.1
into 1.4.0-SNAPSHOT+chi.1
, where 1.2.0-SNAPSHOT+chi.1
is the current POM version.
The basic idea here is to center the merge process around the current version in the pom.xml
file. I.e., the intents
and purposes of the current POM version will dominate those of the given SemVer to merge.
Take the newer between the current POM version and the given version to merge, according to the SemVer precedence.
If the current POM version is newer, no change will be made and the current POM version is the merge result.
Otherwise, if the given version to merge is newer, then to form the merge result, the given version is to be
incremented on the last incremented normal version of the current POM version - major
, minor
, or patch
.
The current POM version’s pre-release and build metadata labels, if any exist, always stay and serve as the final merged version’s labels.
In this case, the given version 1.3.10-HOTFIX
is newer, so it is to be incremented to form the merge result. The
last incremented normal version of the current POM version 1.2.0-SNAPSHOT+chi.1
is minor
, so the given version
1.3.10-HOTFIX
is incremented on its own minor
version number, resulting in 1.4.0
per SemVer spec. (Note that the
given version 1.3.10-HOTFIX
’s last incremented normal version is patch
but that anyway does not matter per the merge
rules here.) Then, the current POM version’s labels (in this case SNAPSHOT
and chi.1
), if any exist, always stay as
they are. Thus, for the final merged version, we have 1.4.0-SNAPSHOT+chi.1
.
Assuming now is 1PM on Jan 31, 2021, then:
mvn semver:merge-calendar -Dsemver=1.3.10-HOTFIX
updates 1.2.0-SNAPSHOT+chi.1
into 1.2021.0-SNAPSHOT+chi.1
, where 1.2.0-SNAPSHOT+chi.1
is the current POM version.
This goal performs similar functions as with semver:merge
, but using calendar value as the update result instead of
simple increment.
mvn semver:finalize-current
changes 1.2.3-SNAPSHOT
or 1.2.3-beta.1+build.10
into 1.2.3
, stripping off all additional labels
mvn semver:verify-current
prints confirmation message if the current version of the local POM is in valid SemVer format, errors otherwise.
mvn semver:verify-current -Dforce-stdout -q
prints the current POM version and nothing else (e.g. 1.2.3-beta.4+build.5
) in std out if it is a valid SemVer.
For a clean print out of the project’s SemVer with nothing else, you need the -q
or --quiet
option to suppress
the usual Maven messages.