简介

git-commit-id-maven-plugin 是一个maven 插件,用来在打包的时候将git-commit 信息打进jar中。

这样做的好处是可以将发布的某版本和对应的代码关联起来,方便查阅和线上项目的维护。至于它的作用,用官方说法,这个功能对于大型分布式项目来说是无价的。

功能

你是否经常遇到这样的问题:

  • 测试提交了一个bug,开发人员无法确认是哪个版本有这个问题,当前测试环境部署的是某个版本吗?生产环境会不会也有这个问题?

  • 公司内部的项目,总共几十、几百个服务,每天都有服务的生产环境部署,一个服务甚至一天上线好几次,对于项目管理来说无法清晰了解某一时刻某个服务的版本

  • 如何验证我的代码是否已经上线?

  • 。。。。。。

以上种种,都有一个共同的诉求,就是我希望在打包的时候将最后一次 git commit id 和当前 jar 关联起来并可试试查询jar对应的git commit id 。

实践

引入插件

本例SpringBoot版本为 2.7.6,java版本为11

此插件已经上传到中央仓库(https://central.sonatype.com/artifact/io.github.git-commit-id/git-commit-id-maven-plugin?smo=true)

在项目pom.xml 中引入如下插件



<project>
    ......
    <build>
        <plugins>
            <!--  git-commit-id-maven-plugin :打包的时候携带git提交信息  -->
            <plugin>
                <groupId>io.github.git-commit-id</groupId>
                <artifactId>git-commit-id-maven-plugin</artifactId>
                <version>5.0.0</version>
                <executions>
                    <execution>
                        <id>get-the-git-infos</id>
                        <goals>
                            <goal>revision</goal>
                        </goals>
                        <phase>initialize</phase>
                    </execution>
                </executions>
                <configuration>
                    <generateGitPropertiesFile>true</generateGitPropertiesFile>
                    <generateGitPropertiesFilename>${project.build.outputDirectory}/git.</generateGitPropertiesFilename>
                    <includeOnlyProperties>
                        <includeOnlyProperty>^git.build.(time|version)$</includeOnlyProperty>
                        <includeOnlyProperty>^git.commit.id.(abbrev|full)$</includeOnlyProperty>
                    </includeOnlyProperties>
                    <format>txt</format>
                    <commitIdGenerationMode>full</commitIdGenerationMode>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
  • generateGitPropertiesFilename:用于指定生成的gitCommitInfo存放到哪个位置,后缀可以任意指定,如果不指定将使用format的值
  • format:指定文件后缀,一般为 properties , json
  • commitIdGenerationMode:记录完整信息,若format为json,此值必须为full

此外为了能成功打出jar包,还需要如下插件的配合:



<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>${spring-boot.version}</version>
    <configuration>
        <includeSystemScope>true</includeSystemScope>
        <excludes>
            <exclude>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
            </exclude>
        </excludes>
    </configuration>
    <executions>
        <execution>
            <id>repackage</id>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
    </executions>
</plugin>

使用maven执行 clean and package ,将在target\classes下生成 git.json文件,内容如下:


#Generated by Git-Commit-Id-Plugin
git.build.time=2024-02-21T10\:41\:24+0800
git.build.version=0.0.1-SNAPSHOT
git.commit.id.abbrev=3fc9c80
git.commit.id.full=3fc9c8009a48e22ef171c98a97398005e9f30a4a

同时,如果我们反编译生成的jar包,将在BOOT-INF/classes下看到git.json 文件

GitCommitIdMavenPlugin插件有丰富的配置选项,更多配置参考:



<configuration>
    <!--
                    git文件记录,默认是
                    ${project.basedir}/.git
                    如果非默认,可以指定,例如: ${project.basedir}/../.git
                -->
    <dotGitDirectory>${project.basedir}/.git</dotGitDirectory>
    <!--
                    属性前缀,可以理解为namespace,默认是git, 例如 `${configured-prefix}.commit.id`.
                   
                    更多信息可以参考 (see
                    https://github.com/git-commit-id/git-commit-id-maven-plugin/issues/137#issuecomment-418144756
                    for a full example).
                -->
    <prefix>git</prefix>
    <!-- @since 2.2.0 -->
    <!--
                    默认的日期格式,使用方式(e.g. `git.commit.time` and `git.build.time`).
                 -->
    <dateFormat>yyyy-MM-dd'T'HH:mm:ssZ</dateFormat>
    <!-- @since 2.2.0 -->
    <!--
                    时区(java.util.TimeZone.getDefault().getID()).
                    *Note*: 指定时区可以如下 `MAVEN_OPTS=-Duser.timezone=UTC mvn clean package`, `mvn clean package -Duser.timezone=UTC`
                   或者使用 Asia/Shanghai 直接指定,该属性会使用在
                    (e.g. `git.commit.time` and `git.build.time`).
                -->
    <dateFormatTimeZone>${user.timezone}</dateFormatTimeZone>
    <!--
                    默认false,构建时打印信息
                -->
    <verbose>false</verbose>
    <!--
                    默认false, 如果是true, 会生成properties 文件(填充文件中的属性值),文件配置在 generateGitPropertiesFilename 中, 构建时间使用如下
                    ``` git.build.time=${git.build.time}
                    ```
                -->
    <generateGitPropertiesFile>true</generateGitPropertiesFile>
    <!--
                    默认文件
                    ${project.build.outputDirectory}/git.properties
                    该路径可以使用相对于${project.basedir}的相对路径(e.g. target/classes/git.properties),或者全路径(e.g. ${project.build.outputDirectory}/git.properties)
                -->
    <generateGitPropertiesFilename>${project.build.outputDirectory}/git.properties</generateGitPropertiesFilename>
    <!--
                   文件格式,默认properties,可以使用json
如果将其设置为“json”,则还应该签出关于 `commitIdGenerationMode` 而且设置
                    `<commitIdGenerationMode>full</commitIdGenerationMode>`.
                -->
    <format>properties</format>
    <!--
                    默认是true,如果打包是pom(e.g. `<packaging>pom</packaging>`),则运行该插件
                -->
    <skipPoms>true</skipPoms>
    <!-- @since 2.1.4 -->
    <!--
                    告诉maven git commit id将git属性注入到所有reactor项目中,而不仅仅是现在的那个。默认情况下,属性设置为“false”,以防止重写可能与项目无关的属性。如果需要公开git属性对于另一个maven模块(例如maven antrun plugin),您需要将其设置为“true”。
                -->
    <injectAllReactorProjects>false</injectAllReactorProjects>
    <!-- @since 2.0.4 -->
    <!-- 默认false, 指定在找不到.git目录时插件是否应失败。当设置为“false”并且没有找到.git目录时,插件将跳过执行。
                -->
    <failOnNoGitDirectory>true</failOnNoGitDirectory>
    <!-- @since 2.1.5 -->
    <!--
                    默认true,默认情况下,如果插件无法获取足够的数据来完成,跳过执行该插件。
                -->
    <failOnUnableToExtractRepoInfo>true</failOnUnableToExtractRepoInfo>
    <!-- @since 2.1.8 -->
    <!--
                    默认false, 当设置为“true”时,插件执行将完全跳过。这对于配置文件激活的插件调用或使用属性来启用/禁用pom功能。在版本*2.2.3*中,您还可以使用命令行选项跳过插件`-Dmaven.gitcommitid.skip=true`
                -->
    <skip>false</skip>
    <!-- @since 3.0.1 -->
    <!--
                   默认false,当设置为“true”时,插件将不会尝试联系任何远程存储库。任何操作都将只使用回购的本地状态。如果设置为“false”,它将执行“git fetch”操作,例如确定“ahead”和“behind”分支信息。
                -->
    <offline>false</offline>
    <!-- @since 2.1.12 -->
    <!--
默认 false,如果为true,只在一个模块中运行一次。这意味着插件的效果对执行图中的第一个项目执行一次
                -->
    <runOnlyOnce>false</runOnlyOnce>
    <!-- @since 2.1.9 -->
    <!--
                    排除属性                    
                -->
    <excludeProperties>
        <!-- <excludeProperty>git.user.*</excludeProperty> -->
    </excludeProperties>
    <!-- @since 2.1.14 -->
    <!--
                    只包含某类属性,和excludeProperties相对
                -->
    <includeOnlyProperties>
        <!-- <includeOnlyProperty>^git.commit.id.full$</includeOnlyProperty> -->
    </includeOnlyProperties>
    <!-- @since 2.2.3 -->
    <!--
                    属性替换,匹配到规则的属性值在某个阶段替换为另外的属性值
                -->
    <replacementProperties>
        <!--
                      example:
                      apply replacement only to the specific property git.branch and replace '/' with '-'
                      see also [issue 138](https://github.com/git-commit-id/git-commit-id-maven-plugin/issues/138)
                  <replacementProperty>
                    <property>git.branch</property>
                    <propertyOutputSuffix>something</propertyOutputSuffix>
                    <token>^([^\/]*)\/([^\/]*)$</token>
                    <value>$1-$2</value>
                    <regex>true</regex>
                    <forceValueEvaluation>false</forceValueEvaluation>
                    <transformationRules>
                      <transformationRule>
                        <apply>BEFORE</apply>
                        <action>UPPER_CASE</action>
                      </transformationRule>
                      <transformationRule>
                        <apply>AFTER</apply>
                        <action>LOWER_CASE</action>
                      </transformationRule>
                    </transformationRules>
                  </replacementProperty>
                  -->
    </replacementProperties>
    <!-- @since 2.1.10 -->
    <!--
                    默认false,此插件附带自定义的“jgit”实现,用于获取所有相关信息。如果设置为“true”,则此插件将使用本机“git”二进制文件而不是自定义的“jgit”, 也可以使用以下命令开启 `-Dmaven.gitcommitid.nativegit=true`
                -->
    <useNativeGit>false</useNativeGit>
    <!-- @since 3.0.0 -->
    <!--
                    默认情况下,此超时设置为30000(30秒),允许指定使用本机获取信息的超时(毫秒)
                -->
    <nativeGitTimeoutInMs>30000</nativeGitTimeoutInMs>
    <!-- @since v2.0.4 -->
    <!--
默认7,配置缩写git提交id的长度(`git.commit.id.abbrev`)到长度至少为N。`0'具有特殊含义(签出git/git文档描述-描述.md)对于特殊情况,缩写为0)。最大值为“40”,因为最大SHA-1长度。
                 -->
    <abbrevLength>7</abbrevLength>
    <!-- @since v2.2.0 -->
    <!--
                    目前,交换机允许两种不同的选择:1默认情况下,此属性设置为“flat”,并将生成以前已知的财产`git.commit.id`就像以前版本的插件一样。保持默认情况下,它将“flat”保留向后兼容性,不需要进一步的操作最终用户调整。2如果将此开关设置为“full”,则插件将导出以前已知的属性`git.commit.id`作为`git.commit.id.full`因此将生成完全有效的导出机制中的json对象。
                -->
    <commitIdGenerationMode>flat</commitIdGenerationMode>
    <!-- @since 2.1.0 -->
    <!--
                    可以用作非常强大的版本控制助手, 可以参考https://git-scm.com/docs/git-describe
                -->
    <gitDescribe>
        <!--
                        默认false, 如果true,则不使用该配置
                    -->
        <skip>false</skip>
        <!--
                       默认true,
在某些情况下,在提交附近找不到标记(例如,通常在执行浅克隆)。如果将其设置为“true”,并且未找到标记,则此属性将改为回退到提交的id(当“true”时,此属性不会变为空)
                    -->
        <always>true</always>
        <!--
                        在describe输出中,哈希的对象id总是缩写为N个字母(默认为7)
                    -->
        <abbrev>7</abbrev>
        <!--
                        Default (optional):
                        -dirty
                        在处于“脏状态”(未提交)的存储库上运行“描述”时更改),说明输出将包含一个附加后缀
                    -->
        <dirty>-dirty</dirty>
        <!--
                        默认:*,包含所有信息,
Git describe可能包含标记名的信息。将此配置设置为仅考虑与给定模式匹配的标记。这可以用来避免从存储库泄漏私有标记。
                    -->
        <match>*</match>
        <!--
默认false,运行git describe时,默认情况下只查找*带注释的标记*。如果您希望在描述中也考虑*轻量级标记*,则需要把这个转换成'true'。
                        depth here: https://github.com/git-commit-id/git-commit-id-maven-plugin/#git-describe-and-a-small-gotcha-with-tags
                    -->
        <tags>false</tags>
        <!--
默认情况下,如果当前提交被标记,git descripe只返回标记名。将此选项设置为“true”以强制它使用典型的describe格式化输出格式(“${tag name}-${committes_from_tag}-g${commit_id-maybe_dirty}”),即使是“on”标记
                    -->
        <forceLongFormat>false</forceLongFormat>
    </gitDescribe>
    <!-- @since 2.2.2 -->
    <!--
附加的验证实用程序,可用于验证项目属性是否设置
                -->
    <validationProperties>
        <validationProperty>
            <!--
用于识别验证的描述性名称,不匹配(将显示在错误消息中)
                        -->
            <name>validating project version</name>
            <!--
                             需要验证的值*注意*:为了能够验证在pom本身您可能需要设置配置`<injectAllReactorProjects>true</injectAllReactorProjects>`。
                        -->
            <value>${project.version}</value>
            <!--
                            the expected value
                        -->
            <shouldMatchTo><![CDATA[^.*(?<!-SNAPSHOT)$]]></shouldMatchTo>
        </validationProperty>
        <!-- the next validationProperty you would like to validate -->
    </validationProperties>
    <!-- @since 2.2.2 -->
    <!--
                    默认true,如果有与预期不符,则校验失败
                -->
    <validationShouldFailIfNoMatch>true</validationShouldFailIfNoMatch>
    <!-- @since 2.2.4 -->
    <!--默认值(可选):默认情况下,此属性只需设置为“HEAD”,它应该引用最新的在存储库中提交。
说明:
允许告诉插件应该使用什么提交作为生成属性来自。
一般情况下,可以将此属性设置为“HEAD^1”或指向分支或标记名称。为了支持任何类型或用例,也可以设置此配置整个提交哈希或它的缩写版本。
                -->
    <evaluateOnCommit>HEAD</evaluateOnCommit>
    <!-- @since 3.0.0 -->
    <!--
默认true,当设置为“true”时,此插件将尝试使用生成环境中的分支名称。
                -->
           useBranchNameFromBuildEnvironment>true</useBranchNameFromBuildEnvironment> <!-- @since 3.0.0 -->
<!--
默认true,说明:
当设置为“true”时,此插件将尝试将生成的属性公开到`System.getProperties()`. 设置为{@code'false'}以避免此曝光。 -->
<injectIntoSysProperties>true</injectIntoSysProperties>
</configuration>

查询gitCommitInfo

通过编写一个接口,用来查询生成的GitCommitInfo,核心代码如下:


import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.*; @Slf4j
@RestController
@RequestMapping("/version")
public class VersionController {     /**
     * 获取 git.json 中的内容
     * @return
     * @throws IOException
     */
    @GetMapping("/gitCommitId")
    public String getGitCommitId() throws IOException {
        //git.json  or  git.properties
        File file = ResourceUtils.getFile("classpath:git.json");
        if (file.exists()) {
            String s = "";
            InputStreamReader in = new InputStreamReader(new FileInputStream(file), "UTF-8");
            BufferedReader br = new BufferedReader(in);
            StringBuffer content = new StringBuffer();
            while ((s = br.readLine()) != null) {
                content = content.append(s);
            }
            return content.toString();
        } else {
            return "";
        }
    }
}

兼容性

与java的兼容性

  • java8:插件版本=4.x
  • java11:插件版本>=5

与maven的兼容性

  • maven3:插件版本=4.x
  • maven3.2.x:插件版本>=7

引用

SpringBoot使用git-commit-id-maven-plugin打包的更多相关文章

  1. linux显示git commit id,同时解决insmod模块时版本不一致导致无法加载问题

    linux内核默认会包含git的commit ID. 而linux的内核在insmod模块时,会对模块和内核本身的版本做严格的校验.在开发产品时,改动内核后,由于commit ID变更,会导致linu ...

  2. Spring Boot Maven Plugin打包异常及三种解决方法:Unable to find main class

    [背景]spring-boot项目,打包成可执行jar,项目内有两个带有main方法的类并且都使用了@SpringBootApplication注解(或者另一种情形:你有两个main方法并且所在类都没 ...

  3. SpringBoot项目eclipse运行正常maven install打包启动后报错ClassNotFoundException

    parent的pom.xml <groupId>cn.licoy</groupId> <artifactId>parent</artifactId> & ...

  4. Spring Boot的Maven插件Spring Boot Maven plugin详解

    Spring Boot的Maven插件(Spring Boot Maven plugin)能够以Maven的方式为应用提供Spring Boot的支持,即为Spring Boot应用提供了执行Mave ...

  5. SpringBoot使用Maven插件打包部署

    [问题] 之前一直用SpringBoot做一些小项目,想打包部署在环境上,总是少依赖包jar.百度下可以通过Spring Boot Maven plugin插件,把Maven配置的依赖包都打到项目包里 ...

  6. SpringBoot使用maven插件打包時報:[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/PluginExecutionException的處理方案

    SpringBoot使用maven插件打包時報:[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/PluginExec ...

  7. git rev-parse介绍;获取commit id

    git rev-parse master^{commit} 是什么意思 显示master提交的SHA1值 if you want to make sure that the output actual ...

  8. git rev-list 按照时间来列出两个 commit id 之间的相差数

    git rev-list 按照时间来列出两个 commit id 之间的相差数 git rev-list: Lists commit objects in reverse chronological ...

  9. IntelliJ IDEA自身以及maven项目打包方式

    1. Idea自身打包方式 1.1 创建Artifacts 快捷键(Ctrl+Alt+Shift+S)打开项目的Project Structure.在Artifacts创建 接着,指定main cla ...

  10. 学习Maven之Cobertura Maven Plugin

    cobertura-maven-plugin是个什么鬼? cobertura-maven-plugin是一个校验单元测试用例覆盖率的工具,可以生成一个测试覆盖率报告,可以给单元测试用例编写提供参考. ...

随机推荐

  1. c# 编写 WebAssembly

    创建一个.net 7.0类库工程,引用下面的nuget包: <PackageReference Include="Microsoft.AspNetCore.Components.Web ...

  2. ONVIF网络摄像头(IPC)客户端开发—最简RTSP客户端实现

    前言: 网上对于RTSP协议客户端的表述和实现非常不清晰,在实际使用中,FFMPEG和live555这些软件已经实现了RTSP客户端和服务端的所有功能,但是它们并没有将RTSP协议独立出来,通过看li ...

  3. Oracle19c 多字符集支持的PDB

    Oracle19c 多字符集支持的PDB 背景 想在一个数据库里面支持多种字符集 突然发现Oracle12c开始已经可以实现一个CDB下面可以有多个不同字符集的PDB了 所以想着今天验证一下. 环境信 ...

  4. 快速定位Java应用卡顿的原因

    快速定位Java应用卡顿的原因 背景 同事的环境说出现了一周的卡顿现象. 元旦加班期间告诉我时已经是2024.1.1下午五点了. 当时没有来得及去查看. 上班之后发现问题很简单. 不过为了能够指导一下 ...

  5. PG数据库存储验证

    PG数据库存储验证 背景 最近学习了SQLServer数据库的varchar和nvarchar的存储 想到PG数据库其实没让选择字符集,也没有nvarchar 所以想学习一下nvarchar的使用情况 ...

  6. [转帖]如何修改Bash Shell的提示符的格式和配色

    https://zhuanlan.zhihu.com/p/348416919 我们大多数使用的shell提示符,显示用户名.主机名和当前所在目录.在本文将会介绍如何定制一个自己喜欢的Bash. 了解B ...

  7. [转帖]oracle 审计日志清理

    https://www.cnblogs.com/bangchen/p/7268086.html   --进入审计日志目录: cd $ORACLE_BASE/admin/$ORACLE_SID/adum ...

  8. [转帖]Kafka中offsets.retention.minutes和log.retention.minutes之间的区别

    https://www.cnblogs.com/lestatzhang/p/10771115.html 前言 在Kafka中,我们可能会发现两个与retention相关的配置: log.retenti ...

  9. [转帖]如何在Linux系统中使用命令发送邮件

    https://zhuanlan.zhihu.com/p/96897532 Linux系统更多的被用来做服务器系统,在运维的过程中难免我们需要编写脚本监控一些指标并定期发送邮件. 本教程将介绍如何在L ...

  10. [转帖]Datadog 能成为最大的云监控厂商吗

    https://xie.infoq.cn/article/901cfd6b284e3e103ac70aeb3 作者:睿象云 2021-03-25 本文字数:2256 字 阅读完需:约 7 分钟   D ...