每一個可以努力的日子,都是一份厚禮。
使用 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 也可以發表評論或引用到你的網站。除特殊說明外文章均為本人原創,並遵從署名-非商業性使用-相同方式共享創作協議,轉載或使用請註明作者和來源,尊重知識分享。 |
出現同樣的錯誤 Error: No X-Gitlab-Event found on request
Hi,我設置了一個webhook,但是在hook里沒有收到任何請求,是什麼原因?
git已經post一個請求過來了,但是提示
Error: No X-Gitlab-Event found on request
是配置的時候缺了哪個步驟嗎?
我使用了gitlab-webhook-handler,在gitlab那裡也配置好了webhook。但是handler.on(‘push’)事件一直都沒反應,請問能指點一下原因嗎?
ps:我用node的http模塊來監聽post事件,是可以監聽得到的,但發現request.body一直為undefined,是不是這個原因導致handler的push監聽不到嗎?
修改了下代碼,可以用在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’ })
我設置了webhooks,可以當有push時,gitlab沒有發出請求到我指定的url去
repo是建在gitlab上,然後用該教程是報錯的,看了一下github-webhook-handler源碼,原來是header不匹配,請問有什麼解決方案嗎?
gitlab 就沒有驗證 header 的環節吧,你可以試試用樓下提供的 PHP 版本
很不錯,學習了!最近在看Docker,push一個新image可以通過webhook做通知,同時當然可以擴展到如果Github上有新版本更新就直接生成基於這個版本的image,方便開發測試!
PHP版的自動部署腳本:
https://github.com/mdluo/github-webhook-handler-php
學到了,博主文章說的淺顯易懂
謝謝了
博主快來寫年終總結啦~~★_★
不行的
沒看明白。電腦菜鳥
博主快來寫年終總結啦~~★_★
沒用過,試試看行不行
這樣不就把線上服務器的安全性和github帳號掛鈎了嗎。。萬一github帳號失竊、或者擁有github帳號訪問權限的機器失竊/ssh密鑰失竊。。。
GitHub 賬號設置兩步驗證。
擁有 GitHub 賬號訪問權限的機器 == 線上服務器
終於更新了,,只是不是2014年終。。