CI和CD之間的真正區別 -Fire CI

banq發表於2019-12-02

瞭解CI和CD解決的問題以正確使用它們至關重要。這將使您的團隊可以改善您的流程。並避免花力氣追求那些不會給您的過程帶來任何價值的幻想指標。

持續整合是一個團隊問題
如果您在團隊中工作,那麼您是在同一個儲存庫上工作的多個開發人員。儲存庫中有一個主分支,其中載有最新版本的程式碼。開發人員在不同分支上從事不同的工作。變更完成後,他會將其推送或合併到主分支。最終,整個團隊將拉取這一變化。
我們要避免的情況是錯誤的提交使其進入主分支。錯誤意味著程式碼無法編譯或應用程式無法啟動或無法使用。需要永遠不要部署該版本並等待修復。
問題是您的整個團隊都陷入了困境。所有提出錯誤提交的開發人員都將花費5分鐘來思考為什麼它不起作用。有些人可能會嘗試查詢錯誤的提交。有些人會嘗試與有問題的程式碼作者並行解決問題。
這對您的團隊來說是浪費時間。最糟糕的是,重複發生的事件加劇了對主分支機構的不信任,並鼓勵開發人員分開工作。

持續整合就是為了防止主分支被破壞,從而使您的團隊不會陷入困境。這並不是要讓所有測試始終保持綠色並且主分支在每次提交時都可以部署到生產中。

持續整合的過程獨立於任何工具。您可以手動驗證分支和主分支的合併在本地是否有效。然後僅將合併推送到儲存庫。這是非常低效的。這就是為什麼使用自動檢查實現持續整合的原因。
檢查應確保最低限度:

  • 該應用程式應構建並啟動
  • 最關鍵的功能應始終處於工作狀態(使用者註冊/登入過程以及關鍵的業務功能)
  • 所有開發人員都依賴的應用程式的通用層應該是穩定的。這意味著對這些零件進行單元測試。

實際上,這意味著您需要提取適用於您的任何單元測試框架並保護應用程式的公共層。有時,程式碼不是很多,可以很快完成。另外,您還需要新增“煙霧測試”以驗證程式碼是否已編譯以及應用程式是否啟動。這對於帶有瘋狂依賴注入的技術(例如Java Spring或.NET Core)尤其重要。在大型專案中,很容易誤解依賴項,因此必須確認該應用程式至少總是始終啟動。

如果您有成百上千的測試,則不需要為每個合併執行所有測試。這將花費大量時間,並且大多數測試可能會驗證“non team blocker”功能。

我們將在接下來的部分中看到連續交付的流程將如何充分利用這許多測試。

與工具無關
工具和自動檢查都可以。但是,如果您的開發人員合併他們工作了幾個星期的巨型分支機構,那麼工具和自動檢查將無濟於事。團隊將花費大量時間合併分支並修復最終將出現的程式碼不相容問題。與錯誤的提交阻塞在一起一樣浪費時間。

持續整合與工具無關。這是關於小塊工作並將新程式碼整合到主分支並頻繁提取的問題。

通常至少每天一次持續整合。將您正在處理的任務拆分為較小的任務。經常合併您的程式碼,並經常拉取。這樣一來,沒有人能分開工作超過一兩天,就沒有時間滾雪球了。
一項大型任務不必全部都在一個分支中。應該永遠不會。將進行中的工作合併到主分支的技術稱為“抽象分支”和“功能切換”。有關更多詳細資訊,請參見部落格文章“ 如何開始進行持續整合 ”。

優質CI的關鍵點
非常簡單 保持簡短。最多3-7分鐘。這與CPU和資源無關。這與開發人員的生產力有關。生產力的首要規則是專注。做一件事,完成它,然後移到下一件事。
上下文切換成本很高。研究表明,當您被打擾時,大約需要23分鐘才能重新專注於某件事。想象一下,您推動分支進行合併。您開始另一個任務。您花了15到20分鐘才能進入。在您進入區域後的一分鐘,您會從前一個任務的20分鐘的CI構建中收到“構建失敗”通知。您回來修復它。您再按一次。您來回走動很容易超過20分鐘。

每天一次或兩次將20分鐘乘以團隊中開發人員的數量……這是浪費很多寶貴的時間。

現在想象一下反饋在3分鐘之內到來。而且您知道會的。您可能根本不會啟動新任務。您將有證據支援你再次閱讀您的程式碼,或者在等待時檢查PR。失敗的通知將會到來。您將修復它。然後繼續下一個任務。這就是您的流程應啟用的焦點。
保持CI的構建時間短,這是一個折衷方案。在CI範圍內執行時間更長或幾乎沒有價值的測試應移至CD步驟。是的,那裡的故障也需要修復。但是,由於它們不會阻止任何人做他們的事情,因此您可以在完成工作後將這些修補程式作為“下一項任務”。只需在工作時關閉通知並不時檢查即可。保持上下文切換到最小。

