Microsoft が DevOps を使用して開発する方法

Microsoft では、 One Engineering System を使用して、Git の分岐とリリース のフローを中心とした堅牢な DevOps プロセスを使用して、すべての Microsoft 製品をビルドしてデプロイするよう努めています。 この記事では、実用的な実装、システムが小規模なサービスから大規模なプラットフォーム開発ニーズにどのようにスケーリングされるか、およびさまざまな Microsoft チームでシステムを使用して学んだ教訓について説明します。

標準化された開発プロセスを採用することは、野心的な取り組みです。 さまざまな Microsoft 組織の要件は大きく異なり、組織内のさまざまなチームの要件は規模と複雑さに応じて拡張されます。 これらのさまざまなニーズに対処するために、Microsoft では トランクベースの分岐戦略を 使用して、製品の迅速な開発、定期的な展開、運用環境への変更の安全な提供を支援しています。

Microsoft リリース フロー

すべての組織は、チーム間の一貫性を確保するために、標準のコード リリース プロセスに落ち着く必要があります。 Microsoft リリース フローには、開発からリリースまでの DevOps プロセスが組み込まれています。 リリース フローの基本的な手順は、ブランチ、プッシュ、プル要求、マージで構成されます。

[Branch]\(ブランチ)

バグを修正したり、機能を実装したりするために、開発者はメイン統合ブランチから新しいブランチを作成します。 Git ライトウェイト ブランチ モデルでは、コードの投稿ごとに短命の トピック ブランチが作成されます。 開発者は早期にコミットし、 機能フラグを使用して実行時間の長い機能ブランチを回避します。

プッシュ

開発者がチームの残りの部分に変更を統合して発送する準備ができたら、ローカル ブランチをサーバー上のブランチにプッシュし、プル要求を開きます。 多数のブランチで作業する数百人の開発者を持つリポジトリでは、サーバー ブランチの名前付け規則を使用して、混乱と ブランチの拡散を軽減します。 開発者は通常、アカウント名という<username>名前users/<username>/featureのブランチを作成します。

Pull request

pull requests control topic branch merges into the main branch and ensureed the branch policies are satisfied. プル要求プロセスは、提案された変更をビルドし、クイック テスト パスを実行します。 第 1 レベルと第 2 レベルのテスト スイートは、5 分以内に約 60,000 個のテストを実行します。 これは完全な Microsoft テスト マトリックスではありませんが、プル要求に対する信頼を迅速に提供するのに十分です。

次に、チームの他のメンバーがコードを確認し、変更を承認します。 コード レビューでは、自動テストが中断された場所が取り上げられ、アーキテクチャの問題を検出するのに特に役立ちます。 手動のコード レビューでは、チームの他のエンジニアが変更を確実に把握し、コード品質が高いままであることを確認します。

マージする

プル要求がすべてのビルド ポリシーを満たし、レビュー担当者がサインオフすると、トピック ブランチがメイン統合ブランチにマージされ、プル要求が完了します。

マージ後、完了するまでに時間がかかる他の受け入れテストが実行されます。 これらの従来のチェックイン後テストでは、より徹底的な検証が行われます。 このテスト プロセスは、プル要求レビュー中に高速テストを行うのと、リリース前に完全なテスト カバレッジを持つことのバランスを取ります。

GitHub Flow との違い

GitHub Flow は、組織が Git にスケーラブルなアプローチを実装するための一般的な トランクベースの開発 リリース フローです。 ただし、一部の組織では、ニーズが高まるにつれて、GitHub Flow の一部から分岐する必要があることに気が付く場合があります。

たとえば、GitHub Flow の見過ごされがちな部分は、プル要求がメイン ブランチにマージされる前に、テストのために運用環境にデプロイする必要があるということです。 このプロセスは、すべてのプル要求がマージのためにデプロイ キュー内で待機することを意味します。

一部のチームには、1 つのリポジトリで数百人の開発者が常に作業しており、1 日あたり 200 件を超えるプル要求をメイン ブランチに完了できます。 各プル要求でテストのために世界中の複数の Azure データ センターへのデプロイが必要な場合、開発者はソフトウェアを記述するのではなく、ブランチのマージを待つ時間を費やします。

