使用node.js通过github的webhooks,自动更新远程服务器代码

 费德  2016/09/23 19:25  1,015 次

题外话

在写这篇文章前,和同学解释可以通过github的webhooks,自动更新远程服务器代码。他直接就问我,为什么不直接在服务器上搭一个git服务器?其实,这个并不是没有尝试过。具体原因大致如下:

  1. 配置多人协同合作的账号较为麻烦,而且管理起来容易出问题。

  2. 对于push等日志,缺乏可视化的界面。

  3. 服务器不够稳定,可能会影响协同合作。
    鉴于,上述原因,我们团队采用了如题的方式开发。废话不多说,进入正题。

一、自动化部署脚本

首先要保证要部署的 Web 目录就是 git clone 下来的一个 repository。这样 rollback 也方便,直接 checkout 某一个历史版本就好。

很简单地写了个 shell 脚本 deploy.sh

#!/bin/bash
 
WEB_PATH='/home/wwwroot/chat/'
WEB_USER='www'
WEB_USERGROUP='www'
 
echo "Start deployment"
cd $WEB_PATH
echo "pulling source code..."
git reset --hard origin/master
git clean -f
git pull origin master
git checkout master
echo "changing permissions..."
chown -R $WEB_USER:$WEB_USERGROUP $WEB_PATH
echo "Finished."

注意,需要在更新代码的那个文件夹,先执行如下命令。

git remote add origin {your_git_url}

二、监听 Web Hooks

20160923192918.png
那个 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 github-webhook-handler

好了,万事俱备,下面是 NodeJS 的监听程序 deploy.js

var http = require('http')
var createHandler = require('github-webhook-handler')
var handler = createHandler({ path: '/incoming', secret: '2010collect' }) 
 
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.sh'], function(text){ console.log(text) });
})

执行如下命令,即可运行起来。

node deploy

三、后台不间断执行

关于永久执行程序,我们可以使用nohup node deploy &,让该进程在后台静默执行,及时关闭shell命令行,也不会停止。
不过,这里我们采用另一个更高逼格的方式:forever
首先,我们安装forever.

$ npm install forever

再执行

$ forever start deploy.js

这样就算这段 NodeJS 代码某处出错挂了,它也会自动重新启动一个进程,保证服务仍可用。forever 的几个命令还是蛮简单的

$ forever list
$ forever stop 1
$ forever restartall

微信截图_20160923192610.png

四、测试

完成上述工作后,我们在本地push代码到github,如果出现类似以下信息,则表示配置完成。
20160923192810.png

 作者:费德

少年费德的奇幻漂流

本博客如无特殊说明皆为原创,转载请注明来源:使用node.js通过github的webhooks,自动更新远程服务器代码

添加新评论