持續交付和部署是工程問題
讓我們解決一下定義,以消除這些障礙。
持續交付是指能夠隨時部署任何版本的程式碼。實際上,它是指程式碼的最新版本。您不會自動部署,通常是因為您不必或不受專案生命週期的限制。但是隻要有人願意,就可以在最短的時間內完成部署。有人可以成為想要在暫存或預生產環境中進行測試的測試/ QA團隊。或者實際上可能是時候將程式碼推向生產了。
連續交付的想法是準備與您要在環境中執行的東西儘可能接近。如果使用Java,則可以是jar或war檔案,如果使用.NET,則可以是可執行檔案。它們也可以是已轉譯的JS程式碼的資料夾,甚至是Docker容器的資料夾,無論使部署變得更短(即,您已儘可能預先構建)。
透過準備這些腳手架,這通常是一些指令碼和執行時間。準備方式:

執行所有測試,以確保程式碼一旦部署便可以正常工作。如果可以自動執行單元測試,整合測試,端到端測試,甚至效能測試。

這樣,您可以過濾主分支的哪些版本實際上已準備好生產,哪些尚未準備就緒。理想的測試套件:

  • 確保應用程式關鍵功能正常工作。理想情況下,涵括所有功能
  • 確保沒有引入效能破壞因素,因此當您的新版本受到眾多使用者的歡迎時,它就有機會持續生存
  • 空執行您的程式碼避免需要的任何資料庫更新,以免出現意外

它不需要非常快。30分鐘或1小時是可以接受的。
持續部署是下一步。您將程式碼的最新版本和生產就緒版本部署到某些環境。如果您足夠信任CD測試套件,則是理想的生產方式。
請注意,根據上下文,這並非總是可能或值得付出。持續交付通常足以提高生產力。特別是如果您在封閉的網路中工作並且環境有限,則可以部署到該環境。也可能是軟體的釋出週期阻止了計劃外的部署。
持續交付和持續部署(從現在起將它們稱為CD)不是團隊問題。他們的目的是在執行時間,維護工作和測試套件的相關性之間找到合適的平衡點,以便能夠說“此版本可以正常工作”。這是一個平衡。如果您的測試持續30個小時,那就有問題了。有關Oracle資料庫測試套件的外觀,請參見這篇史詩般的帖子如果您花費大量時間使測試與最新程式碼保持最新,從而阻礙了團隊的進步,那也不是一件好事。而且,如果您的測試套件幾乎沒有任何保證……那基本上是沒有用的。

在理想的世界中,我們每次向主分支提交都需要1組可部署的工件。您可以看到我們有一個垂直的可擴充套件性問題:我們從程式碼轉移到工件的速度越快,我們就越準備好部署最新版本的程式碼。

有什麼大不同?
持續整合是一個水平可伸縮性問題。您希望開發人員經常合併其程式碼,因此檢查必須快速。理想情況下,幾分鐘之內就可以避免開發人員始終透過CI版本的高度非同步反饋來切換上下文。
您擁有的開發人員越多,則在所有活動分支上執行簡單檢查(構建和測試)所需的計算能力就越高。

良好的CI構建:

  • 確保沒有將破壞基本內容並阻止其他團隊成員工作的程式碼引入主分支
  • 足夠快,可以在幾分鐘內向開發人員提供反饋,以防止任務之間進行上下文切換

持續交付和部署是垂直可伸縮性問題。您需要執行一個相當複雜的操作。

良好的CD釋出:

  • 確保儘可能多的功能正常執行
  • 速度越快越好,但這不是速度問題。30至60分鐘的構建就可以了

一個常見的誤解是將CD視為諸如CI之類的水平可擴充套件性問題:從程式碼移至工件的速度越快,實際處理的提交越多,並且越接近理想的情況。但是我們不需要。儘可能快地為每次提交生產腳手架通常是過大的。您可以盡最大的努力很好地使用CD:擁有一個CD構建,它將在給定構建完成後立即選擇最新提交進行驗證。
毫無疑問CD真的很難。獲得足夠的測試信心才能說您的軟體已準備好自動部署,通常可以在諸如API或簡單UI之類的底層應用程式上使用。在複雜的UI或大型整體系統上很難實現。

結論
用於執行CI和CD的工具和原理通常非常相似。但是目標是非常不同的。
持續整合是在反饋給開發人員的反饋速度與執行的檢查(構建和測試)的相關性之間做出的折衷。沒有任何妨礙團隊進步的程式碼可以進入主分支。
持續交付部署是要進行徹底檢查,以發現程式碼問題。檢查的完整性是最重要的因素。通常以測試的程式碼覆蓋率或功能覆蓋率來衡量。儘早發現錯誤可以防止將損壞的程式碼部署到任何環境,並節省測試團隊的寶貴時間。
​​​​​​​精心設計CI和CD版本以實現這些目標並保持團隊的生產力。沒有工作流程是完美的。問題會時不時地發生。每次使用它們時,都可以將其作為學習的經驗教訓來加強您的工作流程。

相關文章