背景

每当我们接收一份新的版本,代码拿到手要做的第一件事就是查看 git log,看看这份代码的提交记录,最近代码做什么修改。如果我们看到 git log 杂乱无章,如果不知道每次提交的代码到底是做了什么,那么对于我们来说是比较痛苦的事情。所以说,规范的 CHANGELOG 不仅有助于他人帮忙 review 代码,也能高效的输出 Release Note,对版本管理也至关重要。

所以我们可以考虑使用 Gitlab 的服务端 hook 来针对git change log 进行校验,拦截不符合我们规范的提交到仓库。

方案设计

服务端 git hook 分为三种,分别是:

  • pre-receive(推送前)
  • update
  • post-receive(推送后)

这三个步骤就是我们本地 push 完代码服务端要做的事情,如图所示:

gitlab hook 参数 gitlab hooks_git

我们可以在 pre-receive(推送前)阶段来做提交信息的校验,如果不符合我们的要求,直接返回,则该推送便不会推送到 GitLab 仓库中去。

实践落地

环境说明

gitlab版本:14.3.3

gitlab hook 参数 gitlab hooks_gitlab_02

hook 配置

第一步,找到要配置仓库在 gitlab 中存储的路径,但因 gitlab 的仓库自某个版本开始采用 hash 存储,我们想要知道仓库对应的物理路径,可以通过管理员账号拿到对应的物理路径;

这里以某工程举例:

gitlab hook 参数 gitlab hooks_gitlab_03

第二步,当拿到仓库对应的相对物理路径后,我们打开,目录如下:

gitlab hook 参数 gitlab hooks_gitlab_04

[root@vm-gitlab 785f3ec7eb32f30b90cd0fcf3657d388b5ff4297f2f9716ff66e9b69c05ddd09.git]# pwd
/srv/gitlab/data/git-data/repositories/@hashed/78/5f/785f3ec7eb32f30b90cd0fcf3657d388b5ff4297f2f9716ff66e9b69c05ddd09.git
[root@vm-gitlab 785f3ec7eb32f30b90cd0fcf3657d388b5ff4297f2f9716ff66e9b69c05ddd09.git]# ls -l
总用量 24
drwxr-sr-x 2 libstoragemgmt polkitd    6 12月 14 14:32 branches
-rw-r--r-- 1 libstoragemgmt polkitd  126 12月 14 14:32 config
-rw-r--r-- 1 libstoragemgmt polkitd   73 12月 14 14:32 description
-rw-r--r-- 1 libstoragemgmt polkitd   21 12月 14 14:32 HEAD
drwxr-sr-x 2 libstoragemgmt polkitd 4096 12月 14 14:32 hooks
drwxr-sr-x 2 libstoragemgmt polkitd   33 12月 14 20:00 info
-rw-r--r-- 1 libstoragemgmt polkitd 1308 12月 14 15:06 language-stats.cache
drwxr-sr-x 4 libstoragemgmt polkitd   30 12月 14 20:00 objects
-rw-r--r-- 1 libstoragemgmt polkitd  103 12月 14 15:06 packed-refs
drwxr-sr-x 2 libstoragemgmt polkitd    6 12月 15 20:00 refs

第三步,hooks 中是 gitlab 示例的一些钩子,我们这里首先新建目录 custom_hooks,然后用再创建文件 pre-receive(推送前),pre-receive 文件内容如下(脚本语言为 shell),同时修改 pre-receive 文件的权限。

修改文件权限:

chmod +777 pre-receive
#!/bin/bash

echo "开始提交信息检查..."

# 从标准输入获取本次提交的commit id及分支的信息
read normalInput
ARR=($normalInput)
parentCommitId=${ARR[0]}
currentCommitId=${ARR[1]}
branch=${ARR[2]}

echo "您提交的分支为:$branch"

# 获取coomit的信息,用户,邮箱,msg等
user=$(git log --pretty=format:"%an" $currentCommitId -1)
echo "提交者为:$user"

commitDate=$(git log --pretty=format:"%cd" $currentCommitId -1)
echo "提交日期为:$commitDate"

msg=$(git log --pretty=format:"%s" $currentCommitId -1)
echo "提交的注释为:$msg"

flag=$(echo $msg | grep -E "fix.*|add.*|del.*|update.*|temp.*|test.*|revert.*|Merge.*")
if [ -z "$flag" ]; then
    echo "[ERROR]提交信息校验未通过,需以 fix|add|del|update|temp|test|revert 开头"
    exit 1
fi

第四步,在本地尝试推送,推送显示如下,如果不符合规范则无法提交成功。

gitlab hook 参数 gitlab hooks_推送_05

第五步,我们再次查看目录如下:

gitlab hook 参数 gitlab hooks_devop_06

踩坑

gitlab 的不同版本,所安装的 git 版本也会不一致,不同版本的 git 相同的命令的输出也有可能不一致,这点需要特别注意。

git log --no-merges --date-order -1