當(dāng)Dev遇上CI與CD

簡(jiǎn)述

從剛開(kāi)始的時(shí)候兩眼一抹黑,到磕磕碰碰的終于讓測(cè)試包可以在代碼提交的時(shí)候順利的自動(dòng)構(gòu)建,團(tuán)隊(duì)終于向CI和CD的開(kāi)發(fā)生活邁出了歷史性的一步,中間踩了不少坑,也有不少收獲,寫(xiě)一篇東西紀(jì)念一下。

感覺(jué)這篇東西都是鍵者不成熟的思緒,滿滿的水貨~

1. 原生之初

公司的研發(fā)團(tuán)隊(duì)本身是小團(tuán)隊(duì),再經(jīng)典的劃分為前端后端,而當(dāng)前研發(fā)中的應(yīng)用是處于功能實(shí)現(xiàn)階段,也就是幾乎每天都會(huì)發(fā)布新功能,也幾乎每天都有可能有已有的功能發(fā)生變動(dòng)。

于是問(wèn)題也開(kāi)始接踵而至……

1.1 完整性

鍵者簡(jiǎn)單通過(guò)一段對(duì)話來(lái)還原一下這個(gè)場(chǎng)景:

  • 飛哥,你是不是提交漏了代碼?(從QQ上發(fā)來(lái)一張編譯報(bào)錯(cuò)的截圖)
  • 啊,不好意思,等下我現(xiàn)在補(bǔ)。
  • 好了,你去pull一下
  • 還是不行?。ǖ诙埥貓D)……
  • o_O

相信這個(gè)場(chǎng)景在沒(méi)有完整測(cè)試環(huán)境的小團(tuán)隊(duì)中不會(huì)太陌生。

某個(gè)正在開(kāi)發(fā)A模塊的攻城獅,忽然收到要快速修復(fù)B模塊的某個(gè)bug的需求。

在本地修完以后把涉及到fix的代碼提交了,本地繼續(xù)保留正在dev的代碼,繼續(xù)開(kāi)發(fā),可是有時(shí)候一個(gè)還處于開(kāi)發(fā)中的不成熟系統(tǒng)的某個(gè)最大特點(diǎn)就是:某些bug其實(shí)是牽連很廣,開(kāi)發(fā)者用IDE一鍵修改了很多牽連到的模塊,但是提交的時(shí)候卻會(huì)漏了提交,導(dǎo)致代碼倉(cāng)庫(kù)中的最新版本可能其實(shí)并不可編譯(就更別提功能是否完成或者可靠了),也就是提交的代碼是不完整的。

一種最傳統(tǒng)的做法應(yīng)該是遵循git flow的流程在當(dāng)前主干上增加一個(gè)分支專門修復(fù)bug,修復(fù)完成后將分支合并到主干,并提交到代碼倉(cāng)庫(kù)。

傳統(tǒng)有時(shí)候好就好在可靠,但對(duì)于小團(tuán)隊(duì)來(lái)說(shuō),過(guò)多的分支處理起來(lái)并不輕松,更多時(shí)候,我們其實(shí)可以接受某個(gè)提交的節(jié)點(diǎn)其實(shí)是不完整的,很多時(shí)候缺少什么代碼沒(méi)提交也很容易發(fā)現(xiàn)的,只要在一個(gè)“干凈”的環(huán)境編譯一次就知道了,然后把欠缺的部分重新提交一下就好。

但提交者本身的環(huán)境是包含完整的代碼的(至少我們的攻城獅提交代碼前肯定都會(huì)先在本地測(cè)過(guò)可以完整使用),只是提交的時(shí)候發(fā)生了遺漏,而這個(gè)遺漏往往是同事更新了新的代碼后才發(fā)現(xiàn)的。

當(dāng)然,我們可以要求每個(gè)人在本地保留一塊干凈的開(kāi)發(fā)環(huán)境,每次push之前先完整的模擬一次從無(wú)到有的編譯過(guò)程,以確保自己提交了完整的代碼。

但有時(shí)候這并不簡(jiǎn)單,還記得那個(gè)說(shuō)做菜實(shí)在太難了,因?yàn)槊看味夹枰葴?zhǔn)備一個(gè)干凈碟子的冷笑話么……

1.2 可靠性

一個(gè)項(xiàng)目的代碼可以編譯成功了,就算可靠了么?

顯然,我們希望是,但可惜,并不能。

