从git branch派生maven工件版本

Tho*_*sen 60 git maven mavanagaiata

我们有一个工作流程要求,这实际上意味着我们需要从git中的当前分支外部定义模块的工件版本.

即如果我们在git的master分支上,我需要<version>master-...</version>,如果我们在bugfixX分支上,我需要<version>bugfixX-....</version>为这个pom.xml生成工件.

我之前发现https://github.com/koraktor/mavanagaiata可以提供SHA-1哈希作为属性,从文档中可以看出它也可以提供分支,所以也许它可以在早期运行我们可以设置属性并放入<version>${our.version}</version>pom的过程.如果这是可能的,我非常希望看到一个有效的pom.xml(并为它奖励500点赏金).

如果没有,我想我们正在进行预处理或"git checkout"使用一些钩子做一些额外的魔法(我还没有尝试过,工作代码也会很棒).

我们有一个顶级pom,可以在构建模块之前运行以生成".."中的属性文件,其中我要求的这个功能需要去.

关于如何解决这个问题的任何建议?

Tim*_*mur 45

实际上,Maven无法在一次运行中改变其自身项目的版本与其他目标.最重要的是,据我所知,Maven不支持<version>标签中的任意属性.因此,需要单独执行才能运行将改变POM版本的目标.有各种插件可以做到 - 在这种情况下,可以使用插件中的versions:set目标versions- http://mojo.codehaus.org/versions-maven-plugin/set-mojo.html

因此,可以按如下方式执行它,例如:

mvn versions:set -DgenerateBackupPoms=false -DnewVersion=$branch-SNAPSHOT
Run Code Online (Sandbox Code Playgroud)

其中$branch变量具有包含当前GIT中分支名; 它可以git rev-parse像这样提取:

branch=$(git rev-parse --abbrev-ref HEAD)
Run Code Online (Sandbox Code Playgroud)

但是,仍然需要以某种方式执行它.你可以手动完成,但很麻烦.所以,我的猜测是,确实最强大的解决方案是从Git方面解决这个问题.那是 - 一个Git钩子.这是完整的Git post-checkout钩子,它将完成这项工作(与上面的代码相同,只有在检出分支时才进行一些过滤来运行钩子,而不仅仅是单个文件):

#!/bin/bash

echo 'Will change the version in pom.xml files...'

# check if the checkout was to checkout a branch
if [ $3 != '1' ]
    then echo 'git checkout did not checkout a branch - quitting';exit
fi

# get current branch name
branch=$(git rev-parse --abbrev-ref HEAD)
version=$branch-SNAPSHOT

# run maven versions plugin to set new version
mvn versions:set -DgenerateBackupPoms=false -DnewVersion=$version

echo 'Changed version in pom.xml files to $version'
Run Code Online (Sandbox Code Playgroud)

将此内容放入文件PROJECTDIR\.git\hooks\post-checkout文件中.请注意,钩子文件应该是可执行的以运行它(chmod +x post-checkout).

关于versions插件的几点注意事项- 它非常灵活,支持很多选项,并且很少有其他可能有帮助的目标,具体取决于你的项目结构(你是否使用父poms,孩子们有自己的版本,或者他们是从父母那里得到的)等).因此,可以通过使用versions插件中的其他目标或指定其他参数来略微修改上面的钩子以支持您的特定情况.

优点:

  • 强大的
  • 无需更改pom.xml文件中的任何内容即可使其工作
  • 只需通过停用钩子(删除或不可执行)即可关闭此"功能" - 再次,pom.xml中不需要进行任何更改

缺点:

  • 一个人不能强制其他人使用钩子 - 它应该在克隆repo后手动安装(或者,如果假设Git用户害怕触摸.git目录中的内容,你可以提供一个安装钩子的脚本).

UPDATE

此后是更复杂的钩子版本,它不仅将版本设置为分支名称,还将保留旧版本的后缀.例如,提供旧版本master-1.0-SNAPSHOT,切换到feature1分支将更改项目的版本feature1-1.0-SNAPSHOT.这个bash脚本遇到的问题很少(需要名称中没有破折号(-)的分支名称,只接受根pom的版本),但可能会想知道如何扩展钩子:给定混合mvn和bash命令可以提取和更新POM中的大量信息.

#!/bin/bash

echo 'Will change the version in pom.xml files...'

# check if the checkout was to checkout a branch
if [ $3 != '1' ]
    then echo 'git checkout did not checkout a branch - quitting';exit
