共用方式為


Microsoft 如何使用 DevOps 進行開發

Microsoft 致力於使用 一個工程系統 來構建和部署所有 Microsoft 產品,其可靠的 DevOps 流程以 Git 分支和發布流程為中心。 本文重點介紹實際實作、系統如何從小型服務擴展到大規模平台開發需求,以及從跨各個 Microsoft 團隊使用該系統中學到的經驗教訓。

採用標準化的開發流程是一項雄心勃勃的事業。 不同 Microsoft 組織的需求差異很大,組織內不同小組的需求會隨著規模和複雜性而調整。 為了滿足這些不同的需求,Microsoft 使用 主幹型分支策略 來協助快速開發產品、定期部署產品,並將變更安全地傳遞至生產環境。

Microsoft 也使用 平臺工程原則 作為其 One Engineering System 的一部分。

Microsoft 發行流程

每個組織都應該採用標準程式碼發行流程,以確保團隊之間的一致性。 Microsoft 發行流程會整合從開發到發行的 DevOps 程式。 發佈流程的基本步驟包括建立分支、推送、提出拉取請求和合併。

分支

若要修正錯誤或實作功能,開發人員會在主要整合分支中建立新分支。 Git 輕量型分支模型會為每個程式碼貢獻建立這些短期 主題 分支。 開發人員會儘早提交,並使用 功能旗標來避免長時間執行的功能分支。

推送

當開發人員準備好整合變更並將其交付給小組的其餘成員時,他們會將其本機分支推送至伺服器上的分支,並開啟提取要求。 在許多分支中工作數百名開發人員的儲存庫使用伺服器分支的命名慣例來減輕混亂和 分支擴散。 開發人員通常會建立名為 users/<username>/feature的分支,其中 <username> 是他們的帳戶名稱。

提取要求

提取請求控制主題分支合併到主分支中,並確保滿足分支策略。 提取要求程式會建置建議的變更,並執行快速測試階段。 第一級和第二級測試套件在不到五分鐘的時間內運行了大約 60,000 個測試。 這不是完整的 Microsoft 測試矩陣,但足以快速提供對提取請求的信心。

接下來,團隊的其他成員審查程式碼並批准變更。 程式碼審查從自動化測試中斷的地方繼續,對於發現架構問題特別有用。 手動程式碼審查可確保團隊中的其他工程師能夠了解變更,並且程式碼品質保持較高。

合併

一旦提取要求滿足所有建置原則,且檢閱者已簽核,主題分支就會合併到主要整合分支中,且提取要求即完成。

合併之後,會執行其他驗收測試,這些測試需要更多時間才能完成。 這些傳統的簽入後測試會進行更徹底的驗證。 此測試過程在提取請求審查期間進行快速測試和在發布之前擁有完整的測試覆蓋率之間提供了良好的平衡。

與 GitHub Flow 的差異

GitHub Flow 是一種流行的 基於主幹的開發 發布流程,供組織實施可擴展的 Git 方法。 然而,一些組織發現,隨著需求增長,他們必須離開 GitHub Flow 的某些部分。

例如,GitHub Flow 中經常被忽略的部分是,提取請求必須部署到生產環境進行測試,然後才能合併到主分支。 此程序表示所有拉取請求都會在部署佇列中等待合併。

有些團隊有數百名開發人員在單一儲存庫中持續工作,他們每天可以完成 200 多個拉取請求到主分支。 如果每個提取請求都需要部署到全球多個 Azure 數據中心進行測試,開發人員會花時間等待分支合併,而不是編寫軟件。

相反地,Microsoft 團隊會繼續在主要分支中開發,並將部署匯整成週期性發布,通常與三週的 衝刺 步調對齊。

實作詳細資料

以下是 Microsoft 發行流程的一些重要實作詳細數據:

Git 存放庫策略

不同的團隊有不同的策略來管理其 Git 儲存庫。 有些團隊將大部分程式碼保存在一個 Git 儲存庫中。 程式碼會分解成元件,每個元件都位於自己的根層級資料夾中。 大型元件 (尤其是較舊的元件) 可能有多個子元件,這些子元件在父元件內具有個別的子資料夾。

顯示 Git 存放庫結構的螢幕擷取畫面。

附屬儲存庫

有些團隊也會管理附屬儲存庫。 例如,建置和發行 代理程式工作VS Code 延伸模組開放原始碼專案 都是在 GitHub 上開發的。 組態變更簽入至個別存放庫。 團隊相依的其他套件來自不同來源,並透過 NuGet 使用。

單一存放庫或多重存放庫

