flow.ci 持續整合技術實踐
網際網路時代,人人都在追求產品的快速響應、快速迭代和快速驗證。不論是創業團隊還是大中型企業,都在探索屬於自己的敏捷開發、持續交付之道。fir.im 團隊也在全面實施敏捷,並推出新持續整合服務 —flow.ci(http://u6.gg/adck),以幫助企業將開發測試流程自動化,更快速地交付產品。
這次分享由 fir.im CTO 郭揚,從敏捷方法論的角度來講解 fir.im 團隊的 CI 技術實踐,希望能帶給你一些思考。
郭揚,fir.im CTO,曾就職於賓士戴姆勒創新實驗室,Thoughtworks,索尼行動通訊,網易等公司,擔任 DevLead,負責組建技術團隊,管理專案進度與專案風險,軟體及 DevOps 的架構設計、高併發條件下的效能調優、敏捷教練等工作。
持續整合做什麼
持續整合的概念出現在 2001 年,它其實是一個 XP 極限程式設計的工程實踐。那麼持續的是什麼,整合是什麼呢,非常簡單就是“一直不停地整合程式碼”。
持續整合是把程式碼頻繁的合併到主幹,通過自動構建的方式驗證軟體的質量,讓團隊快速的響應質量,快速的修復問題,快速的給客戶解決問題,快速地交付更好的軟體質量。
我們為什麼要做持續整合
開發人員對下面的軟體開發場景很熟悉,比如:
- 場景一:開發了新功能,老功能產生新的 bug;
- 場景二:修好一個 bug,又產生其他 bug,甚至出現連環 bug;
- 場景三:出現的 bug 比較多,修改程式碼要很謹慎,不熟悉的模組一般不敢動,怕引起問題;
持續整合是如何緩解這個問題的,Martin Fowler 大師曾經說過:
“Continuous Integration doesn’t get rid of bugs, but it does make them dramatically easier to find and remove.” — Martin Fowler
如上面所說,持續整合不能消除 bug ,但能更容易地發現 bug且更快速地修復,提升產品質量。那麼,持續整合能給我們帶來哪些價值呢?
從這張圖上可以看到,持續整合形成一個完美的閉環。通過持續的整合進行不斷地檢查、調整,同時專案的透明性也得到了最大的體現。
fir.im 如何進行持續整合實踐
這是一個常見的持續整合流水線:
在日常的開發過程中,程式設計師在本地提交程式碼,持續整合流水線要求先做一次本地整合,在本地進行驗證後提交到原始碼管理倉庫中,之後原始碼工具會發出 webhook 觸發到持續整合系統中。當構建/測試完成後,會及時通過釘釘或郵件通知團隊(測試/研發/boss/產品經理)整合狀態,產品經理或專案經理收到通知後會在測試環境做驗收測試,這是一個比較完美的反饋環。
假如測試通過驗收完畢後,持續整合系統會自動觸發部署到類生產環節或測試環境,或由專人手動部署到生產環境。
為什麼要做本地整合
首先,程式碼在遠端進行管理,每個人都會提交程式碼,遠端的程式碼倉庫會產生變化,所以在本地整合的時候要求進行程式碼合併,以免出現分支衝突和程式碼衝突。其次,不要依賴於持續整合系統給你結果,可能需要 30 分鐘的時間,不要讓開發人員等待,一定要先做本地整合。
如何做版本提交
再說一個提交的問題,我們儘量保證每一次提交都是一個完整的提交,也就是原子提交。
當代碼變動你想建立提交時,這個提交應該儘可能的小量,並且包含一個不可分割的特性(feature)、修復(fix)或優化(improved)。
拿每個產品開發都會遇到的 login 功能開發舉例,當填完的使用者名稱和密碼傳到資料庫,做完驗證後給使用者返回一個結果。那什麼是一個原子提交?比如,提交驗證一個使用者名稱,這是一個完整的 feature ;驗證密碼是否符合格式(6位/8位),這也是一個完整的 feature ;當我驗證完使用者名稱和密碼後再傳到資料庫之後,查詢正確與否,這也是一個完整的 feature ;保證每次提交是一個完整的 feature 或修復了一個 bug,不要程式碼寫成半截。
持續整合系統
這裡講的是狹義的持續整合系統,通常的 CI 系統收到提交之後會觸發構建,構建會有資訊返回比如 commit id 、commit 資訊、程式碼變更等,收到程式碼提交後會觸發自動構建,接著安裝依賴進行編譯,並觸發質量保證流程,也就是說自動化測試集。
自動化測試集包括程式碼靜態檢查-單元測試-整合測試-驗收測試-效能測試,也會有壓力測試、迴歸測試、monkey test等等一系列的測試。
接下來,我們具體講一下 fir.im 團隊如何進行持續整合實踐的。
fir.im 的敏捷環境
fir.im 是一個內測分發平臺,我們也做了一個持續整合 CI 產品-flow.ci。先來看一下我們正在使用的敏捷環境:
- Trello 看板;
- 三個環境(類生產環境,測試環境,生產環境);
- CI 工具(Jenkins/flow.ci)
說一下 Git 分支管理
我們在應用 3 個分支 —— master/develop/feature 分支,對 feature 命名會有一些要求,持續整合系統一定會反饋到 trello 的 kanban 裡,所以對於 feature 分支我們也有這樣的命名 feature/fci-{card number} 以方便區分。
多分支如何做頻繁地持續整合?
master 分支,即線上分支。線上通常會有一些 hotfix, 任何產品都不可能避免線上的 bug ,這些 bug 需要在 master 分支進行修復,修復完成後持續整合系統會告知已上線,收到團隊反饋,這些程式碼會要求更新在 develop 分支上,之後所有團隊也會收到相關通知,那麼 feature 分支會有變化嗎?答案是肯定的,因為頻繁的整合可以防止程式碼偏離。這就是我們多分支構建的策略。
還有一個策略——不同的分支不同的構建,持續整合系統跑完整個流程會很長,所以在 feature 分支頻繁度會比在本地構建要高一些,但是也沒有那麼高。為了保證持續整合系統能快速地收到反饋,需要在 feature 分支上做一些定製的 workflow ,所以我們做了程式碼靜態分析和單元測試。
當 feature 分支的 card 做完之後(scrum 中 done 的含義是指測試驗收完畢),整合到 develop 分支,develop 分支會自動部署到測試環境,會跑一個整個自動化測試集,為什麼是這樣的構建策略呢?
本地整合的頻率非常高,遠端構建對應的是 feature 分支,會相對低一下。QA 環境對應的是 develop 分支的構建粒度。這樣的構建每天都會產生,所以做完之後不要積壓,一定要保持上線節奏。
kanban + scrum 結合的方式構成我們每日構建,這是一個整體的構建策略和上線頻率。
fir.im 的持續整合系統演變過程
羅馬不是一天建成的,持續整合不是一開始就是完美的,每個開發者心中都有一個比較理想的自動化工作流——持續部署,大概會經歷這幾個演變階段:
- 最初階段:提交程式碼-自動部署;
- 一般進階:提交程式碼-程式碼靜態分析-自動部署,最簡單先再加入程式碼靜態分析;
- 高階進階:提交程式碼-程式碼靜態分析-自動化測試集-自動部署;
這是我們在用的自動化測試集,下面分別說下靜態檢查分析、單元測試、驗收測試、效能測試的具體用途。
Step 1. 靜態程式碼分析
每個公司都會有自己的程式碼規範,程式碼靜態分析工具能夠保證程式碼質量,現成的工具有 java 的 FindBugs,ruby 的 rubocop 等。利用程式碼檢查工具可以幫助團隊發現可重構的地方,輸出產出 – HTML 報告,也會發現潛在 bug;有的程式碼檢查工具還會檢查出一些安全漏洞。
Step 2. “單元測試”
這裡的 “單元測試”也加上了整合測試,畢竟創業公司要求資源最大化。程式設計師一定要寫單元測試,要克服開發的慣性思維,不要甩鍋。下面有一些注意的點和大家分享:
- 測試異常——不僅僅測試正確情況,也要主動測試異常;
- 減少耦合——保證獨立的可測試性;
- 功能分離——單元測試流太長,超過 20 分鐘的話要詳細想一下如何將功能單獨拆開,效率更高;
- 測試=需求——從測試程式碼看到每個 class 是幹什麼的,同時出現 bug 時,第一時間是看測試,想想如何從測試中復現;
Step 3. 驗收測試
驗收測試是端對端的測試,從收到使用者名稱密碼到返回結果,是不是我們所期望的一個值,這是驗收 Acceptance Test,其實是驗收了整個功能。程式碼靜態檢查和單元測試,保證了我們如何怎麼去寫程式碼,驗收測試保證了寫正確程式碼,符合開發需求。
flow.ci 做驗收測試比較多,用的是比較流行的框架 Cucumber + Selenium WebDriver,目前支援 3 種資料庫,5 種 git 倉庫,7 種 開發語言跑在 docker 容器雲上,支援 iOS 構建跑在 mac 機器上,要保證這些排列組合正常執行,這是 flow.ci 做驗收測試最核心的價值。
其實,持續整合是一個工作流,當 push 程式碼的時候才會 run 起來,但是 flow.ci 本身系統也有外部依賴的特殊性,會依賴一些第三方的 sevice(比如 GitHub/GitLab 等),驗收測試應該一直保持不斷地執行,也可以叫持續測試吧。因為我們永遠不能保證第三方的 api 會不會改變。
Step 4. 效能測試
我們的效能測試做的比較簡單,主要測試 api.因為 fir.im 做 app 的內測分發,我們需要效能測試保證 app 上傳下載的正常穩定。效能測試是單使用者的,壓力測試是多使用者的,這是兩者之間的區別。
效能測試會有一些不確定性,有很多系統會產生快取。flow.ci 的效能測試跑在 docker 上,是一個乾淨獨立的環境,需要讓系統預熱執行一下。Locust/JMeter/LoadRunner是目前比較流行的效能測試工具。 flow.ci目前用的是 locust,可以參考一下。
持續整合的視覺化、資料分析
我們認為一個好的持續整合系統也要做到專案進度的透明化,最傳統的方式是傳送相關的郵件,但實質上有幾個人去看呢?為此我們採購了一個大的螢幕來解決這個問題,用來時刻提醒團隊的某個構建結果。當然也可以用閃爍燈或音訊的方式。
說到資料統計分析,整個 CI流程跑下來產生的很多資料也非常有挖掘的價值。比如,對於程式碼靜態分析有多少 Offence、Risk、Bug,對於單元測試有失敗率、測試覆蓋率;對於驗收測試或效能測試有多少的失敗率,這些資料都有可能成為衡量一個程式設計師的標準。
結語
CI 就像蓋樓房的腳手架一樣,沒有腳手架就沒辦法蓋出一個足夠高的樓,沒有 CI 就無法交付質量足夠好的軟體!
文章來自微信公眾號:逼格運維說