[原創(chuàng)] “亂彈系列”之持續(xù)集成工具 -- Simpler chronicle of CI(Continuous Integration)

引言

有句話說有人的地方就有江湖,同樣,有江湖的地方就有恩怨。在軟件行業(yè)歷史長河(雖然相對于其他行業(yè)來說,軟件行業(yè)的歷史實(shí)在太短了,但是確是充滿了智慧的碰撞也是十分的精彩)中有一些恩怨情愁,分分合合的小故事,比如類似的有,從一套代碼發(fā)展出來后面由于合同到期就分道揚(yáng)鑣,然后各自發(fā)展成獨(dú)門產(chǎn)品的Sybase DB和微軟的SQL Server;另外一個例子是,當(dāng)時JBPM的兩個主要開發(fā)的小伙伴離開當(dāng)時的RedHat,在JBPM基礎(chǔ)上自立門戶新創(chuàng)建的Java工作流管理軟件Activiti,等等。在持續(xù)集成工具龍頭老大這個寶座,也曾經(jīng)發(fā)生過合作合并,吵架分家,再對著干的事情,今天分享一下這前前后后有趣的故事。

DevOps

首先,防止先入為主,以為大家都知道這個那個的。先普及下相關(guān)背景知識,如果已經(jīng)了解的同學(xué)可以跳過。目前在軟件工程領(lǐng)域已經(jīng)火了好幾年的DevOps領(lǐng)域,核心的模塊就是CI與'CD',即Continuous Integration與Continuous Deployment,也就是持續(xù)集成與持續(xù)部署,這個對于處于敏捷開發(fā)環(huán)境下尤其是互聯(lián)網(wǎng)等需要高速迭代是個核心的功能,可以說沒有CI,就不可能達(dá)到像Google或者Facebook這些一天有多個release的情況。

CI

CI(Continuous Integration) 持續(xù)集成起源于 XP(極限編程)與 TDD (Test Driven Develop)也就是以測試驅(qū)動的開發(fā)模式,是防止出現(xiàn)所謂的'集成地獄',即防止程序員在正常編碼工作中,需要寫新的業(yè)務(wù)邏輯,添加新的代碼,但是同時也新引入了bug。CI會持續(xù)的(重復(fù)的)進(jìn)行一些小的工作,比如不斷的跑測試用例,去掃描代碼等工作。以減輕或者很大程度上避免這個個新引入的bug對軟件交付質(zhì)量引起的負(fù)面影響。目前,市場上有很多的CI解決方案及工具,常用的如下幾個,


CI 的進(jìn)化史

世界上本來沒有CI,用的人多了也就成就了CI。本來軟件工程里是沒有這個概念的。最開始,就像下圖中描述的帝國時代里,整個社會節(jié)奏平穩(wěn)而緩慢,每個程序員自己做自己的開發(fā),然后各自把自己的工作上次(提交),整個團(tuán)隊把代碼放在一起,然后整個人過來,啟動make/build,后面有個人去把編譯好的代碼放到測試機(jī)器上,每個程序員自己或者單獨(dú)的測試團(tuán)隊去測試程序,如果沒有問題,另外的人去發(fā)布到生產(chǎn)環(huán)境上。這些都是或多或少由人手工去做的。

但是就像很多人類的發(fā)明就是為了人類"偷懶"一樣,CI慢慢在一些想偷懶的牛人腦子里形成。這其中就有Kent Beck (多說一句,這個現(xiàn)在工作于Facebook的牛人,還發(fā)明創(chuàng)造了很多到現(xiàn)在還在流行的東西,比如Agile敏捷開發(fā),以JUnit為代碼的xUnit測試?yán)砟?,TDD測試驅(qū)動開發(fā)等等),在上個世紀(jì)最后幾年,Kent Beck創(chuàng)造了XP(注意這個不是Bill的那個XP操作系統(tǒng)),是eXtreme Programming,即極限編程。雖然現(xiàn)在看起來極限編程有很多很詭異不太現(xiàn)實(shí)的方式,比如兩個程序員坐在一起,使用一臺電腦一起寫一段程序等天馬行空的想法。但是其中一個理念就是“持續(xù)集成”(CI)。以此理念,后面出現(xiàn)了使用各種語言寫的CI的工具,其中的老大是CruiseControl。這個就像是上圖中那個跑車一樣,在當(dāng)時整個緩慢的大環(huán)境下其提升工作效率的效果十分的吸眼。