雖然某些小組選擇擁有單一整合型存放庫,即 單一存放庫,但其他 Microsoft 產品會使用 多重存放庫 方法。 例如,Skype 有數百個小型儲存庫,這些儲存庫以各種組合拼接在一起,以建立許多不同的用戶端、服務和工具。 特別是對於採用微服務的團隊來說,多存儲庫可能是正確的方法。 通常,從單體架構開始的舊產品會發現單一儲存庫策略是過渡到 Git 版本控制系統的最容易方法,其程式碼組織也反映了這一點。

發行分支

Microsoft 版本流程會讓主分支隨時保持可建置。 開發人員在合併到 main 的短期主題分支中工作。 當小組準備好發佈時,無論是在衝刺結束時還是進行重大更新,他們都會從主要分支啟動新的發行分支。 發行分支永遠不會合併回主要分支,因此可能需要選擇性套用重要的變更。

下圖以藍色顯示短期分支,以黑色顯示釋放分支。 一個具有需要挑選的提交分支顯示為紅色。

顯示 Git 發行分支結構的圖表。

分支原則和權限

Git 分支原則有助於強制執行發行分支結構,並保持主要分支乾淨。 例如,分支原則能防止直接推送至主要分支。

為了讓分支階層保持整潔,小組會使用許可權來封鎖階層根層級的分支建立。 在下列範例中,每個人都可以在 users/features/teams/ 等資料夾中建立分支。 只有發行管理員有權在 releases/下建立分支,而某些自動化工具有權存取 integrations/ 資料夾。

顯示分支的螢幕擷取畫面。

Git 存放庫工作流程

在儲存庫和分支結構中,開發人員進行日常工作。 工作環境因團隊和個人而異。 有些開發人員更喜歡命令列,有些開發人員喜歡 Visual Studio,而有些開發人員則在不同的平台上工作。 Microsoft 存放庫上的結構和原則可確保堅實且一致的基礎。

一般工作流程涉及下列常見工作:

建置新功能

構建新功能是軟件開發人員工作的核心。 該過程的非 Git 部分包括查看遙測數據、提出設計和規範,以及編寫實際代碼。 然後,開發人員透過同步到main上的最新提交來開始使用儲存庫。 主分支總是可建造的,所以它保證是一個很好的起點。 開發人員檢出一個新功能分支,修改程式碼、提交至版本庫、推送到伺服器,並開啟新的拉取請求。

使用分支原則和檢查

建立拉取請求時,自動化系統會檢查新程式碼是否能夠成功建置、不會破壞現有功能,也不會違反任何安全或遵循性政策。 此程式不會封鎖其他工作並行進行。

分支政策和檢查項目可能需要成功的建置,包括通過的測試、涉及程式碼擁有者的簽核,以及若干外部檢查,以在完成拉取請求前驗證公司政策。

螢幕擷取畫面顯示提取要求的檢查。

與 Microsoft Teams 整合

許多團隊配置 與 Microsoft Teams 的整合,這會向開發團隊宣布新的 pull request。 任何觸及的程式碼的擁有者都會自動新增為檢閱者。 Microsoft 小組通常會針對許多人接觸的程式碼(例如 REST 用戶端產生和共用控制項)使用選擇性檢閱者,以取得專家對這些變更的關注。

顯示 Teams 整合的螢幕擷取畫面。

螢幕擷取畫面顯示提取要求的 Teams 通知。

使用功能旗標進行部署

一旦審查者、程式碼擁有者和自動化都滿意,開發人員就可以完成拉取請求。 如果發生合併衝突,開發人員會取得如何同步處理衝突、修正衝突以及重新推送變更的指示。 自動化會在固定程式碼上再次執行,但人類不必再次簽核。

分支會合併成 main,而新程式碼會在下一個短期衝刺或主要版本中部署。 這並不意味著新功能會立即出現。 Microsoft 會使用 功能旗標來分離新功能的部署和公開。

即使該功能在準備好展示之前需要更多工作,如果產品構建和部署,也可以安全地使用 main 。 一旦進入 main,程式碼就會成為官方建置的一部分,並再次進行測試、確認符合政策並進行數位簽署。

左移及早發現問題

此 Git 工作流程提供數個優點。 首先,從單一主要分支機構中工作實際上消除了 合併債務。 其次,拉取請求流程提供了一個共通介面,可以在管線早期強制進行測試、程式碼審查和錯誤偵測。 這種 左移 策略有助於縮短對開發人員的回饋週期,因為它可以在幾分鐘內檢測到錯誤,而不是幾小時或幾天。 此策略也為重構提供了信心,因為所有變更都會不斷測試。

