从git分支获取maven工件版本

rpppsulh  于 2022-12-17  发布在  Git
关注(0)|答案(7)|浏览(237)

bounty将在3天后过期。此问题的答案可获得+500声誉奖励。Thorbjørn Ravn Andersen正在查找此问题的最新答案:10年后的今天,情况可能发生了变化,找到了更聪明的解决方案。

我们有一个工作流需求,它本质上意味着我们需要从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,在构建我所询问的功能需要用到的模块之前,可以运行它在“..”中生成一个属性文件。
对于如何解决这个问题有什么建议吗?

r8uurelv

r8uurelv1#

事实上,Maven不能在一次运行中更改自己项目的版本,而且据我所知,Maven不支持<version>标记中的任意属性。需要一个单独的执行来运行一个目标,这将改变POM的版本。有各种插件可以做到这一点-对于这种情况,可以使用来自versions插件-http://mojo.codehaus.org/versions-maven-plugin/set-mojo.htmlversions:set目标
因此,可以按如下方式执行它:

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钩子,它将完成这项工作(与上面相同的代码,但进行了一些过滤,以便只在分支被 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插件的一些注意事项--它非常灵活,支持许多选项,并且几乎没有其他可能有用的目标,这取决于您的项目结构(你是否使用父pom,查尔兹是否有自己的版本,或者它们是从父pom派生的,等等)。上面的钩子可能会被稍微修改以支持你的特定情况,通过使用versions插件的其他目标或者通过指定额外的参数。
优点:

  • 稳健
  • 不需要更改pom.xml文件本身的任何内容就可以实现这一点
  • 这个“功能”可以通过取消激活钩子(删除或使其不可执行)来关闭-同样,不需要在pom.xml中进行任何更改

缺点:

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

下面是更复杂版本的钩子,它不仅将版本设置为分支名称,而且还将保留旧版本的后缀,例如,提供旧版本master-1.0-SNAPSHOT。切换到feature1分支会将项目的版本更改为feature1-1.0-SNAPSHOT。(要求分支名称中没有破折号(-),并且只接受根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'
zpjtge22

zpjtge222#

很抱歉再次提出这个问题,并在最近发布了另一个解决方案,但确实有可能动态更改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>
...

该扩展也可以作为插件扩展使用,并允许更多的配置,例如在您不想使用快照的情况下。查看project页面了解完整的使用场景描述。
也有一个gradle plugin可用,做或多或少相同。

***[编辑1]对 solr 比约恩·拉文·安德森评论的答复

该插件不会修改原始pom文件或build.gradle文件。
对于maven插件,修改既在maven对象模型的内存中完成,又被写入到temp目录的临时文件中。计算仅基于git元数据(tags,commits,...)。
这种不修改的方式不会污染git历史记录。当你对git提交满意时,标记为git tag -a x.y.zmvn deploy:就这样。
您的项目文件中的版本,现在是无用的,可以设置为0,例如。
到目前为止,由于IDEA-155733,只有最新的EAP版本的IntelliJ可以使用maven插件,Eclipse和Netbeans没有问题。

wf82jlnq

wf82jlnq3#

免责声明:我是作者
我的maven核心扩展将基于当前分支或标记设置版本。您可以根据需要配置自定义版本格式模式。
https://github.com/qoomon/maven-git-versioning-extension

版本格式示例

lskq00tm

lskq00tm4#

maven-3.5.0开始,支持 version 标记中的${revision}、${sha1}和${changelist}属性。例如,如果您要将Git分支名称合并到配置项构建作业的版本中,则此功能可能足以满足您的需要。请参见Maven CI Friendly Versions
基本上,在pom.xml中,将固定版本替换为:

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

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

-Drevision=1.2.3
-Dchangelist=-SNAPSHOT

将此文件签入到版本控制中,并在升级项目修订时更新它。
在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}"
  • (您可能更喜欢git symbolic-ref --short HEAD来获取分支名称YMMV)*

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

yourproject-1.2.3-feature-branchname.jar

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

yourproject-1.2.3-SNAPSHOT.jar
xmq68pz9

xmq68pz95#

如果在工件文件名中设置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>
goqiplq2

goqiplq26#

你有没有检查过buildnumber-maven-plugin,它可以让你使用git的版本号,但是你需要一些不同的东西。此外,我建议你做一件事,比如:

1.0.0-SNAPSHOT 
   1.0.0-SNAPSHOT

在主设备上运行
在分支上,您可以简单地将版本更改为

1.0.0-BF-SNAPSHOT
z9gpfhce

z9gpfhce7#

您是否尝试过使用此插件?:您可以配置它来生成一个属性文件,其中包含有关您的存储库状态的所有相关信息:

  • 分支
  • 描述
  • 提交ID
  • 生成用户名
  • 构建用户电子邮件
  • 构建时间
  • 提交用户名
  • 提交用户电子邮件
  • 提交消息简短
  • 提交消息已满
  • 提交时间

相关问题