DevOps

ヒント

このコンテンツは eBook の「Azure 向けクラウド ネイティブ .NET アプリケーションの設計」からの抜粋です。.NET Docs で閲覧できるほか、PDF として無料ダウンロードすると、オンラインで閲覧できます。

Cloud Native .NET apps for Azure eBook cover thumbnail.

ソフトウェア コンサルタントのお気に入りのスローガンは、尋ねられたどの質問に対しても "場合による" と回答することです。 これはソフトウェア コンサルタントが態度をはっきりさせたくないからではありません。 ソフトウェアではどの質問にも 1 つの正解が存在するわけではないからです。 絶対的な善や悪ではなく、正反対の間でのバランスです。

たとえば、Web アプリケーション開発の主要な 2 つの方式として、シングル ページ アプリケーション (SPA) とサーバー側アプリケーションがあります。 一方で、ユーザー エクスペリエンスは SPA の方が優れる場合が多く、Web サーバーへのトラフィック量を最小限に抑えて、静的ホストなど単純な方法でホストすることができます。 他方で、SPA は開発に時間がかかり、テストが困難になります。 どちらが正しい選択でしょうか。 それは状況によって異なります。

クラウドネイティブ アプリケーションは、これと同様の二分法と無縁ではありません。 開発の速度、安定性、スケーラビリティの面で明確な利点がありますが、管理がかなり難しくなる可能性があります。

数年前には、アプリケーションの開発環境から運用環境への移行に 1 か月あるいはそれ以上かかることは珍しくありませんでした。 企業は 6 か月または 1 年ごとにソフトウェアをリリースしました。 常に最新状態である Windows 10 以前に許容されていたリリースのペースについて調べるために、Microsoft Windows よりも前にさかのぼる必要はありません。 Windows XP から Vista までは 5 年間、Vista から Windows 7 まではさらに 3 年間かかりました。

現在、ソフトウェアを迅速にリリースできることによって、動きの速い企業が、ナマケモノのような競合他社に比べて市場で優位に立てるということがかなり定着してきました。 これが Windows 10 の重大な更新が約 6 か月おきに行われる理由です。

より高速で、より信頼性が高いリリースを可能にして、ビジネスに価値をもたらすパターンとプラクティスは、DevOps と総称されます。 これらは、アプリケーションの指定からアプリケーションのデリバリと運用まで、ソフトウェア開発ライフ サイクル全体にわたるさまざまなアイデアで構成されます。

DevOps はマイクロサービスよりも前に登場しました。目的のサービスに合わせて、より小さくよりフィットさせるという方向への動きは、DevOps なしでは不可能だったと考えられます (DevOps のおかげで、1 つだけではなく多数のアプリケーションの運用環境でのリリースと運用がたやすくなります)。

Figure 10-1 Search trends show that the growth in microservices doesn't start until after DevOps is a fairly well-established idea.

図 10-1 - DevOps とマイクロサービス。

優れた DevOps プラクティスを利用すれば、アプリケーションを実際に運用する山のような作業に押しつぶされなくても、クラウドネイティブ アプリケーションの利点を実現できます。

DevOps に関する万能のツールはありません。 高品質のアプリケーションをリリースして運用するための、完全かつ包括的なソリューションを販売することは不可能です。 これは、アプリケーションがそれぞれ大きく異なるためです。 しかし、DevOps にかなり取り組みやすくなるツールはあります。 このようなツールの 1 つは Azure DevOps と呼ばれます。

Azure DevOps

Azure DevOps には長い歴史があります。 ルーツは Team Foundation Server 最初にオンラインに移行したときまでたどれます。その後、Visual Studio Online や Visual Studio Team Services といったさまざまな名前の変更が行われました。 しかし、年を経て、以前のものよりも格段に向上しています。

Azure DevOps は、次の 5 つの主要コンポーネントに分かれます。

Figure 10-2 The five major areas of Azure DevOps

図 10-2 - Azure DevOps。

Azure Repos - 従来の Team Foundation バージョン管理 (TFVC) と業界の定番である Git がサポートされるソース コード管理。 プル要求によって、変更を行う際のディスカッションを促進しながら、ソーシャル コーディングを実現する方法が提供されます。

Azure Boards - 問題や作業項目の追跡ツールが提供され、これによって最も適したワークフローをユーザーが選択できるようになります。 スクラムやかんばんスタイルの開発をサポートするテンプレートを含め、事前構成されたテンプレートが多数用意されています。

