[toc]
使用Gitlab给公司搭建了一套Git仓库服务器,结合OpenLDAP授权给研发人员使用已经半年有余了,大家也逐渐适应了新的Git Flow(工作流),期间也遇到了很多问题或者需求,比如:
- 怎么禁止提交不安全的文件类型?
- 怎么强制研发人员遵守代码规范?
目的是:
-
通过限制文件类型,可以禁止研发上传例如.rar/.zip/.gz/.tgz/.mdb/.sql/.bak等文件,防止研发备份的程序或者代码通过自动发布系统上传到服务器后,被黑客恶意下载从而导致信息数据泄露。另外限制二进制数据还可以节省Git服务器空间
-
强制研发人员遵守代码规范,简洁整齐、规范统一的代码让别人读起来会更容易理解,团队协作也会更高效,因此从Git服务器上进行严格规范限制,不合格的代码不让提交
自然想到的解决办法就是使用Git的pre-receive
钩子了。
我的Git服务器目录结构如下:
/data/git-data/
├───────────── custom_hooks
│ ├── pre-receive # 钩子脚本
├───────────── repositories # Git数据目录
└───────────── set_hook.sh # 计划任务脚本(对新增仓库自动添加custom_hooks)
一、下载安装phpcs
下载phpcs(PHP_CodeSniffer)工具
注意: phpcs依赖php运行环境,请提前自行安装php
wget -O /usr/local/bin/phpcs \
https://github.com/squizlabs/PHP_CodeSniffer/releases/download/3.0.2/phpcs.phar
chmod +x /usr/local/bin/phpcs
二、设置hooks脚本
自定义钩子脚本
- 创建
/data/git-data/custom_hooks
目录,用于存放钩子脚本 - 创建
/data/git-data/custom_hooks/pre-receive
文件,脚本内容如下:
#!/usr/bin/env bash
#
# Pre-receive hook that will block any new commits that contain files ending
# with .gz, .zip or .tgz .sql .log .svn
#
# More details on pre-receive hooks and how to apply them can be found on
# https://help.github.com/enterprise/admin/guides/developer-workflow/managing-pre-receive-hooks-on-the-github-enterprise-appliance/
#
#TEMPDIR=`mktemp -d --tmpdir=/dev/shm`
zero_commit="0000000000000000000000000000000000000000"
# Do not traverse over commits that are already in the repository
# (e.g. in a different branch)
# This prevents funny errors if pre-receive hooks got enabled after some
# commits got already in and then somebody tries to create a new branch
# If this is unwanted behavior, just set the variable to empty
excludeExisting="--not --all"
RETVAL=0
while read oldrev newrev refname; do
# branch or tag get deleted
if [ "$newrev" = "$zero_commit" -o "$oldrev" = "$zero_commit" ]; then
continue
fi
newfiles=`git diff --name-only --diff-filter=A $oldrev $newrev`
for FILE in $newfiles
do
case $FILE in
*.ipk|*.ipa|*.apk|*.war|*.exe|*.db|*.zip|*.rar|*.gz|*.tgz|*.7z|*.log|*.ai|*.psd|*.svn|*.bak|*Thumbs.db|.idea )
echo "+================================ ERROR =============================+"
echo "| FILE: $FILE"
echo "| REFNAME: $refname"
echo "| OLDREV: $oldrev"
echo "| NEWREV: $newrev"
echo "+============================== 禁止提交 ============================+"
RETVAL=1
;;
*.php | *.php5 )
if [ -n "echo $f|grep -oP '.+/(Org/Thrift|Vendor)/.+'" ]; then
continue # 忽略的目录
fi
if [ "$f" = "$FILE" ]; then
object=`git ls-tree --full-name -r ${newrev} | egrep "(\s)${FILE}$" | awk '{ print $3 }'`
if [ -z ${object} ]; then continue; fi
git cat-file blob ${object} | /usr/local/bin/phpcs --error-severity=1 --warning-severity=8 --extensions=php,php5 --standard=PSR2 --ignore=*/Run/*,*/Runtime/*
if [ $? -eq 0 ]; then continue; fi
echo "+================================ ERROR =============================+"
echo "| FILE: $FILE"
echo "| REFNAME: $refname"
echo "| OLDREV: $oldrev"
echo "| NEWREV: $newrev"
echo "+============================== 校验错误 ============================+"
RETVAL=1
fi
;;
esac
done
done
exit $RETVAL
- 修改目录和文件权限
chmod -R 755 /data/git-data/custom_hooks
三、设置计划任务
创建计划任务脚本、设置计划任务,自动将custom_hooks目录链接到相应Git仓库下使之生效。
/data/git-data/set_hook.sh
脚本如下:
#!/bin/sh
# 忽略一些目录
/bin/find /data/git-data/repositories/ -name '*.git' ! -name '*.wiki.git' ! -path '*/mob/*' ! -path '*/docs/*' ! -path '*/ops/*' -type d | while read gitdir
do
/bin/ln -s /data/git-data/custom_hooks $gitdir/ # 创建软连接
done
加可执行权限
chmod +x /data/git-data/set_hook.sh
crontab -e
创建计划任务,每天执行一次:
0 0 * * * /data/git-data/set_hook.sh