都9012年了,你還在手動部署代碼嗎

背景

公司從當初的SVN代碼版本控制,FTP手動上傳項目代碼zip壓縮包,到現在的git代碼版本控制,jenkins一鍵打包部署環境,已經初步完成了手動到自動的大躍進.回過頭來看看本身的項目,還處在本地倉庫修改代碼 -> 提交遠程github倉庫 -> 本身上服務器手動pull最新分支代碼的原始階段.不能忍javascript

OK,接下來讓咱們開始咱們的進化偷懶之旅,你們一塊兒跟隨個人心路歷程一塊兒進化.java

目標

當咱們本地倉庫修改完成push遠程倉庫以後, 服務器可以自動拉取最新分支代碼,自動完成項目部署.node

前置條件(廢話)
  1. 有個本地倉庫可以鏈接到遠程倉庫,可以push代碼
  2. 服務器倉庫可以從遠程倉庫pull代碼
  3. 遠程倉庫有webhooks功能

行動

工欲善其事必先利其器,開始行動前有必要理解一波webhooks鉤子自動部署原理;nginx

webhooks自動部署原理
本地倉庫 -> (push提交代碼) -> 遠程倉庫(webhooks鉤子) -> (發送帶有key的post請求) -> 測試/生產服務器(執行部署腳本) 
複製代碼

知悉了原理以後咱們來看看咱們須要準備些什麼:git

  • 帶有webhooks的遠程倉庫(gitlab,github,gitee等等)
  • 可以接收post請求的服務和測試/生產服務器
  • 部署腳本(.sh)
遠程倉庫webhooks設置

遠程倉庫的webhooks設置你只須要找到具體位置點進去:github

  1. URL: 設置post請求的地址(即服務器服務地址)web

  2. key: 這個key能夠設置也能夠不設置,建議設置,防止他人隨意請求服務器接口而後自動瘋狂拉代碼部署,至關於一個驗籤shell

部署腳本auto_build.sh

部署腳本(.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

編寫服務deploy.js

接下來的重頭戲就是構建起一個可以接收遠程倉庫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 									// 查看目錄文件確認依賴是否安裝
複製代碼

確認安裝後能夠經過如下步驟解決:

  1. 進入deploy.js所在目錄
  2. 執行如下命令
npm link github-webhook-handler
複製代碼

如今,你須要作的是將auto_build.shdeploy.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.js

咱們但願deploy服務可以一直運行在服務器上,當遠程倉庫發送post請求提示咱們有新代碼push的時候可以正常執行部署腳本.這時咱們須要以守護進程的方式來啓動deploy.js服務,當服務意外崩潰時可以重啓服務,完全解放咱們的雙手.

這裏提供兩種方法供你們選擇,均可以經過npm安裝:

  1. forever就是保證進程退出時,應用會自動重啓。
forever start deploy.js		   				  // 啓動服務進程
forever list								  // 列出全部進程
forever logs id								  // 查看進程輸出日誌
forever stop id								  // 中止服務進程
forever restart id							  // 重啓服務進程
forever -m 5 deploy.js						  // 最多重啓次數爲5
複製代碼
  1. pm2功能強大,除了重啓進程之外,還能實時收集日誌和監控。
pm2 start deploy.js		   				  // 啓動服務進程
pm2 list								  // 列出全部進程
pm2 logs id								  // 查看進程輸出日誌
pm2 stop id								  // 中止服務進程
pm2 restart id							  // 重啓服務進程
pm2 delete id							  // 刪除服務進程
複製代碼
Nginx反向代理

由於個人服務器在騰訊雲上面,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

Bug

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,大大減小人力成本,減小人爲錯誤的發生,提升你們的工做效率.

相關文章
相關標籤/搜索