為什麼要做
今年4月份,開始自己的第二份工作,習慣了老東家如絲般的釋出體驗,一下子感覺來到了“原始社會”。 首先這是一篇長文,主要介紹自己在做自動釋出這個過程的一些思考。
引用玉伯的Web研發模式演變來說,現在我們處於 - Web1.0時代:
- 前後端程式碼耦合
- java環境對前端過於複雜
- 缺乏工具和規範,程式碼難維護
- 內嵌程式碼:html內嵌js,jsp內嵌java邏輯
- 頁面級程式碼,程式碼疊加:單檔案js隨意2000行以上
- 人工手動釋出,變更麻煩
遇到這種情況,首先會想到的肯定是前後端分離。但考慮到目前的人員、技術儲備情況,直接過渡到基於NodeJS的全棧式開發,阻力大,週期長,很可能會難產。
而我們首要要解決的問題
是:
- 前後端職責清晰
- 提升開發效率、體驗
- 自動化釋出
所以我們暫時先做到前後端物理分離
,大致如 - Web2.0時代
- 程式碼倉庫分離,分開維護
- 釋出部署分離
- 模板由前端維護,在瀏覽器渲染,後端只提供基礎頁面容器(視情況而定)
- 互動性、非SEO頁面:後端負責介面,前端負責展現,通過介面讀取資料在瀏覽器端渲染
- 需要SEO的頁面:相關模板還是放在後端,但是會減少業務邏輯
目標
我們先從開發、釋出流程來看我們最終希望的結果是什麼,然後再分析如何完成這一目標
開發流程
- 專案遵循流程:需求評審 -> 視覺評審 -> 介面約定 -> 需求評估 -> TC評審 -> 並行獨立開發 -> 聯調 -> 測試 -> 釋出
- 開發過程前後端明確任務,獨立並行開發
釋出流程
- 釋出要嚴格遵守流程,測試稽核通過才能上線
- 整個流程只需簡單釋出指令,所有的編譯構建、同步伺服器的事情交給任務去做(後面我們會提到釋出任務需要做哪些事情)
分離需要做什麼
- 程式碼分離 使用git來做程式碼版本管理,申請新應用維護前端程式碼
- 使用webpack,做模組管理 程式碼分離後,我們可以使用目前前端主流的框架、工具,搭建友好的開發環境、流程
- 分離之後,請求後端介面,聯調、debug,都需要設定代理
- 自動化釋出
- 伺服器配置 考慮如何部署前端程式碼
自動化釋出
首先聊一下一般釋出的流程:
- 程式碼提交
- 打包構建
- 備份伺服器當前檔案 - 回滾使用
- 將構建結果同步到伺服器目錄
- 合併程式碼到Master - 保證後續的程式碼都是最新的
這是一些純體力活,要保證步驟順序和正確性,容易出問題,而且沒有記錄和日誌,所以一般做許可權控制,釋出個普通需求還要找對應的同學釋出,變更麻煩
所以釋出必須自動化
,網上搜前端自動化釋出,大多數的結果都是Jenkins + githook (
Jenkins+github 前端自動化部署)
其核心原理主要是通過
- 提交程式碼觸發webhook push event
- Jenkins監聽到webhook post請求,執行編寫好的指令碼構建、同步伺服器(主要依賴於指令碼)
但是如果我想要檢視釋出記錄、回滾、控制釋出流程,看起來Jenkins就幫不上忙了(可能有對應的外掛,沒深究)
同樣的釋出指令碼,用node也能執行,所以我們打算使用node來寫一個釋出整合服務
來代替Jenkins,它可以做更細緻的控制:
- 提交程式碼不代表釋出,可能只是程式碼備份,釋出指令才代表釋出
- 可以生成釋出記錄,在釋出平臺展示,方便檢視和回滾
- 實時反饋釋出流程資訊
- 控制釋出流程,加入稽核、CodeReview,讓釋出更安全
所以我們的釋出自動化主要做三個東西
- CLI:讓熟悉命令列的同學,git push後馬上就可以敲命令釋出(建立新發布、釋出)
- 釋出平臺:檢視釋出記錄,釋出,稽核,檢視日誌,回滾
- 整合釋出服務:執行釋出指令碼,同步伺服器,備份近期釋出檔案(快速回滾),反饋釋出資訊,釋出控制
CLI
該CLI是一套標準的前端開發生命週期命令,通過幾個子命令去完成前端開發流程的各個任務,包含了:
- init:初始化專案結構,類似於
vue-cli init
,不過比較入門簡單(因為暫時業務的體量並不需要頻繁建立新專案) - dev:啟動開發除錯服務,主要是
npm run dev
,也不是重點 - publish:釋出專案程式碼,執行publish後將執行專案倉庫中對應開發分支下的程式碼釋出任務。在雲端構建後的程式碼最終會發布到對應的環境(SIT、UAT、生產)。
關於CLI的開發參考 - 如何用Node開發CLI 主要是:commander + inquirer
從此釋出就變成了一個命令的事
釋出平臺
釋出平臺提供了比CLI更多的功能:
- 檢視釋出記錄
- 檢視日誌
- 回滾
- 釋出管理、控制
整合釋出服務
到了重頭戲,這裡就介紹一些概念
釋出流程
為什麼在雲端構建釋出
首先,最終程式碼部署到伺服器肯定都是通過scp等命令來同步檔案到伺服器,因為許可權問題,通過雲端統一管控是比較靠譜的。
然後,每個人的機器環境都不一樣,有可能在A這構建成功,在B那卻構建失敗(比如A新增了一個依賴,但沒有儲存dependencies),所以以統一的環境來編譯構建,可以避免因為環境問題引起的構建問題。
最後,需要一個地方去統一管理髮布記錄,避免釋出衝突,記錄釋出日誌,方便回滾操作等。
分支管理
每個人都基於Master拉取自定義分支開發,最終通過釋出自動同步到Master分支,保證開發時都是基於最新的線上程式碼,同時釋出時做衝突檢查,保證釋出安全。
釋出過程的分支變化如下:
釋出管理
在整個釋出過程,我們的程式碼要通過日常、預發測試才能最終上線,這個過程是需要佔用對應伺服器並保持穩定,需要避免出現其他同學釋出覆蓋的情況,所以我們使用MongoDB來維護釋出記錄
,實現釋出控制和流程控制
釋出控制
當指定釋出環境有一個專案釋出時,該環境被佔用,其他專案釋出會提示有其他專案釋出,聯絡對應的釋出同學
,雙方根據重要性來決定是否退出釋出讓後來的專案先上
流程控制
為了保證最終上線的程式碼是正確執行的,整個過程需要測試和Code Review,必須通過測試、稽核
才能進入下一個環節
釋出反饋
釋出指令碼需要執行上面提到一系列的過程,這需要一個等待的過程,我們需要實時給釋出同學提供釋出反饋(釋出流程、成功與否),並將相關資訊儲存到日誌。所以釋出過程通過soket.io建立socket連結,整合釋出服務有任何流程變化都會反饋
同步伺服器
同步伺服器可以使用 scp 或 rsync 命令,關於它們的介紹和不同看這個
這兩個命令通過ssh同步,都需要在執行命令後輸入密碼,所以需要配合expect來實現自動同步
最終整個服務選用了:express + socket.io + mongodb,這裡就不贅述了