DevOps メトリクスによる CI/CD パフォーマンスの測定

CI サーバーもしくは「ビルドサーバー」は、VCS 内の変更の監視から新しいビルドのデプロイに至るすべての CI/CD プロセスのステップを連携させます。

CI サーバーを使用すると、継続的インテグレーションデリバリー/デプロイ(CI/CD)のプロセスを合理化できます。 CI サーバーはバージョン管理システム(VCS)を監視して自動ビルド、テスト、およびデプロイの各タスクをトリガーし、それぞれの結果を集約し、パイプラインの次のステージを開始する役割を担っています。

CI/CD はビルドサーバーがなくても実践できますが、多くの開発チームはプロセスを連携させて各ステップの結果を引き継ぐ目的で CI ツールを使用することを選択しています。 このガイドでは、CI サーバーが行うことと、それによって CI/CD を最大限に活用する方法について見ていきます。

CI サーバーを使用する理由

CI サーバーは、CI/CD のすべての動作を連携させるための中心点として機能します。 CI サーバーを使用すると、以下が可能になります。

  • すべてのコミットを CI/CD に通す: CI サーバーを VCS と統合することで、すべてのコード変更を自動ビルド、テスト、およびデプロイの各プロセスに通すことができます。各開発者が余計な手間をかける必要はありません。
  • ビジネスロジックを調整する: 適用するテストカバレッジのレベルから自動テストプロセスの各ステージの「合格」条件まで、CI サーバーは組織の要件に関する唯一の信頼できる情報源となります。
  • ツールチェーンと統合する: CI サーバーは VCS やビルドツールと同様に課題トラッカーやコミュニケーションプラットフォームと統合することで、ビルド、テスト、およびデプロイの各プロセスの更新情報を自動的に提供することができます。
  • 過去のビルドの記録を残す: ビルドアーティファクトのアーカイブがあれば、捉えにくいバグがコードベースに侵入したタイミングを特定する必要がある場合などに非常に役立ちます。
  • 関係者にリリースの進捗を示す: CI サーバーをビルドとデプロイの正確なステータスを一元的に確認できる情報源として使用することで、より幅広い組織に進捗を周知できます。
  • 変更の監査ログを得る: ワークフローとビジネスロジックは時間の経過とともに変化する可能性があります。 CI サーバーを使用すると、以前の実装に戻したくなった場合に CI/CD プロセスの変更記録を取得できます。

CI サーバーを使用することで、コードの変更に対する迅速なフィードバック、早い段階でのバグの特定、リリース頻度の向上といった多くの CI/CD のメリットを得られます。

CI/CD サーバーを使用する理由

CI サーバーの仕組み

実際のプロセスはチームや組織の要件によって異なりますが、CI サーバーは一般的に以下のステップを実行します。

  1. バージョン管理システムと連携し、関連するブランチへのコミットの有無を監視します。
  2. 変更がコミットされるたびに一連のビルドタスクとテストタスクを開始します。 これらのタスクはビルドファーム内の他のマシンに分散される場合もあれば、CI サーバー上で直接実行される場合もあります。
  3. これらのタスクの結果を集約し、そのデータを使用してプロセスの次のステージに進むかどうかを判定します。
  4. 中央のアーカイブにビルドアーティファクトを保存します。
  5. 新しいバージョンを本番環境にデプロイします。
  6. プロセス全体のフィードバックを提供します。
CI サーバーの仕組み

バージョン管理の監視

すべての CI/CD パイプラインは、バージョンまたはソース管理システムとの連携から始まります。

CI サーバーは一般的に決まったブランチのコミットをリッスンし、変更が生じるたびにパイプラインを新たに実行するように構成されています。 それによって開発者が変更を共有するたびにビルドとテストが確実に実行されるため、コードベース全体の正常な動作を維持できます。

CI サーバーによってはこの構成をさらに進化させ、開発者が CI ブランチに変更を共有する前にローカルで変更をビルドしてテストすることを要求できるものもあります。 それでも次のステップで確実に合格できるわけではありませんが、ビルドの失敗とそれに伴う遅延を減らすことができます。 また、CI サーバーをコードレビューツールと統合し、コードレビューステージに合格しなければ個々のコミットを共有できないようにすることもできます。