目前,具有 200+ 提取請求的產品每天可能會產生 300+ 個持續整合組建,相當於每 24 小時執行 500+ 次測試。 如果沒有基於主幹的分支和發布工作流程,這種級別的測試是不可能的。

在衝刺里程碑上發布

在每個短衝結束時,團隊會從主幹分支建立發佈分支。 例如,在短期衝刺 129 結束時,小組會建立新的發行分支 releases/M129。 然後,團隊將 sprint 129 分支部署到生產環境。

在發行分支的分支之後,主要分支會保持開啟狀態,供開發人員合併變更。 這些變更將在三週後在下一個短期衝刺部署中部署。

第 129 次 Sprint 發布分支的示意圖。

發行 Hotfix

有時變更需要快速投入生產。 Microsoft 通常不會在衝刺過程中添加新功能,但有時希望快速引入錯誤修復以解鎖用戶。 問題可能是次要的,例如拼字錯誤,或大到足以導致可用性問題或 即時網站事件

糾正這些問題從正常工作流程開始。 開發人員建立分支來自 main,對其進行程式碼審查,並完成拉取要求以合併它。 該過程總是從更改 main 開始。 這可讓您快速建立修正程式,並在本機驗證它,而不需要切換至發行分支。

遵循此過程還可以保證更改被納入 main,這一點非常關鍵。 修正發行分支中的錯誤而不將變更帶回 main,意味著在下一次部署時,當 Sprint 130 的發行分支自 main 建立時,該錯誤將會再次發生。 在停電引起的混亂和壓力中,很容易忘記更新 main 。 將變更帶到 main 這表示首先要在主要分支和發行分支中始終保有這些變更。

Git 功能可啟用此工作流程。 若要立即將變更納入生產環境,一旦開發人員將提取請求合併到 main中,他們就可以使用提取請求頁面將變更挑選到發行分支中。 此程序會建立一個新的拉取請求,目標為發行分支,將剛合併到 main 的內容回遷。

挑選修補程式提交到分支 129 的範例。

使用 cherry-pick 功能可迅速建立拉取請求,提供分支政策的可追溯性和可靠性。 可以在伺服器上進行挑選,而不需要將發行分支下載到本地電腦。 由於兩個分支之間的差異而進行更改、修復合併衝突或進行細微更改都可能發生在伺服器上。 團隊可以直接從基於瀏覽器的文本編輯器或通過 提取請求合併衝突擴展 編輯更改,以獲得更高級的體驗。

一旦拉取請求針對發行分支,小組會再次審查它、評估分支策略、測試拉取請求,然後合併它。 合併之後,修正程式會在幾分鐘內部署至伺服器的第一個 。 從那裡,團隊會使用部署通道逐步將修正程式部署到更多帳戶。 當變更部署給更多使用者時,小組會監視成功,並驗證變更是否修正了錯誤,同時不會引入任何缺陷或速度減慢。 修正程式最終會部署至所有 Azure 資料中心。

繼續進行下一個衝刺

在接下來的三週內,小組會完成將功能新增至衝刺週期 130,並準備好部署這些變更。 他們從 releases/M130建立新的發行分支,main並部署該分支。

此時,實際上有兩個分支正在生產中。 透過環式部署安全地將變更引入生產環境,快速環會接收迭代130的變更,而慢速環伺服器則保持在迭代129,並在生產環境中驗證新變更。

在部署中間進行 Hotfix 變更可能需要 Hotfix 兩個不同的版本,即短期衝刺 129 版本和短期衝刺 130 版本。 小組會將 Hotfix 移植並部署至兩個發行分支。 130 分支會將修補程式重新部署至已升級的環。 129 分支會使用 Hotfix 重新部署至尚未升級至下一個短期衝刺版本的外環。

完成所有環的部署後,舊的 Sprint 129 分支將被廢棄,因為作為熱修復帶入 Sprint 129 分支的所有變更也已經在 main 中進行。 因此,這些變更也會在 releases/M130 分支中進行。

第 130 次迭代的發佈分支示意圖。

總結

發行流程模型是 Microsoft 如何使用 DevOps 進行開發以提供線上服務的核心。 此模型使用簡單的、基於主幹的分支策略。 但是,Microsoft 發布流程不會讓開發人員陷入部署隊列中,等待合併他們的更改,而是讓開發人員繼續工作。

此發佈模型也允許以有節奏的方式定期在 Azure 資料中心部署新功能,儘管 Microsoft 程式碼庫龐大且其中工作的開發人員眾多。 該模型還允許快速高效地將修補程序引入生產環境。