How about the following approach:
- Use the
buildnumber-maven-plugin
to fetch information from git and populate specific Maven properties (we are interested specifically in the scmBranch
property (that is, the current git branch)
- Use the
build-helper-maven-plugin
to check whether we are in a feature branch or not (via a regex, excluding well-known branches like master
, develop
, etc.) and populate (or not) a new Maven property, say branch.classifier
- Use the
maven-jar-plugin
to set a classifier on the generated artifacts, based on what the previous step set, that is, using the new branch.classifier
property: if empty, no classifier will be applied (default behavior, applied to the develop
branch, for example); otherwise a classifier named after the current branch will be dynamically applied.
Here is a minimal example:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>create</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.10</version>
<executions>
<execution>
<id>regex-property</id>
<goals>
<goal>regex-property</goal>
</goals>
<configuration>
<name>branch.classifier</name>
<value>${scmBranch}</value>
<regex>(^develop)|(^master)|(^release.*)</regex>
<replacement></replacement>
<failIfNoMatch>false</failIfNoMatch>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<classifier>${branch.classifier}</classifier>
</configuration>
</plugin>
</plugins>
</build>
The snippet below is basically populating the scmBranch
property dynamically, then setting the branch.classifier
to its value only if different than develop
, master
or release*
, then setting it as a classifier.
Main advantages of this approach:
- No pom changes will be applied, hence no merging issues at all
- No clashes on Nexus working on the same version of the project but on different branches: the classified artifact will have different Maven coordinates, that is, the GAV (groupId, artifactId, version) becomes unique GAVC (+classifier)
- That's actually a meaningful usage of the
classifier
attribute of an artifact:
The classifier allows to distinguish artifacts that were built from the same POM but differ in their content.
- The generated artifact will be dynamically different in Nexus, according to its source branch, hence having implicit traceability: no intervention from developers (no error prone, implicit convention), no intervention from CI job (easier maintenance), completely transparent
- Using classifiers, will be easier to use the artifacts generated by a branch as a maven dependency (e.g. in case of library project): I want to use the dependency currently under development on branch xxx
Examples
Hence, you would have the following artifacts generated:
- When working on
develop
: e.g. project-1.0.0-SNAPSHOT.jar
(empty classifier, hence not applied, as handled by the regex)
- When working on
featureA
: e.g. project-1.0.0-SNAPSHOT-featureA.jar
- When working on
hotfix-JIRA123
: e.g. project-1.0.0-hotfix-JIRA123.jar
- When working on
release-sprint42
: that's up to you, I added this case to not apply the branch name, simply because in these cases I prefer to esplicitely set a special classifier, RC<number>
, for release candidates, but that's a matter of conventions/taste/habits, you can apply the same approach on this branch as well, as long as no clashes will be created on Nexus. Also note: when using JIRA/Stash/Git integration, the release branch name is normally something like release/v0.1.0
, where the /
character may cause issues in some OS (still something fixeable via further regex replacing though, if really required).
- When working on
master
: hey, no one should work on master
:) the case is there just as a double check, but that's actually not required
Warnings on this approach:
- As explained in the discussion below via comments, if the concerned Maven project is already using classifiers and even more via inter-modules dependencies (e.g. dependendies on test scope classes from another module), then this approach should be carefully tested, since it might have some drawbacks
- The publication of the
<artifactId>.pom
files containing branch classifier can get into conflicts with the mainline build (i.e. overriding it)
maven-release-plugin:branch
goal? It will create the branch automatically and will update the version, that you can set tox.x-my-branch
or something similar. – Keirakeisermvn versions:set -DnewVersion=1.2-BRANCH-SNAPSHOT
in the branch to keep it distinct. – Minify