# Continuous Delivery 107-124
---
## 第五章 部屬流水線解析
---
### 引言
---
### 什麼是部屬流水線?
---
### 抽象層面上
指軟體從版本控制
到使用者手中期間的
**自動化表現形式**
---
>具體呈現出查看與控制每個變更的整個歷程
>包括每次變更被**提交**到版本控制開始
>直到通過各種**測試**和**佈署**
>最後**發布**給使用者
> 容器化之後 會把部屬跟發布做結合
---
### 實際上
將客戶或使用者腦中的一個想法
變成其手中真實可用的特性
![](https://i.imgur.com/MMTiyLg.jpg)
本書僅討論右邊三個
---
![](https://i.imgur.com/fzZQPRF.jpg "" =800x480)
> 起點是每次對版本控制的提交
---
![](https://i.imgur.com/ogLR54z.jpg)
---
有效阻止**未經充分測試**
![](https://i.imgur.com/AbQP3GN.jpg)
或**未滿預期的版本**進入生產環境
也能避免回歸缺陷
---
當部屬和發布都被自動化之後
這些活動就變成快速、可重複且可靠
---
發布工作變得容易
變成一件"平常"的事務
只要願意 就能頻繁發布
---
如果支援了自動化的安全還原
發布風險就能大幅降低
最糟的狀況就是還原
---
過程可分成下面四個階段
---
### 提交階段
從技術角度斷言整個系統是可以運作的
此階段會進行編譯,執行自動化測試
> 主要是單元測試
程式碼分析
---
### 自動化驗收測試階段
從功能性與非功能性的角度
斷言整個系統是可以運作的
針對系統行為,能滿足使用者的需要
並可符合客戶的需求規格
---
### 手動測試階段
斷言系統的可用性
滿足系統要求
試圖發現自動化測試未能捕獲的缺陷
驗證系統是否已為使用者提供價值
通常包括
* 探索性測試
* 整合環境測試
* 使用者驗收測試
---
### 發布階段
將軟體交付給使用者
可能是**套裝軟體**
也可能是佈署到**生產環境**
或**試運行環境**
---
佈署流水線就是由上述階段
以及為軟體交付流程建模所需的其他階段共同組成
有時也可稱為持續整合流水線、建置流水線、佈署生產線或現行建置
---
根本上而言 就是個自動化的軟體交付流程
不是指不需要人的參與
指在執行階段,易出錯且複雜的步驟
會轉變成**可靠**且**可重複**的自動化流程
---
## 最基本的佈署流水線
![](https://i.imgur.com/m7KmjZ3.jpg)
---
### 第一階段
* 編譯程式碼
* 單元測試
* 程式碼分析
* 建立產出物
流程順利的話
會產生軟體binary,composer vendor,node_modules之類的流程產出物
利用Nexus,Artifactory之類的工具管理產出物
---
### 第二階段
執行時間較長的自動化驗收測試
最好能支援將測試分成多組
以便能併行 提高執行效率
使能**更快獲取回饋**
應該是第一階段成功完成後能自動觸發
---
可能會有分支出現
可獨立佈署到多個不同的環境 例如
* 使用者驗收測試環境
* 容量測試環境
* 生產環境
---
**不需要完全自動**
讓測試人員或業務人員可以手動選擇佈署腳本來執行
人員應可以看到版本做過哪些修改
以及簽入的註釋
之後只需點擊按鈕 即可觸發相應的佈署腳本
---
不同階段的使用者各自傭有其環境使用許可
特定人士才有權限可以佈署
---
所做的一切都是為了能盡快得到回饋
為了加速回饋
應讓每個部屬版本在流水線的哪個階段都要顯而易見
以方便追蹤是哪個版本在哪個階段出問題
---
## 佈署流水線的相關測試
推薦實踐
---
### 只產生一次binary(產出物)
如果每次都重新產生
可能版本之間使用的產出物會不一樣
導致問題難以追蹤
或者導致使用到本來不打算使用的版本
---
重複編譯違反兩個重要原則
1. 保證佈署流水線導致的效率提升,使團隊提早得到回饋
2. 始終在**已知可靠**的基礎上進行建置
---
此原則的必然成果之一是
能夠在任意環境上佈署產出物
促使將程式碼(對不同的環境是相同的)與設置(因環境而不同)分開放置
---
### 為什麼產出物不應該與環境有相關性
不利於佈署的靈活性、方便性、和系統的可維護性
但有些工具會鼓勵這麼做
---
### 對不同環境採用相同的佈署方式
* 使用屬性檔保存設置資訊
* 放到目錄服務中
* 放在資料庫
* 設定管理服務
---
完全可以從**同一個來源**
找到在**所有環境**中執行之**所有應用程式**設置資訊
---
使用相同的腳本對開發環境和生產環境佈署
此為避免"他在我的機器上可以運作"症狀的法寶
---
如果使用同一個腳本在全部的環境下進行佈署
那當某個環境上的佈署失效時
就可以確定其原因一定來自於下面三方面
* 與該環境相關的設定檔,某項設置有問題
* 基礎設施或應用程式所依存的某個服務有問題
* 環境本身的設置有問題
要找出原因可以用下面兩個實踐解決問題
---
### 對佈署進行冒煙測試
啟動應用程式,檢查是否能看到主頁面,並且看到正確的內容即可
應檢查依存的服務是否都已經啟動,且能正常執行了,例如資料庫 MQ 或外部服務
---
### 在生產環境的副本中佈署
盡量在與生產環境相似的環境中進行測試和持續測試
確保
* 基礎設施是相同的,例如:網路拓撲結構和防火牆
* 作業系統(包含修補程式的版本)是相同的
* 應用程式使用的軟體堆疊是相同的
* 應用程式的資料處於已知且有效的狀態
___
### 每次變更都要立即在流水線中傳遞
---
#### 持續整合出現之前
許多專案有個個階段的執行時間表
* 每小時建置一次
* 每天晚上執行一次驗收測試
* 每周末執行一次容量測試
---
#### 部署流水線下的狀況
* 每次簽入都要觸發第一個階段的執行
* 第一個階段執行成功才執行下一個階段
---
##### 頻繁簽入的狀況
當簽入頻率過高
建置就會漸漸落後於開發人員的開發速度
---
##### 另一種建置策略
前次的建置過程跑完以後 就自動檢查是否有新的簽入
如果有 就把新的版本拿來跑(可能一次跨多個簽入)
所以有錯誤時 流水線 無法判斷是哪個簽入導致的問題
但開發人員自己可以發現問題在哪
---
### 只要有環節失敗,就停止整個流水線
本書所描述的目標
> **迅速、可重複且可靠的發布**
假如某個環境上的某次部屬失敗
整個團隊就要對這次失敗負責
必須停下手邊工作
直到修復後再做其他事情
---
## 提交階段
每次簽入都會產生佈署流水線的新實例
如果提交階段的測試通過
此版本就會視為候選發布版本之一
---
### 第一階段目標
消除那些不適合生產環境的建置
儘快回饋錯誤
---
### 最好在五分鐘之內完成 最多不能超過十分鐘
* 編譯程式碼
* 執行一套提交測試
* 為後續階段建立binary
* 執行程式碼分析來檢查程式碼的健康狀況
* 為後續階段作準備工作
---
#### 編譯原始碼的最新版本
如果出現錯誤
就像最後一次簽入成功之後
所有簽入過程式碼的人送通知
失敗就讓整個提交階段失敗
不考慮後續工作
---
#### 執行測試集合
最好進行最佳化 讓他執行的飛快
提交測試大部分是單元測試
但同時包含一小部分其他類型的測試
是非常有用的
---
會更有信心說
只要提交階段成功
就證明我們的應用程式是可以正常執行的
---
此測試集合也是開發人員在向版本控制系統之前
需要在本地執行的測試
或是在一個建置網格上執行的預提交測試
---
#### 通過編譯和測試不是一切
* 測試覆蓋率
* 重複程式碼的數量
* 圈複雜度
* 輸入耦合度和輸出耦合度
* 編譯警告的數量
* 程式碼風格
---
### 提交階段的最佳實踐
開發人員需要一直等到部屬流水線的
提交階段成功完成
如果失敗了
開發人員得快速的將問題修復
否則也得將變更還原
---
#### 部屬流水線此用語的來源
pipeline
可並行
如果其中一個工作失敗即停止
---
#### 第一階段的成功
一旦通過此關卡
開發人員就會從上一個任務釋放出來
開始下一個任務
---
然而,開發人員依然有責任監視後續階段的執行狀況
如後續階段發生問題
開發團隊須將修復失敗的建置放在必須首先完成的重點工作
---
我們賭自己能成功
可能會賭輸
但也已經準備好去償還技術債
> 提早回饋可以減少賭輸時的成本
---
{"metaMigratedAt":"2023-06-14T17:36:00.580Z","metaMigratedFrom":"YAML","title":"Continuous Delivery 107-124","breaks":"true","slideOptions":"{\"transition\":\"slide\"}","contributors":"[{\"id\":\"1d1f8686-14d3-4db9-819f-53aaf77970cd\",\"add\":3983,\"del\":154}]"}