[英]Avoiding maven repository version collision when using feature branches
问题:您如何处理 Maven 多项目构建的功能分支?
Jenkins 构建和部署这些分支以将开发人员的构建开销保持在最低限度,但开发和功能分支不能构建相同的 Maven 版本,否则我们可能会面临工件和源代码不匹配的风险。
我们有一个脚本来更改子 pom 中的父版本和根 pom 中的版本。 虽然这会隔离 Maven 空间中的分支,但合并时会导致额外的工作。
我认为 nexus pro 暂存功能可能会帮助我们避免这种要求,并使每个功能分支使用一个特定的存储库,我们可以在分支删除/合并后轻松删除该存储库。
再次:如何处理多个分支和maven的问题?
以下方法如何:
buildnumber-maven-plugin
从 git 中获取信息并填充特定的 Maven 属性(我们对scmBranch
属性(即当前的 git 分支)特别感兴趣)build-helper-maven-plugin
检查我们是否在功能分支中(通过正则表达式,不包括master
、 develop
等知名分支)并填充(或不)新的 Maven 属性,例如branch.classifier
maven-jar-plugin
在生成的工件上设置分类器,基于上一步设置的内容,即使用新的branch.classifier
属性:如果为空,则不应用分类器(默认行为,应用于develop
分支,例如); 否则将动态应用以当前分支命名的分类器。这是一个最小的例子:
<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
属性,然后仅当与develop
、 master
或release*
不同时才将branch.classifier
设置为其值,然后将其设置为分类器。
这种方法的主要优点:
classifier
属性的一个有意义的用法:
分类器允许区分由相同 POM 构建但内容不同的工件。
例子
因此,您将生成以下工件:
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
工作 :) 这种情况只是作为一个双重检查,但这实际上不是必需的这种方法的警告:
<artifactId>.pom
文件的发布可能会与主线构建发生冲突(即覆盖它)当从顶级父级运行时,这不起作用在整个构建和 GC 错误中导致警告。
理想情况下,我们希望使用版本来区分特征分支和主线,因为这是正常的 Maven 方式,并且分类器操作会导致各种问题。
由于 maven 可以将环境变量用于属性,并且我们已经使用脚本初始化了构建环境(我们还有 git hook 脚本可以从分支名称设置环境变量)我们可以使用 env 来控制版本。
<groupID>my.project</groupId>
<artifactID>database</artifactId>
<version>1.2.0${env.BRANCHMODIFIER}-SNAPSHOT</version>
如果在开发我们的脚本时将BRANCHMODIFIER设置为“”
如果在 feature/JIRA-30495 上,我们的脚本将BRANCHMODIFIER设置为“.30495”
这在 eclipse 或 Intellij 中是如何工作的? 目前还没有任何线索。
我们使用与 Peter Kahn 类似的技术,在构建之前修改分支的版本。 我们的“准备步骤”分为三个步骤:
echo VERSION=$(echo ${GIT_BRANCH} | sed 's_^.*\\/__') > env.properties
env.properties
versions:set -DgenerateBackupPoms=false -DnewVersion=${VERSION}-SNAPSHOT
我很确定这可以通过两个甚至一个步骤来完成,也可以只执行一步,其背后的原理是相同的。
我们之所以不直接在分支中更改pom.xml文件中的版本,确实是在合并。 使用 SVN,这是可能的(与--accept-mine-conflict
合并。使用 GIT,这不再存在,因此我们停止更改版本并创建此预构建步骤。
对于 Maven ge 3.5.0,试试这个https://maven.apache.org/maven-ci-friendly.html这是推荐的 Maven 解决方案。 唯一的问题(但不寻常)可能是 maven 依赖项的数字版本解析。 但这只会出现,如果您使用模块的不同 SNAPSHOT 依赖项,无论如何这都是一个坏主意。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.