原理
利用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进行静态网站的自动化部署