Gitlab 是不错的代码托管工具,最近一年更新也很频繁。最新的 8.15 版本加入了自定义 git hook 的支持,在服务器端写脚本控制用户的提交情况变得很方便。这里介绍如何配置服务器端 hook。
Gitlab custom hook 官方文档在此: Custom Git Hooks - GitLab Documentation
Tips: Git hook 是 git 提供的特定工作流事件自动触发脚本机制,本文介绍的是配置所有项目通用的 server hook,如果要使用 local hook,建议使用 git template + 软链接解决分发和更新的问题。
具体步骤
1. 修改 gitlab 配置 vi /etc/gitlab/gitlab.rb
,增加 custom_hooks_dir 路径:
gitlab_shell['custom_hooks_dir'] = "<custom_hooks_dir>"
2. 执行 sudo gitlab-ctl reconfigure
Tips:不要尝试直接修改
<gitlab-shell>/config.yml
的文件内容,文件中有说明:
This file is managed by gitlab-ctl. Manual changes will be erased! To change the contents below, edit /etc/gitlab/gitlab.rb and runsudo gitlab-ctl reconfigure
.
3. 创建 hook 文件
自定义脚本目录要符合 <custom_hooks_dir>/<hook_name.d>/*
的规范。具体来说就是:
- 在自定的
custom_hooks_dir
目录下可创建三个文件夹对应三类server hook name
:- pre-receive.d
- update.d
- post-receive.d
- 在每个文件夹下可创建任意文件,在对应的 hook 时期,gitlab 就会主动调用
- 文件名以
~
结尾的文件会被忽略 - 如果想看这部分的实现细节可以看
<gitlab-shell>/lib/gitlab_custom_hook.rb
文件
目录结构示意:
[root@localhost custom_hooks]# tree
.
├── post-receive.d
│ ├── 01.sh
│ └── 02.sh~
├── pre-receive.d
│ ├── 01.sh
│ ├── 02.py
│ └── 03.rb
└── update.d
├── 01.sh
└── 02.sh
4. 编写 hook 脚本
Hook 脚本就是 git 自身的规范,写 shell、python、ruby 都可以。
留意脚本最后的退出值:0 正常退出,用户可以 push;非 0 异常退出,中断提交(pre-receive 和 update) 。
细节参见: 5.4 Git钩子:自定义你的工作流 · geeeeeeeeek/git-recipes Wiki · GitHub
如果想让用户 push 时看到相应的日志直接在脚本中 echo 即可。
这里举两个例子:
🌰:Say hi.
#!/bin/sh
echo "Say hi from gitlab server. 😄"
exit 0
🌰:检查提交修改的文件,发现有特定内容禁止提交
#!/bin/sh
FIND_KEY='.test.51offer.com'
OLD_VALUE=$2
NEW_VALUE=$3
FILES=$(git rev-list --objects $OLD_VALUE...$NEW_VALUE | egrep '\.(jsp|vm|java)$' | awk '{print $2}' | sort | uniq )
FLAG=0
for FILE in $FILES
do
git show $NEW_VALUE:$FILE | grep -q "$FIND_KEY"
if [ $? -eq 0 ]
then
FLAG=1
echo "📃 包含非法字段 '$FIND_KEY' : $FILE"
fi
done
if [ $FLAG -eq 0 ]
then
echo "✅ 代码检查通过."
else
echo "❌ 代码检查不通过!"
exit 1
fi
exit 0
4. Enjoy!
上面第二个例子中,尝试 git push
,就能看到如下的日志:
Pushing to git@gitlab.51offer.inner:mall/paycenter.git
remote: 📃 包含非法字段 '.test.51offer.com' : service/src/main/java/com/horizon/module/paycenter/service/PayService.java
remote: ❌ 代码检查不通过!
remote: error: hook declined to update refs/heads/test
To git@gitlab.51offer.inner:mall/paycenter.git
= [up to date] release/old -> release/old
= [up to date] v1.0.0.2016.9.8 -> v1.0.0.2016.9.8
! [remote rejected] test -> test (hook declined)
error: failed to push some refs to 'git@gitlab.51offer.inner:mall/paycenter.git'
Completed with errors, see above
总结:
Gitlab 官方对配置细节的表达并不清楚,配置过程中走了些弯路,翻了翻源码才摸索成功。 在此记录下来,过程并不算繁琐。
其实在 8.15 之前的版本通过修改 <gitlab-shell> 下的 hook 文件也能达到自定义 hook 的目的,不过升级版本可能会被冲掉。
毕竟官方提供了新的自定义方式,推荐大家用新方式来配置,后续维护都会容易很多。