一個(gè)編譯成功的程序,在運(yùn)行的時(shí)候,有太多的可能導(dǎo)致它會(huì)崩潰了,哪怕它只是在啟動(dòng)的時(shí)候讀取一下配置,也有可能因?yàn)樽x到了有問(wèn)題的配置,導(dǎo)致無(wú)法正常工作。

也有可能啟動(dòng)的時(shí)候沒(méi)什么問(wèn)題,在工作的時(shí)候,處理某個(gè)輸入的時(shí)候,產(chǎn)生了異常,導(dǎo)致崩潰??。

這個(gè)異常可能是原來(lái)就有的bug,也有可能是為了修復(fù)某個(gè)bug而牽一發(fā)動(dòng)全身,導(dǎo)致其他地方本來(lái)沒(méi)問(wèn)題的地方產(chǎn)生的bug。

理論上,bug總是存在的,一個(gè)存在bug的程序并不一定不能穩(wěn)定的運(yùn)行。

就像沒(méi)有一個(gè)人是完美的,但不完美并不是不能很好的生活下去。

例如鍵者這種上了年紀(jì)的老人家,雖然斷更了很久但還是偶然會(huì)詐尸一下寫(xiě)篇東西吹吹水。

但對(duì)于一個(gè)程序的來(lái)說(shuō),至少預(yù)期應(yīng)有的功能都應(yīng)該提供到位,否則就還不是一個(gè)能發(fā)布的版本。這個(gè)時(shí)候我們?cè)趺粗肋@個(gè)程序已經(jīng)達(dá)到了正常工作的地步?找個(gè)人專門把所有功能都跑一遍么?騷年,我很看好你喲,事實(shí)上,軟件測(cè)試工程師就是負(fù)責(zé)這項(xiàng)工作的。

但其實(shí)有些功能的bug我們可以直接用代碼測(cè)試出來(lái),有問(wèn)題早知道,不是更方便么。

沒(méi)錯(cuò),這就是寫(xiě)測(cè)試代碼的價(jià)值,一個(gè)項(xiàng)目稍微具有規(guī)模后,如果沒(méi)有足夠的測(cè)試,哪怕是開(kāi)發(fā)者本人,也很容易陷入下邊這種情況:

  • 這段代碼你看著“感動(dòng)”嗎?
  • 不敢動(dòng)不敢動(dòng)Orz……

所謂泥足深陷,積重難返,莫過(guò)于此……

能通過(guò)測(cè)試的代碼未必就是可靠的,但至少,連測(cè)試都通不過(guò),那至少這個(gè)版本是有問(wèn)題的。
要么是項(xiàng)目有問(wèn)題,要么是測(cè)試邏輯或者數(shù)據(jù)沒(méi)及時(shí)更新。

1.3 可用性

在軟件可靠的情況下,下一個(gè)要考慮的是可用性,先不說(shuō)真正面向的大眾客戶的可用性,首先要保證的其實(shí)是開(kāi)發(fā)的可用性。

某個(gè)功能的開(kāi)發(fā),往往是前端和后端協(xié)同工作的成果,在功能還未穩(wěn)定的時(shí)候,前端直接連接后端的開(kāi)發(fā)機(jī)做聯(lián)調(diào)測(cè)試是很常見(jiàn)的情況,但是隨著功能增加,需求的分化,前端會(huì)更多的關(guān)注展示(Display)方面的問(wèn)題,而后端開(kāi)始關(guān)注高并發(fā),高可用,彈性擴(kuò)展的問(wèn)題,如果每次聯(lián)調(diào)都需要占用一個(gè)后端工程師,有時(shí)候未必是有必要的。

如果持續(xù)讓一個(gè)后端工程師運(yùn)行著一個(gè)最新版的Server呢?不是不可以,但畢竟不太方便,而且還是容易產(chǎn)生前文的完整性和可靠性問(wèn)題,畢竟后端的開(kāi)發(fā)機(jī)上跑著的未必是完整的版本,可能有他正在調(diào)試或者開(kāi)發(fā)的其他功能,而前端如果依賴于這個(gè)版本進(jìn)行開(kāi)發(fā),有些場(chǎng)景下可能會(huì)產(chǎn)生不一致的問(wèn)題。

例如后端攻城獅把原來(lái)的某段未提交的代碼在提交前刪了之類……

因此,一個(gè)常見(jiàn)的解決方案是把本機(jī)當(dāng)作開(kāi)發(fā)環(huán)境,專門跑一臺(tái)(組)測(cè)試環(huán)境,把當(dāng)前最新可用版本(或者最近幾個(gè)可靠版本)部署到測(cè)試服務(wù)器,然后前端的日常開(kāi)發(fā)中,特別是不需要與后端聯(lián)調(diào)的開(kāi)發(fā)中,只要連接到這個(gè)測(cè)試服務(wù)器就可以了。