こういったビジネスロジックの追加レイヤーをプロセスの始めに適用しておくことで、コードベースをクリーンに維持し、リリースできる状態を保ちやすくなる一方、パイプラインの中断や遅延を最小限に抑えられるようになります。

ビルドとテストの管理

CI サーバーは変更が検知されてパイプラインの実行がトリガーされるたびにビルドタスクとテストタスクを連携させます。 通常、これらのタスクは専用のビルドマシンか「エージェント」に割り当てられます。 その後、ビルドエージェントは CI サーバーから受け取った指示に従ってビルドを開始してテストを実行するという手間のかかる処理を行います。

CI サーバーで直接ビルドタスクとテストタスクを実行する方法もあります。 ただし、この方法ではリソースの競合が発生したり、込み入ったコードベースでパフォーマンスが低下したりする可能性があります。

CI サーバーを使用してパイプラインのステージのロジックを構成する際、広範な詳細とルールを指定することができます。 たとえば、以下を行うことができます。

  • メインブランチへのコミットに対してはすべての自動テストを実行するが、フィーチャーブランチでは比較的少ない数のチェックを実行する。
  • テストデータベースを同時に呼び出せるビルドの数を制御する。
  • ステージング環境へのデプロイを週 1 回に制限し、より多くの人が手動テストに参加できるようにする。

複数の異なるビルドエージェントを使用して特定のタスクを同時に実行すると、パイプラインの効率を高めることができます。 この方法は、複数の異なるオペレーティングシステムでテストを実行する必要がある場合や、テスト数が数十万件に及ぶ大規模なコードベースを取り扱っており、並列化のみが現実的な選択肢である場合に便利です。 後者の場合は複合ビルドをセットアップして結果を集約すると、タスクを単一のビルドステップとして扱えるようになります。

AWS などのクラウドでホスティングされているインフラストラクチャと統合されたビルドサーバーの場合、ビルドとテストを実行するための弾力性のあるスケーラブルなリソースのメリットが得られます。 インフラストラクチャのニーズが大きい場合は、コンテナー化されたビルドエージェントと Kubernetes との統合のサポートを利用して、クラウドかオンプレミスかに関係なくビルドリソースを効率的に管理することができます。

合格条件と失敗条件の定義

ビジネスロジックには、CI/CD パイプラインの各ステージにおける「失敗」を定義する重要な役割があります。

CI サーバーではさまざまな失敗条件を構成することができます。 CI サーバーは個々のステップのステータスを特定してパイプラインの次のステップに進むかどうかを決めるため、それらの失敗条件を満たしているかどうかを確認します。

エラーコードを返しているビルドやテストの実行に失敗しているテストなどといった自明の失敗に加えて、ビルドサーバーによって収集されたデータに基づいて他の失敗条件を定義できます。

たとえば、以前のビルドよりもテストカバレッジが低下している場合(最新のコード変更に対応したテストが追加されていない可能性あり)や、最後に成功したビルドよりも無視されたテストの数が増えている場合が挙げられます。

これらのメトリクスは、コードの品質が劣化していることを示す警告信号の役目も果たします。 こういった理由によって失敗をトリガーし、これらの失敗をオーバーライドする権限を持つユーザーを制限することで、望ましい行動を促進することができます。

ビルドアーティファクトの保存

変更が正しく行われると、CI サーバーはそのビルドプロセスのアーティファクトを保存します。 このアーティファクトには、バイナリ、インストーラー、コンテナーイメージ、ソフトウェアのデプロイに必要なその他のリソースが含まれる場合があります。

そのアーティファクトをそのまま最終的に本番環境にデプロイする前に本番前環境にデプロイし、さらにテストを実行することができます。 そうすることで、すべてのステージで同じ結果が確実にテストされるようになるため、毎回デプロイする前にソースコードからビルドし直すよりもはるかに信頼性が高くなります。 具体的には、依存関係の不足やその他の矛盾が発生するリスクを回避できます。

