使用功能分支时避免maven存储库版本冲突

Pet*_*ahn 10 nexus maven-3 maven git-flow jenkins

问题:如何处理maven多项目构建的功能分支?

Jenkins构建和部署这些分支以将开发人员的构建开销保持在最低限度,但开发和功能分支无法构建相同的maven版本,或者我们存在工件和源之间不匹配的风险.

我们有一个脚本来更改子poms中的父版本和root pom中的版本.虽然这会分隔maven空间中的分支,但在合并时会产生额外的工作.

我认为nexus pro staging功能可以帮助我们避免这个要求,并使每个功能分支使用特定的repo,我们在分支删除/合并后很容易丢弃.

再说一遍:如何处理多个分支和maven的问题?

A_D*_*teo 7

以下方法怎么样:

  • 使用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>
Run Code Online (Sandbox Code Playgroud)

下面的代码段基本上填充scmBranch动态属性,则设置branch.classifier到其值仅当比不同develop,master或者release*,然后将其设置为分类器.

这种方法的主要优点:

  • 不会应用任何pom更改,因此根本不会出现合并问题
  • Nexus在相同版本的项目上工作但在不同分支上没有冲突:分类工件将具有不同的Maven坐标,即GAV(groupId,artifactId,version)变为唯一的GAVC(+分类器)
  • 这实际上是classifier对工件属性的有意义的用法:

    分类器允许区分从相同POM构建但其内容不同的工件.

  • 根据其源分支,生成的工件在Nexus中将是动态不同的,因此具有隐式可跟踪性:没有开发人员的干预(不容易出错,隐式约定),CI工作没有干预(更容易维护),完全透明
  • 使用分类器将更容易使用分支生成的工件作为maven依赖项(例如,在库项目的情况下):我想使用当前正在开发的分支xxx上的依赖项

示例
因此,您将生成以下工件:

  • 处理时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:)案件就像双重检查,但实际上并不需要

这种方法的警告:

  • 正如下面通过注释讨论中所解释的那样,如果相关的Maven项目已经在使用分类器,甚至更多地通过模块间依赖关系(例如,依赖于来自另一个模块的测试范围类),那么应该仔细测试这种方法,因为它可能具有一些缺点
  • <artifactId>.pom包含分支分类器的文件的发布可能与主线构建冲突(即覆盖它)