每一个可以努力的日子,都是一份厚礼。
使用 GitHub / GitLab 的 Webhooks 进行网站自动化部署
老早就想写这个话题了,今天正好有机会研究了一下 git 的自动化部署。最终做到的效果就是,每当有新的 commit push 到 master 分支的时候,就自动在测试/生产服务器上进行 git pull 拉取最新的代码,免去了程序猿兼职运维 ssh 上去拉代码部署的重复性工作。我们也要 Agile development 不是?什么敏捷开发啊,极限编程啊,快速迭代啊,持续集成啊,精益创业啊,口号怎么高端怎么来,最后就是写了个自动化脚本……
一、自动化部署脚本
首先要保证要部署的 Web 目录就是 git clone 下来的一个 repository。这样 rollback 也方便,直接 checkout 某一个历史版本就好。
很简单地写了个 shell 脚本 deploy.sh
#!/bin/bash WEB_PATH='/var/www/dev.lovelucy.info' WEB_USER='lovelucydev' WEB_USERGROUP='lovelucydev' echo "Start deployment" cd $WEB_PATH echo "pulling source code..." git reset --hard origin/master git clean -f git pull git checkout master echo "changing permissions..." chown -R $WEB_USER:$WEB_USERGROUP $WEB_PATH echo "Finished." |
下面要做的就是每当有 push 的时候就自动调用这个脚本。
二、监听 Web Hooks
GitHub 和 GitLab 本身都支持 Webhooks 的设定
那个 Payload URL 上填上需要部署到的服务器的网址,比方说 http://dev.lovelucy.info/incoming。然后之后每次有 push 事件 GitHub 都会主动往这个地址发送一个 POST 请求,当然你也可以选择任何事件都发个 POST 通知你。GitHub 还有个 Secret 的设定,就是一个字符串,如果加上的话就在 POST 请求的 HTTP 头中会带一个 Hash 值做验证密文,证明这个 POST 真是来自 GitHub,不然任何人都往那个地址 POST 忽悠你你都不知道谁是谁对吧……
然后我们就要写一个脚本在 http://dev.lovelucy.info/incoming 这里接受 POST 请求了。因为本人机器上跑的是 node,俺就找了个 nodejs 的中间件 github-webhook-handler 。如果你要部署的是 PHP 网站,那你应该找一个世界上最好的语言 PHP 的版本,或者自己写一个,只需要接收 $_POST
嘛,好简单的,不多废话啦。么么哒 ( • ̀ω•́ )
$ npm install -g github-webhook-handler |
鉴于在天朝的服务器上 npm 拉 repo 比拉屎还难的状况,我们可以 选用 阿里的镜像,据说 10 分钟和官方同步一次。_(:3 」∠ )_
$ npm install -g cnpm --registry=http://r.cnpmjs.org $ cnpm install -g github-webhook-handler |
好了,万事俱备,下面是 NodeJS 的监听程序 deploy.js
var http = require('http') var createHandler = require('github-webhook-handler') var handler = createHandler({ path: '/incoming', secret: 'myHashSecret' }) // 上面的 secret 保持和 GitHub 后台设置的一致 function run_cmd(cmd, args, callback) { var spawn = require('child_process').spawn; var child = spawn(cmd, args); var resp = ""; child.stdout.on('data', function(buffer) { resp += buffer.toString(); }); child.stdout.on('end', function() { callback (resp) }); } http.createServer(function (req, res) { handler(req, res, function (err) { res.statusCode = 404 res.end('no such location') }) }).listen(7777) handler.on('error', function (err) { console.error('Error:', err.message) }) handler.on('push', function (event) { console.log('Received a push event for %s to %s', event.payload.repository.name, event.payload.ref); run_cmd('sh', ['./deploy-dev.sh'], function(text){ console.log(text) }); }) /* handler.on('issues', function (event) { console.log('Received an issue event for % action=%s: #%d %s', event.payload.repository.name, event.payload.action, event.payload.issue.number, event.payload.issue.title) }) */ |
于是直接就可以跑起来了
$ nodejs deploy.js |
当然为了防止 NodeJS 自己挂掉,我们可以启用进程管理服务 forever,它类似 python 里面的 supervisor。
$ cnpm install -g forever $ forever start deploy.js |
这样就算这段 NodeJS 代码某处出错挂了,它也会自动重新启动一个进程,保证服务仍可用。forever 的几个命令还是蛮简单的
$ forever list
$ forever stop 1
$ forever restartall |
上面的 NodeJS 将 Web 服务跑在了 7777 端口,我们可以用 Nginx 反向代理到 80 端口(可选)
server { listen 80; server_name dev.lovelucy.info; # ... location / { # ... } location /incoming$ { proxy_pass http://127.0.0.1:7777; } }
三、集成第三方 Service
注意到 GitHub 项目后台还有个 Service 的 tab 没?
这是 GitHub 官方集成的大量的第三方服务,有点类似 IFTTT 的节奏,能做的事情就很多了。比如我设定了如果有人 push 代码,就在我们 hipchat 内部聊天群里发一个通知;如果有人提 issue,就自动给他回一封 welcome 的邮件……
GitLab 也有这些,更多玩法还是自己去钻研吧~
– EOF –
最后,催我写年终总结的童鞋,我不是真的忘了,要写的很多,最近太忙,等放假了一定补上……
(๑•́ ₃ •̀๑)
这篇文章由lovelucy于2015-01-19 22:06发表在Linux。你可以订阅RSS 2.0 也可以发表评论或引用到你的网站。除特殊说明外文章均为本人原创,并遵从署名-非商业性使用-相同方式共享创作协议,转载或使用请注明作者和来源,尊重知识分享。 |
Google Chrome 57.0.2987.133 Windows 7 大约7年前
出现同样的错误 Error: No X-Gitlab-Event found on request
Google Chrome 51.0.2704.106 Windows 7 大约8年前
Hi,我设置了一个webhook,但是在hook里没有收到任何请求,是什么原因?
Google Chrome 51.0.2704.84 Mac OS X 10_11_4 大约8年前
git已经post一个请求过来了,但是提示
Error: No X-Gitlab-Event found on request
是配置的时候缺了哪个步骤吗?
Google Chrome 51.0.2704.84 Mac OS X 10_11_4 大约8年前
我使用了gitlab-webhook-handler,在gitlab那里也配置好了webhook。但是handler.on(‘push’)事件一直都没反应,请问能指点一下原因吗?
ps:我用node的http模块来监听post事件,是可以监听得到的,但发现request.body一直为undefined,是不是这个原因导致handler的push监听不到吗?
Safari 601.3.9 Mac OS X 10_11_2 大约8年前
修改了下代码,可以用在Gitlab的node.js的 Webhooks
https://github.com/caviler/gitlab-webhook-handler
去掉了gitlab 就没有验证 header 的环节,不需要secret
把 github-webhook-handler 换成gitlab-webhook-handler即可
var handler = createHandler({ path: ‘/incoming’ })
Mozilla Firefox 43.0 Windows NT 大约8年前
我设置了webhooks,可以当有push时,gitlab没有发出请求到我指定的url去
Google Chrome 45.0.2454.93 Windows NT 大约9年前
repo是建在gitlab上,然后用该教程是报错的,看了一下github-webhook-handler源码,原来是header不匹配,请问有什么解决方案吗?
Google Chrome 46.0.2490.80 Mac OS X 10_11_1 大约9年前
gitlab 就没有验证 header 的环节吧,你可以试试用楼下提供的 PHP 版本
Google Chrome 43.0.2357.134 Windows NT 大约9年前
很不错,学习了!最近在看Docker,push一个新image可以通过webhook做通知,同时当然可以扩展到如果Github上有新版本更新就直接生成基于这个版本的image,方便开发测试!
Google Chrome 45.0.2454.101 Mac OS X 10_11_0 大约9年前
PHP版的自动部署脚本:
https://github.com/mdluo/github-webhook-handler-php
Google Chrome 44.0.2403.130 Mac OS X 10_11_0 大约9年前
学到了,博主文章说的浅显易懂
QQ Browser 7.7.26717.400 Windows NT 大约9年前
谢谢了
Google Chrome 43.0.2357.132 Windows NT 大约9年前
博主快来写年终总结啦~~★_★
QQ Browser 8.1.3703.400 Windows 7 大约9年前
不行的
Google Chrome 31.0.1650.63 Windows 7 大约9年前
没看明白。电脑菜鸟
Safari 533.1 Android 2.3.4 GT-S5570 Build/GINGERBREAD 大约9年前
博主快来写年终总结啦~~★_★
Mozilla Firefox 34.0 Windows XP 大约9年前
没用过,试试看行不行
Google Chrome 39.0.2171.95 Windows 7 大约9年前
这样不就把线上服务器的安全性和github帐号挂钩了吗。。万一github帐号失窃、或者拥有github帐号访问权限的机器失窃/ssh密钥失窃。。。
Google Chrome 39.0.2171.99 Mac OS X 10_10_1 大约9年前
GitHub 账号设置两步验证。
拥有 GitHub 账号访问权限的机器 == 线上服务器
Safari 7543.48.3 iPad OS 6_1 like Mac OS X 大约9年前
终于更新了,,只是不是2014年终。。