成功したビルドのアーティファクトリポジトリを管理しておくと、ソフトウェアの前のバージョンに戻す必要がある場合や、特定の問題が発生したタイミングを特定する場合にも役立ちます。

ビルドのデプロイ

「CI サーバー」という名称から、その使用は継続的インテグレーションに限られているように思えますが、ほとんどの CI サーバーは継続的デリバリーデプロイもサポートしています。

継続的インテグレーションのフェーズでビルドアーティファクトを生成して最初のテストセットを実行したら、次のステップでそのビルドアーティファクトを QA 環境にデプロイし、さらに詳細なテストを実施します。 その後、ステージングに移行して関係者に新しいビルドを試してもらいます。 それが正常に動作するようであれば、通常は本番環境にリリースできます。

CI サーバーを使用すると、パイプライン内の各環境のパラメーターを保存して管理できます。 そのため、前のステージの結果に基づいてデプロイスクリプトを自動的にトリガーするかどうかを指定できます。

フィードバックの提供

CI サーバーの主な役割は、ビルドとテストの各ステージに関するフィードバックを迅速に提供することです。 IDE やコミュニケーションプラットフォームと統合する CI サーバーには、何らかの変更が原因でパイプラインが失敗した場合に通知する機能があります。そのため、頻繁に進捗を監視する必要はありません。

ビルドサーバーには以下のようにも機能します。

  • 実行中のビルドとテストに関する報告をリアルタイムで行い、完了したビルドステップのステータスを通知する。
  • 課題追跡ツールとの統合により、コミットに含まれる修正の詳細を確認して失敗の原因を素早く調査できるようにする。
  • デプロイの頻度、次の失敗までの時間、および解決までの平均時間に関する統計を集約することで、開発プロセスを評価して改善できるようにする。
  • CI サーバーとビルドマシンの使用状況とパフォーマンスに関するインサイトを提供し、パイプラインの最適化に活用できるようにする。
ビルドサーバーの機能

独自の CI サーバーを構築すべきか否か

独自の CI サーバーを構築するのは魅力的な選択肢に思えます。 独自のソリューションを設計すると、ライセンス費用を発生させることなくニーズに合ったものを構築できるためです。

ただし、独自のツールを構築することはほんの始まりに過ぎません。 構築後は発生するバグの対応や要件の変化に合った新機能の開発など、最新の状態を維持するために時間を費やすことになるでしょう。

CI サーバーをツールチェーンに組み込む作業にかかる労力を考慮することも重要です。 最初の設計は現時点で使用しているバージョン管理システム、課題トラッカー、ビルドツール、テストフレームワークに対応できるとしても、新しい製品やテクノロジーに乗り換えた場合はどうなるのでしょうか?

独自の CI サーバーを構築すると自分のユースケースに合わせて柔軟にツールを作成できますが、最初の取り組みとその後の保守には多大な努力が継続的に必要となります。

まとめ

継続的インテグレーション (CI) サーバーは、CI/CD パイプラインを実装し、プロセスのさまざまなステップを調整・トリガーし、各ステージから得られるデータを照合・提供する上で、欠くことのできない役割を果たしています。 組織に最適な CI サーバーを選択するためのヒントについては、CI/CD ツールのガイドをご覧ください。

TeamCity のメリット

TeamCity は、Git、Perforce、Mercurial、Subversion を含むすべての主要なバージョン管理システムだけでなく、さまざまなホスティングサービスとも統合できます。 また、各種のビルドツールやテストフレームワーク、さらには IDE、課題トラッカー、メッセージングプラットフォーム、コンテナーマネージャーとの統合についても幅広くサポートしています。

TeamCity Professional または Enterprise では CI サーバーをオンプレミスでも任意のクラウドでもホスティングできます。また、TeamCity Cloud ならフルマネージドソリューションを利用することもできます。 柔軟性の高いパイプライントリガーのセットを使用することで、事前テスト済みのコミット、機能ブランチのサポート、スケジュールビルドなど、ニーズに合わせて CI/CD プロセスを構成できます。 UI を使用してパイプラインロジックを構成したら、構成をコードとして保存し、CI/CD プロセスを完全にバージョン管理下に置くことができます。