當(dāng)然該聯(lián)調(diào)的時(shí)候還是可以聯(lián)調(diào)的。

2. CI/CD的自動(dòng)化

其實(shí)鍵者猜想,上邊提的問(wèn)題,對(duì)很多小伙伴來(lái)說(shuō)可能并不算真的問(wèn)題,因?yàn)槿粘F(tuán)隊(duì)協(xié)作及開(kāi)發(fā)中,各個(gè)團(tuán)伙一般早就行程了自己的開(kāi)發(fā)流程,從設(shè)計(jì)開(kāi)發(fā)測(cè)試部署都會(huì)有自己的一套方案。

2.1 不是AI,而是CI

持續(xù)集成(Continuous Integration,簡(jiǎn)稱CI),本身并沒(méi)有跳出這個(gè)流程,它只是強(qiáng)調(diào)將這個(gè)流程的周期變短。

也許短到每次提交代碼都執(zhí)行一次。

但如果項(xiàng)目達(dá)到一定規(guī)模,這個(gè)規(guī)??赡苁枪δ?、復(fù)雜度等達(dá)到一定規(guī)模,也可能是參與開(kāi)發(fā)的人員達(dá)到一定規(guī)模,CI的實(shí)現(xiàn)就越來(lái)越難以用人工維護(hù),因?yàn)槿肆Τ杀臼呛芨叩?,而且持續(xù)而單調(diào)(是的,大部分時(shí)候這個(gè)工作非常單調(diào)),單調(diào)意味著人工容易出錯(cuò)。

其實(shí),CI本身并沒(méi)有“自動(dòng)化”這種含義,事實(shí)上,它并不關(guān)心執(zhí)行的是誰(shuí),是一個(gè)個(gè)集成工程師、開(kāi)發(fā)工程師或者運(yùn)維工程師,抑或是某一個(gè)程序,或者某段腳本。

2.2 不是AD,而是CD

而與CI經(jīng)常一起出現(xiàn)的,是CD。而這里的CD其實(shí)有兩個(gè)解,一個(gè)是持續(xù)交付(Continuous Dselivery),另一個(gè)是持續(xù)部署(Continuous Ceployment),后者是前者的下一步。

而鍵者在這里討論的是后者,項(xiàng)目實(shí)施中一般說(shuō)的CD也是后者,因?yàn)?code>持續(xù)部署提倡的是從代碼的提交測(cè)試構(gòu)建部署都是自動(dòng)完成的。

也就是說(shuō),每個(gè)成功的成功提交的節(jié)點(diǎn)應(yīng)該都是可部署的,哪怕只是部署到測(cè)試機(jī)。

更詳細(xì)的概念筆者放在了附錄

3. 實(shí)現(xiàn)思路

自動(dòng)化這個(gè)東西,說(shuō)起來(lái)可能都很好理解,簡(jiǎn)單講,就是從提交代碼開(kāi)始,后續(xù)所有的流程全部由計(jì)算機(jī)自動(dòng)完成,并及時(shí)把結(jié)果(特別是異常結(jié)果)反饋給開(kāi)發(fā)者,以便開(kāi)發(fā)者作出響應(yīng)。

但是實(shí)現(xiàn)的時(shí)候其實(shí)還是挺多問(wèn)題的,因?yàn)樽詣?dòng)化意味著以前可以人工處理的異常都要自動(dòng)化處理,我們?cè)谠O(shè)計(jì)CI/CD方案的時(shí)候需要預(yù)先考慮到一般場(chǎng)景下可能會(huì)出現(xiàn)的問(wèn)題,并作出合理的響應(yīng),是自動(dòng)修正并繼續(xù)部署,抑或是打斷當(dāng)前流程并通知開(kāi)發(fā)者跟進(jìn)處理,都是要預(yù)先考量的。

當(dāng)然,就像很多開(kāi)發(fā)時(shí)一樣,我們可以先考慮最正常的情況,然后根據(jù)各種遇到的異常一點(diǎn)點(diǎn)處理。

3.1 環(huán)境(environment)

CD的最終目的應(yīng)該是最終程序總是可以在預(yù)期的環(huán)境中按預(yù)期的邏輯運(yùn)行,所以環(huán)境雖然并不是CD的流程中的一個(gè)環(huán)節(jié),但鍵者在這里還是把這個(gè)問(wèn)題拿出來(lái)單獨(dú)討論。

