三宪摧、持續(xù)集成(Continuous Integration)

在軟件工程中沿后,集成是一個(gè)漫長(zhǎng)而又不可預(yù)測(cè)的過(guò)程。因此一些公司開始嘗試讓團(tuán)隊(duì)中的成員每天集成一次,這樣開發(fā)者不會(huì)偏離項(xiàng)目目標(biāo)太遠(yuǎn)撼唾,只需要短短的幾分鐘就可以糾正過(guò)來(lái)。集成中的錯(cuò)誤也可以盡快的被發(fā)現(xiàn)和修復(fù)宇驾。

當(dāng)人們第一次聽到這種方法是课舍,有兩種反應(yīng):

  • 在這里行不通
  • 這樣做不能帶來(lái)多少改變

但當(dāng)他們嘗試的時(shí)候,實(shí)踐它比聽著要簡(jiǎn)單站辉,而且給開發(fā)帶來(lái)了巨大的不同。然后人們的反應(yīng)就是:“是的汰蓉,我們這樣做祝钢,你沒(méi)有這樣做怎么活下來(lái)的?”

盡管,CI不需要特殊的工具來(lái)部署,但我們發(fā)現(xiàn)使用一個(gè)CI服務(wù)器非常有用肃晚。比較出名的有Cruise control

Building a Feature with Continuous Integration

使用CI開發(fā)一個(gè)功能

最簡(jiǎn)單的介紹CI的方式展示一個(gè)例子。假設(shè),我要開發(fā)一個(gè)功能倦春,不論這個(gè)功能大小,假設(shè)它可以在幾個(gè)小時(shí)內(nèi)開發(fā)出來(lái)呢堰。
我開始從源碼庫(kù)拉代碼。一個(gè)源碼控制系統(tǒng)保存著項(xiàng)目上的所有源碼。系統(tǒng)當(dāng)前狀態(tài)通常被叫做“主線”席舍,即mainline。任何時(shí)候,一個(gè)開發(fā)者從源碼庫(kù)復(fù)制代碼到本地機(jī)器滑黔,被稱作‘檢出’,即checking out。開發(fā)者本機(jī)的復(fù)制品被稱為‘工作副本’肛根,即working copy。

一切就緒后狮辽,我開始盡我所能的完成這個(gè)功能椰苟。這里面包括調(diào)整生產(chǎn)的代碼以及增加或者改變自動(dòng)化測(cè)試用例舆蝴。CI需要一個(gè)高度的自動(dòng)化的測(cè)試:稱為自測(cè)代碼,這一般需要一個(gè)自動(dòng)化測(cè)試框架叫胖。
當(dāng)我的開發(fā)完成后瓮增,在我開發(fā)機(jī)器上執(zhí)行一個(gè)自動(dòng)化編譯。這會(huì)編譯我的代碼谬运,并將我的代碼鏈接到一個(gè)可執(zhí)行文件膝藕,并跑自動(dòng)化測(cè)試芭挽。只有編譯和測(cè)試都沒(méi)有錯(cuò)誤才算完成。

本地編譯通過(guò)后,就會(huì)考慮提交我的變更到代碼倉(cāng)庫(kù)腊状。當(dāng)然,其他開發(fā)者可能在我之前已經(jīng)提交了他的變更映屋。所以首先我要使用他的變更更新我本地的代碼副本湾蔓,然后重新編譯颁股。如果他的變更和我的變更沖突,在編譯或單元測(cè)試的時(shí)候都會(huì)報(bào)錯(cuò)。這是我的責(zé)任就是修復(fù)這個(gè)沖突,然后重新編譯注竿,直到編譯通過(guò),然后提交變更到倉(cāng)庫(kù)。

至此還未結(jié)束,代碼提交到倉(cāng)庫(kù)后嗦嗡,會(huì)在CI機(jī)器上自動(dòng)編譯,或者認(rèn)為觸發(fā)編譯,這是如果編譯報(bào)錯(cuò)應(yīng)該盡快被解決。在一個(gè)好的團(tuán)隊(duì)中,編譯成功的次數(shù)應(yīng)該大于編譯失敗的次數(shù)葛假。

以上工作完成后抱究,會(huì)產(chǎn)生一個(gè)包含很少bug勋磕,運(yùn)行良好的的代碼苦银。

CI的一些實(shí)踐

