[Gitlab]使用Webhook實現前端專案自動釋出

mykurisu發表於2018-03-27

喜聞樂見的背景故事時間--承接[prerender-spa-plugin]--微型Vue專案的靜態化利器,官網上線之後,就開始琢磨,每次改動都得上伺服器部署一下,是不是有點麻煩了,是時候該整個自動化部署惹:)然後就開始自己挖坑自己填啦。

本文將會涉及的內容--

  • Webhook是啥?什麼時候該使用它?
  • 該怎麼利用Webhook解放我們的雙手?
  • 小結

Webhook是啥?什麼時候該使用它?

以我司為例,我們團隊內部使用Gitlab作為程式碼倉庫,所以以下內容都是在Gitlab中進行實踐的,當然在Github上其實也是大同小異的。

Webhook顧名思義,其實就是一鉤子。當我們在Gitlab上做出某些特定操作時,可以觸發鉤子,去進行一些我們事先設定好的指令碼,以達到某些特定功能(例如--前端專案自動釋出)。

也許熟悉Gitlab的同學會說了,這不就是CI嗎,為什麼好好的CI放著不用要去搞webhook呢?確實,CI也能完成一樣的功能,但是也要結合業務實際狀況而言。該專案並非公司核心專案,跑CI的runner需要有Gitlab控制許可權的同事幫忙配置,本著不騷擾同事的原則,個人認為應該自己動手豐衣足食,既然有簡單便捷的webhook為什麼不用呢?

什麼時候才應該去使用它呢?個人認為至少要有這幾點:

  • 專案不是一成不變的
  • 你是專案的負責人
  • 你有許可權進入部署專案的伺服器
  • 你能擠得出時間來踩坑

該怎麼利用Webhook解放我們的雙手?

[Gitlab]使用Webhook實現前端專案自動釋出

上圖是Gitlab中有關webhook的配置頁面,當我們成功進行了[Trigger]內部的某些或某些操作時,比如Push events--成功push了一次程式碼,無論是向哪個分支push,都可以觸發hook......

之後Gitlab將會自動的替我們向URL中的連結發去POST請求,這裡可以是指令碼也可以是服務,只要能夠成功接收來自Gitlab的請求即可。在本次實踐中,我起了一個node服務來幫助完成自動化部署。

那麼就有一個問題了,請求那個URL就會觸發node服務中的部署流程,那麼萬一有人一直在玩那個介面,會不會把服務搞掛或是把網站搞掛呢?還真有可能...所以Gitlab給了我們設定Secret Token的機會,我們檢測到請求有帶有這段特殊的token才能認為本次請求是安全可接受的。

It will be sent with the request in the X-Gitlab-Token HTTP header.

這裡需要注意一下的是,實際上我們並不會找到X-Gitlab-Token這個請求頭,我們只會匹配到x-gitlab-token這個欄位,別問我為什麼知道的,大家注意避坑就好:)

下面講講在伺服器上我們是怎麼接收Gitlab的請求並且執行部署的--

const exec = require('child_process').exec
const express = require('express')
const app = express()

let isLocking = false

app.post('/deploy', function (req, res) {
    let headers = req.headers
    let cmdStr = 'cd ... && git fetch origin && ...'
    if (!isLocking && headers['x-gitlab-token'] === 'xxx') {
        isLocking = true
        exec(cmdStr, function (err, stdout, stderr) {
            if (err) {
                // ...
                console.log('error:' + stderr);
            } else {
                // ...
                console.log(stdout)
                isLocking = false
            }
        })
    }
    // ......
})

app.listen(1234, '0.0.0.0', function () {
    console.log(`listening on port 1234`)
})
複製程式碼

在專案部署的機器上,跑了這個簡單的node服務,大意是當Gitlab POST一個請求過來時,我們進行鑑權,隨後通過node去執行一段命令列語句,根據執行的結果呼叫不同的方法。這裡有幾個坑點--

node服務搭建

貪圖方便,依賴了一下express,當然我們是可以用http模組來完成這些操作的,另外監聽埠的時候需要確認當前埠是否可被外網訪問。

node執行伺服器命令列

我們可以使用node中'child_process'模組的exec方法來執行命令列語句,將定義好的命令列語句字串傳入exec方法作為第一個引數即可,後面一個引數則是執行結果的回撥,依照業務需要設計即可。

釋出鑑權&&釋出狀態

通過Gitlab請求中帶來的token來鑑定本次請求是否能夠觸發下面的部署,並且需要設定一個"釋出中"的狀態,防止多次請求帶來的各種無法預知的後果。

上面的程式碼只是最基本的釋出服務,在裡面可以做任何事,釋出完成或失敗的各種通知,甚至還可以對提交的程式碼進行檢測,倘若不符合規範還可以拒絕本次自動部署......只要想踩坑,一切皆有可能~這樣反映出webhook的靈活,只需對git做一個簡單的操作,就可以推倒多米諾骨牌,完成一些意想不到的操作。

小結

本切圖仔第一次踩這方面的坑,希望對萌新們有所幫助,也希望大大們輕拍。接下來,可能會有一個基於python的自動部署完成後微信通知指令碼,敬請期待,當然也可能沒有:)畢竟只是個切圖仔,搬完該搬的磚就到睡點了> <

[Gitlab]使用Webhook實現前端專案自動釋出

相關文章