利用webhook自动更新服务器代码

今天聊一聊webhooks

起因:前段时间跟朋友聊天,听朋友说到git钩子挺好用的(当时的我是一脸懵逼~~)。
好奇心使然,晚上我查了一些资料,发现真的好用。因为同事还有对git不怎么熟悉的,有时候他们提交代码时,忘记了先pull,然后就出现冲突了。
然后我就在pre-commit 和 pre-push 的hook里面,加了一些判断,防止他们提交代码的时候又忘记拉取代码。

只是一些简单的判断,下面附上代码:

git commit hook

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/sh
git fetch -q
# 获取当前的分支名
bna=$(cat .git/HEAD)
thisBranch=${bna:15}
localHash=`cat .git/refs/heads"${thisBranch}"`
remoteHash=`cat .git/refs/remotes/origin"${thisBranch}"`
if [[ $localHash != $remoteHash ]]; then
msg='Sorry, there are new updates in the remote, please update your local code first.'
echo -e "\n\033[31m $msg \033[0m\n"
cmds="git stash && git pull && git stash pop"
echo "You can execute: "
echo -e "\n\033[32m $cmds \033[0m\n"
echo "and then continue do it of your previous command."
cmds2="git add . && git commit -m [description]"
echo -e "if no merging, you can excuting \033[32m $cmds2 \033[0m\n."
exit 1
fi

git push hook

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/bin/sh
git fetch -q
# 获取当前的分支名
bna=$(cat .git/HEAD)
thisBranch=${bna:15}
localHash=`cat .git/refs/heads"${thisBranch}"`
remoteHash=`cat .git/refs/remotes/origin"${thisBranch}"`
git cat-file -p $localHash > calcpartimes
parentTimes=`grep -o 'parent' calcpartimes |wc -l`
originUpdated=`grep -o $remoteHash calcpartimes |wc -l`
rm -rf calcpartimes
if [[ $localHash != $remoteHash ]]; then
if [[ !($parentTimes -eq 1 && $originUpdated == 1) ]]; then
msg='Sorry, there are new updates in the remote, please update your local code first.'
echo -e "\033[31m $msg \033[0m"
cmds="git reset --soft HEAD~1 && git stash && git pull && git stash pop"
echo "You can execute: "
echo -e "\n\033[32m $cmds \033[0m\n"
echo "and then continue do it of your previous command."
exit 1
fi
fi

上面是本地的hook利用,下面说一下服务器上的hook(这里就以github为例):

找到项目的setting,然后添加一个webhook,填写你服务器上的一个接口:

http://static.togor.cn/blog/20180927/1.png

之后就是服务器上面的事情了。

我是用node启的服务,利用child_process调用shell,当请求接口时,执行shell脚本,拉取远程的代码。

1
2
3
4
5
6
7
const { exec } = require('child_process')
exports.gitPull = function () {
exec('cd ** && git pull', function (err, stdout, stderr) {
if(err) throw err
console.log(stdout)
});
}
1
2
3
4
app.post('****', function (req, res, next) {
sys.gitPull();
res.send({status: true});
});

如此而已。