基于 Git WebHook 自动部署实现

目录
[隐藏]

因为项目版本迭代比较快,而每次迭代都需要重复的上服务器进行部署,实在是有些繁琐。特别是对于频繁修改的 API 文档站点,一天可能有好几次更新推送,于是乎就有了自动部署的想法。本文主要记录怎么去实现自动部署的,对于更详细的概念只会给出参考链接,不会过多赘述。

1、一个版本发布的一般过程(基于 Git 管理)

1. git pull origin xxxx  将远程仓库分支拉取到本地

2. 编写代码进行开发

3. git add .

4. git commit -m 'xxxx'

5. git push origin xxxx              将最新版本推送到远程仓库

6. 登录项目服务器

7. 进入项目所在目录

8. git pull origin xxx

对于一个单一项目,迭代很少或者不频繁,那倒不觉得这几步有多麻烦。但如果使用了像 Slate 这样的在线API 文档,那每天都要重复好几次上述步骤。引入自动构建发布后,就可以简单的在本地修改推上去,然后啥都不用管了,还是会便捷很多(谁用谁知道)。

2、自动部署

在我这里,这个词实际和 Push To Deploy 是基本画上等号的。简单说就是,我只管 Push 我的代码,Push

完后服务器上就会自动拉取最新代码进行部署。

要实现自动部署,很关键的一个依赖就是 Git 提供的钩子(hook)

这个 hook 会被某些 Git 事件所触发,例如 Push、Tag Push 等。想了解 GitHook 相关,在文末给出了相关参考链接,可以先去了解下。

一般的代码托管平台,例如 GitHub、阿里云代码托管 等都会对每个托管的项目提供 webhook 的设置,这个 webhook 就是设置当 Git 的钩子被触发时,应该向哪个处理程序发送请求,进行下一步处理。

看下 GitHub 和 阿里云的 webhook 的设置界面:

可以看到不同平台提供的 webhook 设置会略有差异。

2.1 阿里云 webhook

上面第一张图是 阿里云的 webhook 设置界面

箭头1 指向的是阿里云提供的 webhook 介绍的链接,

箭头2 勾选则表示阿里云的服务器和处理程序所在服务器通讯需要使用 SSL 验证

箭头3 指向输入框就是要填写 处理程序的URL,当钩子被触发时,就会发送请求到这个 URL 上

箭头4 指向是使用哪种钩子,也就是在 Git 上发生什么事件时,就会触发钩子然后去发送请求

阿里云的 webhook 不允许设置请求体的格式,在文档介绍中可以知道,发送给处理程序的是 POST 请求,而请求体是 json 格式的原始字符串。

设置好 URL,Trigger 就可以点击左下方的 ADD WEB HOOK 添加一个 web hook 了。添加后会在页面最下方显示该 web hook,并且提供了 TEST 按钮可以测试 URL 是否通畅。

注意:因为 SSL Verification 默认是开启的,而且放在比较不显眼的位置,容易被忽略。如果你的处理程序所在服务器没有 SSL 证书,但又开启了 SSL Verification,那就无法通信了,所以如果不是特别危险,建议可以关闭。

2.2 GitHub webhook

GitHub 的 webhook 设置和阿里云的大同小异,也提供了相应的文档。

对比两者可以看到:阿里云使用 SSL 验证,但 GitHub 提供对称密钥认证(就是你在Secret 中设置一个复杂的 token,然后 GitHub 在给你的处理程序发送 POST 请求时,就会带上根据这个 token 生成的 hash signature,这样你就可以在处理程序中验证这个请求是由 GitHub 发送的,就可以避免接受不必要的请求了),显然后者更加灵活。另外,GitHub 支持 json 和 x-www-form-urlencode 两种请求体的格式,也提供了更好的灵活性。更多资料看文末给出的参考链接即可,这里不再赘述了。

3、另一个关键:处理程序

经过上面的设置, Git 的事情就基本做完了,接下来就到了实现自动部署的另一个关键点:处理程序的实现

处理程序可以使用你熟悉的任何一种语言、任何方法去完成。我这里用的php-fpm + nginx(主要是因为项目就是用的这两者)

处理程序的内容也是比较简单的:

从请求头中获取 X_GITLAB_EVENT (所有 Git 钩子发送的请求,都会有该字段,标识是什么事件)

钩子一般发送的都是 POST 请求,而且请求体中数据比较多,所以不会用 x-www-form-urlencoded 这种表单形式,通常是原始的 json 格式的字符串。

对于 PHP 来说,PHP 底层不会处理 json 格式的原始字符串然后封装进 $_POST 中,要获取原始 POST 请求数据,就要从 php://input 这个流中去读取,所以要用  file_get_contents('php://input') 去读取,然后用 json_decode 将 json 字符串反序列化。默认是转成一个 对象,可以传入第二参数 true ,就可以转换成 数组形式。这些数据里面包含了很多信息(包括分支名、Tag、提交人等等)

然后根据情况,调用对应的 bash 脚本(一般会需要将 分支名、Tag 作为参数传入脚本)

一个简单的处理程序如下:

$json = file_get_contents('php://input');   //获取原始 POST 数据

$data = json_decode($json,true);            //反序列为数组

$ref_arr = explode('/',$data['ref']);       //获取 ref 的值

$ref_detail = $ref_arr[count($ref_arr) - 1]; // 获取具体分支名/Tag 值

$bash = './test.sh '.$ref_detail;            // 拼接外部脚本命令

exec($bash);                                 // 执行外部脚本


这只是给出一个样例,实际上还可以更加完善,包括做安全检测、记录日志等

3.1 脚本内容

这里要调用的 bash 脚本内容也是十分简单的:

cd 项目所在目录

git pull origin $1

$1 表示传入的参数~~

4、总结

要实现一个自动部署其实还是比较简单的,关键还是看自动部署后,怎么继续接入持续的工作流中。也没必要为了自动部署而自动部署,而是确实要有需求再去做。

再回顾一下整个自动部署:

根据 Git 的钩子就可以对各种事件进行反应,然后代码托管平台通常提供设置 webhook,这个 webhook 的关键在于设置好 处理程序(也就是填好 URL,这样在对应事件发生时就会向该 URL 发送 POST 请求了)。POST 请求中是包含很多信息的,所以在处理程序中就可以得知推送的 分支/Tag。然后再调用脚本,脚本内容就是手动部署时所执行的命令。

需要注意的是:在 Linux 下一定要注意好权限问题,特别是处理程序调用外部脚本,一定要确定运行处理程序的用户是否有权限读写日志文件,是否有权限执行脚本。

5、参考

阿里云webhook: 

      https://code.aliyun.com/help/web_hooks/web_hooks

      https://help.aliyun.com/document_detail/60949.html?spm=5176.doc60763.6.550.cN2gIN

GitHub webhook:

      https://developer.github.com/webhooks/

Git 钩子相关:

      https://aotu.io/notes/2017/04/10/githooks/index.html

       m.blog.csdn.net/iiiiher/article/details/70255934



发表评论

电子邮件地址不会被公开。 必填项已用*标注

To