互聯網時代,人人都在追求產品的快速響應、快速迭代和快速驗證。不管是創業團隊仍是大中型企業,都在探索屬於本身的敏捷開發、持續交付之道。fir.im 團隊也在全面實施敏捷,並推出新持續集成服務— flow.ci ,以幫助企業將開發測試流程自動化,更快速地交付產品。java
4月15日,fir.im CTO 郭揚在「光環國際·2017敏捷春季峯會」帶來了《敏捷工程實踐的基石——持續集成》的技術實踐,從敏捷方法論的角度分享了持續集成流程的質量實踐與 fir.im 團隊的 CI 技術實踐。演講實錄整理以下,但願能帶給你一些思考。git
郭揚,fir.im CTO,曾就任於奔馳戴姆勒創新實驗室,Thoughtworks,索尼移動通訊,網易等公司,擔任 DevLead,負責組建技術團隊,管理項目進度與項目風險,軟件及 DevOps 的架構設計、高併發條件下的性能調優、敏捷教練等工做。程序員
持續集成的概念出如今 2001 年,它實際上是一個 XP 極限編程的工程實踐。那麼持續的是什麼,集成是什麼呢,很是簡單就是「一直不停地集成代碼」。github
持續集成是把代碼頻繁的合併到主幹,經過自動構建的方式驗證軟件的質量,讓團隊快速的響應質量,快速的修復問題,快速的給客戶解決問題,快速地交付更好的軟件質量。web
開發人員對下面的軟件開發場景很熟悉,好比:docker
持續集成是如何緩解這個問題,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,更快速地修復,提高產品質量。那麼,持續集成能給咱們帶來哪些價值?api
從這張圖上能夠看到,持續集成造成一個完美的閉環。經過持續的集成進行不斷地檢查、調整,同時,項目的透明性也獲得了最大的體現。緩存
這是一個常見的持續集成流水線:
在平常的開發過程當中,程序員在本地提交代碼,持續集成流水線要求先作一次本地集成,在本地進行驗證後提交到源代碼管理倉庫中,以後源代碼工具會發出 webhook 觸發到持續集成系統中。當構建/測試完成後,會及時經過釘釘或郵件通知團隊(測試/研發/boss/產品經理)集成狀態,產品經理或項目經理收到通知後會在測試環境作驗收測試,這是一個比較完美的反饋環。
假如測試經過驗收完畢後,持續集成系統會自動觸發部署到類生產環節或測試環境,或由專人手動部署到生產環境。
首先,代碼在遠程進行管理,每一個人都會提交代碼,遠程的代碼倉庫會產生變化,因此在本地集成的時候要求進行代碼合併,以避免出現分支衝突和代碼衝突。其次,不要依賴於持續集成系統給你結果,可能須要 30 分鐘的時間,不要讓開發人員等待,必定要先作本地集成。
再說一個提交的問題,咱們儘可能保證每一次提交都是一個完整的提交,也就是原子提交。
當代碼變更你想建立提交時,這個提交應該儘量的小量,而且包含一個不可分割的特性(feature)、修復(fix)或優化(improved)。
拿每一個產品開發都會遇到的 login 功能開發舉例,當填完的用戶名和密碼傳到數據庫,作完驗證後給用戶返回一個結果。那什麼是一個原子提交?好比,提交驗證一個用戶名,這是一個完整的 feature ;驗證密碼是否符合格式(6位/8位),這也是一個完整的 feature ;當我驗證完用戶名和密碼後再傳到數據庫以後,查詢正確與否,這也是一個完整的 feature ;保證每次提交是一個完整的 feature 或修復了一個 bug,不要代碼寫成半截。
這裏講的是狹義的持續集成系統,一般的 CI 系統收到提交以後會觸發構建,構建會有信息返回好比 commit id 、commit 信息、代碼變動等,收到代碼提交後會觸發自動構建,接着安裝依賴進行編譯,並觸發質量保證流程,也就是說自動化測試集。
自動化測試集包括代碼靜態檢查-單元測試-集成測試-驗收測試-性能測試,也會有壓力測試、迴歸測試、monkey test等等一系列的測試。
接下來,咱們具體講一下 fir.im 團隊如何進行持續集成實踐的。
fir.im 是一個內測分發平臺,咱們也作了一個持續集成 CI 產品-flow.ci。先來看一下咱們正在使用的敏捷環境:
咱們在應用 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 分支會自動部署到測試環境,會跑一個整個自動化測試集,爲何是這樣的構建策略呢?
咱們會作代碼 review ,當 feature 分支提 pr 到 develop 分支上,這樣 develop 分支的構建條件是:當收到 pr 以後,開始跑持續集成。假如部署完成整個測試跑過了產品經理驗收以後,沒毛病了,終於能夠發佈了到 master 分支。
整個團隊的構建頻率能夠看下這張圖:
本地集成的頻率很是高,遠程構建對應的是 feature 分支,會相對低一下。QA 環境對應的是 develop 分支的構建粒度。這樣的構建天天都會產生,因此作完以後不要積壓,必定要保持上線節奏。
kanban + scrum 結合的方式構成咱們每日構建,這是一個總體的構建策略和上線頻率。
羅馬不是一天建成的,持續集成不是一開始就是完美的。每一個開發者心中都有一個比較理想的自動化工做流——持續部署,大概會經歷這幾個演變階段:
這是咱們在用的自動化測試集,下面分別說下靜態檢查分析、單元測試、驗收測試、性能測試的具體用途。
每一個公司都會有本身的代碼規範,代碼靜態分析工具可以保證代碼質量,現成的工具備 java 的 FindBugs,ruby 的 rubocop 等。利用代碼檢查工具能夠幫助團隊發現可重構的地方,輸出產出 – HTML 報告,也會發現潛在 bug;有的代碼檢查工具還會檢查出一些安全漏洞。
這三點是代碼靜態分析最重要的做用。這裏也分享一個 GitHub 地址,列出一些主流語言的代碼分析工具,能夠參考一下。
這裏的 「單元測試」也加上了集成測試,畢竟創業公司要求資源最大化。程序員必定要寫單元測試,要克服開發的慣性思惟,不要甩鍋。下面有一些注意的點和你們分享:
驗收測試是端對端的測試,從收到用戶名密碼到返回結果,是否是咱們所指望的一個值,這是驗收 Acceptance Test,實際上是驗收了整個功能。代碼靜態檢查和單元測試,保證了咱們如何怎麼去寫代碼,驗收測試保證了寫正確代碼,符合開發需求。
flow.ci 作驗收測試比較多,用的是比較流行的框架 Cucumber + Selenium WebDriver,目前支持 3 種數據庫,5 種 git 倉庫,7 種 開發語言跑在 docker 容器雲上,支持 iOS 構建跑在 mac 機器上,要保證這些排列組合正常運行,這是 flow.ci 作驗收測試最核心的價值。
其實,持續集成是一個工做流,當 push 代碼的時候纔會 run 起來,可是 flow.ci 自己系統也有外部依賴的特殊性,會依賴一些第三方的 sevice(好比 GitHub/GitLab 等),驗收測試應該一直保持不斷地運行,也能夠叫持續測試吧。由於咱們永遠不能保證第三方的 api 會不會改變:)
咱們的性能測試作的比較簡單,主要測試 api.由於 fir.im 作 app 的內測分發,咱們須要性能測試保證 app 上傳下載的正常穩定。性能測試是單用戶的,壓力測試是多用戶的,這是二者之間的區別。
性能測試會有一些不肯定性,有不少系統會產生緩存。flow.ci 的性能測試跑在 docker 上,是一個乾淨獨立的環境,須要讓系統預熱運行一下。Locust/JMeter/LoadRunner是目前比較流行的性能測試工具。 flow.ci 目前用的是 locust,能夠參考一下。
咱們認爲一個好的持續集成系統也要作到項目進度的透明化,最傳統的方式是發送相關的郵件,但實質上有幾我的去看呢?爲此咱們採購了一個大的屏幕來解決這個問題,用來時刻提醒團隊的某個構建結果。固然也能夠用閃爍燈或音頻的方式。
說到數據統計分析,整個 ci 流程跑下來產生的不少數據也很是有挖掘的價值。好比,對於代碼靜態分析有多少 Offence、Risk、Bug,對於單元測試有失敗率、測試覆蓋率;對於驗收測試或性能測試有多少的失敗率,這些數據都有可能成爲衡量一個程序員的標準。
CI 就像蓋樓房的腳手架同樣,沒有腳手架就沒辦法蓋出一個足夠高的樓,沒有 CI 就沒法交付質量足夠好的軟件!
歡迎分享你的觀點。