gitlab在服务端侧加钩子

发布于 2024-07-19  842 次阅读


一、场景说明

服务端要求,git进行提交的时候,检验提交的格式如下,需要添加钩子

@所有人所有人的遵循一下提交规范,不要再111222了
【D】XXX表示删除
【M】XXX表示修改
【A】XXX表示新增
【U】XXX表示优化
每次提交只写一行消息不要有特殊字符,内容写的至少自己明白,如果不规范提交,我会直接进行
【回退操作】白搞

Git钩子

整个核心流程是使用了Git钩子,钩子分成两种,一种是客户端的钩子,另外一种是服务端的。我们这里使用的是服务端的钩子,服务端钩子有三个:pre-receive、update和post-receive。

pre-receive

预提交钩子,它是服务端最先调用的钩子,我们可以使用此钩子来指定强制执行的开发策略,例如拒绝一些糟糕内容的提交。

update

update钩子在pre-receive之后被调用,它们工作原理类似,它会在真实提交之前执行,可以拒绝提交。与pre-receive不同的是,它会为每一个准备更新的分支各运行一次。也就是说我们同时向多个分支推送内容,pre-receive只运行一次,而update则会为每一个分支各运行一次。

post-receive

此钩子在成功推送之后调用,可以用来更新服务和通知等等。例如,后端提交了接口代码,可以利用此钩子更新接口代码。

了解了上面几个钩子,我们选择了使用post-receive钩子来更新同步代码。

本地钩子,请自行参考https://www.jianshu.com/p/68131fd0c503

服务端的钩子

hook 配置

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

数据库查找项目的物理路劲

方法1:先网页打开获取id

一般就是在项目名的下面,如图,如果没有,就找到设置里面找就找到了
file
如上,获取的ip是392,执行下面命令

## 如果不知道是那个用户,可以 grep psql | grep /etc/passwd
### 查询物理地址
sudo gitlab-psql -d gitlabhq_production -c "SELECT * FROM project_repositories WHERE project_id = 392;"
#                                   disk_path                                    
#--------------------------------------------------------------------------------
# @hashed/6e/a2/6ea2fdb3399f4d2e806beb01e9a3371bd622bed6a409acf3151818d738c370ec
#(1 row)

对应的路劲是,前面加上/var/opt/gitlab/git-data/repositories/+物理地址

gitlab# pwd
#/var/opt/gitlab/git-data/repositories/@hashed/6e/a2/6ea2fdb3399f4d2e806beb01e9a3371bd622bed6a409acf3151818d738c370ec.git

方法2:直接通过链接查


缺点:如果有项目名重名的话,无法确定,需要用方法1打开网页确认。建议用方法1

如知道链接
http://xxxx/root/gouzi
项目名,就是gouzi

gitlab# sudo gitlab-psql -d gitlabhq_production -c "SELECT pr.disk_path FROM projects p INNER JOIN project_repositories pr ON p.id = pr.project_id WHERE p.path = 'gouzi';"
#                                   disk_path                                    
#--------------------------------------------------------------------------------
# @hashed/6e/a2/6ea2fdb3399f4d2e806beb01e9a3371bd622bed6a409acf3151818d738c370ec

编写钩子脚本

一般hooks是系统自带的,如果没有,可以自己建,为了防止和系统的钩子冲突,可以使用custom_hooks(用户自定义钩子)

cd /var/opt/gitlab/git-data/repositories/@hashed/6e/a2/6ea2fdb3399f4d2e806beb01e9a3371bd622bed6a409acf3151818d738c370ec.git
mkdir custom_hooks
cat > custom_hooks/pre-receive << EOF
#!/bin/sh

