简体   繁体   English

从 git 分支派生 maven 工件版本

[英]Deriving maven artifact version from git branch

We have a workflow requirement that essentially mean that we need to have the artifact version of a module externally defined from the current branch in git.我们有一个工作流要求,本质上意味着我们需要从 git 中的当前分支外部定义模块的工件版本。

Ie if we are on the master branch in git, I need <version>master-...</version> and if we are on the bugfixX branch, I need <version>bugfixX-....</version> for the generated artifact for this pom.xml.即如果我们在 git 的 master 分支上,我需要<version>master-...</version>而如果我们在 bugfixX 分支上,我需要<version>bugfixX-....</version>为此 pom.xml 生成的工件。

I have previously found that https://github.com/koraktor/mavanagaiata can provide the SHA-1 hash as a property and it appears from the documentation that it can also provide the branch, so perhaps if it could be run early enough in the process we could set the property and just put <version>${our.version}</version> in the pom.我之前发现https://github.com/koraktor/mavanagaiata可以提供 SHA-1 哈希作为属性,并且从文档中可以看出它也可以提供分支,所以如果它可以在足够早的时候运行我们可以设置属性并将<version>${our.version}</version>放入 pom.xml 的过程。 If this is possible, I would very much like to see a working pom.xml (and reward a 500 point bounty for it too).如果这是可能的,我非常希望看到一个可以工作的 pom.xml (并为此奖励 500 点赏金)。

If not, I guess we are into either preprocessing or "git checkout" do extra magic with some of the hooks (which I have not yet tried, working code would be great too).如果没有,我想我们要么进入预处理,要么“git checkout”用一些钩子做额外的魔法(我还没有尝试过,工作代码也会很棒)。

We have a top level pom, which can be run to generate a property file in ".." before building the modules where this functionality I'm asking about needs to go.我们有一个顶级 pom,可以运行它以在“..”中生成一个属性文件,然后再构建我要询问的这个功能需要去的模块。

Any suggestions on how to solve this?关于如何解决这个问题的任何建议?

Indeed, Maven can't change the version of it's own project in one run with other goals.事实上,Maven 不能在一次运行中更改它自己项目的版本与其他目标。 On top of it, as far as I know, Maven doesn't support arbitrary properties in the <version> tag.最重要的是,据我所知,Maven 不支持<version>标记中的任意属性。 Therefore, a separate execution is required to run a goal which will change the version of the POM.因此,需要单独执行来运行将更改 POM 版本的目标。 There are various plugins which can do it - for this case one might use the versions:set goal from versions plugin - http://mojo.codehaus.org/versions-maven-plugin/set-mojo.html有各种插件可以做到这一点 - 对于这种情况,可以使用版本:从versions插件versions:set目标 - http://mojo.codehaus.org/versions-maven-plugin/set-mojo.html

So, one might execute it as follows for example:因此,可以按如下方式执行它,例如:

mvn versions:set -DgenerateBackupPoms=false -DnewVersion=$branch-SNAPSHOT

where the $branch variable has to contain current Git branch name;其中$branch变量必须包含当前 Git 分支名称; it can be extracted with git rev-parse , like this:它可以用git rev-parse提取,如下所示:

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

But still, one needs to execute it somehow.但是,仍然需要以某种方式执行它。 You can do manually, but it is cumbersome.你可以手动做,但是很麻烦。 So, my guess is that indeed the most robust solution would be to approach this from Git side.所以,我的猜测是,确实最强大的解决方案是从 Git 方面解决这个问题。 That is - a Git hook.那就是——一个 Git 钩子。 Here is the complete Git post-checkout hook which will do the job (same code as above with some filtering to run the hook only when the branch is checked out, not the individual files only):这是完整的 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'

Put this content to the file PROJECTDIR\.git\hooks\post-checkout file.将此内容放入文件PROJECTDIR\.git\hooks\post-checkout文件中。 Note that the hook file should be executable to run it ( chmod +x post-checkout ).请注意,挂钩文件应该是可执行的以运行它( chmod +x post-checkout )。

