使用功能分支时避免Maven存储库版本冲突 [英] Avoiding maven repository version collision when using feature branches
问题描述
问题:如何处理Maven多项目构建的功能分支?
Question: How do you handle feature branches for maven multi project builds?
Jenkins构建并部署了这些分支,以将开发人员的构建开销降至最低,但开发和功能分支无法构建相同的Maven版本,否则我们将冒着工件与源代码不匹配的风险.
Jenkins builds and deploys these branches to keep build overhead on developers to a minimum but develop and feature branches cannot build the same maven version or we risk mismatch between artifacts and source.
我们有一个脚本来更改子pom中的父版本和root pom中的版本.虽然这会将分支隔离在Maven空间中,但合并时会导致额外的工作.
We have a script to change parent version in child poms and version in root pom. While this segregates the branches in maven space, it results in extra work when merging.
我认为nexus pro分期功能可以帮助我们避免此要求,并使每个功能分支使用特定的回购协议,我们可以在删除/合并分支后轻松删除该回购协议.
I think nexus pro staging feature might help us avoid this requirement and make each feature branch use a specific repo which we easily drop after branch deletion/merge.
再次:如何处理多个分支和Maven的问题?
Again: how to handle the problem of multiple branches and maven?
推荐答案
以下方法如何:
- 使用
buildnumber-maven-plugin
从git中获取信息并填充特定的Maven属性(我们对scmBranch
属性(即当前的git分支)特别感兴趣 - 使用
build-helper-maven-plugin
检查我们是否在功能中是否分支(通过 regex 排除)知名分支(例如master
,develop
等)并填充(或不填充)新的Maven属性,例如branch.classifier
- 使用
maven-jar-plugin
在生成的工件上设置分类器,基于上一步的设置,即使用新的branch.classifier
属性:如果为空,则不会应用分类器(例如,默认行为,应用于develop
分支);否则,将动态应用以当前分支命名的分类器.
- Use the
buildnumber-maven-plugin
to fetch information from git and populate specific Maven properties (we are interested specifically in thescmBranch
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 likemaster
,develop
, etc.) and populate (or not) a new Maven property, saybranch.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 newbranch.classifier
property: if empty, no classifier will be applied (default behavior, applied to thedevelop
branch, for example); otherwise a classifier named after the current branch will be dynamically applied.
这是一个最小的示例:
<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>
下面的代码段基本上是动态填充scmBranch
属性,然后将branch.classifier
设置为其值(只有与develop
,master
或release*
不同),然后将其设置为分类器.
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.
此方法的主要优点:
- 不会更改pom,因此完全没有合并问题
- 在相同项目版本但在不同分支上运行的Nexus上没有冲突:分类的工件将具有不同的
classifier
属性的有意义的用法:
- 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:
分类器可以区分由相同POM构建但内容不同的工件.
The classifier allows to distinguish artifacts that were built from the same POM but differ in their content.
示例
因此,您将生成以下工件:
Examples
Hence, you would have the following artifacts generated:
- 使用
develop
时:例如project-1.0.0-SNAPSHOT.jar
(空分类符,因此不适用,由正则表达式处理) - 使用
featureA
时:例如project-1.0.0-SNAPSHOT-featureA.jar
- 使用
hotfix-JIRA123
时:例如project-1.0.0-hotfix-JIRA123.jar
- 在
release-sprint42
上工作时:完全由您决定,我添加了这种情况以不应用分支名称,这仅仅是因为在这些情况下,我倾向于为发布候选者专门设置特殊的分类器RC<number>
,但这就是出于惯例/品味/习惯的考虑,只要在Nexus上不会产生冲突,您也可以在此分支上应用相同的方法.另请注意:使用JIRA/Stash/Git集成时,发行分支名称通常类似于release/v0.1.0
,其中/
字符可能会在某些操作系统中引起问题(如果确实需要,则可以通过进一步的正则表达式替换来修复某些问题) - 在
master
上工作时:嘿,没有人应该在master
上工作:)这种情况只是作为双重检查而已,但这实际上不是必需的
- 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 likerelease/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 onmaster
:) the case is there just as a double check, but that's actually not required
有关此方法的警告:
- 如以下讨论中通过注释所述,如果有关的Maven项目已经在使用分类器,甚至更多地通过模块间的依赖关系(例如,依赖于另一个模块的测试范围类),则应仔细测试此方法,因为它可能有一些缺点
- 包含分支分类器的
<artifactId>.pom
文件的发布可能会与主线版本发生冲突(即覆盖它)
- 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存储库版本冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!