上面大概介紹了CI,以及在工作中是怎么運(yùn)用的。讓上面的一切能正常工作并不容易主胧。下面簡(jiǎn)單介紹一些關(guān)鍵點(diǎn):

1. 維護(hù)一個(gè)源代碼倉(cāng)庫(kù)

一個(gè)軟件項(xiàng)目包含了很多文件图毕,跟蹤記錄這些文件很費(fèi)時(shí),特別是有很多人一起工作的時(shí)候予颤。所以使用一些源代碼管理工具就可以大大提高開發(fā)效率囤官。常見有:

倉(cāng)庫(kù)可以包含你完成這個(gè)項(xiàng)目所有需要的所有東西,包括測(cè)試腳本蛤虐、配置文件党饮、數(shù)據(jù)庫(kù)schema、安裝腳本驳庭、其他第三方庫(kù)等刑顺。

2. 自動(dòng)化編譯

讓一堆代碼變成可以運(yùn)行的系統(tǒng)是一個(gè)復(fù)雜的工作氯窍,包括編譯蹲堂、鏈接狼讨、加載表結(jié)構(gòu)到數(shù)據(jù)庫(kù)等等一系列動(dòng)作。但是這些工作都可以被自動(dòng)化政供。讓人來(lái)敲這些奇怪的命令或者點(diǎn)擊對(duì)話框既費(fèi)時(shí)又容易出錯(cuò)执泰。
在Unix世界,自動(dòng)化的工具已經(jīng)出現(xiàn)了很久,JAVA社區(qū)開發(fā)出了Ant腻暮,.NET社區(qū)有Nant,現(xiàn)在又有了MSBuild。
在自動(dòng)化編譯中,一個(gè)常見的錯(cuò)誤是不將所有的工作包含在其中腿短。一個(gè)主要的原則是:任何一個(gè)人可以在一臺(tái)裸機(jī)上钝诚,拉取源碼后芦岂,執(zhí)行一個(gè)簡(jiǎn)單的命令就可以讓這個(gè)系統(tǒng)在機(jī)器上運(yùn)行川无。
一個(gè)完整的編譯會(huì)很耗時(shí)疹味,如果你只改了很少的代碼,不希望編譯所有的文件婴渡。所有一個(gè)好的編譯工具可以分析出哪些文件做了改變需要編譯岭接。常見的方法是檢查源碼的日期和對(duì)象文件的日期窄锅,只編譯源碼日期靠后的殿雪。但如果文件之間有依賴可能就發(fā)現(xiàn)不了河泳。

3. 自動(dòng)化測(cè)試

程序可以運(yùn)行,但并不表示做著正確的事情。靜態(tài)輸入語(yǔ)言可以發(fā)現(xiàn)很多bug,但還是有漏網(wǎng)之魚纽乱。
一個(gè)更快更有效發(fā)現(xiàn)bugs的方法是在build的過(guò)程中包含自動(dòng)化測(cè)試薯嗤。測(cè)試并不是完美的,但可以發(fā)現(xiàn)很多bugs。特別是隨著極限編程(XP)和測(cè)試驅(qū)動(dòng)開發(fā)(TDD)的興起,自測(cè)代碼(self-testing code)變得越來(lái)越流行桥爽。

為了測(cè)試代碼,需要一整套的自動(dòng)化測(cè)試用例來(lái)檢查大部分的代碼是否有bug缕碎。測(cè)試用例需要能夠很簡(jiǎn)單的就發(fā)起处嫌,并能自測(cè)赚楚。測(cè)試用例失敗必須引起整個(gè)build失敗。
近幾年(指二十一世紀(jì)初)開源的XUnit家族開始流行服猪,當(dāng)然還有其他流行的單元測(cè)試框架:

還有很多不詳細(xì)列舉供填。
當(dāng)然不可能依靠測(cè)試發(fā)現(xiàn)所有的問(wèn)題。但是不完美的測(cè)試跑100遍罢猪,也好過(guò)完美的測(cè)試一遍就不跑近她。

4. 每個(gè)人每天都要提交代碼

集成主要在于溝通。集成允許一個(gè)開發(fā)者告訴其他開發(fā)者他做了哪些變更坡脐。頻繁的溝通可以讓開發(fā)者很快的知道代碼做了哪些改變泄私。
代碼提交的越頻繁,發(fā)現(xiàn)代碼沖突的可能就越大备闲,需要解決的沖突就越小晌端。
頻繁提交代碼,也可以讓開發(fā)者更合理地分解自己的工作

