github的webhook是個有用的功能,允許開發人員指定一個伺服器的url。當開發者對github倉庫施加操作,比如送出代碼,建立issue時,github網站會自動向該url指定的伺服器推送事件。借助webhook,我們可以實作很多自動化流程。比如部署一個應用在AWS上,本地送出代碼後,github網站自動觸發webhook,調用AWS上應用的邏輯,在AWS上将本地送出的最新代碼用git pull抓取到AWS上并重新部署。
下面我們通過一個具體的例子來學習github webhook的用法。
建立一個github倉庫,點選Settings連結:
在Payload url裡指定一個應用的url,該url對應的應用監聽github網站推送的事件。
Content Type指定成application/json便于我們在nodejs應用裡解析payload。
建立後點Add webhook儲存,github會發送一個json paload到這個url指定的應用上。
在Recent Deliveries裡檢視負載明細:
負載明細如下:
我們現在來做個實驗,把webhook指定的url對應的應用設定一個斷點,然後在github倉庫裡建立一個issue:
斷點立即觸發了。
從調試器裡能觀察到這個create issue事件的所有負載。
我部署在AWS上監聽github webhook架構推送github repository發生變化的事件的應用源代碼,可以從我的github上擷取:
https://github.com/i042416/webhookstudy 代碼很短,我的同僚Haytham寫的:var http = require('http')
var createHandler = require('github-webhook-handler')
var handler = createHandler({ path: '/push', secret: 'dis-koi' })
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(8083)
handler.on('error', function (err) {
console.error('Error:', err.message);
})
handler.on('push', function (event) {
switch(event.payload.repository.name)
{
case 'githubHook':
//this push event is from my persional github account, as SAP github.tool's github hook do not work, so I use this one to test push event
console.log("reveive a push event from githubHook");
run_cmd('sh', ['./webshop.sh'], function(text){ console.log(text) });
break;
case 'frontend-web':
//push event from frontend-web
console.log("reveive a push event from frontend-web");
run_cmd('sh', ['./webshop.sh'], function(text){ console.log(text) });
break;
case 'backend-ms':
//push event from backenf-ms
console.log("reveive a push event from backend-ms");
run_cmd('sh', ['./backend_ms.sh'], function(text){ console.log(text) });
break;
}
})
handler.on('issues', function (event) {
console.log('Received an issue event for %s action=%s: #%d %s',
event.payload.repository.name,
event.payload.action,
event.payload.issue.number,
event.payload.issue.title);
})