Azure Pipelines - Azure との緊密な統合がサポートされる、ビルドおよびリリース管理システム。 ビルドは、Windows、Linux、macOS までさまざまなプラットフォームで実行できます。 ビルド エージェントは、クラウドまたはオンプレミスでプロビジョニングできます。

Azure Test Plans - Test Plans 機能によって提供されるテスト管理および探索的テスト サポートにより、QA 担当者が取り残されることはありません。

Azure Artifacts - 企業が独自に社内で NuGet や npm などのバージョンを作成できるようにする成果物フィード。 一元管理されるリポジトリに障害が発生した場合にアップストリーム パッケージのキャッシュとして機能するという、もう 1 つの目的も果たします。

Azure DevOps の最上位の組織単位は、プロジェクトと呼ばれています。 各プロジェクト内で、Azure Artifacts などのさまざまなコンポーネントをオンまたはオフにできます。 これらの各コンポーネントには、クラウドネイティブ アプリケーションに対してさまざまな利点があります。 最も役に立つのは、リポジトリ、ボード、パイプラインの 3 つです。 ユーザーがソース コードを別のリポジトリ スタック (GitHub など) で管理するが、Azure Pipelines や他のコンポーネントも利用したい場合、完全に可能です。

幸運にも、開発チームにはリポジトリを選択する際に多くのオプションがあります。 そのうちの 1 つが GitHub です。

GitHub のアクション

2009 年に開設された GitHub は、プロジェクト、ドキュメント、コードをホストするための広く普及した Web ベース リポジトリです。 Apple、Amazon、Google などの大規模な技術系企業や主要企業の多くが GitHub を使用しています。 GitHub では、Git という名前のオープンソースの分散型バージョン管理システムが基盤として使用されます。 その上に、欠陥追跡、機能およびプル要求、タスク管理、各コード ベース用の wiki など、独自の機能セットが追加されます。

GitHub の進化に伴って、DevOps 機能も追加されています。 たとえば、GitHub には、GitHub Actions と呼ばれる独自の継続的インテグレーション/継続的デリバリー (CI/CD) パイプラインがあります。 GitHub Actions は、コミュニティを利用したワークフロー自動化ツールです。 DevOps チームはこれを既存のツールと統合し、新しい製品と適切に組み合わせて、既存の CI/CD パートナーを含むソフトウェア ライフサイクルに結び付けることができます。"

GitHub は 4000 万を超えるユーザーを抱える、世界最大のソース コード ホストです。 2018 年 10 月に Microsoft が GitHub を買収しました。 Microsoft は、GitHub は引き続きオープン プラットフォームのままであり、開発者がプラグインおよび拡張できることを保証しました。 独立した企業として経営が続けられます。 GitHub には、enterprise、team、professional、および free アカウントのプランが用意されています。

ソース管理

クラウドネイティブ アプリケーションのコードの整理は、困難になる可能性があります。 クラウドネイティブ アプリケーションは、1 つの大きなアプリケーションではなく、互いにやり取りする小規模アプリケーションの組み合わせで構成される傾向があります。 あらゆることを考慮した結果、コードの最適な配置は、未解決の問題として残されます。 さまざまな種類のレイアウトを使用して成功を収めたアプリケーションの例がありますが、最も広く普及しているのは 2 つの種類です。

実際のソース管理そのものに取り組む前に、適切なプロジェクトの数を決めておくことをお勧めします。 単一プロジェクト内では、複数のリポジトリおよびビルド パイプラインがサポートされます。 ボードは少し複雑になりますが、1 つのプロジェクト内でも複数のチームに簡単にタスクを割り当てることができます。 1 つの Azure DevOps プロジェクトで、数百人あるいは数千人の開発者をサポートすることが可能です。 これがおそらく最適なアプローチです。すべての開発者が作業を行うことができる 1 つの場所が提供され、アプリケーションが含まれるプロジェクトに確信がないときにアプリケーションを探す戸惑いが軽減されるためです。

Azure DevOps プロジェクト内のマイクロサービスのコードを分割することは、多少困難な場合があります。

Figure 10-3 Single versus Multiple Repositories

図 10-3 - 1 つのリポジトリと多数のリポジトリ。

マイクロサービスごとのリポジトリ