5. 每一次主干分支上的提交都應(yīng)該在CI機(jī)器上編譯

由于代碼提交頻繁了恬砂,就必須保證主干分支狀態(tài)正常咧纠。所以每次提交必須保證編譯都能成功通過(guò)。開發(fā)者需要關(guān)注自己的每次代碼提交后編譯的結(jié)果泻骤,最好能有編譯監(jiān)控漆羔,失敗后可以發(fā)送郵件給到相關(guān)開發(fā)人員。
不要在晚上編譯(一些公司會(huì)這么做)狱掂,這樣會(huì)讓編譯錯(cuò)誤在一天后才能被發(fā)現(xiàn)演痒。錯(cuò)誤被發(fā)現(xiàn)的越晚,修復(fù)的成本就越高趋惨。

6. 快速修復(fù)失敗的build

CI中最關(guān)鍵的一點(diǎn)就是主干編譯失敗鸟顺,需要馬上修復(fù),必須保證主干分支在一個(gè)穩(wěn)定的狀態(tài)。
Kent Beck曾說(shuō)過(guò):“沒(méi)有什么任務(wù)比修復(fù)一個(gè)build優(yōu)先級(jí)更高讯嫂”姆妫”
但這并不意味著需要整個(gè)開發(fā)團(tuán)隊(duì)停止工作來(lái)做這件事情,通常一兩個(gè)人負(fù)責(zé)這個(gè)事情就行了欧芽。

一般最快修復(fù)build的方法就是回滾上一次的提交莉掂,讓系統(tǒng)回到最近一個(gè)好的編譯。當(dāng)然最好不要嘗試在一個(gè)壞的主干上做調(diào)試千扔,除非可以很容易發(fā)現(xiàn)問(wèn)題在哪里憎妙,只需要回滾,然后在一個(gè)開發(fā)機(jī)器上調(diào)試這個(gè)問(wèn)題曲楚。
可以使用pending head來(lái)避免損壞主干分支尚氛。

剛開始運(yùn)行CI這種工作方式,出錯(cuò)在所難免洞渤。所以要有耐心,遇到問(wèn)題不要?dú)怵H属瓣。

7. 讓編譯盡可能的快

CI的關(guān)鍵就是要盡可能快的反饋問(wèn)題载迄,沒(méi)有什么比編譯慢更能堵塞CI的進(jìn)行。
大多數(shù)項(xiàng)目的編譯時(shí)間可以保證在10分鐘以內(nèi)抡蛙,這也是XP提倡的护昧。
由于編譯會(huì)頻繁的進(jìn)行,所以每次編譯節(jié)省一分鐘粗截,累計(jì)下來(lái)可以為開發(fā)人員節(jié)省大量的實(shí)踐惋耙。
通常編譯的瓶頸在測(cè)試,特別是需要依賴外部服務(wù)比如數(shù)據(jù)庫(kù)熊昌。
還可以建立一個(gè)部署pipeline绽榛,讓多個(gè)build有序的完成。代碼提交到主干后編譯是第一個(gè)build婿屹,被叫做commit build灭美。commit build需要在很短的時(shí)間內(nèi)完成。這一步主要是代碼編譯和本地的一些單元測(cè)試昂利。但是需要依賴其他外部組件的測(cè)試需要很長(zhǎng)時(shí)間届腐,這個(gè)測(cè)試可以放到另外的機(jī)器上完成。
commit build經(jīng)常作為CI主要的步驟蜂奸。如果在第二個(gè)stage中發(fā)現(xiàn)bug犁苏,那么可以考慮這個(gè)bug的測(cè)試是否可以放在commit
build中,這樣會(huì)增強(qiáng)第一步測(cè)試的準(zhǔn)確性扩所。

8. 在準(zhǔn)生產(chǎn)測(cè)試

環(huán)境的不同围详,可能導(dǎo)致測(cè)試結(jié)果的不同,所以測(cè)試環(huán)境要盡量模擬生產(chǎn)碌奉。比如使用同一個(gè)數(shù)據(jù)庫(kù)軟件和版本短曾、同一個(gè)操作系統(tǒng)寒砖、同樣的庫(kù)文件、同一種硬件等等嫉拐。
在實(shí)際生產(chǎn)實(shí)踐中可能有一些限制哩都,如果你在開發(fā)一款桌面應(yīng)用,可能沒(méi)有那么容易在每一個(gè)用戶的桌面環(huán)境中測(cè)試婉徘。還有一種情況是復(fù)制生產(chǎn)環(huán)境需要高昂的成本漠嵌。盡管如此,但還是要盡量模擬生產(chǎn)盖呼,并了解測(cè)試和生產(chǎn)的不同之處在哪里儒鹿。