就像前文說(shuō)的,第一步是準(zhǔn)備一個(gè)干凈的碟子。

我們提交的是代碼,如果把代碼看作原材料,我們要把菜端上桌,就勢(shì)必要進(jìn)行一定的加工,而廚房就是我們加工的場(chǎng)所,恰到好處的加工場(chǎng)所,才能確保加工的結(jié)果是可重現(xiàn)的。

可能很多時(shí)候腳本語(yǔ)言并不需要加工,但也需要一個(gè)可重現(xiàn)的運(yùn)行環(huán)境。

而準(zhǔn)備環(huán)境的重要性在于,一個(gè)程序測(cè)試時(shí)有測(cè)試環(huán)境;構(gòu)建時(shí)有構(gòu)建環(huán)境;運(yùn)行時(shí)有運(yùn)行環(huán)境。對(duì)于一個(gè)可靠的提交代碼版本,它應(yīng)該是能在給定的環(huán)境下通過(guò)測(cè)試,構(gòu)建成功,并穩(wěn)定運(yùn)行的。

怎么樣是一個(gè)給定的環(huán)境?鍵者認(rèn)為,至少是當(dāng)你面對(duì)一臺(tái)新的主機(jī)(例如公司新租的一臺(tái)ECS),你能復(fù)現(xiàn)的環(huán)境。一個(gè)應(yīng)用的測(cè)試、構(gòu)建、運(yùn)行等環(huán)境可以是一樣的,也可以是不一樣的。

例如說(shuō),構(gòu)建環(huán)境中可能涉及到編譯器,涉及到當(dāng)前項(xiàng)目依賴的第三方包,甚至涉及構(gòu)建時(shí)執(zhí)行的命令。而運(yùn)行環(huán)境中,你并不需要有編譯器,甚至不需要有源代碼,你可能只需要一個(gè)可執(zhí)行程序即可。

但在CD中,你最好盡量保證你每次開(kāi)始一輪新的任務(wù)時(shí),初始的環(huán)境都是一樣的,這樣可以最大程度的保證你的代碼被別的同事下載,或者上線運(yùn)行的時(shí)候,不會(huì)出現(xiàn)不完整的問(wèn)題。

所謂干凈的碟子,不一定是一個(gè)全新安裝的操作系統(tǒng),一般更合理的是具備了項(xiàng)目團(tuán)隊(duì)公開(kāi)指定的所有工具及三方庫(kù)的環(huán)境,而且每次運(yùn)行過(guò)后,都應(yīng)該把這個(gè)環(huán)境還原到上次運(yùn)作的狀態(tài)。

例如,某次測(cè)試的時(shí)候自動(dòng)生成了一個(gè)文件,生成成功并校驗(yàn)通過(guò)表示測(cè)試通過(guò)。則測(cè)試完畢后,應(yīng)立即刪除這個(gè)文件,避免下次測(cè)試的時(shí)候,誤以為上次下載的文件是這次下載的,導(dǎo)致放過(guò)了可能存在的bug。

為什么說(shuō)應(yīng)該是公開(kāi)指定呢?有時(shí)候我們可以在開(kāi)發(fā)的時(shí)候引入了新的第三方包,但沒(méi)有及時(shí)同步,可能會(huì)導(dǎo)致其他攻城獅編譯出錯(cuò)得莫名其妙,此時(shí)CD環(huán)節(jié)就會(huì)報(bào)錯(cuò),你就可以及時(shí)發(fā)現(xiàn)自己沒(méi)有提交關(guān)于新包的配置。

如果嚴(yán)謹(jǐn)?shù)目紤],應(yīng)至少準(zhǔn)備三套環(huán)境,一個(gè)用于測(cè)試,一個(gè)用于構(gòu)建,一個(gè)用于運(yùn)行,在團(tuán)隊(duì)中,一次合格的提交不能只滿足于能在本地的開(kāi)發(fā)機(jī)上完整、可靠、可用的通過(guò)。

linux下的應(yīng)用開(kāi)發(fā)的話,Docker顯然是在處理環(huán)境問(wèn)題目前可能是最好用的工具,不過(guò)今天只講理論,就不多說(shuō)了~

3.2 提交(commit)

就像再厲害的程序,也要被執(zhí)行(Exec)才能變成進(jìn)程一樣,CD的啟動(dòng)也需要一個(gè)觸發(fā)的契機(jī),除了手動(dòng)觸發(fā)的情況之外,我們一般會(huì)在每次提交(commit)代碼的時(shí)候自動(dòng)觸發(fā)。

