search
尋找貓咪~QQ 地點 桃園市桃園區 Taoyuan , Taoyuan

flow.ci 持續集成技術實踐

持續集成做什麼

持續集成的概念出現在 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;有的代碼檢查工具還會檢查出一些安全漏洞。

這三點是代碼靜態分析最重要的作用。這裡也分享一個 GitHub 地址(https://github.com/mre/awesome-static-analysis),列出一些主流語言的代碼分析工具,可以參考一下。

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 就無法交付質量足夠好的軟體!



熱門推薦

本文由 yidianzixun 提供 原文連結

寵物協尋 相信 終究能找到回家的路
寫了7763篇文章,獲得2次喜歡
留言回覆
回覆
精彩推薦