使用功能分支时避免Maven存储库版本冲突 [英] Avoiding maven repository version collision when using feature branches

查看:189
本文介绍了使用功能分支时避免Maven存储库版本冲突的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题:如何处理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 排除)知名分支(例如masterdevelop等)并填充(或不填充)新的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 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.

这是一个最小的示例:

<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设置为其值(只有与developmasterrelease*不同),然后将其设置为分类器.

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.

  • 所生成的工件根据其源分支在Nexus中将动态变化,因此具有隐式可追溯性:无需开发人员干预(无错误,隐式约定),无需CI作业干预(易于维护),完全透明
  • 使用分类器,可以更轻松地将分支生成的工件用作maven依赖项(例如,在库项目的情况下):我想使用当前在分支xxx上正在开发的依赖项
  • 示例
    因此,您将生成以下工件:

    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 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

    有关此方法的警告:

    • 如以下讨论中通过注释所述,如果有关的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屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