Few notes about versions plugin - it is pretty flexible and supports many options and have few other goals which might be of help, depending on your project structure (do you use parent poms or not, do childs have their own versions or do they derive from parent, etc.).关于versions插件的一些注意事项 - 它非常灵活并且支持许多选项并且几乎没有其他可能有帮助的目标,具体取决于您的项目结构(您是否使用父 pom,孩子是否有自己的版本或它们是否来自父母等)。 So, the hook above might be modified slightly to support you specific case by using other goals from versions plugin or by specifying additional parameters.因此,可以通过使用versions插件中的其他目标或指定其他参数来稍微修改上面的钩子以支持您的特定情况。

Pros:优点:

  • Robust强大的
  • No need to change anything in the pom.xml files themselves to make this work无需更改 pom.xml 文件本身中的任何内容即可完成此工作
  • This "functionality" can be turned off simply by deactivating the hook (remove or make not executable) - again, no changes are required in the pom.xml只需停用挂钩(删除或使其不可执行)即可关闭此“功能” - 同样,不需要在 pom.xml 中进行任何更改

Cons:缺点:

  • One can't enforce others to use a hook - it should be installed manually after the repo is cloned (or, you can provide a script to install the hook if supposed Git users are afraid of touching the stuff inside .git directory).不能强制其他人使用钩子——它应该在克隆 repo 后手动安装(或者,如果假设的 Git 用户害怕接触 .git 目录中的东西,你可以提供一个脚本来安装钩子)。

UPDATE更新

Hereafter is the more complicated version of the hook, which will not only set the version to the branch name, but will also preserve the suffix of the old version.之后是更复杂的钩子版本,它不仅会将版本设置为分支名称,还会保留旧版本的后缀。 For example, provided old version master-1.0-SNAPSHOT , switching to feature1 branch will change the version of the project to feature1-1.0-SNAPSHOT .例如,提供旧版本master-1.0-SNAPSHOT ,切换到feature1分支会将项目的版本更改为feature1-1.0-SNAPSHOT This bash script suffers from few problems (requires branch names without dash symbol ( - ) in the name, and only takes the version of the root pom), but may give an idea of how the hook may be extended: given a mix of mvn and bash commands you can extract and update quite a lot of the information in the POM.这个 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'

Sorry to revive this question and to post very lately another solution but it is possible indeed to change maven version dynamically and to use some git features, a little bit like git describe would do.很抱歉重新提出这个问题并最近发布了另一个解决方案,但确实可以动态更改 maven 版本并使用一些 git 功能,有点像git describe会做。

The project that does this is jgitver-maven-plugin (disclaimer; I am the author) , it uses jgitver a jgit based library in order to derive maven project version from git information .执行此操作的项目是jgitver-maven-plugin (免责声明;我是作者) ,它使用jgitver一个基于 jgit 的库,以便从 git 信息派生 maven 项目版本。

在此处输入图像描述

It is very easy to use as a maven extension它很容易用作 maven 扩展

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

The extension can also be used as a plugin extension, and then allows more configuration , for example in case you would not like to use SNAPSHOTS.该扩展也可以用作插件扩展,然后允许更多配置,例如在您不想使用 SNAPSHOTS 的情况下。 See the project page for a description of full usage scenarios.有关完整使用场景的描述,请参阅项目页面。

There is also a gradle plugin available that does more or less the same.还有一个可用的gradle 插件或多或少是相同的。


[edit 1] : answer to Thorbjørn Ravn Andersen comment [编辑 1] :回答 Thorbjørn Ravn Andersen 评论

The plugin does not modify the original pom files or the build.gradle files.该插件不会修改原始 pom 文件或 build.gradle 文件。
For the maven plugin, modifications are done both in memory in the maven Object Model and written to a temporary file in temp directory.对于 maven 插件,修改在 maven 对象模型的内存中完成,并写入临时目录中的临时文件。 The calculation is based on the git metadata only (tags, commits, ...).计算仅基于 git 元数据(标签、提交等)。
This non modification allows to not pollute the git history.这种非修改允许不污染 git 历史记录。 WHen your are satisfied with a git commit, tag it git tag -a xyz and mvn deploy : that's all.当您对 git 提交感到满意时,将其标记为git tag -a xyzmvn deploy :仅此而已。
The version in your project files, is now useless and can be set to 0 for example.项目文件中的版本现在无用,例如可以设置为 0。

