原文鏈接:https://fire.ci/blog/the-difference-between-ci-and-cd/有很多介紹什么是持續(xù)集成、持續(xù)交付和持續(xù)部署的內(nèi)容。但是這些流程首先要做什么?了解 CI 和 CD 解決的問題以正確使用它們至關(guān)重要。這將使您的團(tuán)隊(duì)可以改善您的流程。并避免花力氣追求那些不會給您的過程帶來任何價(jià)值的幻想指標(biāo)。持續(xù)集成是一個(gè)團(tuán)隊(duì)問題
如果您和同一團(tuán)隊(duì)的多個(gè)開發(fā)者在一個(gè)存儲庫中工作,其中載有最新版本的代碼位于存儲庫的主分支。開發(fā)人員在不同分支上從事不同的工作。一旦某人完成變更后,他會將其推送或合并到主分支。最終,整個(gè)團(tuán)隊(duì)將拉取到這一變更。我們要避免的情況是錯(cuò)誤的提交進(jìn)入主分支。錯(cuò)誤意味著代碼無法編譯,或者應(yīng)用無法啟動或無法使用。為什么?并不是因?yàn)閼?yīng)用程序損壞了或者因?yàn)樗袦y試必須始終為綠色。那不是問題,您可能永遠(yuǎn)不會部署該版本并等待修復(fù)。問題是您的整個(gè)團(tuán)隊(duì)都陷入了困境。所有拉渠道錯(cuò)誤提交的開發(fā)人員都會花 5 分鐘的時(shí)間來排查為什么程序無法運(yùn)行。有些人可能會嘗試查找錯(cuò)誤的提交。有些人會嘗試與有問題的代碼作者并行解決問題。這對您的團(tuán)隊(duì)來說是浪費(fèi)時(shí)間。最糟糕的是,重復(fù)發(fā)生的事件加劇了對主分支的不信任,并鼓勵(lì)開發(fā)人員分開工作。持續(xù)集成就是為了防止主分支被破壞,從而使您的團(tuán)隊(duì)不會陷入困境。也就是說,這并不是要讓所有測試始終保持綠色并且主分支在每次提交時(shí)都可以部署到生產(chǎn)中。
持續(xù)集成的過程獨(dú)立于任何工具。您可以手動驗(yàn)證分支和主分支的合并在本地是否有效,然后將合并推送到存儲庫,但是這種方式是非常低效的。這就是使用自動檢查實(shí)施持續(xù)集成的原因。- 該應(yīng)用程序應(yīng)能夠構(gòu)建并啟動
- 最關(guān)鍵的功能應(yīng)始終處于工作狀態(tài)(用戶注冊/登錄過程以及關(guān)鍵的業(yè)務(wù)功能)
- 所有開發(fā)人員都依賴的應(yīng)用程序的通用層應(yīng)該是穩(wěn)定的。這意味著需要對這些通用代碼進(jìn)行單元測試。
實(shí)際上,這意味著您需要拉取適用于您的任何單元測試框架并保護(hù)應(yīng)用程序的公共層。有時(shí),代碼不是很多,可以很快完成。另外,您還需要添加“冒煙測試”以驗(yàn)證代碼是否已編譯以及應(yīng)用程序是否啟動。這對于帶有瘋狂依賴注入的技術(shù)(例如 Java Spring 或 .NET Core)尤其重要。在大型項(xiàng)目中,很容易錯(cuò)誤修改依賴項(xiàng),因此必須確認(rèn)該應(yīng)用程序至少總是始終啟動。如果您有成百上千的測試,則無需為每個(gè)合并運(yùn)行所有測試。這將花費(fèi)大量時(shí)間,并且大多數(shù)測試可能會驗(yàn)證“非團(tuán)隊(duì)阻止者”功能。
我們將在接下來的部分中看到持續(xù)交付的流程將如何充分利用這許多測試。與工具無關(guān)
工具和自動檢查都可以。但是,如果您的開發(fā)人員僅合并他們工作了幾個(gè)星期的巨型分支機(jī)構(gòu),那么他們將無濟(jì)于事。團(tuán)隊(duì)將花費(fèi)大量時(shí)間合并分支并修復(fù)最終將出現(xiàn)的代碼不兼容問題。與錯(cuò)誤的提交阻塞在一起一樣浪費(fèi)時(shí)間。持續(xù)集成與工具無關(guān)。這是關(guān)于小塊工作并將新代碼集成到主分支并頻繁提取的問題。
通常至少每天一次,將您正在處理的任務(wù)拆分為較小的任務(wù),經(jīng)常合并您的代碼,并經(jīng)常拉取。這樣一來,沒有人能分開工作超過一兩天,問題就沒有時(shí)間滾雪球了。一項(xiàng)大型任務(wù)不必全部都在一個(gè)分支中。應(yīng)該永遠(yuǎn)不會。將進(jìn)行中的工作合并到主分支的技術(shù)稱為“抽象分支”和“功能切換”。有關(guān)更多詳細(xì)信息,請參見博客文章“如何開始進(jìn)行持續(xù)集成”。良好的 CI 關(guān)鍵點(diǎn)
這非常簡單,保持簡短,最多 3-7 分鐘。這與CPU和資源無關(guān),這與開發(fā)人員的生產(chǎn)力有關(guān)。生產(chǎn)力的首要規(guī)則是專注。做一件事,完成它,然后移到下一件事。上下文切換成本很高。研究表明,當(dāng)您被打擾時(shí),大約需要 23 分鐘才能重新專注于某件事。想象一下,您推動分支進(jìn)行合并,然后您開始另一個(gè)任務(wù)。您花了15到20分鐘才能解決。在您進(jìn)入?yún)^(qū)域后的一分鐘,您會從前一個(gè)任務(wù)的20分鐘的 CI 構(gòu)建中收到“構(gòu)建失敗”通知。您再次推送它,您來回切換很容易超過20分鐘。每天一次或兩次將 20 分鐘乘以您的團(tuán)隊(duì)中的開發(fā)人員的數(shù)量……這浪費(fèi)了很多寶貴的時(shí)間。
現(xiàn)在想象一下反饋在 3 分鐘之內(nèi)到來。而且您知道會的。您可能根本不會啟動新任務(wù)。您將有時(shí)間再次閱讀您的代碼,或者在等待時(shí)檢查 PR,失敗的通知將會到來。您將修復(fù)它,然后繼續(xù)下一個(gè)任務(wù)。這就是您的流程應(yīng)啟用的焦點(diǎn)。
保持 CI 的構(gòu)建時(shí)間短,這是一個(gè)折衷方案。在 CI 范圍內(nèi)運(yùn)行時(shí)間更長或幾乎沒有價(jià)值的測試應(yīng)移至 CD 步驟。是的,那里的故障也需要修復(fù)。但是,由于它們不會阻止任何人做他們的事情,因此您可以在完成工作后將這些修補(bǔ)程序作為“下一項(xiàng)任務(wù)”。只需在工作時(shí)關(guān)閉通知并不時(shí)檢查即可。保持上下文切換到最小。
持續(xù)交付和部署是工程問題
持續(xù)交付是指能夠隨時(shí)部署任何版本的代碼。實(shí)際上,它是指代碼的最新版本。您不會自動部署,通常是因?yàn)槟槐鼗虿皇茼?xiàng)目生命周期的限制。但是只要有人愿意,就可以在最短的時(shí)間內(nèi)完成部署。有人可以成為想要在暫存或預(yù)生產(chǎn)環(huán)境中進(jìn)行測試的 test/QA 團(tuán)隊(duì)。或者實(shí)際上可能是時(shí)候?qū)⒋a推向生產(chǎn)了。持續(xù)交付的思想是準(zhǔn)備與您要在環(huán)境中運(yùn)行的制品盡可能接近。如果使用 Java,則可以是 jar 或 war 文件,如果使用 .NET,則可以是可執(zhí)行文件。它們也可以是已轉(zhuǎn)譯 JS 代碼的文件夾,甚至是 Docker 容器,或者其他使部署變得更短(即,您已盡可能預(yù)先構(gòu)建)。通過準(zhǔn)備制品,我不是要把代碼變成制品。這通常是一些腳本和執(zhí)行時(shí)間。準(zhǔn)備意味著:運(yùn)行所有測試,以確保代碼一旦部署便可以正常工作。如果可以自動執(zhí)行單元測試,集成測試,端到端測試,甚至性能測試。
這樣,您可以過濾主分支的哪些版本實(shí)際上已準(zhǔn)備好生產(chǎn),哪些尚未準(zhǔn)備就緒。理想的測試套件:- 確保應(yīng)用程序關(guān)鍵功能正常工作。理想情況下,所有功能正常
- 確保沒有引入性能破壞因素,因此當(dāng)您的新版本受到眾多用戶的歡迎時(shí),它就有機(jī)會發(fā)生
- 空運(yùn)行您的代碼需要的任何數(shù)據(jù)庫更新,以免出現(xiàn)意外
它不需要非常快。30分鐘或1小時(shí)是可以接受的。持續(xù)部署是下一步。您將代碼的最新版本和生產(chǎn)就緒版本部署到某些環(huán)境。如果您足夠信任 CD 測試套件,則是理想的生產(chǎn)方式。請注意,根據(jù)上下文,這并非總是可能或值得付出。持續(xù)交付通常足以提高生產(chǎn)力。特別是如果您在封閉的網(wǎng)絡(luò)中工作并且環(huán)境有限,則可以部署到該環(huán)境。也可能是軟件的發(fā)布周期阻止了計(jì)劃外的部署。持續(xù)交付和持續(xù)部署(從現(xiàn)在起將其稱為 CD)不是團(tuán)隊(duì)問題。他們的目的是在執(zhí)行時(shí)間,維護(hù)工作和測試套件的相關(guān)性之間找到適當(dāng)?shù)钠胶猓员隳軌蛘f“此版本應(yīng)能正常工作”。這是一個(gè)平衡。如果您的測試持續(xù) 30 個(gè)小時(shí),那就有問題了。有關(guān) Oracle 數(shù)據(jù)庫測試套件的例子,請參見這篇史詩般的帖子。如果您花費(fèi)大量時(shí)間使測試與最新代碼保持最新,從而阻礙了團(tuán)隊(duì)的進(jìn)步,那也不是一件好事。而且,如果您的測試套件幾乎沒有任何保證……那基本上是沒有用的。在理想的世界中,我們每次向主分支提交都需要 1 組可部署的制品。您可以看到我們有一個(gè)垂直的可擴(kuò)展性問題:我們從代碼轉(zhuǎn)移到制品的速度越快,我們就越準(zhǔn)備好部署最新版本的代碼。最大的不同是什么?
持續(xù)集成是一個(gè)水平可伸縮性問題。您希望開發(fā)人員經(jīng)常合并其代碼,因此檢查必須快速。理想情況下,幾分鐘之內(nèi)就可以避免開發(fā)人員始終通過 CI 版本的高度異步反饋來切換上下文。您擁有的開發(fā)人員越多,則在所有活動分支上運(yùn)行簡單檢查(構(gòu)建和測試)所需的計(jì)算能力就越高。- 確保沒有將破壞基本內(nèi)容并阻止其他團(tuán)隊(duì)成員工作的代碼引入主分支
- 足夠快,可以在幾分鐘內(nèi)向開發(fā)人員提供反饋,以防止任務(wù)之間進(jìn)行上下文切換
持續(xù)交付和部署是垂直可伸縮性問題。您需要執(zhí)行一個(gè)相當(dāng)復(fù)雜的操作。一個(gè)常見的誤解是將 CD 視為諸如 CI 之類的水平可擴(kuò)展性問題:從代碼移至制品的速度越快,實(shí)際處理的提交越多,并且越接近理想的情況。但是我們不需要。盡可能快地為每次提交生產(chǎn)制品通常是過度的。您可以盡最大的努力很好地使用 CD:擁有一個(gè) CD 構(gòu)建,它將在給定構(gòu)建完成后立即選擇最新提交進(jìn)行驗(yàn)證。毫無疑問 CD 真的很難。獲得足夠的測試信心才能說您的軟件已準(zhǔn)備好自動部署,通常可以在諸如 API 或簡單 UI 之類的底層應(yīng)用程序上使用。在復(fù)雜的 UI 或大型整體系統(tǒng)上很難實(shí)現(xiàn)。結(jié)論
用于執(zhí)行 CI 和 CD 的工具和原理通常非常相似。但是目標(biāo)是非常不同的。持續(xù)集成是在給開發(fā)人員的反饋速度與執(zhí)行的檢查(構(gòu)建和測試)的相關(guān)性之間做出的折衷。沒有任何妨礙團(tuán)隊(duì)進(jìn)步的代碼可以進(jìn)入主分支。持續(xù)交付部署是要進(jìn)行徹底檢查,以發(fā)現(xiàn)代碼問題。檢查的完整性是最重要的因素。通常以測試的代碼覆蓋率或功能覆蓋率來衡量。盡早發(fā)現(xiàn)錯(cuò)誤可以防止將壞代碼部署到任何環(huán)境,并節(jié)省測試團(tuán)隊(duì)的寶貴時(shí)間。精心設(shè)計(jì) CI 和 CD 構(gòu)建以實(shí)現(xiàn)這些目標(biāo)并保持團(tuán)隊(duì)的生產(chǎn)力。沒有工作流是完美的。問題會時(shí)不時(shí)地發(fā)生。每次使用它們時(shí),都可以將其作為學(xué)習(xí)的經(jīng)驗(yàn)教訓(xùn)來加強(qiáng)您的工作流程。
點(diǎn)亮,服務(wù)器三年不宕機(jī)