add by zhj: 先說一下持續集成的定義,這是ThoughtWorks首席科學家Martin Fowler在《持續集成》第二版中給出的,「持續集成是一種軟件開發實踐。在持續集成中,團隊成員頻繁集成他們的工做成果,通常每人天天至少集成一次,也能夠屢次。每次集成會通過自動構建(包括自動測試)的驗證,以儘快發現集成錯誤。許多團隊發現這種方法能夠顯著減小集成引發的問題,並能夠加快團隊合做軟件開發的速度。」html
這裏是《持續集成》第二版的一些簡單介紹:http://www.infoq.com/cn/articles/ci-theory-practice服務器
原文:http://www.infoq.com/cn/news/2011/01/ci-check-in-dance分佈式
衆所周知,敏捷軟件開發方法中有多種最佳實踐,既有管理方面的,也有技術方面的。在嘗試敏捷之初,並非每一個團隊都能使用所有最佳實踐,也不是每一個實踐都能在短期內見效。但其中有一種最佳實踐倒是團隊的必選,那就是持續集成,但這並不表示持續集成很是容易。ide
儘管Thoughtworks的首席科學家Martion folwer 爲「持續集成 」下了定義,但因爲自身背景與經歷的不一樣,每一個人對其都有不一樣的理解。從狹義上講,持續集成能夠認爲是一種基於某種或者某些變化對軟件系統進行的常常性的構建活動(注:這裏的構建活動不只指編譯打包工做,還包含各種自動化測試、部署及發佈活動)。然而,它忽視了一點,即:任何實踐中都應該包含「與人的交互」這一因素。所以,從廣意上講,持續集成應該是軟件開發團隊在上述活動的約束下所採用的整個開發流程及活動。它強調開發團隊與持續集成系統之間的互動性。咱們既見過持續集成作得很是成功的團隊,也見過效果不佳的持續集成,甚至失敗的案例。工具
那麼,到底如何從持續集成中獲得最大的收益呢?這要從持續集成所涉及的諸多方面進行分析,並根據團隊具體狀況(好比團隊規模、人員組成以及是否爲分佈式團隊 等)及所開發軟件自身的特色(是企業應用軟件,仍是中間件?是嵌入式軟件,仍是互聯網產品等)制定實踐策略與實現步驟。本專欄將與你們共同探討與持續集成、持續部署及持續交付相關的方法、工具與經驗。做者本人在Thoughtworks公司曾參與的一款持續集成與發佈管理產品Go的交付和對外諮詢服務爲專欄提供了頗有素材,同時感謝肖鵬 、 李彥輝 、胡凱 、李劍等對欄目內容的支持和幫助。測試
在軟件開發中,持續集成實踐可以解決的問題是儘早的集成和儘早的反饋。所以,儘管目前流行的全部版本控制工具都提供了分支/合併功能,但在少於20人的團隊中實現持續集成的話,推薦使用Single Branch開發策略。這樣會減小多分支開如在合併時的開銷。另外,因爲理想狀況下,每一個分支都須要有專屬的持續集成環境(包括持續集成服務器、構建環境和測試環境等),因此Single Branch也減小了對持續集成環境的需求量(當編譯時間較長或測試用例較多時,這個因素的影響尤爲重要)。ui
當團隊完成最初搭建持續集成服務器,編寫好一鍵式編譯和測試腳本工做後,就須要考慮如何利用持續集成環境高效地進行團隊協做開發了。必定有人會問:版本控制
「多人同時在一個分支上開發的話,每一個人提交時都要合併代碼,不是更浪費時間嗎?」htm
這個問題也正是持續集成指望解決的問題。每當開發人員提交代碼時,就是其與其餘開發人員工做成果的一次集成。若是每一個人都可以頻繁提交代碼,那麼代碼集成的頻率就會提升,在持續集成的有力支持下,代碼中潛在的問題就會更早地暴露出來(好比代碼編譯連接問題,自動化測試失敗反映出來的代碼功能問題,或需求理解不一致等問題),以便團隊儘早解決之。中間件
固然,持續集成所鼓勵的頻繁提交併非指那種僅將版本控制庫當成備份工具,無約束的「隨意」提交,還須要團隊開發流程約束的。下面咱們來一同探討「持續集成環境中的團隊開發流程是什麼樣的」。
讓咱們先設想一個軟件開發場景。
故事的主人公叫Joe,他打算寫一個遊戲,因此用Subversion創建了一個版本控制庫用於保存代碼,而後就動手寫代碼了。Joe的開發流程是這樣的。
如圖1所示。
「每次在本地手工運行自動化測試太麻煩了,」Joe想到,「這種重複的工做爲何不讓機器來作呢」。
因而,Joe上網查了一下,發現持續集成工具是作這個事情的,就找來一臺舊機器,用CruiseControl搭建了一個持續集成服務器。他的開發流程也變爲:
兩週後,遊戲初見原型,Joe向他的幾個朋友介紹了他的遊戲建立,他們都很是喜歡,所以也加入了遊戲開發。麻煩很快就出現了。持續集成服務器中構建結果常常失敗,因此每次檢出代碼後都要作問題清理工做。因而,Job與朋友們坐下來討論如何解決這個問題。
Alice說:「咱們每一個人都拉一個獨立分支,當每一個人的功能開發完成之後,再合併到一塊兒不就好了嗎?」
Joe不一樣意這樣的作法。「遊戲的需求還不明晰,要常常合在一塊兒看一下效果。因此仍是在同一個分支上開發吧。下面,咱們討論一下如何讓這種失敗少一些吧。」
因而,他們花了點兒時間,發現有兩個主要緣由致使失敗。
Joe提出,開發流程應該變成如圖3所示:
但是,Alice提出反對意見。她認爲:「既然本地已經運行了測試,爲何還要在持續集成服務器上再次運行呢?」
Joe解釋到:「主要是由於咱們每一個人的本地環境都不徹底相同,極可能出現‘它在個人機器沒有問題呀’的這個現象,因此仍是要在獨立的持續集成服務器上再運行一次。」
所以,你們就這麼決定了。
四周後的一天,Joe花了很長時間完成了某個新功能後,打算提交了。因而他把分支當前的代碼與其本地代碼進行了一次合併。而後運行了本地測試,但測試失敗了。他用了很長時間來定位該問題是在他本身修改的功能裏,仍是在被合入的代碼中。這讓他對提交流程進行了反思。
「要是在合入他人代碼以前,可以先運行一次本地測試,驗證一下個人代碼沒問題就行了,反正本地測試所花的時間也不長。」
因而,他把這個想法告訴了其餘人,最後大部分人都贊成這麼作。因而,其提交流程就變成了這樣:?
這個過程就被稱爲「Check-in Dance」。
Alice還說道:「咱們在從主分支上檢出代碼時,必定是那個經過持續集成驗證的最新版本。這樣能夠避免檢出的代碼就是有問題的,而影響本身本地的代碼。」整個過程如圖4所示。
過了幾天,有人把你們叫到了一塊兒,此次是Alice。她說:
「我今天遇到一個問題。我提交代碼以後,正等着持續集成服務器返回結果呢,Bob就提交代碼了。幸虧我提交的代碼經過了測試,不然的話,我就要在Bob的代碼之上修復啦。因此,我建議咱們須要設立一個提交令牌,只有拿到這個提交令牌的人才能提交。也就是說,當一我的作完本地測試以後,去拿這個令牌。拿到以後,再進行代碼合併、本地測試和提交。提交之後當持續集成服務器返回成功經過的結果時,才能交還令牌。這樣就不會出現我和Bob這種狀況了。」
可Bob並不一樣意這樣的作法,「此次沒有出什麼問題,爲何還要這麼作呢?」
此時,Joe把話接了過來,說道:「Alice的這個建議很好,我已經趕上過一次這樣的事情了,那次測試失敗之後,我花了很長時間才發現問題並不在個人提交中,而是在Mary的提交中。我把它修復後,又作了一次提交。」因爲大多數人都贊成這麼作,所以團隊決定試一試。由於目前測試運行時間很短,因此提交和集成工做沒有遇到什麼瓶頸。提交流程如圖5所示。
彷佛事情到這裏就結束了。然而,這個遊戲被某投資公司看中,決定作更大的投入,招更多的開發人員,讓它成爲一個開放遊戲平臺。那麼,接下來Joe與他的朋友們還會遇到哪些問題呢?
感謝張凱峯對本文的策劃及審校。