Microsoft は 、One Engineering System を使用して、Git の分岐とリリースフローを中心とした堅牢な DevOps プロセスを使用して、すべての Microsoft 製品をビルドしてデプロイするよう努めています。 この記事では、実際の実装、システムが小規模なサービスから大規模なプラットフォーム開発ニーズにスケーリングする方法、およびさまざまな Microsoft チームでシステムを使用して学んだ教訓について説明します。
標準化された開発プロセスの採用は、野心的な取り組みです。 さまざまな Microsoft 組織の要件は大きく異なり、組織内のさまざまなチームの要件は規模と複雑さに応じて拡張されます。 これらのさまざまなニーズに対応するために、Microsoft は トランクベースの分岐戦略を 使用して、製品の迅速な開発、定期的な展開、運用環境への変更の安全な提供を支援します。
Microsoft では、One Engineering System の一部としてプラットフォーム エンジニアリングの原則も使用しています。
Microsoft リリース フロー
すべての組織は、チーム間の一貫性を確保するために、標準のコード リリース プロセスに落ち着く必要があります。 Microsoft リリース フローには、開発からリリースまでの DevOps プロセスが組み込まれています。 リリース フローの基本的な手順は、ブランチ、プッシュ、プル要求、マージで構成されます。
Branch
バグを修正したり、機能を実装したりするために、開発者はメイン統合ブランチから新しいブランチを作成します。 Git ライトウェイト ブランチ モデルでは、すべてのコードコントリビューションに対して、これらの有効期間の短い トピック ブランチが作成されます。 開発者は、機能フラグを使用して、早期にコミットし、実行時間の長い機能ブランチを回避 します。
プッシュ
開発者がチームの残りのメンバーに変更を統合してリリースする準備ができたら、ローカルブランチをサーバー上のブランチにプッシュし、プルリクエストを開きます。 多数のブランチで作業する数百人の開発者が参加するリポジトリでは、サーバー ブランチの名前付け規則を使用して、混乱と ブランチの急増を軽減します。 開発者は通常、 users/<username>/featureという名前のブランチを作成します。ここで、 <username> は自分のアカウント名です。
Pull request(プルリクエスト)
Pull Requestsは、トピックブランチをメインブランチに統合し、ブランチポリシーが遵守されていることを確認します。 pull request プロセスは、提案された変更をビルドし、迅速なテスト パスを実行します。 第 1 レベルと第 2 レベルのテスト スイートは、約 60,000 個のテストを 5 分以内で実行します。 これは完全な Microsoft テスト マトリックスではありませんが、プル要求に対する自信をすばやく得るのに十分です。
次に、チームの他のメンバーがコードを確認し、変更を承認します。 コード レビューでは、自動テストが中断した場所が選択され、アーキテクチャの問題を見つけるのに特に役立ちます。 手動のコード レビューにより、チーム内の他のエンジニアが変更を可視化し、コード品質が高いままであることを確認します。
Merge
pull request がすべてのビルド ポリシーを満たし、レビュー担当者がサインオフすると、トピック ブランチがメイン統合ブランチにマージされ、pull request が完了します。
マージ後、完了するまでに時間がかかる他の受け入れテストが実行されます。 これらの従来のチェックイン後テストでは、より詳細な検証が行われます。 このテスト プロセスでは、プル要求のレビュー中に高速テストを実行することと、リリース前に完全なテスト カバレッジを用意することのバランスを取ることができます。
GitHub Flow との違い
GitHub Flow は、組織が Git にスケーラブルなアプローチを実装するための一般的な トランクベースの開発 リリース フローです。 ただし、一部の組織では、ニーズが高まるにつれて、GitHub Flow の一部から分岐する必要があることがわかります。
たとえば、GitHub Flow の見落としが多い部分は、プル要求をメイン ブランチにマージする前に、テストのために運用環境にデプロイする必要があるということです。 このプロセスは、すべてのプル要求がマージのためにデプロイ キューで待機することを意味します。
一部のチームには、1 つのリポジトリで数百人の開発者が絶えず作業しており、1 日あたり 200 を超えるプル要求をメイン ブランチに完了できます。 各プル要求でテストのために世界中の複数の Azure データ センターへのデプロイが必要な場合、開発者はソフトウェアを記述するのではなく、ブランチのマージを待つ時間を費やします。
代わりに、Microsoft チームはメイン ブランチで開発を続け、デプロイを時間指定のリリースにバッチアップします。通常は 3 週間の スプリント 周期に合わせて調整されます。
実装の詳細
Microsoft リリース フローの主要な実装の詳細を次に示します。
Git リポジトリ戦略
チームによって、Git リポジトリを管理するための戦略が異なります。 一部のチームは、コードの大部分を 1 つの Git リポジトリに保持します。 コードはコンポーネントに分割され、それぞれ独自のルート レベルのフォルダーに格納されます。 大きなコンポーネント (特に古いコンポーネント) には、親コンポーネント内に個別のサブフォルダーを持つ複数のサブコンポーネントがある場合があります。
補助リポジトリ
一部のチームでは、補助リポジトリも管理します。 たとえば、 エージェント と タスクのビルドとリリース、 VS Code 拡張機能、 オープンソース プロジェクト は GitHub で開発されています。 構成変更は別のリポジトリにチェックインされます。 チームが依存している他のパッケージは、他の場所から取得され、NuGet 経由で使用されます。
Monoリポジトリまたはマルチリポジトリ
一部のチームは単一のモノリシック リポジトリ ( mono-repo) を選択しますが、他の Microsoft 製品では マルチリポジトリ アプローチを使用します。 たとえば、Skype には、さまざまなクライアント、サービス、ツールを作成するために、さまざまな組み合わせで結合される数百の小さなリポジトリがあります。 特にマイクロサービスを受け入れるチームの場合は、マルチリポジトリが適切なアプローチになる可能性があります。 通常、モノリスとして始まった古い製品は、Git への最も簡単な移行であるモノリポジトリアプローチを見つけ、そのコード組織はそのことを反映しています。
リリース ブランチ
Microsoft リリース フローでは、メイン ブランチを常にビルド可能な状態に保ちます。 開発者は、 mainにマージする有効期間の短いトピック ブランチで作業します。 スプリントの終了時でもメジャーアップデートでも、チームは発送の準備ができたら、メインブランチから新しいリリースブランチを開始します。 リリース ブランチはメイン ブランチにマージされないため、 チェリー ピック の重要な変更が必要になる場合があります。
次の図は、有効期間の短いブランチを青で、リリース ブランチを黒で示しています。 桜狩りが必要なコミットを持つ 1 つのブランチが赤で表示されます。
ブランチ ポリシーとアクセス許可
Git ブランチ ポリシーは、リリース ブランチ構造を適用し、メイン ブランチをクリーンに保つのに役立ちます。 たとえば、ブランチ ポリシーでは、メイン ブランチへの直接プッシュを防ぐことができます。
ブランチ階層を整理するために、チームはアクセス許可を使用して、階層のルート レベルでブランチの作成をブロックします。 次の例では、すべての人がusers/、features/、teams/のようなフォルダーにブランチを作成できます。 リリース/でブランチを作成する権限を持つのは リリース マネージャーのみであり、一部のオートメーション ツールには 統合/ フォルダーへのアクセス許可があります。
Git リポジトリワークフロー
リポジトリとブランチ構造内で、開発者は毎日の作業を行います。 作業環境は、チームと個人によって大きく異なります。 コマンド ラインを好む開発者もいれば、Visual Studio のような開発者もいれば、異なるプラットフォームで動作する開発者もいます。 Microsoft リポジトリに配置されている構造とポリシーにより、強固で一貫性のある基盤が確保されます。
一般的なワークフローには、次の一般的なタスクが含まれます。
新しい機能を構築する
新しい機能の構築は、ソフトウェア開発者の仕事の中核です。 プロセスの Git 以外の部分には、テレメトリ データの確認、設計と仕様の作成、実際のコードの記述などがあります。 その後、開発者は、 mainの最新のコミットに同期することで、リポジトリの操作を開始します。 メイン ブランチは常にビルド可能であるため、適切な開始点であることが保証されます。 開発者は、新しい機能ブランチをチェックアウトし、コードを変更し、コミットし、サーバーにプッシュして、新しいプル要求を開始します。
ブランチ ポリシーとチェックを使用する
プル要求を作成すると、自動システムは、新しいコードがビルドされ、何も中断せず、セキュリティまたはコンプライアンス ポリシーに違反していないことを確認します。 このプロセスでは、他の作業が並行して実行されるのをブロックしません。
ブランチ ポリシーとチェックでは、成功したテスト、タッチされたコードの所有者によるサインオフ、プル要求を完了する前に企業ポリシーを検証するためのいくつかの外部チェックなど、ビルドの成功が必要になる場合があります。
Microsoft Teams との統合
多くのチーム が Microsoft Teams との統合を構成します。これにより、開発者のチームメイトに新しい pull request がアナウンスされます。 タッチされたコードの所有者は、レビュー担当者として自動的に追加されます。 Microsoft チームは、REST クライアントの生成や共有コントロールなど、多くのユーザーが触れるコードにオプションのレビュー担当者を使用して、それらの変更に関する専門家の目を得ます。
機能フラグを使用したデプロイ
レビュー担当者、コード所有者、自動化が満たされたら、開発者は pull request を完了できます。 マージの競合が発生した場合、開発者は競合に同期し、修正し、変更を再度プッシュする方法の指示を受け取ります。 自動化は固定コードで再び実行されますが、人間は再びサインオフする必要はありません。
ブランチは mainにマージされ、新しいコードは次のスプリントまたはメジャー リリースでデプロイされます。 これは、新機能がすぐに表示されることを意味するわけではありません。 Microsoft では、 機能フラグを使用して、新機能の展開と公開を切り離します。
機能を表示する準備が整う前にもう少し作業が必要な場合でも、製品がビルドされてデプロイされる場合は、 main に移動しても安全です。
mainに入ると、コードは公式ビルドの一部になり、そこで再びテストされ、ポリシーを満たすことが確認され、デジタル署名されます。
左にシフトして問題を早期に検出する
この Git ワークフローには、いくつかの利点があります。 まず、1 つのメイン ブランチから作業すると、 マージ負債が実質的に排除されます。 次に、プル要求フローは、パイプラインの早い段階でテスト、コード レビュー、およびエラー検出を適用するための共通のポイントを提供します。 この シフト左 戦略は、数時間または数日ではなく数分でエラーを検出できるため、開発者へのフィードバック サイクルを短縮するのに役立ちます。 この方法では、すべての変更が常にテストされるため、リファクタリングに対する自信も与えられます。
現在、200 以上のプル要求を含む製品では、1 日あたり 300 以上の継続的インテグレーション ビルドが生成され、24 時間ごとに 500 以上のテスト実行が行われる可能性があります。 トランクベースの分岐とリリースのワークフローがないと、このレベルのテストは不可能です。
スプリントのマイルストーンでリリースする
各スプリントの最後に、チームはメイン ブランチからリリース ブランチを作成します。 たとえば、スプリント 129 の終了時に、チームは新しいリリース ブランチ releases/M129を作成します。 その後、チームはスプリント 129 ブランチを運用環境に配置します。
リリースブランチが切られた後、開発者が変更をマージできるように、メインブランチは開いたままにされています。 これらの変更は、次のスプリントデプロイで 3 週間後にデプロイされます。
緊急修正プログラムをリリース
変更をすぐに運用環境に移行する必要がある場合があります。 Microsoft は通常、スプリントの途中で新機能を追加しませんが、ユーザーのブロックを解除するためにバグ修正を迅速に取り込みたい場合があります。 問題は、入力ミスなどの軽微な問題や、可用性の問題や ライブ サイト インシデントを引き起こすのに十分な大きさである可能性があります。
これらの問題の修正は、通常のワークフローから始まります。 開発者は、 mainからブランチを作成し、コード を確認して、マージするプル要求を完了します。 プロセスは常に、最初に main 変更を行うことによって開始されます。 これにより、リリース ブランチに切り替えることなく、修正プログラムをすばやく作成し、ローカルで検証できます。
このプロセスに従って、変更が mainに入ることも保証されます。これは重要です。 変更を main に戻さずにリリース ブランチのバグを修正することは、スプリント 130 が mainからブランチをリリースするときに、次のデプロイ中にバグが繰り返されることを意味します。 停止中に発生する可能性のある混乱とストレスの間に main を更新することを忘れてしまいます。
mainに変更を加えるということは、メイン ブランチとリリース ブランチの両方に常に変更を加えるということです。
Git 機能により、このワークフローが有効になります。 変更を運用環境にすぐに反映するには、開発者が pull request を main にマージした後、pull request ページを使用して、リリース ブランチに変更を選択できます。 このプロセスにより、リリース ブランチを対象とする新しいプル要求が作成され、 mainにマージされた内容がバックポートされます。
cherry-pick 機能を使用することで、ブランチ ポリシーの追跡可能性と信頼性が確保された状態で、プル要求をすぐに開くことができます。 チェリー ピックは、リリース ブランチをローカル コンピューターにダウンロードしなくても、サーバー上で実行できます。 2つのブランチ間の違いによって、変更を加えることや、マージの競合を解決すること、細かい修正を行うことは、すべてサーバー上で実行されます。 Teams では、ブラウザー ベースのテキスト エディターから直接、または Pull Request Merge Conflict Extension を使用して変更を直接編集して、より高度なエクスペリエンスを実現できます。
プル要求がリリース ブランチをターゲットにしたら、チーム コードでもう一度レビューし、ブランチ ポリシーを評価し、プル要求をテストしてマージします。 マージ後、修正プログラムはサーバーの最初の リング に数分でデプロイされます。 そこから、チームは展開リングを使用して、より多くのアカウントに修正プログラムを段階的にデプロイします。 変更がより多くのユーザーに展開されると、チームは成功を監視し、その変更によってバグが修正されることを確認しますが、欠陥や速度低下は発生しません。 この修正プログラムは、最終的にすべての Azure データ センターにデプロイされます。
次のスプリントに進む
次の 3 週間の間に、チームはスプリント 130 への機能の追加を完了し、それらの変更をデプロイする準備を整えます。 新しいリリース ブランチを作成し、releases/M130からmainし、そのブランチをデプロイします。
この時点で、実稼働には 2 つのブランチがあります。 リングベースのデプロイを使用して運用環境に変更を安全に導入すると、高速リングはスプリント 130 の変更を取得し、低速リング サーバーは運用環境で新しい変更が検証されている間、スプリント 129 にとどまります。
展開の途中で変更を修正するには、スプリント 129 リリースとスプリント 130 リリースの 2 つの異なるリリースを修正する必要があります。 チームは、両方のリリース ブランチに修正プログラムを移植して展開します。 130 ブランチは、既にアップグレードされているリングに修正プログラムを再デプロイします。 129 ブランチは、修正プログラムを使用して、次のスプリントのバージョンにまだアップグレードしていない外側のリングに再デプロイします。
すべてのリングが展開されると、スプリント 129 ブランチに修正プログラムとして取り込まれた変更がすべてmainに含まれているため、古いスプリント 129 ブランチは廃止されます。 そのため、これらの変更は releases/M130 ブランチにも含まれます。
概要
リリース フロー モデルは、Microsoft が DevOps を使用してオンライン サービスを提供する方法の中心にあります。 このモデルでは、トランクベースの単純な分岐戦略を使用します。 ただし、Microsoft リリース フローでは、開発者を配置キューに入れておく代わりに、変更のマージを待つ代わりに、開発者は作業を続けることができます。
また、このリリース モデルでは、Microsoft コードベースのサイズと作業する開発者の数に関わらず、定期的に Azure データ センター全体に新機能をデプロイすることもできます。 このモデルでは、修正プログラムを迅速かつ効率的に運用環境に取り込むこともできます。