As of today, and due to IDEA-155733 only recent EAP versions of IntelliJ work with the maven plugin.截至今天,由于IDEA-155733 ,只有 IntelliJ 的最新 EAP 版本才能与 maven 插件一起使用。 Eclipse & Netbeans have no problem. Eclipse & Netbeans 没有问题。


Disclaimer: I am the author免责声明:我是作者

My maven core extension will virtually set the version based on the current branch or tag.我的 maven 核心扩展将根据当前分支或标签虚拟设置版本。 You can config custom version format patterns as you like.您可以根据需要配置自定义版本格式模式。

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

Version Format Example版本格式示例在此处输入图像描述

From maven-3.5.0 on there is support for ${revision}, ${sha1} and ${changelist} properties within the version tag.maven-3.5.0开始,版本标签内支持 ${revision}、${sha1} 和 ${changelist} 属性。 This feature may be sufficient for your purpose if, for example you want to incorporate the Git branchname into the version for a CI build job.如果您想将 Git 分支名称合并到 CI 构建作业的版本中,则此功能可能足以满足您的目的。 See Maven CI Friendly Versions请参阅Maven CI 友好版本

Basically, in your pom.xml replace the fixed version by:基本上,在您的 pom.xml 中,将固定版本替换为:

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

Set default values for revision and changelist in the project root dir by creating a file .mvn/maven.config containing:通过创建包含以下内容的文件.mvn/maven.config在项目根目录中设置修订变更列表的默认值:

-Drevision=1.2.3
-Dchangelist=-SNAPSHOT

Check this file into version control, update it when you bump your project revision.将此文件检查到版本控制中,当您遇到项目修订时更新它。

In your CI system you can then override the changelist variable using a cleaned-up representation of the Git branch name, eg.然后,在您的 CI 系统中,您可以使用 Git 分支名称的清理表示覆盖changelist变量,例如。

# 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}"

(You may prefer git symbolic-ref --short HEAD for fetching the branchname, YMMV) (您可能更喜欢git symbolic-ref --short HEAD来获取分支名称,YMMV)

Your artifact built by the CI system for branch feature/branchname will then have a versioned-branch suffix like: CI 系统为分支feature/branchname将具有版本化分支后缀,例如:

yourproject-1.2.3-feature-branchname.jar

whilst developers who do not use any overrides will still build it as:而不使用任何覆盖的开发人员仍将其构建为:

yourproject-1.2.3-SNAPSHOT.jar

If it is sufficient to set the git tag and version information in the artifact file name, you can use maven-jgit-buildnumber-plugin :如果在工件文件名中设置 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>

Have you checked the buildnumber-maven-plugin which gives you the opportunity to use the revision number of git.您是否检查过buildnumber-maven-plugin ,它使您有机会使用 git 的修订号。 But you needed something different.但是你需要一些不同的东西。 Furthermore i would suggest to do a thing like:此外,我建议做这样的事情:

   1.0.0-SNAPSHOT 
   1.0.0-SNAPSHOT 

beeing on master蜂拥而至

on a branch you can simple change the version to在分支上,您可以简单地将版本更改为

  1.0.0-BF-SNAPSHOT 

Have you tried using this plugin?: https://github.com/ktoso/maven-git-commit-id-plugin .你试过使用这个插件吗?: https ://github.com/ktoso/maven-git-commit-id-plugin。 You can configure it to generate a properties file with all the relevant info about your repo state:您可以将其配置为生成一个包含有关您的 repo 状态的所有相关信息的属性文件:

  • branch分支
  • describe描述
  • commitId提交 ID
  • buildUserName构建用户名
  • buildUserEmail建立用户邮箱
  • buildTime构建时间
  • commitUserName提交用户名
  • commitUserEmail提交用户电子邮件
  • commitMessageShort commitMessageShort
  • commitMessageFull commitMessageFull
  • commitTime提交时间

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM