原理
利用Github在仓库进行操作时,可以通过配置webhook向服务器发送请求,在服务器端接到请求后,使用脚本来自动进行git pull操作。

图片来源:Github的webhook触发vps上的脚本
构建 Webhook 服务
通过执行
1
   | npm i -g github-webhook-handler
   | 
来安装  github-webhook-handler 中间件
新建文件 webhook.js
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
   | var http = require('http') var createHandler = require('github-webhook-handler') var handler = createHandler({ path: '/', secret: 'root' })
  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',event.payload.repository.name], function(text){ console.log(text) }); })
  | 
 
其中
1
   | var handler = createHandler({ path: '/', secret: 'root' })
  | 
secret 字段为 Github 中设置的,需要与这里相对应
注意,在运行的时候如果提示 github-webhook-handler is not defined 未找到 ,可以在目录中执行 npm link github-webhook-handler
同一服务多个 webhook
当你有多个仓库需要自动部署时,可以在一个服务上开启多个 webhook。
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
   | var http = require('http') var createHandler = require('node-github-webhook') var handler = createHandler([    {     path: '/app1',     secret: 'CUSTOM'   },   {     path: '/app2',     secret: 'CUSTOM'   } ])
 
  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   )   switch (event.path) {     case '/app1':       runCmd('sh', ['./app1_deploy.sh', event.payload.repository.name], function (text) { console.log(text) })       break     case '/app2':       runCmd('sh', ['./app2_deploy.sh', event.payload.repository.name], function (text) { console.log(text) })       break     default:              break   } })
  function runCmd (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)   }) }
  | 
 
同一服务多个webhook时,最终你的payload URL 则为:http:/yourdomain:7777/app1 或者 http:/yourdomain:7777/app2 ,注意我在实践过程中发现,不能使用 / 目录,会无法监听到 webhook。
参考地址:https://github.com/rvagg/github-webhook-handler/pull/22#issuecomment-274301907
完成 shell 脚本
在使用脚本之前,先要对网站根目录做一些处理
1 2 3 4 5 6
   | # 打开网站根目录 cd /home/wwwroot/domain.com # 采用 Git 文件控制 git init # 添加远程 Git 仓库地址 git remote add origin https://xx.git
   | 
 
参考地址:
How do I force “git pull” to overwrite local files?
然后再创建 deploy.sh,与 webhook.js 在同一个目录下
1 2 3 4 5 6 7 8 9 10 11
   | #!/bin/bash
  WEB_PATH='/home/wwwroot/domain.com'   echo "start deployment" cd $WEB_PATH echo "fetching from remote..."
  git fetch --all git reset --hard origin/master echo "done"
   | 
 
由于 Linux 文件权限问题,可能无法执行,建议先执行 chmod 777 ./deploy.sh
使用pm2进行进程守护
安装pm2:
运行webhook.js
进入Gtihub后台进行设置
进入需要自动部署的项目的github地址添加webhook,进入Settings设置页面,点击左侧的 Webhooks

参考地址:
利用Github的Webhook进行静态网站的自动化部署