到了2005年,當(dāng)時就職于Sun(沒錯,就是創(chuàng)造了Java的那家公司)的一個叫川口浩介(Kohsuke Kawaguchi)的日本人,就是上圖這位“霓虹”的小哥,敢于冒險,重新“發(fā)明輪子”,不顧如日中天的CruiseControl,設(shè)計并開發(fā)了一個新的持續(xù)集成的軟件,起名叫做Hudson。它提供了很多強(qiáng)大的功能,比如提供插件機(jī)制,這樣就使其幾乎集成了市面上所有的源代碼管理工具,比如CVS, Subversion, Git, Perforce等。除此之外,它還提供了界面的擴(kuò)展能力,另外還支持基于Apache Ant 和 Apache Maven的項目,除了xNix,還支持Windows環(huán)境等一眾強(qiáng)大功能。聽起來這么牛逼的工具,很快,在大約2007年的時候Hudson已經(jīng)超越CruiseControl。然后在2008年5月的JavaOne大會上,Hudson獲得了開發(fā)解決方案類的Duke's Choice獎項。從此,小弟翻身做大哥,Hudson成為CI的代名詞。其主要開發(fā)者 Kohsuke Kawaguchi 還獲得了Google-O'Reilly Open Source Award。他后來也不用自己苦逼的寫代碼了,只要到處受邀去演講做是如何受什么啟發(fā)創(chuàng)造并發(fā)明了這么好的工具,造福大批程序員。再后來他還離職創(chuàng)立了公司CloudBees,出任CEO,迎娶白富美,走上人生新巔峰。(也難怪上圖中他笑的如此開心)

一切看起來都是那么美好。但是,天有不測風(fēng)云,在2009年6月,Oracle收購Sun,所有人都蒙逼了,是不是寫反了?一個傳統(tǒng)數(shù)據(jù)庫的公司收購了在Java及開源老大的Sun???!這個消息公布之后,兩個公司內(nèi)部各個產(chǎn)品及項目就被整合,調(diào)整,Hudson也不例外。這也就算了,反正誰給錢不是干活哪,但是在2010年9月,Oracle竟然暗戳啜的把Hudson變成了注冊商標(biāo)。2010年11月,Hudson社區(qū)的核心開發(fā)人員發(fā)現(xiàn)了這個事情,他們覺得這對于一個一直標(biāo)榜自己是開源CI領(lǐng)域“誠實(shí)可靠小郎君”的Hudson來說是個玷污。雙方進(jìn)行了會談,過程不太友好,然后就不出意料的談崩了。2011年圣誕節(jié)過后,幾個禿頂?shù)拇笫逵X得不要再跟Oracle的律師在這里瞎扯淡了,他們決定自立門戶,自己起個新的名字叫Jenkins。然后湊錢注冊網(wǎng)址,買服務(wù)器,列出下面的清單,統(tǒng)統(tǒng)改名,

然后把代碼fork出一份來(這里好笑的是Hudson與Jenkins都聲稱對方是自己這里的子分叉,都跟孩子斗氣似的),即便分出來了,但是絕大部分還是基于之前的核心代碼,所以你可以通過下圖看到Hudson與Jenkins的界面都十分類似。

Jenkins的界面

Hudson的界面

但是有一個值得注意的地方就是兩個系統(tǒng)的logo,其中Hudson是一個高傲的老頭子,而Jenkins是一個謙卑為你服務(wù)的老頭子。


