在早期 輕鬆部署 Laravel 應用 課程開始編寫之前,就考慮到一個非常重要的問題:如何保證 Laravel-China 上釋出的文章與 GitHub 倉庫內的 Markdown 原始檔保持同步?
問題
最原始的辦法是每次更新後 -> 找到對應文章的 URL -> 在網站上作出同樣的修改。
但這個想法很快就被打消了。原因很多:
- 純手工,容易產生操作失誤。
- 費時費力的重複性無意義工作,耽擱主要生產力(編寫內容)的輸出。
懶。
咳咳。
效果一覽
最終決定完全自動化,力爭一勞永逸。經過一段時間折騰,目前效果如下:
思路
結合自己多年前的抓包分析技能以及如今的 CI 技能,基本思路為:
- 作出變更,
git commit
+git push
- GitHub 通知 Travis CI
- Travis CI 執行持續交付流程
- 風格檢查
- 釋出文章
通過以上的釋出流程,不僅可以達到趨近實時的文章更新,還能夠解決以下問題:
- 釋出前確保行文規範,包括標點使用無誤、中英文之間空格等;接到 PR 時也能自動檢查,方便社群貢獻。
- 釋出前對內容預處理,例如去掉內容中的一級標題,插入固定簡介、目錄等。
前 2 步中 GitHub + Travis 的相關文章有很多,比如 這篇部落格,在此暫不詳述;接下來我將重點分析第 3 步的流程。
風格檢查
我使用 這篇博文 中介紹的 Lint-md 專案實現。為了方便 CI 使用,我還特意提交了一個 Pull Request,用於支援 Docker 映象。
具體程式碼非常簡單,只有一行。你可以在 這裡 找到:
docker run --rm -v $dir:/data yuque/lint-md lint-md -c /data/lint-md.json /data/src
熟悉 Docker 的話很容易讀懂;若是不熟悉,你可以閱讀 這篇文章。
其中,$dir
是專案根目錄,lint-md -c /data/lint-md.json /data/src
便是普通的 Lint-md 使用方法。
釋出文章
整套釋出的流程比較複雜,可拆分為以下小步驟:
- 使用長期 Cookies 換取臨時 Cookies
- 獲得 CSRF Token
- 拉取已釋出的文章列表
- 遍歷本地 Markdown 原始檔列表
- 根據本地檔名解析文章標題
- 檢索是否已釋出,並取得文章 ID
- 預處理文章內容(插入簡介、拼接完整標題)
- 將最終內容釋出(建立或更新)
- 迴圈執行 5 - 8 直到遍歷完成
其中,使用粗體標註的 1、2、3、8,需要與伺服器進行通訊;不過我沒有 Laravel-China 的介面,也不好意思麻煩 @Summer。所以乾脆自己動手,豐衣足食 —— 利用 Chrome Developer Tool 的 Network 功能快速抓包,分析整理後使用 PHP 實現一款小工具,名為 learnku-deploy-bot,我暫時稱它為「部署機器人」。
這個機器人可拆分為三大部分,你可以 Git Clone 原始碼後檢視 src
目錄:
Requests
:包含所有的 HTTP 請求定義,基於 Buzz(一個相容 PSR-7、PSR-17、PSR-18 的 HTTP 客戶端)實現,你可以理解為 MVC 中的 Models。Extractors
:包含所有的請求解析器,利用正規表示式等字串處理方式提取文字;你可以理解為 MVC 中的 Views。Commands
:包含所有的 CLI 命令,基於 Symfony 的 Console 擴充套件包實現;在這裡例項化併傳送 Requests,再交給 Extractors 提取需要的資料。你可以理解為 MVC 中的 Controllers。
對於使用者(我自己 :joy:)來說,只需關心公開的 Commands 即可,例如驗證 Session 的 session
,更新文章的 article:update
;資料來源 Requests 和 Extractors 由 Commands 進行統一調配。
由於是個人使用的小工具,所以設計比較簡陋,許多地方並不完善,建議僅作學習使用。
為了提高可複用性,learnku-deploy-bot
並沒有與課程有任何直接的關係;你可以把它理解為一個通用的 Laravel-China CLI 客戶端。
至於剩下的 4、5、6、7、9,也就是和課程直接相關的釋出流程,是使用 Bash 指令碼實現,原始碼 與課程檔案位於同一倉庫;通過該指令碼遍歷文章,並呼叫部署機器人提供的 Commands,完成統一的課程釋出工作。