9. 方便獲取最新的可執(zhí)行文件

軟件開發(fā)中最困難的之一就是確保制作正確的軟件。我們發(fā)現(xiàn)要提前知道人們要什么并且是想要的很困難几晤。為了做到這一點(diǎn)爷抓,開發(fā)團(tuán)隊(duì)的任何人需要可以拿到最新的可執(zhí)行文件并可以運(yùn)行它:用來(lái)驗(yàn)證、測(cè)試或者看看最近有哪些改變捧搞。
做到這一點(diǎn)很容易:確保這些可執(zhí)行文件放在一個(gè)大家都知道的地方腹尖。

10. 每一個(gè)人可以看到當(dāng)前發(fā)生了什么

CI主要是關(guān)于溝通,所以需要確保每一個(gè)可以很容易看到系統(tǒng)的狀態(tài)以及最近的一些改變憾朴。
通常在CI服務(wù)器的編譯過(guò)程中會(huì)有很多指示編譯狀態(tài)變化的標(biāo)識(shí)狸捕,比如紅色表示編譯失敗,綠色表示編譯成功

11. 自動(dòng)部署

為了完成CI众雷,你需要多套環(huán)境灸拍,一個(gè)跑主干測(cè)試,一個(gè)或者多個(gè)跑分支測(cè)試砾省。所以你需要將可以執(zhí)行文件在多套環(huán)境中移動(dòng)鸡岗,當(dāng)然你想讓這些步驟都是自動(dòng)。

如果你是自動(dòng)部署生產(chǎn)環(huán)境编兄,那么可能也會(huì)考慮自動(dòng)回滾纤房。意外經(jīng)常會(huì)發(fā)生,如果能夠快速回滾到上一個(gè)穩(wěn)定的版本自然很好翻诉∨谝蹋可以自動(dòng)回滾,也可以鼓勵(lì)人們更多的部署而不必考慮太多碰煌。
集群環(huán)境的部署一般采用金絲雀發(fā)布舒岸,即一次只部署一個(gè)節(jié)點(diǎn),讓流量平滑的切換到整個(gè)集群芦圾。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蛾派,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌洪乍,老刑警劉巖眯杏,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異壳澳,居然都是意外死亡岂贩,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門巷波,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)萎津,“玉大人,你說(shuō)我怎么就攤上這事抹镊★鼻” “怎么了?”我有些...
    開封第一講書人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵垮耳,是天一觀的道長(zhǎng)颈渊。 經(jīng)常有香客問(wèn)我,道長(zhǎng)终佛,這世上最難降的妖魔是什么儡炼? 我笑而不...
    開封第一講書人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮查蓉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘榜贴。我一直安慰自己豌研,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開白布唬党。 她就那樣靜靜地躺著鹃共,像睡著了一般。 火紅的嫁衣襯著肌膚如雪驶拱。 梳的紋絲不亂的頭發(fā)上霜浴,一...
    開封第一講書人閱讀 49,829評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音蓝纲,去河邊找鬼阴孟。 笑死,一個(gè)胖子當(dāng)著我的面吹牛税迷,可吹牛的內(nèi)容都是我干的永丝。 我是一名探鬼主播,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼箭养,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼慕嚷!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤喝检,失蹤者是張志新(化名)和其女友劉穎嗅辣,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體挠说,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡澡谭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了纺涤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片译暂。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖撩炊,靈堂內(nèi)的尸體忽然破棺而出外永,到底是詐尸還是另有隱情,我是刑警寧澤拧咳,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布伯顶,位于F島的核電站,受9級(jí)特大地震影響骆膝,放射性物質(zhì)發(fā)生泄漏祭衩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一阅签、第九天 我趴在偏房一處隱蔽的房頂上張望掐暮。 院中可真熱鬧,春花似錦政钟、人聲如沸路克。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)精算。三九已至,卻和暖如春碎连,著一層夾襖步出監(jiān)牢的瞬間灰羽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工鱼辙, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留廉嚼,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓倒戏,卻偏偏與公主長(zhǎng)得像前鹅,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子峭梳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容