分家之后,Hudson有Oracle和Sonatype's corporate的支持和Hudson的注冊商標(biāo),而Jenkins擁有的是大多數(shù)的核心開發(fā)者,社區(qū),和后續(xù)更多的commit。比如下圖是分家之后兩個軟件的對比。兩個軟件的活躍程度十分明顯,Jenkins遙遙領(lǐng)先。

CI持續(xù)集成的工作原理

上面講完了主流CI工具的江湖故事后,我們來看下這類工具本身的技術(shù)情況。其實(shí)這類工具的工作原理大同小異,比如下圖,一個典型的用例是

  • 程序員在本地開發(fā)完成后把代碼提交到VCS (Version Control System)比如SVN, Git, Perforce, RTS等
  • CI工具發(fā)現(xiàn)有新的check in 自動啟動去抓取最新的代碼。當(dāng)然這里有很多不同的配置,比如除了主動監(jiān)視VSC外,還可以使用CRON等配置按時啟動,比如每隔一個小時啟動一次,或者每兩次check in 啟動一次,等等很多的策略。
  • CI可以配置使用集群的編譯機(jī)器,去選擇最合適的機(jī)器(有不同的策略,比如找到最清閑或者離代碼文件距離最近的機(jī)器等)來編譯源代碼
  • 根據(jù)不同的配置,CI有可能會調(diào)用配置好的測試用例,如果測試失敗,根據(jù)策略(比如少于幾個錯誤就先忽略)要么通知用戶,要么繼續(xù)跑測試用例
  • 根據(jù)配置,CI可能會去執(zhí)行其他操作,比如靜態(tài)源代碼分析,如代碼有沒有不符合公司安全要求,把連接密碼寫在代碼里面等等,還有比如生成文檔,測試報告,等。
  • 如果所有定義好的jobs跑完,去生成最終報告并送給用戶
  • 生成一些分析報表,比如最近成功率,最近哪些程序員造成的錯誤最多等等。
  • 一些高級的CI,比如Jenkinsg還支持自定義擴(kuò)展,也會去按配置去執(zhí)行。
jenkins-plugin-diagram-saci

這其中如果任何一步出現(xiàn)了錯誤,比如某個程序員在提交代碼時忘記同時提交一個新寫的類,造成失敗,首先在CI(比如Jekins,或者Travis)上會顯示錯誤 (比如下圖),同時還可以配置CI工具會發(fā)出郵件提醒,甚至可以根據(jù)提交信息智能的顯示出來是哪個程序員搞砸的。

總而言之,這個自動化的過程就像是一個可以配置的流水線,在其上可以添加任意個不同類型的節(jié)點(diǎn),在每個節(jié)點(diǎn)可以通過靈活的配置來設(shè)置需要完成的工作,還提供了統(tǒng)計及報表,郵件通知等功能,方便團(tuán)隊高效的管理軟件的持續(xù)集成。

發(fā)展及未來

目前的CI也在處于高速發(fā)展期,比如最新的Jenkins 2 可以支持使用Groovy編寫插件,pipeline等。同時也出現(xiàn)了像是開源的Travis之類的持續(xù)集成service,即你不用自己去安裝調(diào)試Jenkins,直接寫個YAML文件 (.travis.yaml)放到云上,自動就可以使用其提供的服務(wù)了。

另外,持續(xù)集成也在跟其他新興技術(shù)相結(jié)合使用,比如結(jié)合云計算及分布式處理,可以提高CI的運(yùn)行速度和容錯能力,比如下圖中的各個服務(wù)器可以分別使用cluster(集群)而非一臺機(jī)器,這樣就可以避免所謂的SPOF (Single Point of Failure)單點(diǎn)故障。

如果有什么問題或者想要跟我討論,請通過如下方式找到我。

聯(lián)系我:

Reference

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容