一見すると、このアプローチは、マイクロサービスのソース コードを分割するための最も論理的なアプローチのように見えます。 各リポジトリに、1 つのマイクロサービスを構築するために必要なコードを含めることができます。 このアプローチの利点は、すぐにわかります。

  1. アプリケーションのビルドおよび保守の手順を、各リポジトリのルートにある README ファイルに追加できます。 リポジトリを切り替えるとき、これらの手順を簡単に見つけることができ、開発者が作業を始める際の時間が短縮されます。
  2. すべてのサービスが論理的に配置され、サービス名がわかっていれば簡単に見つけることができます。
  3. 所有するリポジトリに変更が加えられたときにのみビルドがトリガーされるように簡単に設定できます。
  4. リポジトリに加えられる変更の数は、プロジェクトで作業する少数の開発者に限定されます。
  5. セキュリティは、開発者が読み取りおよび書き込みのアクセス許可を持つリポジトリを制限することで簡単に設定できます。
  6. リポジトリ レベルの設定を、所有するチームが変更でき、他のユーザーとの協議は最小限に抑えられます。

マイクロサービスの背後にある主要な考え方の 1 つは、サービスをサイロ化して分離させる必要があるということです。 ドメイン駆動設計を使用してサービスの境界を決定すると、サービスはトランザクションの境界として機能します。 データベースの更新が複数のサービスにまたがることはできません。 関連データのこのようなコレクションは、境界コンテキストと呼ばれます。 この考え方には、データベースに対するマイクロサービス データの分離 (その他のサービスから切り離されて自律している) が反映されています。 この考え方をソース コードにまで適用することは、きわめて理にかなっています。

ただし、このアプローチにも問題があります。 現代の開発における最悪の問題の 1 つは、依存関係の管理です。 平均的な node_modules ディレクトリを構成するファイル数を考えてみてください。 create-react-app などを新たにインストールすると、おそらく数千個のパッケージがもたらされます。 これらの依存関係をどのように管理するかというのは難しい質問です。

依存関係が更新されると、ダウンストリーム パッケージでもこの依存関係を更新する必要があります。 残念ながら、これには開発作業が必要であり、常に node_modules ディレクトリには、1 つのパッケージの複数のバージョンが生成されます。それぞれは、わずかに異なる間隔でバージョン管理される他のパッケージの依存関係です。 アプリケーションを配置するとき、どのバージョンの依存関係を使用すればよいでしょうか。 現在運用中のバージョンでしょうか。 現在ベータ版だが、いずれ運用中になるバージョンでしょうか (その時点までにコンシューマーによって運用環境に提供される可能性があります)。 マイクロサービスを使用するだけでは解決されない難しい質問です。

多様なプロジェクトが依存しているライブラリがあります。 リポジトリごとに 1 つずつマイクロサービスを分割することで、内部リポジトリ Azure Artifacts を使用して、内部の依存関係を最適に解決できます。 ライブラリのビルドにより、最新バージョンが内部使用のために Azure Artifacts にプッシュされます。 ダウンストリーム プロジェクトは、新しく更新されたパッケージ上の依存関係を利用するように、引き続き手動で更新する必要があります。

サービス間でのコードの移動には、もう 1 つ欠点があります。 アプリケーションのマイクロサービスへの最初の分割が 100% 正しいと信じられればよいですが、実際には、サービス分割で間違わないと予見できることはまれです。 したがって、機能とそれを実現するコードは、サービスからサービス (リポジトリからリポジトリ) に移動する必要が生じます。 1 つのリポジトリから別のリポジトリに移ると、コードの履歴は失われます。 多くのケースで、特に監査の場合には、一連のコードに関する完全な履歴が重要になります。

最後の最も大きな欠点は、変更の調整です。 本当のマイクロサービス アプリケーションでは、サービス間に配置の依存関係はありません。 サービス A、B、および C は、疎結合であるため、任意の順序で配置できます。 しかし、実際には、複数のリポジトリにまたがる変更を同時に行うことが望ましい場合もあります。 たとえば、ライブラリを更新して、セキュリティ ホールを対策したり、すべてのサービスで使用される通信プロトコルを変更したりする場合です。

複数リポジトリの変更を行うには、各リポジトリへのコミットが連続して行われる必要があります。 各リポジトリの各変更は、個別にプル要求されて確認される必要があります。 このアクティビティは、調整が難しい場合があります。