fi

# get current branch name
branch=$(git rev-parse --abbrev-ref HEAD)

# get current version of the top level pom
current_version=$(mvn help:evaluate -Dexpression=project.version | grep -v '\[.*')

# extract version suffix
suffix=$(echo $current_version | cut -d \- -f 2)

# build new version
version=$branch-$suffix

# run maven versions plugin to set new version
mvn versions:set -DgenerateBackupPoms=false -DnewVersion=$version

echo 'Changed version in pom.xml files to $version'
Run Code Online (Sandbox Code Playgroud)


Mat*_*ARD 13

很抱歉重新回答这个问题并且最近发布了另一个解决方案,但确实可以动态地更改maven版本并使用一些git功能,有点像git describe.

执行此操作的项目是jgitver-maven-plugin (免责声明;我是作者),它使用jgitver基于jgit的库,以便从git信息派生maven项目版本.

在此输入图像描述

它非常容易用作maven扩展

...
  <build>
      <extensions>
          <extension>
              <groupId>fr.brouillard.oss</groupId>
              <artifactId>jgitver-maven-plugin</artifactId>
              <version>0.1.0</version>
          </extension>
      </extensions>
     ...
  </build>
...
Run Code Online (Sandbox Code Playgroud)

扩展也可以用作插件扩展,然后允许更多配置,例如,如果您不想使用SNAPSHOTS.有关完整使用方案的说明,请参阅项目页面.

还有一个可用的gradle插件或多或少相同.


[编辑1]:回答ThorbjørnRavnAndersen的评论

该插件不会修改原始pom文件或build.gradle文件.
对于maven插件,修改在maven对象模型的内存中完成,并写入临时目录中的临时文件.计算仅基于git元数据(标记,提交,...).
这种非修改允许不污染git历史.当你对git提交感到满意时,标记它git tag -a x.y.z并且mvn deploy:就是这样.
项目文件中的版本现在没用,例如可以设置为0.

截至今天,由于IDEA-155733,只有最近的EAP版本的IntelliJ与maven插件一起使用.Eclipse和Netbeans没有问题.



qoo*_*mon 12

免责声明:我是作者

我的maven核心扩展将基于当前分支或标记虚拟设置版本.您可以根据需要配置自定义版本格式模式.

https://github.com/qoomon/maven-branch-versioning-extension

版本格式示例 在此输入图像描述

  • 实际上,这是一个非常好的答案,请检查它运行良好的扩展。它就像`jgitver-maven-plugin`,但恕我直言更好 (2认同)
  • 是的,它似乎工作得更好。更容易配置。 (2认同)
  • 扩展的新名称似乎是 maven-git-versioning-extension (2认同)

Ed *_*all 11

maven-3.5.0开始,版本标记中支持 ${revision}、${sha1} 和 ${changelist} 属性。例如,如果您想要将 Git 分支名称合并到 CI 构建作业的版本中,则此功能可能足以满足您的目的。查看Maven CI 友好版本

基本上,在您的 pom.xml 中将固定版本替换为:

<version>${revision}${changelist}</version>
Run Code Online (Sandbox Code Playgroud)

通过创建包含以下内容的文件,在项目根目录中设置修订更改列表.mvn/maven.config的默认值:

-Drevision=1.2.3
-Dchangelist=-SNAPSHOT
Run Code Online (Sandbox Code Playgroud)

将此文件签入版本控制,并在项目修订时更新它。

然后,在 CI 系统中,您可以使用 Git 分支名称的清理表示来覆盖更改列表变量,例如

# sed regex replaces non-(alphanumeric, dot or dash) char sequences with a dash
BRANCHNAME=$(git rev-parse --abbrev-ref HEAD | sed -E -e 's@[^0-9A-Za-z.-]+@-@g')
mvn clean install -Dchangelist="-${BRANCHNAME}"
Run Code Online (Sandbox Code Playgroud)

(您可能更喜欢git symbolic-ref --short HEAD获取分支名称,YMMV)

由 CI 系统为分支构建的工件feature/branchname将具有版本化分支后缀,例如:

yourproject-1.2.3-feature-branchname.jar
Run Code Online (Sandbox Code Playgroud)

而不使用任何覆盖的开发人员仍会将其构建为:

yourproject-1.2.3-SNAPSHOT.jar
Run Code Online (Sandbox Code Playgroud)