从git branch派生maven工件版本

时间:2012-11-27 12:08:57

标签: 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,可以在构建模块之前运行以生成“..”中的属性文件,我要求这个功能需要去。

有关如何解决此问题的任何建议?

7 个答案:

答案 0 :(得分:44)

实际上,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

其中$branch变量必须包含当前的Git分支名称;它可以用git rev-parse提取,如下所示:

branch=$(git rev-parse --abbrev-ref HEAD)

但是,仍然需要以某种方式执行它。你可以手动完成,但很麻烦。所以,我的猜测是,确实最强大的解决方案是从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'

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

关于versions插件的几点注意事项 - 它非常灵活,并且支持很多选项,并且根据您的项目结构,可能有很多其他目标可能会有所帮助(您是否使用父母poms,孩子们有他们的自己的版本或他们从父母等派生出来)。因此,可以通过使用versions插件中的其他目标或指定其他参数来略微修改上面的钩子以支持您的特定情况。

优点:

  • 鲁棒
  • 无需更改pom.xml文件中的任何内容即可使其正常工作
  • 只需停用挂钩(删除或不可执行)即可关闭此“功能” - 再次,pom.xml中不需要进行任何更改

缺点:

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

<强>更新

此后是更复杂的钩子版本,它不仅会将版本设置为分支名称,还会保留旧版本的后缀。例如,提供旧版本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'

答案 1 :(得分:12)

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

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

enter image description here

它非常容易用作maven扩展

...
  <build>
      <extensions>
          <extension>
              <groupId>fr.brouillard.oss</groupId>
              <artifactId>jgitver-maven-plugin</artifactId>
              <version>0.1.0</version>
          </extension>
      </extensions>
     ...
  </build>
...

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

还有gradle plugin可用或多或少相同。

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

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

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

答案 2 :(得分:9)

免责声明:我是作者

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

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

版本格式示例 enter image description here

答案 3 :(得分:4)

如果在工件文件名中设置git标签和版本信息就足够了,可以使用maven-jgit-buildnumber-plugin

<build>
  <finalName>${artifactId}-${git.buildnumber}</finalName>
  <plugins>
    <plugin>
      <groupId>ru.concerteza.buildnumber</groupId>
      <artifactId>maven-jgit-buildnumber-plugin</artifactId>
      <version>1.2.7</version>
      <executions>
        <execution>
          <id>git-buildnumber</id>
          <goals>
            <goal>extract-buildnumber</goal>
          </goals>
          <phase>prepare-package</phase>
        </execution>
      </executions>
    </plugin>
    <!-- more plugins -->
  </plugins>
</build>

答案 4 :(得分:2)

您是否尝试过使用此插件?https://github.com/ktoso/maven-git-commit-id-plugin。您可以将其配置为生成包含有关回购状态的所有相关信息的属性文件:

  
      
  • 分支
  •   
  • 描述
  •   
  • 的commitid
  •   
  • buildUserName
  •   
  • buildUserEmail
  •   
  • 构建时
  •   
  • commitUserName
  •   
  • commitUserEmail
  •   
  • commitMessageShort
  •   
  • commitMessageFull
  •   
  • commitTime
  •   

答案 5 :(得分:1)

您是否检查了buildnumber-maven-plugin,这使您有机会使用git的修订号。但是你需要不同的东西。此外,我建议做一件事:

   1.0.0-SNAPSHOT 
   1.0.0-SNAPSHOT 
主人

在分支上,您可以简单地将版本更改为

  1.0.0-BF-SNAPSHOT 

答案 6 :(得分:1)

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

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

<version>${revision}${changelist}</version>

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

-Drevision=1.2.3
-Dchangelist=-SNAPSHOT

将此文件检查到版本控制中,在更改项目修订版本时对其进行更新。

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

BRANCHNAME=$(git rev-parse --abbrev-ref HEAD | sed -E -e 's@[^0-9A-Za-z.-]+@-@g')
mvn clean install -Dchangelist="-${BRANCHNAME}"

(您最好选择git symbolic-ref --short HEAD来获取分支名称YMMV)

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

yourproject-1.2.3-feature-branchname.jar

不使用任何替代的开发人员仍将其构建为:

yourproject-1.2.3-SNAPSHOT.jar