多数のリポジトリを使用する代わりに、すべてのソース コードを、すべてを把握する巨大な 1 つのリポジトリにまとめることができます。

1 つのリポジトリ

monorepository と呼ばれることもある、このアプローチでは、すべてのサービスのすべてのソース コードが同じリポジトリに格納されます。 まず、このアプローチはいい考えには見えません。ソース コードが扱いづらくなりそうだからです。 ただし、この方法を使用すると、いくつかの利点があります。

1 つ目の利点は、プロジェクト間の依存関係の管理が容易になることです。 プロジェクトは、外部の成果物フィードを利用する代わりに、直接に互いをインポートできます。 つまり、更新が瞬時に行われ、競合するバージョンは、開発者のワークステーション上でコンパイル時に検出されるようになります。 事実上、統合テストの一部がシフト レフトされます。

プロジェクト間でコードを移動しても、ファイルが再書き込みではなく移動されたものとして検出されるため、履歴の保存が容易になりました。

もう 1 つの利点は、サービス境界にまたがる広範な変更を 1 回のコミットで行うことができるようになることです。 このアクティビティにより、多数の変更を個別に確認するオーバーヘッドが軽減されます。

コードの静的分析を実行するツールが多数あり、セキュリティで保護されていないプログラミング手法または API の問題のある使用方法を検出できます。 複数リポジトリの環境では、各リポジトリを繰り返し処理して、それぞれの問題を見つける必要があります。 単一のリポジトリでは、分析をすべて 1 箇所で実行できます。

また、1 つのリポジトリのアプローチには多くの欠点もあります。 最も懸念されるものは、リポジトリが 1 つであることでセキュリティ上の問題が発生することです。 サービスごとに 1 つずつのリポジトリ モデルでは、リポジトリの内容が漏洩しても、失われるコードの量は最小限です。 1 つのリポジトリの場合、会社が所有するすべてが失われる可能性があります。 過去には、これが発生してゲーム開発の作業すべてが無駄になった例が多くあります。 複数のリポジトリがあると、外部からのアクセスにさらされる部分が少なくなります。これは、ほとんどのセキュリティ プラクティスで望ましい特徴です。

1 つのリポジトリのサイズは、急速に、管理できないほどになる可能性があります。 これにより、パフォーマンスに興味深いの影響がいくつか生じます。 場合によっては、Virtual File System for Git など特別なツールの使用が必要になります。これは、本来、Windows チームの開発者のエクスペリエンスを向上させるために設計されたものです。

1 つのリポジトリの使用に関する議論が、Facebook や Google がソース コードの配置にこの方法を使用しているという結論でまとめられることがよくあります。 このアプローチがこれらの会社にとって十分であるのであれば、すべての会社にとって正しいアプローチであるというわけです。 実際のところ、Facebook や Google のような規模で運用している企業はわずかです。 それらの規模で発生する問題は、ほとんどの開発者が直面する問題とは異なります。 片方に適しているからといって、もう一方にも適しているとは限りません。

最終的には、いずれかのソリューションを使用して、マイクロサービスのソース コードをホストできます。 ただし、ほとんどのケースで、1 つのリポジトリで運用する際の管理とエンジニアリングのオーバーヘッドは、わずかなメリットには値しません。 複数のリポジトリにコードを分割すると、問題が適切に分離されるようになり、開発チームの自律性が促進されます。

標準のディレクトリ構造

1 つのリポジトリか複数のリポジトリかという議論に関係なく、サービスごとに独自のディレクトリがあります。 開発者がプロジェクト間を迅速に行きかうようにする優れた最適化の 1 つは、標準のディレクトリ構造を維持することです。

Figure 10-4 A standard directory structure for both the email and sign-in services

図 10-4 - 標準のディレクトリ構造。

新しいプロジェクトを作成するときは常に、適切な構造を配置するテンプレートを使用する必要があります。 このテンプレートには、スケルトンの README ファイルや azure-pipelines.yml などの便利な項目を含めることもできます。 どのマイクロサービス アーキテクチャでも、プロジェクト間の相違が大きい、サービスに対する一括操作がさらに困難になります。

複数のソース コード ディレクトリを含むディレクトリ全体のテンプレートを提供できるツールが多数あります。 Yeoman は JavaScript 環境で普及しています。また、GitHub で最近リリースされた Repository Templates では、ほぼ同じ機能が提供されます。

