快來(lái)學(xué)習(xí)下webhook吧!超級(jí)簡(jiǎn)單易學(xué)

1. Webhook是啥?
簡(jiǎn)單而言,webhook就是一個(gè)監(jiān)聽(tīng)的鉤子,監(jiān)聽(tīng)你push你的代碼到github倉(cāng)庫(kù)之后,發(fā)起一個(gè)請(qǐng)求。這個(gè)請(qǐng)求要請(qǐng)求哪里交給你設(shè)置要。

主要流程

git push xxx 本地代碼提交至遠(yuǎn)程github倉(cāng)庫(kù)
github倉(cāng)庫(kù)收到push后進(jìn)行回調(diào),發(fā)post( Payload url 是來(lái)自webhooks的配置)請(qǐng)求
基于 Payload url 的服務(wù)根據(jù)傳回來(lái)的信息進(jìn)行提取,拉取最新代碼并重新構(gòu)建項(xiàng)目
可以看到,我們只需把代碼提交到github倉(cāng)庫(kù)即可,不用再上服務(wù)器進(jìn)行一些列的操作了
在這里插入圖片描述
2. webhook有什么作用呢?
目前我發(fā)現(xiàn)的我們公司主要是用于 監(jiān)聽(tīng)到開(kāi)發(fā)者 push代碼到倉(cāng)庫(kù)之后就 發(fā)送消息到企業(yè)微信群里。如下圖所示:
在這里插入圖片描述
完成自動(dòng)化部署
3.配置webhook超簡(jiǎn)單
來(lái)到你的倉(cāng)庫(kù),點(diǎn)擊setting

在這里插入圖片描述
然后選中左邊的webhook,就可以配置了

在這里插入圖片描述
4.主要配置四部分:
Payload URL 回調(diào)服務(wù)的地址,就是你想請(qǐng)求的一個(gè)接口的地址,請(qǐng)求方式是POST;

Content type 回調(diào)請(qǐng)求頭,建議JSON格式;

Secret 為了做安全校驗(yàn),設(shè)置后會(huì)在請(qǐng)求 header 中增加如下兩個(gè)屬性,用來(lái)區(qū)分請(qǐng)求的來(lái)源,避免暴露的請(qǐng)求被惡意訪(fǎng)問(wèn);

X-Hub-Signature: ...
X-Hub-Signature-256:...
最后我們選擇由哪些事件來(lái)觸發(fā)webhook回調(diào),push event(代碼推送事件)、everything(所有事件)、某些特定事件三種。

配置完成后,嘗試提交代碼下,然后從Recent Deliveries中你會(huì)發(fā)現(xiàn)有調(diào)用webhook的記錄。

5.實(shí)現(xiàn)自動(dòng)化部署
我們用node簡(jiǎn)單地搭建一個(gè)服務(wù)器

下面講講在服務(wù)器上我們是怎么接收Gitlab的請(qǐng)求并且執(zhí)行部署的--

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`)
})
可以看到,當(dāng)我們配置webhook的請(qǐng)求URL是我們的deploy接口時(shí),當(dāng)webhook監(jiān)聽(tīng)到我們push代碼之后,就會(huì)請(qǐng)求deploy接口,然后執(zhí)行接口里面的邏輯,然后自動(dòng)化部署就是我們?cè)诮涌诶飳?xiě)好的cmdStr字符串了。

6.實(shí)現(xiàn)企業(yè)微信機(jī)器人報(bào)告
企業(yè)微信的配置其實(shí)更簡(jiǎn)單,我們先創(chuàng)建一個(gè)群組,在群組右鍵有個(gè)添加機(jī)器人選項(xiàng),添加成功后會(huì)生成webhook地址。我們只要向這個(gè)地址發(fā)送POST請(qǐng)求,群組內(nèi)就會(huì)收到推送消息。

在這里插入圖片描述
消息內(nèi)容支持文本(text)、markdown(markdown)、圖片(image)、圖文(news)四種消息類(lèi)型,而且還支持在群內(nèi)@群成員,下邊以文本格式做示范。

   curl 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=145a516a-dd15-421f-97a3-ba3bf1479369' \
   -H 'Content-Type: application/json' \
   -d '
   {
        "msgtype": "text",
        "text": {
            "content": "你好,我是程序員內(nèi)點(diǎn)事"
        }
   }'

直接請(qǐng)求 url 發(fā)現(xiàn)消息推送成功,說(shuō)明配置的沒(méi)問(wèn)題。

所以我們可以這樣實(shí)現(xiàn):

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

let isLocking = false

app.post('/deploy', function (req, res) {

  try {
     const content = JSON.parse(req.body.payload) ;
     const name = content.pusher.name;
     const message = content.before;
     
     axios.post('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=145a516a-dd15-421f-97a3-ba3bf1479369',data: {
      "msgtype": "text",
        "text": {
            "content": "你好,我是程序員內(nèi)點(diǎn)事"
        }
     })
  } catch (error) {
    console.log(error);
  }
})

app.listen(1234, '0.0.0.0', function () {
    console.log(`listening on port 1234`)
})
看,基本就是這樣實(shí)現(xiàn)啦,夠簡(jiǎn)單吧,(代碼只是寫(xiě)個(gè)大概,并不完整)。

快去給你的倉(cāng)庫(kù)配置下webhook吧。

作者:事業(yè)有成的張啦啦


歡迎關(guān)注微信公眾號(hào) :前端陽(yáng)光