Webhooks,可以让你在 Git 仓库中操作某些行为后触发指定的行为,比如说在 git push 后由服务器自动 git pull 拉取代码然后执行一些特定行为,比如 npm run build 自动打包项目让生产/测试环境代码第一时间能够自动更新到最新状态。
过程也很简单,选择事件 -> 绑定接口。这样在事件发生的时候 GitLab 会向指定接口发送一个 POST 请求,然后就可以在接口里做剩下的事情了。
下面是所支持的事件钩子:
URL 就是接口地址,Secret Token 是用来在服务器验证接口的,比如如果你收到的请求中 Secret Token 的内容与你设定的内容不一致就不执行任何行为。
接口我是这么写的:
router.post('/build', async function ( ctx ) {
try {
WebHookServer.build( ctx.request.header, ctx.request.body );
ctx.body = 'success'
} catch (err) {
ctx.throw(400, err.toString());
}
})
没有等待打包过程完成直接返回 200,是因为如果项目打包时间如果过长会造成接口超时,我觉得也没有必要。
build 函数:
const exec = require('child_process').exec;
const build = function ( header, body ) {
const token = 'lab build';
return new Promise((resolve, reject) => {
if ( !header['x-gitlab-event'] || header['x-gitlab-token'] !== token ) {
return reject('error');
}
const filename = __dirname + '/build.sh';
exec(filename, function ( err, stdout, stderr ) {
if (err) {
console.log('执行脚本出错', err);
return reject(err);
}
resolve('success');
})
})
}
简单的验证 Secret Token 以后执行脚本。
脚本的内容:
WEB_PATH=/home/...
cd $WEB_PATH
./build.sh
WEB_PATH这个目录路径我就简化了,执行接口所在目录的脚本,这个脚本执行需要构建的项目所在目录下的脚本:(文章底部有为什么写两个脚本来执行的原因)
git pull
npm run build
rm -rf ../......
mv ./dist ../......
这就很容易理解了,拉代码,打包,删除原来目录,打包完的目录移动到指定的目录下。
流程上基本上就是这样了。
来看一下这个 POST 请求的 Header 信息:
"x-gitlab-event" 是触发的钩子名称
"x-gitlab-token" 是所填写的 Secret Token
至于 body 里面有什么可以到时候自行打印 log 查看。
补充:
说一声下为什么要先执行根目录下的脚本然后再执行项目目录下的脚本,直接执行项目目录下的脚本不行吗?可以,但是这样会报错的,因为那样需要输入 GitLab 的账号和密码才可以继续。
简单地来说
在 A 目录下执行脚本的时候不需要输入用户名密码就可以 git pull,因为配置的是 SSH(必须配置SSH),所以脚本可以自动执行完整个过程。
但是在 B 目录下执行 A 目录下的脚本就需要输入用户名密码了,没有细究其中原因,所以才用了两个脚本这种婉转的方式。
另外,如果在执行脚本的时候报错:Permission denied,是因为没权限。
sudo chmod -777 filename