代わりに、Microsoft チームはメイン ブランチで開発を続け、通常は 3 週間の スプリント 周期に合わせて、時間指定リリースにデプロイをバッチアップします。

実装の詳細

Microsoft リリース フローの主な実装の詳細を次に示します。

Git リポジトリ戦略

チームによって、Git リポジトリを管理するための戦略が異なります。 一部のチームは、コードの大部分を 1 つの Git リポジトリに保持します。 コードはコンポーネントに分割され、それぞれ独自のルート レベルのフォルダーに格納されます。 大きなコンポーネント (特に古いコンポーネント) には、親コンポーネント内に個別のサブフォルダーを持つ複数のサブコンポーネントが含まれている場合があります。

Git リポジトリ構造を示すスクリーンショット。

補助リポジトリ

一部のチームでは、補助リポジトリも管理しています。 たとえば、 エージェントタスクのビルドとリリース、 VS Code 拡張機能およびオープン ソース プロジェクト は GitHub で開発されます。 構成の変更は、別のリポジトリにチェックインされます。 チームが依存する他のパッケージは、他の場所から取得され、NuGet 経由で使用されます。

Mono リポジトリまたはマルチリポジトリ

一部のチームは単一のモノリシック リポジトリを使用することを選択しますが、 mono-repo、他の Microsoft 製品では マルチリポジトリ アプローチが使用されます。 たとえば、Skype には、さまざまなクライアント、サービス、ツールを作成するために、さまざまな組み合わせで結合された数百の小さなリポジトリがあります。 特にマイクロサービスを受け入れるチームの場合は、マルチリポジトリが適切なアプローチになる可能性があります。 通常、モノリスとして始まった古い製品では、モノリポジトリアプローチが Git への最も簡単な移行であると見なされ、そのコード組織にはそれが反映されています。

リリース ブランチ

Microsoft リリース フローでは、メイン ブランチを常にビルド可能に保ちます。 開発者は、マージする有効期間の短いトピック ブランチで作業します main。 スプリントの最後でもメジャーアップデートでも、チームが発送する準備ができたら、メイン ブランチから新しいリリース ブランチを開始します。 リリースブランチはメインブランチにマージされないため、重要な変更を チェリーピック する必要がある場合があります。

次の図は、青色の短命ブランチと黒のリリース ブランチを示しています。 チェリーピックが必要なコミットを持つブランチが赤で表示されます。

Git リリースブランチの構造を示す図。

ブランチ ポリシーとアクセス許可

Git ブランチ ポリシーは、リリース ブランチ構造を適用し、メイン ブランチをクリーンに保つのに役立ちます。 たとえば、ブランチ ポリシーはメイン ブランチへの直接プッシュを防ぐことができます。

ブランチ階層を整理するために、チームはアクセス許可を使用して、階層のルート レベルでブランチの作成をブロックします。 次の例では、 すべてのユーザーがユーザー/機能/、 チーム/などのフォルダーにブランチを作成できます。 リリース/でブランチを作成する権限を持つのは リリース マネージャーだけです。一部のオートメーション ツールには 統合/ フォルダーへのアクセス許可があります。

ブランチを示すスクリーンショット。

Git リポジトリ ワークフロー

リポジトリとブランチ構造内では、開発者は毎日の作業を行います。 作業環境はチームと個人によって大きく異なります。 一部の開発者はコマンド ラインを好み、Visual Studio などの他の開発者は異なるプラットフォームで動作します。 Microsoft リポジトリに配置されている構造とポリシーにより、強固で一貫性のある基盤が確保されます。

一般的なワークフローには、次の一般的なタスクが含まれます。

新しい機能を構築する

新機能の構築は、ソフトウェア開発者の仕事の中核です。 このプロセスの Git 以外の部分には、テレメトリ データの確認、設計と仕様の作成、実際のコードの記述などがあります。 次に、開発者は、最新のコミットに同期してリポジトリの操作を開始します main。 メイン ブランチは常にビルド可能であるため、適切な開始点であることが保証されています。 開発者は、新しい機能ブランチをチェックアウトし、コードの変更を行い、コミットし、サーバーにプッシュし、新しいプル要求を開始します。