當(dāng)然,也可以細(xì)分為本地提交,以及push到公共倉(cāng)庫(kù)的時(shí)候。更常見(jiàn)的情況是push到公共倉(cāng)庫(kù)的時(shí)候。

具體的操作就是通過(guò)各種手段(例如git hook,或者寫(xiě)個(gè)輪詢定時(shí)查看等等),監(jiān)控代碼倉(cāng)庫(kù)的變動(dòng)情況,一旦發(fā)生變動(dòng),就執(zhí)行一個(gè)指定的程序(可能就是個(gè)腳本或者觸發(fā)某個(gè)已經(jīng)在運(yùn)行的服務(wù)),這個(gè)程序要接手后續(xù)的工作,完成自動(dòng)部署的后續(xù)工作。

所以,提交這個(gè)場(chǎng)景下,童鞋們需要關(guān)注的是觸發(fā)時(shí)機(jī)以及執(zhí)行者的問(wèn)題。

關(guān)于CD的執(zhí)行者,有很多現(xiàn)成的工具,例如JenkinsTravis、Drone、Gitlab-Runner等,當(dāng)然這里也可以是多個(gè)程序協(xié)同完成工作,不一定是一個(gè)程序。所以童鞋們這里一定要抓住重點(diǎn),是做什么,而不是幾個(gè)人(程序)做,只要能達(dá)成目的,幾個(gè)人做都可以。

3.3 測(cè)試(test)(第一輪)

測(cè)試的問(wèn)題又是要具體情況具體分析的了,很多開(kāi)發(fā)語(yǔ)言都具備一定程度上不用構(gòu)建就能測(cè)試的測(cè)試框架,所以第一輪測(cè)試瞄準(zhǔn)的是具備這一特性的開(kāi)發(fā)場(chǎng)景。

首先當(dāng)然是要初始化測(cè)試環(huán)境,然后下載最新的代碼,根據(jù)項(xiàng)目情況執(zhí)行測(cè)試腳本(或者運(yùn)行特定的測(cè)試工具),根據(jù)測(cè)試結(jié)果決定是應(yīng)該報(bào)警,還是繼續(xù)。

往往是單元測(cè)試……

3.4 構(gòu)建(build)

對(duì)于需要編譯的語(yǔ)言來(lái)說(shuō),可能很多時(shí)候構(gòu)建可能會(huì)被看作一個(gè)編譯的過(guò)程,編譯成功了,構(gòu)建通過(guò)。

腳本就更別說(shuō)了……

然而其實(shí)我們知道,對(duì)于很多應(yīng)用來(lái)說(shuō),可執(zhí)行程序并不是一個(gè)完整的應(yīng)用,一個(gè)完整的應(yīng)用可能還需要包括符合特定目錄結(jié)構(gòu)的配置文件、資源文件等等,所以所謂構(gòu)建在這里是指能把整個(gè)程序完整運(yùn)作的所有應(yīng)有的資源按合理的方式組織好的過(guò)程,其中只是湊巧有些資源是需要通過(guò)代碼編譯出來(lái)的而已。

當(dāng)然,如果你的應(yīng)用確實(shí)只有一個(gè)可執(zhí)行程序,那編譯完就算完事了。

3.5 測(cè)試(test)(第二輪)

第二輪測(cè)試和第一輪測(cè)試的核心區(qū)別在于,第一輪測(cè)試是在構(gòu)建之前進(jìn)行的,針對(duì)的是未構(gòu)建之前的代碼或者資源,而第二輪測(cè)試是在構(gòu)建之后的,針對(duì)的就是一整個(gè)應(yīng)用,或者說(shuō),第二輪測(cè)試更偏向一輪黑盒測(cè)試,測(cè)試的是應(yīng)用能否按預(yù)期工作。

當(dāng)然,無(wú)論是第一輪測(cè)試還是第二輪測(cè)試,都不是必要的,需要根據(jù)自己的項(xiàng)目情況具體決定

3.5 部署(deploy)

部署,簡(jiǎn)單的說(shuō)就是把構(gòu)建環(huán)節(jié)中準(zhǔn)備好的應(yīng)用包,放到指定的運(yùn)行環(huán)境(例如一臺(tái)服務(wù)器的某個(gè)目錄),并運(yùn)行的過(guò)程。

