寫個 Webhook 去構建文件

雨帆發表於2017-04-24

最近寫了一個破開源專案,在寫它的文件的時候,突然想用 rst 和 Sphinx,主要是感覺這個比較好用,寫起來比 Markdown 要強大太多。於是,就遇到了文件部署的問題。

首先是文件放在哪裡,第一時間想到的自然是 Github Pages,但是我這個破文件用的是 Sphinx,自然就沒法直接用 Jeklly 和 Markdown 讓 Github 去自動構建,必須得用靜態資源形式。也就意味著,我每次提交,都得手動將生成的文件檔案,要麼是 Push 到我 master 分支下的 docs目錄,要麼是 gh-pages 分支。

像我這種懶人,寫文件都很懶了,自然是不願意做這種重複工作。換言之,我能寫文件都很不容易了。這東西不自動化怎麼行。於是,Github Pages 方案第一時間 Pass。

接下來,我找到了大名鼎鼎的文件部署站 RTD,它能關聯我的專案,基於 Github Webhook 自動觸發構建,還能生成漂亮的文件,一切都很滿意。但是,因為是免費服務,所以生成的文件都自帶廣告。而且,繫結域名的時候,我鬱悶地發現,它沒法繫結 HTTPS 域名。我的域名加入了 HSTS Preload List,所以所有的瀏覽器訪問我的域名都會預設走 HTTPS。

得,要不我自己部署一個 rtd?於是我找到了它的 開源倉庫地址,看了看它的部署文件,我選擇放棄,需要的東西太多,而且將這個一套文件庫暴露在網站,難免不被人濫用,還無法保證安全性。

選來選去,我決定乾脆自己寫一個吧。

需求如下:

  1. 暴露一個地址,能 HTTP 方式訪問。
  2. 訪問該地址之後,能自動觸發文件構建。
  3. 能將構建好的文件部署到我的伺服器上。

一開始我想基於 Openresty 來寫,直接 access_by_lua然後裡面 os.execute 指定 shell 即可。然後我悲劇地發現,我升級到了最新的 Openresty,春哥已經廢棄了 Lua API,改用純 LuaJIT。亞麻

退而求其次,改用 Nodejs。搜了搜發現,Nodejs 的 require('child_process').spawn 可以去執行 shell 檔案,於是一個大膽的方案出來啦。

const spawn = require('child_process').spawn;
const http = require('http');

const srv = http.createServer((req, res) => {
  res.writeHead(200, {'Content-Type': 'application/json'});
  res.end('{success: true}');
  build_doc();
});

srv.listen(2800);

function build_doc() {
    const build = spawn('./build.sh');
    build.stdout.on('data', (data) => {
      console.log(`stdout: ${data}`);
    });

    build.stderr.on('data', (data) => {
      console.log(`stderr: ${data}`);
    });

    build.on('close', (code) => {
      console.log(`child process exited with code ${code}`);
    });
}

然後使用 forever start trigger.js 保證這貨在後臺監聽 2800 埠。在同級目錄寫個 Shell 檔案來指定文件的構建。

#!/usr/bin/env bash
BASE_DIR=$(dirname $0)
cd ${BASE_DIR}
BASE_DIR=`pwd`
echo ${BASE_DIR}
git clone https://github.com/syhily/gossip.git
cd ${BASE_DIR}/gossip/docs
make html
\cp -rf ${BASE_DIR}/gossip/docs/_build/html/* ${BASE_DIR}
cd ${BASE_DIR}
rm -rf gossip

剩下的就是配置 Virtual Host 啦

location /build {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $http_host;
    proxy_pass http://127.0.0.1:2800;
}

在 Github 上配置好對應的 Webhook 地址,剩下的事情就是愉快地寫文件 Push 啦,自動化真好。

相關文章