タスク管理

タスク管理はどのプロジェクトでも困難な場合があります。 最初に、最適な開発者の生産性を保証するために設定するワークフローの種類に関して、よく寄せられる質問に答えます。

クラウドネイティブ アプリケーションは、従来のソフトウェア製品よりも小さくなる傾向があります。または、少なくとも小さいサービスに分割されています。 これらのサービスに関連する問題またはタスクの追跡は、他のソフトウェア プロジェクトの場合と同様に重要です。 作業項目を追跡できなくなったり、問題が適切に記録されなかったことを顧客に説明したりすることは、だれも望みません。 ボードはプロジェクト レベルで構成されますが、各プロジェクト内で区分を定義できます。 これによって、問題をいくつかのコンポーネントに分解できます。 アプリケーション全体のすべての作業を 1 箇所で保持する利点は、作業項目を、あるチームから、それについてよく理解している別のチームに簡単に移動できることです。

Azure DevOps では、多くの一般的なテンプレートが事前構成されています。 最も基本的な構成では、把握しておく必要があるのは、バックログの内容、担当者が作業している内容、および終了した作業です。 重要なのは、ソフトウェアのビルド プロセスをこのように可視化することです。これにより、作業に優先順位を付けることができ、完了したタスクを顧客に報告できます。 もちろん、to dodoingdone という単純なプロセスに当てはまるソフトウェア プロジェクトはほとんどありません。 QA または Detailed Specification というステップがプロセスに追加されるようになるまで時間はかかりません。

アジャイル手法の重要な部分の 1 つは、定期的な自己イントロスペクションです。 このようなレビューは、チームが直面している問題とその改善方法についての分析情報を得ることを目的としています。 これは、多くの場合、開発プロセス全体で問題と機能のフローを変更することを意味します。 そのため、ステージを追加してボードのレイアウトを拡張するのが非常に健全です。

ボードのステージのみが編成のツールではありません。 ボードの構成によって、作業項目の階層が存在します。 ボードに表示できる最小の項目はタスクです。 既定では、タスクに含まれるのは、タイトル、説明、優先順位、残りの推定作業量のフィールド、および他の作業項目や開発項目 (分岐、コミット、プル要求、ビルドなど) へのリンク機能です。 作業項目は、アプリケーションのさまざまな領域や、さまざまなイテレーション (スプリント) に分類でき、簡単に見つけることができます。

Figure 10-5 An example task in Azure DevOps

図 10-5 - Azure DevOps のタスク。

[説明] フィールドでは、期待される標準スタイル (太字、斜体、アンダースコア、取り消し線)、および画像を挿入する機能がサポートされます。 このために、作業またはバグを指定するときに使用できる強力なツールになります。

タスクをまとめたものがフィーチャーで、これによって、より大きな作業単位が定義されます。 さらに、機能をまとめたものがエピックです。 このような階層でタスクを分類することで、大きな機能のロールアウトにどれくらい近づいているかがわかりやすくなります。

Figure 10-6 Work item types configured by default in the Basic process template

図 10-6 - Azure DevOps の作業項目。

Azure Boards には、問題のさまざまな種類のビューがあります。 まだスケジュールされていない項目はバックログに表示されます。 そこから、スプリントに割り当てることができます。 スプリントとは、作業の一定量が完了すると予想される時間ボックスです。 この作業には、タスクだけでなく、チケットの解決も含まれます。 その後、スプリント全体を、スプリント ボード セクションから管理できます。 このビューには、作業の進行状況が表示されます。また、スプリントが成功するかどうかをについて最新の推定情報がわかるバーン ダウン チャートも含まれています。

Figure 10-7 A board with a sprint defined

図 10-7 - Azure DevOps のボード。

これまでに、Azure DevOps のボードには非常に優れた機能があることが明らかになりました。 開発者にとっては、何の作業が行われているかを簡単に把握できます。 プロジェクト マネージャーにとっては、今後の作業と既存の作業を確認できます。 マネージャーにとっては、リソースや容量に関する豊富なレポートがあります。 残念ながら、クラウドネイティブ アプリケーションに関して作業を追跡する必要がなくなるといった夢のようなことはありません。 しかし、作業を追跡する必要がある場合、Azure DevOps よりもエクスペリエンスが優れているものがいくつかあります。

CI/CD パイプライン

