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


    背景

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

    服务端 hook 介绍

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

    1080×429 45.2 KB

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

    配置服务端 hook

    环境配置

    gitlab 版本:13.2

    hook 配置

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

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

    1. #!/bin/bash
    2. echo "开始提交信息检查..."
    3. # 从标准输入获取本次提交的commit id及分支的信息
    4. read normalInput
    5. ARR=($normalInput)
    6. parentCommitId=${ARR[0]}
    7. currentCommitId=${ARR[1]}
    8. branch=${ARR[2]}
    9. echo "您提交的分支为:$branch"
    10. # 获取coomit的信息,用户,邮箱,msg等
    11. user=$(git log --pretty=format:"%an" $currentCommitId -1)
    12. echo "提交者为:$user"
    13. commitDate=$(git log --pretty=format:"%cd" $currentCommitId -1)
    14. echo "提交日期为:$commitDate"
    15. msg=$(git log --pretty=format:"%s" $currentCommitId -1)
    16. echo "提交的备注为:$msg"
    17. flag=$(echo $msg | grep "modify.*")
    18. if [ -z "$flag" ]; then
    19. echo "[ERROR]提交信息校验未通过,需以modify开头"
    20. exit 1
    21. fi

    Python版本的代码如下:

    1. #!/usr/bin/env python
    2. # -*- encoding: utf-8 -*-
    3. import sys, re, datetime
    4. import fileinput
    5. import shlex, subprocess
    6. import dateutil.parser
    7. import pytz
    8. def datestring2timezone(datestring,timezone='Asia/Shanghai',dateformat='%Y-%m-%d %H:%M:%S'):
    9. """将带有时区的时间统一化规定的时区时间
    10. :param datestring:svn/git时间,eg:2011-01-19T05:13:13.421543Z,2018-11-09 17:38:37 +0800
    11. :param timezone:统一时区,默认是中国时区
    12. :param dateformat:转换成时间格式
    13. :return:
    14. """
    15. local_time = dateutil.parser.parse(datestring).astimezone(pytz.timezone(timezone)) # 解析string 并转换为北京时区
    16. # print(local_time , type(local_time)) # datetime 类型
    17. da = datetime.datetime.strftime(local_time, dateformat) # 将datetime转换为string
    18. return da
    19. print("Begin check your commit info")
    20. """获取用户提交的信息"""
    21. origin_commit, curr_commit, branch = None, None, None
    22. # 读取用户试图更新的所有引用
    23. for line in fileinput.input():
    24. line_list = line.strip().split()
    25. if len(line_list) >= 3:
    26. origin_commit, curr_commit, branch = line_list[:3]
    27. break
    28. # TODO: 目前2.27.0版本的git有点问题,在部署的时候需要额外注意
    29. # git_version = subprocess.check_output(shlex.split('git --version'), shell=False)
    30. # print("git version: {}".format(str(git_version)))
    31. # which_git = subprocess.check_output(shlex.split('which git'), shell=False)
    32. # print("which git: {}".format(str(which_git)))
    33. # 获取commit的信息,用户,邮箱,msg等
    34. commit_user = subprocess.check_output(shlex.split('git log --pretty=format:"%an" {} -1'.format(curr_commit)), shell=False)
    35. commit_date = subprocess.check_output(shlex.split('git log --pretty=format:"%cd" {} -1'.format(curr_commit)), shell=False)
    36. commit_msg = subprocess.check_output(shlex.split('git log --pretty=format:"%s" {} -1'.format(curr_commit)), shell=False)
    37. # 针对merge request的请求,取最新一条非merge request的提交信息进行判断
    38. RULE_MERGE_REQUEST = r'^Merge branch .*(into|.*)'
    39. if re.search(RULE_MERGE_REQUEST, str(commit_msg), flags=0):
    40. # 获取最新一条非merge request的commit的信息,用户,邮箱,msg等
    41. commit_user = subprocess.check_output(shlex.split('git log --no-merges --date-order --pretty=format:"%an" -1'), shell=False)
    42. commit_date = subprocess.check_output(shlex.split('git log --no-merges --date-order --pretty=format:"%cd" -1'), shell=False)
    43. commit_msg = subprocess.check_output(shlex.split('git log --no-merges --date-order --pretty=format:"%s" -1'), shell=False)
    44. start_date = "2021-07-07 19:00:00"
    45. # 提交日期大于给定的开始时间才校验
    46. if start_date >= datestring2timezone(commit_date):
    47. sys.exit(0)
    48. if not re.search(r'^JIRA-[0-9]{4,6}', str(commit_msg), flags=0):
    49. print("ERROR:Comment must start with DPT-<ID>. E.g.: DPT-1234")
    50. sys.exit(1)
    51. sys.exit(0)
    1. 在本地尝试推送,推送显示如下,如果不符合规范则无法提交成功

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

  • 相关阅读:
    解密Kubernetes:探索开源容器编排工具的内核
    【工具推荐】替换typora的又一款神器
    如何在 Blender 中更快地渲染?
    C语言之const
    [SpringBoot]配置文件①(配置文件格式、yaml配置及读取)
    Java测试(11) --- selenium
    centos7.9系统安装cuda+cudnn+pytorch+python
    私有化部署的即时通讯平台,为企业移动业务安全保驾护航
    【MySQL】使用MySQL Workbench软件新建表
    关于IP协议Header_Checksum计算教程
  • 原文地址:https://blog.csdn.net/ceshiren456/article/details/126141570