ブランチ ポリシーとチェックを使用する

プル要求を作成すると、自動化されたシステムは、新しいコードがビルドされ、何も中断せず、セキュリティまたはコンプライアンス ポリシーに違反していないことを確認します。 このプロセスでは、他の作業が並列に行われないことはありません。

ブランチ ポリシーとチェックでは、成功したテスト、タッチされたコードの所有者によるサインオフ、プル要求を完了する前に企業ポリシーを確認するためのいくつかの外部チェックなど、ビルドの成功が必要になる場合があります。

プル要求のチェックを示すスクリーンショット。

Microsoft Teams との統合

多くのチーム が Microsoft Teams との統合を構成します。これにより、開発者のチームメイトに新しいプル要求がアナウンスされます。 タッチされたコードの所有者は、レビュー担当者として自動的に追加されます。 Microsoft チームは、多くの場合、REST クライアントの生成や共有コントロールなど、多くのユーザーが触れるコードにオプションの校閲者を使用して、それらの変更に関する専門家の目を得ます。

Teams の統合を示すスクリーンショット。

プル要求の Teams 通知を示すスクリーンショット。

機能フラグを使用してデプロイする

レビュー担当者、コード所有者、自動化が満たされると、開発者はプル要求を完了できます。 マージの競合が発生した場合、開発者は競合に同期し、修正し、変更を再度プッシュする方法に関する指示を受け取ります。 自動化は固定コードで再度実行されますが、人間はもう一度サインオフする必要はありません。

ブランチがマージ mainされ、新しいコードが次のスプリントまたはメジャー リリースにデプロイされます。 これは、新しい機能がすぐに表示されることを意味するわけではありません。 Microsoft では、 機能フラグを使用して、新機能の展開と公開を切り離します。

機能を表示する準備が整う前にもう少し作業が必要な場合でも、製品がビルドされてデプロイされる場合は安全 main です。 一度入力 mainすると、コードは公式ビルドの一部になり、そこで再びテストされ、ポリシーを満たすことが確認され、デジタル署名されます。

左にシフトして問題を早期に検出する

この Git ワークフローには、いくつかの利点があります。 まず、1 つのメイン ブランチから作業すると、 マージ負債が事実上排除されます。 次に、プル要求フローは、パイプラインの早い段階でテスト、コード レビュー、エラー検出を適用するための共通のポイントを提供します。 この シフト左 戦略は、数時間または数日ではなく数分でエラーを検出できるため、開発者へのフィードバック サイクルを短縮するのに役立ちます。 この戦略では、すべての変更が常にテストされるため、リファクタリングに対する信頼も得ることができます。

現在、200 以上のプル要求を持つ製品では、1 日あたり 300 以上の継続的インテグレーション ビルドが生成される可能性があります。これは、24 時間ごとに 500 以上のテスト実行に相当します。 トランクベースの分岐とリリースのワークフローがないと、このレベルのテストは不可能です。

スプリント マイルストーンでのリリース

各スプリントの最後に、チームはメイン ブランチからリリース ブランチを作成します。 たとえば、スプリント 129 の終了時に、チームは新しいリリース ブランチを作成します releases/M129。 その後、チームはスプリント 129 ブランチを運用環境に配置します。

リリース ブランチのブランチの後、メイン ブランチは開発者が変更をマージできるように開いたままです。 これらの変更は、次のスプリントデプロイで 3 週間後にデプロイされます。

スプリント 129 のリリース ブランチの図。

リリース修正プログラム

場合によっては、変更をすぐに運用環境に移行する必要があります。 Microsoft は通常、スプリントの途中で新機能を追加しませんが、ユーザーのブロックを解除するためにバグ修正を迅速に取り込みたい場合があります。 問題は、入力ミスなどの軽微な問題や、可用性の問題や ライブ サイト インシデントを引き起こすのに十分な大きさである可能性があります。

これらの問題を修正することは、通常のワークフローから始まります。 開発者がブランチを main作成し、コードを確認してマージする pull request を完了します。 プロセスは常に最初に変更 main を加えることで開始されます。 これにより、リリース ブランチに切り替えることなく、修正を迅速に作成し、ローカルで検証できます。