ソフトウェア開発ライフ サイクルにとって、継続的インテグレーション (CI) と継続的デリバリー (CD) の登場ほど革新的な変化はありませんでした。 変更がチェックインされるとすぐに、プロジェクトのソース コードに対して自動テストをビルドして実行することで、エラーを早く検出できます。 継続的インテグレーション ビルドが登場する前は、リポジトリからコードをプルしてから、テストに合格しないことやビルドさえできないことがわかるのも珍しくありませんでした。 この場合、不具合の原因を見つけ出すことになります。

従来、運用環境にソフトウェアを配布するには、大量のドキュメントと手順一覧が必要でした。 これらの手順それぞれを、エラーが発生しやすいプロセスで手動で完了する必要がありました。

Figure 10-8 A checklist

図 10-8 - チェックリスト。

継続的インテグレーションと関係が深い継続的デリバリーでは、ビルトされたばかりのパッケージが環境に配置されます。 手動プロセスは開発の速さに合わせられないため、自動化がより重要になります。 チェックリストはスクリプトに置き換えられ、同じタスクが人間よりも速く、より正確に実行されます。

継続的デリバリーの対象となる環境は、テスト環境の場合もあれば、多くの主要なテクノロジ企業によって行われているように、運用環境の場合もあります。 後者では、高品質のテストに投資して、ユーザーのために運用が中断されないという確信を得る必要があります。 継続的インテグレーションでは早期にコードの問題が検出されるのと同様に、継続的デリバリーでは配置プロセスの問題が早期にわかります。

ビルドおよびデリバリー プロセスを自動化する重要性は、クラウドネイティブ アプリケーションによってさらに際立ちます。 配置は、より頻繁に、より多くの環境に行われるため、手動での配置はほとんど不可能です。

Azure Builds

Azure DevOps によって一連のツールが提供され、継続的インテグレーションと継続的配置がかつてないほど容易になります。 これらのツールは Azure Pipelines にあります。 1 つ目は、Azure Builds です。これは、大規模に YAML ベースのビルド定義を実行するためのツールです。 ユーザーは、自らのビルド用マシンを持ち込むことも (正確に設定された環境がビルドに必要な場合に最適)、Azure でホストされた、常に更新されている仮想マシンのプールからマシンを利用することもできます。 これらのホスト ビルド エージェントには、.NET 開発だけでなく、Java や Python から iPhone 開発まで、さまざまな開発ツールが事前にインストールされています。

DevOps には、すぐに使用できる多様なビルド定義が含まれており、あらゆるビルドに対してカスタマイズできます。 ビルド定義は、azure-pipelines.yml と呼ばれるファイルに定義されて、リポジトリにチェックインされるため、ソース コードと共にバージョン管理できます。 これにより、分岐内のビルド パイプラインに変更を行うのが非常に容易になります。変更はその分岐のみにチェックインされるためです。 完全なフレームワークで ASP.NET Web アプリケーションをビルドする azure-pipelines.yml のサンプルを図 10-9 に示します。

name: $(rev:r)

variables:
  version: 9.2.0.$(Build.BuildNumber)
  solution: Portals.sln
  artifactName: drop
  buildPlatform: any cpu
  buildConfiguration: release

pool:
  name: Hosted VisualStudio
  demands:
  - msbuild
  - visualstudio
  - vstest

steps:
- task: NuGetToolInstaller@0
  displayName: 'Use NuGet 4.4.1'
  inputs:
    versionSpec: 4.4.1

- task: NuGetCommand@2
  displayName: 'NuGet restore'
  inputs:
    restoreSolution: '$(solution)'

- task: VSBuild@1
  displayName: 'Build solution'
  inputs:
    solution: '$(solution)'
    msbuildArgs: '-p:DeployOnBuild=true -p:WebPublishMethod=Package -p:PackageAsSingleFile=true -p:SkipInvalidConfigurations=true -p:PackageLocation="$(build.artifactstagingdirectory)\\"'
    platform: '$(buildPlatform)'
    configuration: '$(buildConfiguration)'

- task: VSTest@2
  displayName: 'Test Assemblies'
  inputs:
    testAssemblyVer2: |
     **\$(buildConfiguration)\**\*test*.dll
     !**\obj\**
     !**\*testadapter.dll
    platform: '$(buildPlatform)'
    configuration: '$(buildConfiguration)'

