公司從當初的SVN代碼版本控制,FTP手動上傳項目代碼zip壓縮包,到現在的git代碼版本控制,jenkins一鍵打包部署環境,已經初步完成了手動到自動的大躍進.回過頭來看看本身的項目,還處在本地倉庫修改代碼 -> 提交遠程github倉庫 -> 本身上服務器手動pull最新分支代碼的原始階段.不能忍javascript
OK,接下來讓咱們開始咱們的進化偷懶之旅,你們一塊兒跟隨個人心路歷程一塊兒進化.java
當咱們本地倉庫修改完成push遠程倉庫以後, 服務器可以自動拉取最新分支代碼,自動完成項目部署.node
工欲善其事必先利其器,開始行動前有必要理解一波webhooks鉤子自動部署原理;nginx
本地倉庫 -> (push提交代碼) -> 遠程倉庫(webhooks鉤子) -> (發送帶有key的post請求) -> 測試/生產服務器(執行部署腳本)
複製代碼
知悉了原理以後咱們來看看咱們須要準備些什麼:git
遠程倉庫的webhooks設置你只須要找到具體位置點進去:github
URL: 設置post請求的地址(即服務器服務地址)web
key: 這個key能夠設置也能夠不設置,建議設置,防止他人隨意請求服務器接口而後自動瘋狂拉代碼部署,至關於一個驗籤shell
部署腳本(.sh)就自由發揮,本身平時怎麼手動部署的就咋寫就完事了,建立文件auto_build.sh
.Linux下建立目錄使用mkdir 目錄名
,建立文件使用touch 文件名
.npm
PROJECTNAME_PATH = '/usr/local/src/項目目錄';
echo "Starting deployment"
cd $PROJECTNAME_PATH
git checkout .
git pull
npm i
gulp release
pm2 start ecosystem.config.js
echo "Finished"
複製代碼
執行腳本的時候注意一下用戶權限的問題以及基本命令的全局安裝.gulp
接下來的重頭戲就是構建起一個可以接收遠程倉庫post請求的服務,這一樣也很簡單.你能夠藉助插件github-webhook-handler 的幫助,快速創建起這樣一個服務,建立文件deploy.js
.
ps: 這裏的secret就是上面webhooks設置中的key
var http = require('http')
var createHandler = require('github-webhook-handler')
var handler = createHandler({ path: '/webhook', secret: 'myhashsecret' })
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)
})
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)
})
複製代碼
ps: 還能夠設置當有人給本身倉庫提issues時發郵件提醒本身23333333
若是服務沒法啓動,報錯相似Error: Cannot find module 'github-webhook-handler'
,但是依賴包明明已經全局安裝過了.確認方法:
npm root -g // 查看npm全局安裝路徑
=> /root/.nvm/versions/node/v9.10.1/lib/node_modules
cd /root/.nvm/versions/node/v9.10.1/lib/node_modules
ll // 查看目錄文件確認依賴是否安裝
複製代碼
確認安裝後能夠經過如下步驟解決:
deploy.js
所在目錄npm link github-webhook-handler
複製代碼
如今,你須要作的是將auto_build.sh
和deploy.js
結合起來.
閱讀上面代碼,你會發現handler
監聽到push
事件調用對應的函數,因此你要作的就是在函數中執行auto_build.sh
命令,你須要在deploy.js
添加以及更改以下代碼
// 新增runCmd函數
funciton runCmd(cmd, args, callback) {
var spawn = require('child_process').spawn; // node子進程
var child = spawn(cmd, args);
var response = '';
child.stdout.on('data', buffer => response += buffer.toStirng());
child.stdout.on('end', () => callback(response));
}
// 修改push監聽事件 我這裏auto_build.sh和deploy.js位於同一目錄文件中
handler.on('push', function(event) {
runCmd('sh', ['./auto_build.sh'], function(text) { console.log(text) });
});
複製代碼
ps: 能夠經過console.log()
在相應的步驟輸出相應提示,方便查錯
咱們但願deploy服務可以一直運行在服務器上,當遠程倉庫發送post請求提示咱們有新代碼push的時候可以正常執行部署腳本.這時咱們須要以守護進程的方式來啓動deploy.js
服務,當服務意外崩潰時可以重啓服務,完全解放咱們的雙手.
這裏提供兩種方法供你們選擇,均可以經過npm
安裝:
forever
就是保證進程退出時,應用會自動重啓。forever start deploy.js // 啓動服務進程
forever list // 列出全部進程
forever logs id // 查看進程輸出日誌
forever stop id // 中止服務進程
forever restart id // 重啓服務進程
forever -m 5 deploy.js // 最多重啓次數爲5
複製代碼
pm2
功能強大,除了重啓進程之外,還能實時收集日誌和監控。pm2 start deploy.js // 啓動服務進程
pm2 list // 列出全部進程
pm2 logs id // 查看進程輸出日誌
pm2 stop id // 中止服務進程
pm2 restart id // 重啓服務進程
pm2 delete id // 刪除服務進程
複製代碼
由於個人服務器在騰訊雲上面,7777端口並未放開,因此經過一個Nginx反向代理到服務器安全組開放端口.
在遠程倉庫發送post測試請求前必定要確認
本身服務器安全組端口已放開!!!
本身服務器安全組端口已放開!!!
本身服務器安全組端口已放開!!!
重要的事情說三遍! 下面是我nginx配置
server {
listen 8080;
server_name localhost;
location /webhook {
proxy_pass http://127.0.0.1:7777;
}
}
複製代碼
ps: Linux下重啓nginx,進入nginx的sbin目錄運行命令./nginx -s reload
Nginx啓動 ! deploy服務啓動 ! 遠程倉庫webhook設置完畢 ! 點擊測試按鈕 !
而後......
報錯!!! (強顏歡笑and笑容逐漸消失.jpg
{
"error": "No X-Hub-Signature found on request"
}
複製代碼
看了半天......纔想起來個人項目代碼遠程倉庫是碼雲gitee.com,由於github私人private倉庫2019年2月以前都是須要付費的,因此涉及私人的項目代碼我都選擇了碼雲做爲遠程倉庫,然而個人插件是github-webhook-handler
!!!!能通才有鬼 TAT
不要緊,小問題.都到這一步了,男人怎麼能說不行!
先去github上搜下有沒有對應gitee的webhook插件,要是沒有就forkgithub-webhook-handler
下來本身改下改爲適配gitee碼雲的.果真讓我搜到了gitee-webhook-middleware
,而後deploy.js
改一改
var createHandler = require('gitee-webhook-middleware');
var handler = createHandler({ path: '/webhook', token: '你的key' });
複製代碼
重啓服務,點擊測試 !
{
"ok": true
}
複製代碼
完美 !
上服務器一看項目代碼仍是舊的,媽耶還有坑...後來發現gitee的post請求事件是Push Hook
// handler.on('push', function() {});
handler.on('Push Hook', function() {});
複製代碼
至此,從新測試,項目代碼更新成功 !
偷懶成功! 偷懶果真是工程師第一輩子產力
如今每當我本地倉庫push代碼到遠程倉庫,服務器就會拉取最新版本代碼自動部署.
這只是我一次簡單嘗試,咱們徹底能夠擴展自動化測試,自動化部署於一體,完成多人協做開發時的CI/CD,大大減小人力成本,減小人爲錯誤的發生,提升你們的工做效率.