# 读取所有提交信息
while read oldrev newrev refname; do
    # 获取最近一次提交的commit ID
    commit=\$(git rev-list -n 1 \${newrev})

    # 读取提交信息
    COMMIT_MSG=\$(git log --format=%B -n 1 \$commit)
    # 提交信息规范正则表达式
    echo ""
    echo "================================格式检查============================================"
    echo "Commit message: \$COMMIT_MSG" >&2
    PATTERN='^【[DMAU]】.+$'
    # 检查提交信息是否符合规范
    if ! echo "\$COMMIT_MSG" | grep -Eq "\$PATTERN"; then
        echo "提交信息不符合规范,请按照以下格式进行提交:"
        echo "【D】XXX表示删除"
        echo "【M】XXX表示修改"
        echo "【A】XXX表示新增"
        echo "【U】XXX表示优化"
        echo "每次提交只写一行消息不要有特殊字符,内容写的至少自己明白"
        echo "提交已退回,请重新执行commit改名 如 git commit --amend -m \"【A】tan\""
        echo "================================驳回提交============================================"
        echo ""
        echo ""
        exit 1
    fi
    echo "================================格式ok================================================"
done

EOF

## 改用户名,加执行权限
chown git:git custom_hooks -R
chmod +x custom_hooks/pre-receive

可以在服务端简单测试

#获取最新的提交哈希值:
gitlab# git log --oneline -n 2
#e419b7a (HEAD -> Develop) 【A】测试提交
#616b286 【A】测试提交
echo "616b286 e419b7a refname" | ./custom_hooks/pre-receive
#================================格式检查============================================
#Commit message: 【A】测试提交
#================================格式ok================================================

客户端测试

演示不符合规范提交

### 下载gouzi.git
git clone http://xxxx/root/gouzi.git
cd gouzi
echo 123 > testfile.txt
## 演示不符合规范提交
git add -A  && git commit -m "[A] 测试提交" && git push origin Develop

#Writing objects: 100% (6/6), 517 bytes | 0 bytes/s, done.
#Total 6 (delta 2), reused 0 (delta 0)
#remote: 
#remote: ================================格式检查============================================
#remote: Commit message: [A] 测试提交
#remote: 提交信息不符合规范,请按照以下格式进行提交:
#remote: 【D】XXX表示删除
#remote: 【M】XXX表示修改
#remote: 【A】XXX表示新增
#remote: 【U】XXX表示优化
#remote: 每次提交只写一行消息不要有特殊字符,内容写的至少自己明白
#remote: 提交已退回,请重新执行commit改名 如 git commit --amend -m "【A】tan"
#remote: ================================驳回提交============================================
#remote: 
#remote: 
#To http://git.yuetanggame.com/root/gouzi.git
# ! [remote rejected] Develop -> Develop (pre-receive hook declined)
#error: failed to push some refs to 'http://xxxx/root/gouzi.git'

错误后,修改名称提交

git commit --amend -m "【A】tan" && git push origin Develop

其他问题

已经push了2次以上,有本地记录,导致提交的时候,提交2份以上,不能通过,如下
remote: 
remote: ================================格式检查============================================
remote: Commit message: 【A】tan
remote: ================================格式ok================================================
remote: 
remote: ================================格式检查============================================
remote: Commit message: [A] 测试提交
remote: 提交信息不符合规范,请按照以下格式进行提交:
remote: 【D】XXX表示删除
remote: 【M】XXX表示修改
remote: 【A】XXX表示新增
remote: 【U】XXX表示优化
remote: 每次提交只写一行消息不要有特殊字符,内容写的至少自己明白
remote: 提交已退回,请重新执行commit改名 如 git commit --amend -m "【A】tan"
remote: ================================驳回提交============================================
remote: 
remote: 
To http://git.yuetanggame.com/root/gouzi.git
 ! [remote rejected] Develop -> Develop (pre-receive hook declined)
error: failed to push some refs to 'http://git.yuetanggame.com/root/gouzi.git'

上面的Commit message: [A] 测试提交 和 Commit message: 【A】tan
一个是最新的符合的,一个是旧的,提交的时候,有2份,导致检查不通过

解决办法

# 执行n次,有多少份,就执行多少次(重置到最新的提交---会删除最新的几份)
git reset --soft HEAD~2
git add -A  && git commit -m "【A】测试提交" && git push origin Develop

### 如果提示还有,那就是提交了更多次,因为这个信息只显示最近的2次,你再次上面执行即可