- task: CopyFiles@2
  displayName: 'Copy UI Test Files to: $(build.artifactstagingdirectory)'
  inputs:
    SourceFolder: UITests
    TargetFolder: '$(build.artifactstagingdirectory)/uitests'

- task: PublishBuildArtifacts@1
  displayName: 'Publish Artifact'
  inputs:
    PathtoPublish: '$(build.artifactstagingdirectory)'
    ArtifactName: '$(artifactName)'
  condition: succeededOrFailed()

図 10-9 - サンプル azure-pipelines.yml

このビルド定義では、いくつもの組み込みタスクが使用されており、ビルドの作成はレゴ ブロックのセットを組み立てるのと同じくらい簡単です (巨大なミレニアム ファルコン号よりも簡単です)。 たとえば、NuGet タスクによって NuGet パッケージが復元される一方で、VSBuild タスクが Visual Studio ビルド ツールを呼び出して、実際のコンパイルを実行します。 Azure DevOps には何百ものさまざまなタスクが用意されており、コミュニティではさらに数千個が管理されています。 どのようなビルド タスクを実行しようとしていても、だれかが既にそれをビルドしている可能性があります。

ビルドのトリガーは、手動で、チェックインによって、スケジュールに基づいて、または別のビルドの完了によって、行うことができます。 ほとんどのケースでは、チェックインのたびにビルドすることをお勧めします。 ビルドをフィルター処理して、リポジトリのさまざまな部分、またはさまざまな分岐に対して、異なるビルドが実行されるようにできます。 これにより、プル要求時にテストを減らした高速ビルドを実行したり、毎晩トランクに対して完全な回帰スイートを実行したりするといったシナリオが実現できます。

ビルドの最終的な結果は、ビルド成果物と呼ばれるファイルのコレクションです。 これらの成果物は、ビルド プロセスの次のステップに渡すことも、Azure Artifacts フィードに追加して、他のビルドで使用することもできます。

Azure DevOps リリース

ビルドによって、ソフトウェアが配布可能なパッケージにコンパイルされます。ただし、継続的デリバリーを完了するために、引き続き成果物をテスト環境にプッシュする必要があります。 このため、Azure DevOps はリリースと呼ばれる別のツールを使用します。 リリース ツールでは、ビルドで使用した同じタスクのライブラリを使用しますが、"ステージ" という概念が導入されています。 ステージは、分離された環境であり、そこにパッケージがインストールされます。 たとえば、ある製品では、開発、QA、および運用環境が使用されます。 コードが継続的に開発環境に提供され、そこで自動テストを実行できます。 これらのテストに合格すると、リリースが手動テストのために QA 環境に移動します。 最終的に、コードが運用環境にプッシュされ、だれでも見えるようになります。

Figure 10-10 An example release pipeline with Develop, QA, and Production phases

図 10-10 - リリース パイプライン

ビルドの各ステージは、前のフェーズの完了によって自動的にトリガーされます。 ただし、多くの場合、これは望ましくありません。 コードの運用環境への移行には、だれかの承認が必要です。 リリース ツールでは、リリース パイプラインの各ステップに承認者を設定することができ、これがサポートされます。 リリースを運用環境に移す前に、特定のユーザーまたはユーザー グループがサインオフする必要があるように、ルールを設定できます。 このようなゲートによって、手動による品質チェックが実現し、関連する規制要件に準拠して、運用環境に移す内容を制御することもできます。

だれでもビルド パイプラインを取得

多数のビルド パイプラインを構成してもコストがかかりません。そのため、マイクロサービスごとに少なくとも 1 つのビルドパイプラインを用意することをお勧めします。 マイクロサービスはどのような環境にも独立して配置できるため、それぞれを独自のパイプラインを通じてリリースでき、関連しない大量のコードをリリースせずに済むことは理想的です。 各パイプラインには、独自の承認セットを設定でき、各サービス用にビルド プロセスのバリエーションが可能になります。

バージョン管理されたリリース

リリース機能を使用する 1 つの欠点は、チェックインされる azure-pipelines.yml ファイル内に定義できないことです。 分岐ごとにリリース定義を行ったり、リリースのスケルトンをプロジェクト テンプレートに含めたりなど、これを望む理由は多数あります。 幸いにも、いくつかのステージのサポートをビルド コンポーネントに移行する作業が進行中です。 これは、マルチステージ ビルドと呼ばれるようになります。最初のバージョンが使用可能になりました