建立一個基於webhook的簡易部署系統

安裝nodejs

安裝nodejs建議直接下載二進制包,把官網上的64位二進制版本下載地址複製下來,執行javascript

wget https://nodejs.org/dist/v6.9.2/node-v6.9.2-linux-x64.tar.xzphp

xz格式的文件按照如下命令解壓:html

  1. xz -d xxx.tar.xz 將 xxx.tar.xz解壓成 xxx.tarjava

  2. tar xvf xxx.tar來解包node

解壓以後把目錄拷貝到/usr/local/node目錄下linux

cp ~/node_v**** /usr/local/nodelaravel

爲了方便全局啓動須要在/usr/local/bin下建立文件軟鏈接git

ln -s /usr/local/node/bin/npm /usr/local/bingithub

ln -s /usr/local/node/bin/node /usr/local/binweb

執行完畢以後就能夠全局使用npmnode命令了。

因爲網絡問題,國內可使用阿里NPM鏡像cnpm

npm install -g cnpm --registry=https://registry.npm.taobao.org

而後一般/usr/bin下面的都是系統預裝的可執行程序,會隨着系統升級而改變/usr/local/bin目錄是給用戶放置本身的可執行程序的地方,推薦放在這裏,不會被系統升級而覆蓋同名文件.若是兩個目錄下有相同的可執行程序,誰優先執行受到PATH環境變量的影響.

編寫webhook代碼

部署腳本

這裏咱們要實現遠程http調用以後能夠啓動shell腳本,因此咱們先編寫部署腳本,因爲這個項目個人開發環境和測試環境的配置文件不同,因此將git目錄和部署目錄分開了。這樣就須要兩個目錄之間的單向同步,這裏我採用的方案是rsync,雖然diff也能實現文件夾比對,可是同步過程複雜,須要手動分析目錄變更。

這個項目的框架是laravelxxx_git是源碼目錄,xxx是部署目錄,具體狀況能夠調整。

這裏咱們對於目錄採用rsync單向同步,對單文件採用cp直接覆蓋方式。

#!/bin/bash
cd /home/wwwroot/xxx_git
git pull origin master
cp /home/wwwroot/xxx_git/composer.json /home/wwwroot/xxx/composer.json
cp /home/wwwroot/xxx_git/composer.lock /home/wwwroot/xxx/composer.lock
cp /home/wwwroot/xxx_git/_ide_helper.php /home/wwwroot/xxx/_ide_helper.php
rsync --delete -avzp /home/wwwroot/xxx_git/app /home/wwwroot/xxx/
rsync --delete -avzp /home/wwwroot/xxx_git/public /home/wwwroot/xxx/
rsync --delete -avzp /home/wwwroot/xxx_git/resources/lang /home/wwwroot/xxx/resources
rsync --delete -avzp /home/wwwroot/xxx_git/resources/views /home/wwwroot/xxx/resources

腳本編寫完畢以後執行下面的命令賦予執行能力

chmod +x ./my_sync.sh.sh

rsync參數:
-a:表示歸檔模式,用遞歸方式傳輸文件
-v:詳細輸出
-z:傳輸時對文件進行壓縮處理
-r:對子目錄進行遞歸
-t:保持文件的時間信息
-p:保持文件的權限
-o:保持文件的屬主信息
-g:保持文件的屬組信息
--delete:表示以服務端爲基準進行同步,保持服務端的目錄文件和客戶端的徹底一致
--progress:用於顯示數據同步的過程
--exclude:排除不須要同步的目錄或者文件

webhook接口編寫

這裏我採用了gitos上面的webhoos,其餘的gitlab、github大同小異。
OSChina的webhook可見這裏

這裏我採用了express + child_process解決調用問題,這個過程就比較簡單了,這裏面須要注意的是檢測提交push操做的是否是master分之,其餘分之的提交使不處理的。

這裏execreq.send()是沒有回調關係的,因此服務器webhook時候不會超時。另外這裏還實現了腳本運行的日誌記錄,能夠針對每次部署來查看具體文件變動狀況。

var express = require('express');
var app = express();
var cp = require('child_process');
var bodyParser = require('body-parser');
var jsonParser = bodyParser.json();
var moment = require('moment');

app.post('/git' , jsonParser ,function(req , res){
    var json = req.body;
    if(json.password == 'xxxx'){
        if (json.ref == 'refs/heads/master'){
            var logName = (moment().format('YYYY-MM-DD_HH:m:s'))+'.log';
            var command = '/home/nodejs/git_puber/my_sync.sh >> /home/nodejs/git_puber/' + logName;
            cp.exec(command, function(err, out, code) {
              if (err instanceof Error) {
                // res.writeHead(500)
                // res.end('Server Internal Error.')
                // throw err
                console.log(err + new Date());
              }else{
                console.log(out + new Date());
              }
            });
        }else{
            console.log('not master branch');
        }
    }else{
        console.log('no auth pass');
    }
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/plain');
    res.send({result:('ok' + new Date()) , msg: 'your message has been delievered'});
    // res.send();
});

app.listen(3000 , function(){
    console.log('Server Is Running' + new Date());
});

參考延伸
《exec與spawn方法的區別與陷阱》

運行監控程序

nodejs是異步單線程,在一些狀況下會出現異常退出的狀況,爲了保證服務常可用,咱們須要一個pm2來保證程序的運行。

npm install pm2 -g

這裏若是安裝速度慢的話可使用cnpm安裝。

執行pm2 start node app.js便可之後臺維護運行node程序。

pm2一些命令
pm2 list
pm2 stop all/[name]
pm2 start all/[name]

自動部署

git checkout dev

切換到dev分支後修改文件

git commit

切換到主分支而後將dev分之合併過來

git checkout dev && git merge dev

提交以後服務器自動部署

git push

相關文章
相關標籤/搜索