但部署其實(shí)也有很多關(guān)注點(diǎn):

  1. 部署到哪一臺(tái)服務(wù)器。
  2. 部署的時(shí)候怎么處理舊版的正在運(yùn)行的應(yīng)用程序(關(guān)了,還是把新應(yīng)用當(dāng)作彈性擴(kuò)展,還是通過(guò)某些策略把舊應(yīng)用的數(shù)據(jù)或者資源移到新應(yīng)用)
  3. 部署的時(shí)候,當(dāng)前應(yīng)用依賴的其它服務(wù)需不需要做什么處理,例如重建數(shù)據(jù)庫(kù)?
  4. 部署時(shí)使用的配置應(yīng)該怎么根據(jù)部署的情況自動(dòng)調(diào)整。
  5. 如果部署失敗了,怎么辦?

這些問(wèn)題其實(shí)都要一一考慮清楚,當(dāng)然,如果是簡(jiǎn)單處理,也并不是所有問(wèn)題都必須解決才能工作。

4. 小結(jié):老生常談的銀色子彈

就像很多童鞋知道和經(jīng)歷過(guò)的一樣,萬(wàn)能的子彈是不存在的,每個(gè)問(wèn)題都要放在具體的場(chǎng)景中,才能產(chǎn)生價(jià)值。

鍵者踩過(guò)的坑,主要還是受限于鍵者的經(jīng)歷以及需求,每次理論到實(shí)踐的過(guò)程都會(huì)出現(xiàn)各種難以預(yù)料的問(wèn)題,但鍵者一直覺(jué)得學(xué)習(xí)一個(gè)新的技術(shù),理解理念和實(shí)際操作同樣重要,一般根據(jù)概念理解操作的邏輯,知其然然后知其所以然,另一方面也要邊實(shí)操邊反饋理論的理解。

鍵者自己經(jīng)常會(huì)遇到這樣的情況,某個(gè)東西以為看懂了,結(jié)果做起來(lái)發(fā)現(xiàn)完全不是那么回事,很多概念的邊界其實(shí)是模糊的,然后又要回來(lái)扣理論,然后再回頭做。

嗯嗯,所以有緣的話鍵者也許會(huì)寫(xiě)一篇干一點(diǎn)的基于Docker+Gitlab的自動(dòng)化部署實(shí)戰(zhàn)。

也希望本文能拋磚引玉,幫助第一次接觸CI/CD自動(dòng)化開(kāi)發(fā)的童鞋整理思路。

5. 附錄

摘自《持續(xù)集成是什么?》(作者:阮一峰)

持續(xù)集成指的是,頻繁地(一天多次)將代碼集成到主干。

(1)快速發(fā)現(xiàn)錯(cuò)誤。每完成一點(diǎn)更新,就集成到主干,可以快速發(fā)現(xiàn)錯(cuò)誤,定位錯(cuò)誤也比較容易。

(2)防止分支大幅偏離主干。如果不是經(jīng)常集成,主干又在不斷更新,會(huì)導(dǎo)致以后集成的難度變大,甚至難以集成。

持續(xù)集成的目的,就是讓產(chǎn)品可以快速迭代,同時(shí)還能保持高質(zhì)量。它的核心措施是,代碼集成到主干之前,必須通過(guò)自動(dòng)化測(cè)試。只要有一個(gè)測(cè)試用例失敗,就不能集成。

Martin Fowler說(shuō)過(guò),"持續(xù)集成并不能消除Bug,而是讓它們非常容易發(fā)現(xiàn)和改正。"
與持續(xù)集成相關(guān)的,還有兩個(gè)概念,分別是持續(xù)交付和持續(xù)部署。


持續(xù)交付(Continuous delivery)指的是,頻繁地將軟件的新版本,交付給質(zhì)量團(tuán)隊(duì)或者用戶,以供評(píng)審。如果評(píng)審?fù)ㄟ^(guò),代碼就進(jìn)入生產(chǎn)階段。

持續(xù)交付可以看作持續(xù)集成的下一步。它強(qiáng)調(diào)的是,不管怎么更新,軟件是隨時(shí)隨地可以交付的。


持續(xù)部署(continuous deployment)是持續(xù)交付的下一步,指的是代碼通過(guò)評(píng)審以后,自動(dòng)部署到生產(chǎn)環(huán)境。

持續(xù)部署的目標(biāo)是,代碼在任何時(shí)刻都是可部署的,可以進(jìn)入生產(chǎn)階段。

持續(xù)部署的前提是能自動(dòng)化完成測(cè)試、構(gòu)建、部署等步驟。

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

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

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