当前位置 : 主页 > 操作系统 > centos >

gitlab 服务端 hook,拦截糟糕的提交到仓库

来源:互联网 收集:自由互联 发布时间:2023-08-21
背景 每当我接收一份新的代码,代码拿到手要做的第一件事就是 git log,看看这份代码的提交记录,最近提交的情况,做了些什么。但往往看到的 git log 杂乱无章,不知道每次提交到底

背景

每当我接收一份新的代码,代码拿到手要做的第一件事就是 git log,看看这份代码的提交记录,最近提交的情况,做了些什么。但往往看到的 git log 杂乱无章,不知道每次提交到底是做了些什么。由此可见,在团队中,CHANGELOG 的重要性不言而喻,不仅有助于他人帮忙 review 代码,熟悉代码,也能高效的输出 CHANGELOG,对项目管理也至关重要。我们本文介绍使用 git 的服务端 hook 来针对 change log 进行校验,拦截不符合我们规范的提交


服务端 hook 介绍

服务端 git hook 分为三种,分别是 pre-receive、update、post-receive,这三个步骤就是我们本地 push 完代码服务端要做的事情,如图 1 所示:

gitlab 服务端 hook,拦截糟糕的提交到仓库_服务端

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


配置服务端 hook

环境配置

gitlab 版本:13.2

hook 配置

1、找到要配置仓库在 gitlab 中存储的路径,但因 gitlab 的仓库自某个版本开始采用 hash 存储,我们想要知道仓库对应的物理路径,需要到 gitlab 的 postgresql 数据库中的表 project_repositories 中,根据 project_id 能拿到对应的物理路径;

2、当拿到仓库对应的物理路径后,我们打开,目录如下:

gitlab 服务端 hook,拦截糟糕的提交到仓库_git_02

3、hooks 中是 gitlab 示例的一些钩子,我们需要新建目录 custom_hooks,然后用 vim 新建文件 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 "modify.*")
if [ -z "$flag" ]; then
echo "[ERROR]提交信息校验未通过,需以modify开头"
exit 1
fi

python 版本的脚本如下:

#!/usr/bin/env python
# -*- encoding: utf-8 -*-


import sys, re, datetime
import fileinput
import shlex, subprocess
import dateutil.parser
import pytz




def datestring2timezone(datestring,timeznotallow='Asia/Shanghai',dateformat='%Y-%m-%d %H:%M:%S'):
"""将带有时区的时间统一化规定的时区时间
:param datestring:svn/git时间,eg:2011-01-19T05:13:13.421543Z,2018-11-09 17:38:37 +0800
:param timezone:统一时区,默认是中国时区
:param dateformat:转换成时间格式
:return:
"""
local_time = dateutil.parser.parse(datestring).astimezone(pytz.timezone(timezone)) # 解析string 并转换为北京时区
# print(local_time , type(local_time)) # datetime 类型
da = datetime.datetime.strftime(local_time, dateformat) # 将datetime转换为string
return da




print("Begin check your commit info")
"""获取用户提交的信息"""
origin_commit, curr_commit, branch = None, None, None
# 读取用户试图更新的所有引用
for line in fileinput.input():
line_list = line.strip().split()
if len(line_list) >= 3:
origin_commit, curr_commit, branch = line_list[:3]
break


# TODO: 目前2.27.0版本的git有点问题,在部署的时候需要额外注意
# git_version = subprocess.check_output(shlex.split('git --version'), shell=False)
# print("git version: {}".format(str(git_version)))
# which_git = subprocess.check_output(shlex.split('which git'), shell=False)
# print("which git: {}".format(str(which_git)))


# 获取commit的信息,用户,邮箱,msg等
commit_user = subprocess.check_output(shlex.split('git log --pretty=format:"%an" {} -1'.format(curr_commit)), shell=False)
commit_date = subprocess.check_output(shlex.split('git log --pretty=format:"%cd" {} -1'.format(curr_commit)), shell=False)
commit_msg = subprocess.check_output(shlex.split('git log --pretty=format:"%s" {} -1'.format(curr_commit)), shell=False)




# 针对merge request的请求,取最新一条非merge request的提交信息进行判断
RULE_MERGE_REQUEST = r'^Merge branch .*(into|.*)'
if re.search(RULE_MERGE_REQUEST, str(commit_msg), flags=0):
# 获取最新一条非merge request的commit的信息,用户,邮箱,msg等
commit_user = subprocess.check_output(shlex.split('git log --no-merges --date-order --pretty=format:"%an" -1'), shell=False)
commit_date = subprocess.check_output(shlex.split('git log --no-merges --date-order --pretty=format:"%cd" -1'), shell=False)
commit_msg = subprocess.check_output(shlex.split('git log --no-merges --date-order --pretty=format:"%s" -1'), shell=False)


start_date = "2021-07-07 19:00:00"
# 提交日期大于给定的开始时间才校验
if start_date >= datestring2timezone(commit_date):
sys.exit(0)




if not re.search(r'^JIRA-[0-9]{4,6}', str(commit_msg), flags=0):
print("ERROR:Comment must start with DPT-<ID>. E.g.: DPT-1234")
sys.exit(1)


sys.exit(0)

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

gitlab 服务端 hook,拦截糟糕的提交到仓库_推送_03


踩坑

1、gitlab 的不同版本,所安装的 git 版本也会不一致,不同版本的 git 相同的命令的输出也有可能不一致,这点需要特别注意,例如获取非合并请求最新的日志命令,在 git 2.27.0 版本下似乎并不生效。

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

更多

如探索更多关于服务端 hook 的功能,可以与第三方系统,例如 jira 等做交互,打造属于自己团队更适用的工具。


【文章原创作者:阿里云代理 http://www.558idc.com/aliyun.html 网络转载请说明出处】
上一篇:一百行代码实现简易版 ChatGPT | 社区征文
下一篇:没有了
网友评论