このプロセスに従って、変更が発生 mainすることも保証されます。これは重要です。 変更を戻さずにリリース ブランチのバグを main 修正すると、スプリント 130 リリースブランチの次のデプロイ中にバグが再発することを意味します main。 停止中に発生する可能性のある混乱とストレスの間に更新 main することを忘れてしまいます。 最初に変更を加 main えるということは、常にメイン ブランチとリリース ブランチの両方に変更を加えるということです。

Git 機能により、このワークフローが有効になります。 変更を運用環境にすぐに取り込 mainむには、開発者が pull request をマージしたら、pull request ページを使用して、リリース ブランチに変更を選択できます。 このプロセスでは、リリース ブランチを対象とする新しいプル要求が作成され、マージされた内容がバックポートされます main

ブランチ 129 への修正プログラムコミットのチェリー選択の図。

チェリーピック機能を使用すると、プル要求をすばやく開き、ブランチ ポリシーの追跡可能性と信頼性を提供します。 チェリーピッキングは、リリース ブランチをローカル コンピューターにダウンロードしなくても、サーバー上で発生する可能性があります。 2 つのブランチ間の違いにより、変更を加えたり、マージ競合を修正したり、小さな変更を加えたりすると、すべてサーバー上で発生する可能性があります。 Teams では、ブラウザー ベースのテキスト エディターまたは Pull Request Merge Conflict Extension を使用して変更を直接編集して、より高度なエクスペリエンスを実現できます。

プル要求がリリース ブランチをターゲットにしたら、チーム コードでもう一度確認し、ブランチ ポリシーを評価し、pull request をテストしてマージします。 マージ後、修正プログラムはサーバーの最初の リング に数分でデプロイされます。 そこから、チームは展開リングを使用して、より多くのアカウントに修正プログラムを段階的にデプロイします。 変更がより多くのユーザーに展開されると、チームは成功を監視し、欠陥や速度低下を発生させず、変更によってバグが修正されることを確認します。 この修正プログラムは最終的にすべての Azure データ センターにデプロイされます。

次のスプリントに移動する

次の 3 週間の間に、チームはスプリント 130 への機能の追加を完了し、それらの変更をデプロイする準備を整えます。 新しいリリース ブランチを作成し、 releases/M130 そのブランチから mainデプロイします。

この時点で、実稼働には実際には 2 つのブランチがあります。 リングベースのデプロイを使用して運用環境に変更を安全に適用すると、高速リングはスプリント 130 の変更を受け取り、低速リング サーバーはスプリント 129 にとどまり、運用環境では新しい変更が検証されます。

展開の途中で変更を修正するには、スプリント 129 リリースとスプリント 130 リリースの 2 つの異なるリリースを修正する必要があります。 チームは、両方のリリース ブランチに修正プログラムをポートして展開します。 130 ブランチは、修正プログラムを使用して、既にアップグレードされているリングに再デプロイします。 129 ブランチは、修正プログラムを使用して、次のスプリントのバージョンにまだアップグレードしていない外側のリングに再デプロイします。

すべてのリングが展開されると、以前のスプリント 129 ブランチは破棄されます。これは、スプリント 129 ブランチに修正プログラムとして加えられた変更も行 mainわれるためです。 そのため、これらの変更はブランチにも含 releases/M130 まれます。

スプリント 130 のリリース ブランチの図。

まとめ

リリース フロー モデルは、オンライン サービスを提供するために Microsoft が DevOps を使用して開発する方法の中心です。 このモデルでは、トランクベースの単純な分岐戦略を使用します。 ただし、開発者がデプロイ キューにスタックしたままにするのではなく、変更のマージを待つ代わりに、Microsoft リリース フローを使用すると、開発者は作業を続けることができます。

このリリース モデルでは、Microsoft のコードベースのサイズと作業している開発者の数にかかわらず、定期的に Azure データ センター全体に新機能をデプロイすることもできます。 このモデルでは、修正プログラムを迅速かつ効率的に運用環境に取り込むこともできます。