写点什么

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

  • 2023-08-18
    北京
  • 本文字数:2304 字

    阅读完需:约 8 分钟

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


服务端 hook 介绍


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



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


配置服务端 hook


环境配置


gitlab 版本:13.2


hook 配置


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

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



#!/bin/bash
echo "开始提交信息检查..."
# 从标准输入获取本次提交的commit id及分支的信息read normalInputARR=($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 1fi
复制代码


Python 版本的代码如下:


#!/usr/bin/env python# -*- encoding: utf-8 -*-
import sys, re, datetimeimport fileinputimport shlex, subprocessimport dateutil.parserimport pytz

def datestring2timezone(datestring,timezone='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)
复制代码


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



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


获取更多技术资料,请点击!

用户头像

社区:ceshiren.com 微信:ceshiren2021 2019-10-23 加入

微信公众号:霍格沃兹测试开发 提供性能测试、自动化测试、测试开发等资料,实时更新一线互联网大厂测试岗位内推需求,共享测试行业动态及资讯,更可零距离接触众多业内大佬。

评论

发布
暂无评论
gitlab 服务端 hook, 拦截糟糕的提交到仓库_霍格沃兹测试开发学社_InfoQ写作社区