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

时间:2016-07-02 18:10:41

标签: maven jenkins maven-3 nexus git-flow

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

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

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

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

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

4 个答案:

答案 0 :(得分:6)

以下方法如何:

  • 使用buildnumber-maven-plugin从git获取信息并填充特定的Maven属性(我们特别感兴趣的是scmBranch属性(即当前的git分支)
  • 使用build-helper-maven-plugin检查我们是否在功能分支中(通过regex,不包括masterdevelop等众所周知的分支。 )并填充(或不填充)新的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属性,然后仅在branch.classifierdevelopmaster不同时将release*设置为其值,然后将其设置为分类器。

这种方法的主要优点

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

    分类器允许区分从同一个POM构建但内容不同的工件。

  • 根据其源分支,生成的工件在Nexus中将是动态不同的,因此具有隐式可跟踪性:没有开发人员的干预(不容易出错,隐式约定),CI工作没有干预(更容易维护),完全透明< / LI>
  • 使用分类器,将分支生成的工件更容易用作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文件的发布可能与主线构建发生冲突(即覆盖它)

答案 1 :(得分:1)

这不起作用从顶级父级运行时,整个构建过程中出现警告并导致GC错误。

理想情况下,我们希望使用version来区分功能分支和主线,因为它是正常的maven方式,分类器操作可能导致各种问题。

由于maven可以将环境变量用于属性,并且我们已经使用脚本初始化构建环境(我们还有可以从分支名称设置环境变量的git钩子脚本),我们可以使用env来控制版本。

<groupID>my.project</groupId>
<artifactID>database</artifactId>
<version>1.2.0${env.BRANCHMODIFIER}-SNAPSHOT</version>

如果开发我们的脚本,请将 BRANCHMODIFIER 设置为“” 如果在feature / JIRA-30495上我们的脚本将 BRANCHMODIFIER 设置为“.30495”

这在eclipse或Intellij中如何工作?还没有任何线索。

答案 2 :(得分:1)

我们使用与Peter Kahn类似的技术,在构建之前修改分支的版本。我们在&#34;预备步骤&#34;中有三个步骤:

  1. 执行shell:echo VERSION=$(echo ${GIT_BRANCH} | sed 's_^.*\/__') > env.properties
  2. 注入环境变量:env.properties
  3. 调用顶级Maven目标:versions:set -DgenerateBackupPoms=false -DnewVersion=${VERSION}-SNAPSHOT
  4. 我很确定这可以通过两个甚至一个也是唯一的步骤完成,其后面的原理也是一样的。

    我们不直接更改分支中pom.xml文件中的版本的原因确实在合并。使用SVN这是可能的(与--accept-mine-conflict合并。使用GIT,这不再存在,所以我们停止更改版本并创建了这个预构建步骤。

答案 3 :(得分:1)

对于Maven ge 3.5.0,请尝试以下https://maven.apache.org/maven-ci-friendly.html 这是推荐的Maven解决方案。 唯一的问题(但不常见)可能是Maven依赖项的数字版本分辨率。但是,如果您使用模块的其他SNAPSHOT依赖项,那么这只会出现,反而是一个坏主意。