『継続的デリバリー』 第3章 学習メモ

継続的インテグレーション(CI)

1.はじめに

継続的デリバリーにおける、継続的インテグレーションについての調査記録です。
継続的デリバリーにおいて、継続的インテグレーションをどのように実現するか記載します。
『継続的デリバリー 信頼できるソフトウェアリリースのためのビルド・テスト・デプロイメントの自動化』の第3章に対応します。

2.概要・目的

CIの目標は、ソフトウェアを常に動く状態とすることである。
CIを実現することで、素早くデリバリーができ、バグの量を削減できる。
また、バグを早期検出することで、修正コストを節約できる。
本稿では、CIを実現する上での準備と、CIにおけるプラクティスを記載する。

3.対応概要

(1)CIを始める前に必要なもの

CIを始めるために、以下の3つが必要となる。

  • バージョン管理
  • 自動ビルド
  • チームの合意

(2)CIシステムの構築

CIシステムは、以下の手順で構築する。

  • CIツールのインストール
  • 設定
    以下の項目を指定する。
  • CIツールでビルドを実行+手順の記録、保存

CIツールでビルドを実行するために、以下の2つが必要となる。

  • システムが依存しているソフトウェアや設定をバージョン管理にチェックイン
  • 新しいボックスのプロビジョニングを行うプロセスの自動化

(3)チェックイン

変更のチェックインの手順は、以下の通りとなる。

  • ビルドが実行中でないことを確認(実行中なら待つ)。
  • 開発環境のコードをバージョン管理の最新バージョンで更新。
  • ビルドスクリプトとテストを開発環境上で実行。または、CIツールの個人ビルド機能を実行。
  • バージョン管理にコードをチェックイン。
  • CIツールのビルドの結果を確認。
  • ビルド失敗→即座に修正→ステップ3に戻る。
  • ビルド成功→修了(次タスクへ)。

4.対応詳細

(1)CIの前提となるプラクティス

CIの前提として、以下の3つのプラクティスがある。

  • 定期的なメインラインへのチェックイン
  • 包括的自動テストスイートの作成
  • ビルドプロセスとテストプロセスを短く保つ

    (2)プロセスの短縮

    a.テストプロセスの分割

    プロセスの短縮のために、テストプロセスをコミットステージと受入テストステージに分割し、複数タスクを並列実行する。
    コミットステージでは、ソフトウェアのコンパイルと、ユニットテストスイートを実行し、デプロイ可能なバイナリを生成する。
    受入テストステージでは、コミットステージからバイナリを取得し、受入テスト(+あれば統合テスト、性能テスト)を実行する。

    b.その他

    プロセスの短縮のために、テストプロセスの分割の他に以下の2つの方法がある。

  • テストスイートの並列実行

  • ビルドグリッド

    (3)開発ワークスペースの管理

    開発者が高い生産性で健全に作業するために、開発環境は以下の条件を満たす必要がある。

  • CIの自動テストに通った、最新のリビジョンでコーディングを始められること。
    このために、ソース・テストデータ・DBスクリプト・ビルド_デプロイスクリプトを、すべてバージョン管理に格納する必要がある。

  • 依存しているサードパーティライブラリを、MavenやIvyのようなツールで管理していること。
  • スモークテストを含む自動テストを、開発環境で実行できること。

実際に、大きな労力なくアプリケーションを開発環境で実行できることは、優れたアプリケーションアーキテクチャの指標となっている。

(4)CIサーバソフトウェア

CIサーバソフトウェアの核心には、以下の2つのコンポーネントがある。

  • 定期的に、シンプルなワークフローを実行する。
  • ビルドやテストの結果を通知し、テストレポートやインストーラへのアクセスを提供する。

また、CIサーバのオプション機能を使うことで、ビルドの状態を可視化できる。

(5)CIを機能させるための必須プラクティス

ソフトウェアが常に動くことを確認するための必須のプラクティスは以下の通り。

  • ビルドが壊れているときはチェックインしてはいけない
    常にグリーンなビルドにする。
  • ローカルでのコミットテストを実行する。
    テストの失敗とコミットの失敗を分離する。
  • 問題が起きても対処できる時間にチェックインする。
  • 常に以前のリビジョンに戻す準備をする。
  • リバート前の修正可能時間を設定する。
  • 失敗したテストをコメントアウトしない。失敗したテストは適切に修正する。
  • 変更者がビルドの成功に対して責任を持つ。また、そのためにコードへのアクセス権を付与する。
  • テスト駆動開発
    UTのカバレッジを高め、CIの核である高速フィードバックを実現するため。

(6)必須ではないがやったほうがよいプラクティス

CIのために、必須ではないがやったほうがよいプラクティスは以下の通り。

  • XPの開発プラクティス。
  • アーキテクチャ上の違反に対して、ビルドを失敗させる。
  • テストが遅い場合に、ビルドを失敗させる。
  • 警告やコードスタイルの違反があったときに、ビルドを失敗させる。
    ラチェット方式で実施する。

    (7)分散したチーム

    CIを分散したチームでやるときは、バージョン管理システムとCIシステム、さらにデプロイメントパイプラインを共有することが最も効果的である。
    その他のアプローチについては、以下の通り。

  • コミュニケーションプロセスの改善などで、チーム間の信頼関係を構築する。

  • 中央集権的CIにより、品質を標準化する。仮想化も、中央集権CIサーバとうまく組み合わせられる。
  • 分散バージョン管理システムを使用することで、回線やネットワークの問題を解消する。
  • 基盤へのアクセスと、基盤についての問題の対応方法を共有する。
  • (非推奨)回線の問題を解消できないときは、CIシステム・テストシステム・バージョン管理システムをローカルに立てる。

    (8)分散バージョン管理システム(DVCS)

    a.メインラインモデル

    バージョン管理のメインラインモデルやCIを実行するために、DVCSでは、一つのリポジトリをマスターと定める
    このリポジトリに変更があったときに、CIサーバが動くよう設定する。

    b.GitHubモデルなどその他のモデル

    GitHubモデルで疑似CIを実行するためには、リポジトリに対してCIビルドを構築する。
    これにより、フォークやメインリポジトリの保守担当者に、フォークがメインリポジトリに統合可能か通知できる。
    DVCSを使うモデルがCIを代替するためには、以下の条件を満たす必要がある。

  • 少人数で洗練されたコミッターのチームが、パッチのプルを管理し、自動テストの面倒を見ることで、ソフトウェア品質を保証すること。

  • フォークから定期的にプルを行い、マージの問題を小さくすること。
  • 少人数の中心的開発者が、比較的ゆっくり作業をする大きなコミュニティに支えられていること。

5.影響・作用

CIを実現することで、アプリケーションは基本的に動く状態となる。
ただし、保証するレベルは、自動テストのカバレッジに依存する。
CIを実現するにあたって、以下の2つが必須となる。

  • 適切な構成管理
  • 自動ビルド・テストプロセスの構築と保守

この2つは、インクリメンタルに実現が可能である。

6.おわりに

以上が、継続的デリバリーにおける継続的インテグレーションの実現のための、準備とプラクティスです。

7.参考文献

『継続的デリバリー 信頼できるソフトウェアリリースのためのビルド・テスト・デプロイメントの自動化』 第3章 継続的インテグレーション