Continuous Integration(CI)は、チームメンバー全員が1日に少なくとも1回は自分の変更を共有リポジトリに統合し、各統合が自動ビルドとテストによって検証される開発プラクティスです。CIはコードの競合やリグレッションエラーを早期に発見し、修正コストを削減します。Puppet State of DevOps Report、2025によると、CIを導入しているチームは、自動化していないチームに比べてバグ修正が4倍高速です。
重要ポイント
Continuous Integration(CI)は、複数の貢献者からのコードを単一のコードベースに統合するプロセスを自動化する開発方法論です。この用語は2000年代初頭にMartin Fowlerによって、“統合地獄”を防ぐための一連のプラクティスとして導入されました。統合地獄とは、開発者が何週間も孤立して作業し、変更をマージする際に無数の競合が発生し、手動での解決に数日を要する状況です。
CIがない場合、開発者は機能を完成させ、変更をmainブランチにマージしようとすると、同僚が同じファイルを変更していたことに気づきます。競合の解決には数時間かかり、多くの場合、動作中のコードが壊れます。CIはこの問題を、1日に複数回の統合を強制することで解決します。統合の頻度が高いほど、競合が少なくなり、解決も容易になります。実際の経験では、毎日統合すれば競合解決に数分しかかかりませんが、毎週の統合では数時間かかります。
IBM Systems Sciences Instituteによると、コーディング段階でのバグ修正コストは25ドル、テスト段階では100ドル、本番段階では2,500ドルです。CIは欠陥検出を可能な限り左にシフト(shift left)し、修正がほぼ無料であるコミット段階でエラーを発見します。CIを導入しているチームはデバッグに平均15%の時間を費やすのに対し、CIのないチームは35%を費やしています。
Martin Fowlerは、テクノロジースタックに関係なく関連性を保つCIの主要なプラクティスを定義しました。これらの原則に従うことで、CIが官僚的な負担ではなく価値をもたらすことが保証されます。モバイル開発では追加の要件が課されますが、核となる部分は変わりません。
すべてのプロジェクトコードは、統一されたバージョン管理システム(Git)を備えた単一のリポジトリに保存されます。単一の真実源により、機能がフォークで開発され、何週間もメインのコードベースと同期されない状況が排除されます。モバイルプロジェクトでは、Android、iOS、バックエンド部分が1つのリポジトリ(モノレポ)に格納されるか、共有バージョンスキームを持つ個別のリポジトリに格納されることを意味します。
プロジェクトのビルドは単一のコマンドで実行可能でなければなりません。Androidの場合は./gradlew assembleDebug、iOSの場合はxcodebuildまたはfastlane buildです。ビルドスクリプトは再現性を検証します。CIサーバーでのビルドは開発者のマシンと同じ結果を生成する必要があります。環境の差異は、コンテナ化またはIaC(Infrastructure as Code)によって排除されます。
ビルド後、すべてのレベルのテスト(ユニット、統合、UI)が実行されます。テストが失敗した場合、コミットは無効と見なされます。グリーンステータスの維持はチーム全体の責任です。モバイルプロジェクトでは、高速テスト(コミットごとに5分以内で実行)と低速テスト(実機でのUIテスト、実行頻度は低い)が分けられることがよくあります。
// CI対応レポート付きユニットテストの例
class LoginViewModelTest {
private val repository = mock<AuthRepository>()
private val viewModel = LoginViewModel(repository)
@Test
fun loginWithValidCredentials_success() {
val email = "test@example.com"
val password = "ValidPass123"
whenever(repository.login(email, password))
.thenReturn(Result.success(User("token-xyz")))
val result = viewModel.login(email, password)
assertEquals(LoginState.Success, result)
verify(repository).login(email, password)
}
}
CIの結果はチーム全体に公開されます。誰でもどのコミットがビルドを壊したかを確認できます。透明性は責任の文化を生み出します。開発者はプッシュ前に変更を確認し、壊れたビルドを順番を待たずに修正します。CIサーバーはビルドステータスの変更時にSlackやTelegramに通知を送信します。
完全なCIシステムは、相互に作用する複数の構成要素で構成されています。各コンポーネントは、トリガーからレポートまでのパイプラインの一部を担当します。CIアーキテクチャを理解することは、問題の診断とパフォーマンスの最適化に役立ちます。
ビルドキュー、リソース割り当て、結果公開を管理する中央コンポーネント。CIサーバーはクラウドベース(GitHub Actions、GitLab CI、CircleCI)またはセルフホステッド(Jenkins、TeamCity)にできます。サーバーはwebhookまたはポーリングを介してリポジトリの変更を監視し、プッシュまたはプルリクエストごとにパイプラインをトリガーします。
ランナーはビルドタスクを実行する仮想マシンまたは物理マシンです。クラウドCIでは、ランナーはプロバイダーによって提供され、使用時間に応じて課金されます。セルフホステッドランナーは自社のインフラにインストールされ、メンテナンスが必要です。iOSビルドにはmacOSランナー、AndroidビルドにはLinuxまたはWindowsが必要です。
ビルド後、CIシステムはアーティファクト(APK、IPA、テストレポート)をストレージに保存します。これらはダウンロードとデプロイに利用できます。実行間の依存関係のキャッシュ(Gradleキャッシュ、CocoaPodsキャッシュ)により、後続のビルドが3~5倍高速化されます。
| コンポーネント | 目的 | 例 |
|---|---|---|
| CIサーバー | ビルドのオーケストレーション | Jenkins、GitHub Actions |
| ランナー | タスクの実行 | iOS用macOSランナー |
| リポジトリ | コードの保存 | GitHub、GitLab |
| アーティファクトストレージ | アーティファクトの保存 | AWS S3、Artifactory |
| 通知 | チームへの通知 | Slack、Telegram、メール |
モバイル開発には、Webやバックエンドプロジェクトとは異なるCIの特別な要件があります。長いビルド時間(Androidは3~15分、iOSは5~20分)、複数のアーティファクトタイプ(APK、AAB、IPA)、署名と難読化の必要性 — これらすべてにCIパイプラインのカスタマイズ設定が必要です。
Androidの典型的なCIには以下が含まれます。リンティング(ktlint、detekt)と静的解析、JUnitとMockKによるユニットテスト、デバッグおよびリリースAPK/AABのビルド、CI内のエミュレーターでのインストルメンテーションテスト、アーティファクトの公開。Gradleキャッシュは繰り返しのビルドを高速化します。これがないと、各ビルドが依存関係を新たにダウンロードし、3~5分をロスします。
iOS CIでは、Swift/Objective-CコードをコンパイルするためにmacOSランナーが必要です。パイプラインには以下が含まれます。CocoaPodsまたはSPM依存関係のインストール、スタイルチェックのSwiftLint、XCTestによるユニットテスト、IPAビルド、Fastlane matchによるコード署名、TestFlightへのアップロード。データセンターのMac miniまたはMac上のセルフホステッドランナーは、クラウドmacOSランナーの代替手段です。
FlutterとReact Nativeは両プラットフォームのネイティブビルドにコンパイルされます。CIは2つのランナーをサポートする必要があります。Androidビルド用のLinuxとiOSビルド用のmacOSです。最適な戦略は分割パイプラインです。LinuxランナーでAndroidビルド、macOSランナーでiOSビルドを行い、両方のアーティファクトを単一のリリースに統合します。
CIツールの選択は、チームの規模、必要なパフォーマンス、予算、テクノロジースタックによって異なります。以下は、モバイル開発に焦点を当てた人気ソリューションの比較です。セルフホステッドソリューションは制御を提供しますが管理が必要であり、クラウドソリューションは利便性を提供しますが設定が制限されます。
パブリックリポジトリでは無料(2000分/月)。GitHub ActionsはAndroid(gradle/actions)およびiOS(apple-actions)向けの既製アクションのエコシステムを提供します。欠点は、macOSランナーが有料プランでのみ利用可能なことです。オープンソースや既にGitHubを使用している小規模チームに最適です。
セルフホステッドのオープンソースCIサーバー。JenkinsはGroovy Pipelineを介して設定され、数百のプラグインをサポートし、任意のハードウェアで動作します。セットアップとメンテナンスにはDevOpsエンジニアが必要です。インフラの制御が重要なエンタープライズセグメントで人気があります。
オープンなランナーアーキテクチャを備えたGitLabに組み込まれたCI/CD。GitLab CIでは、無料プランで独自のランナー(macOSを含む)を使用できます。YAML設定はGitHub Actionsより強力ですが、習得が難しいです。GitLabを単一のDevOpsプラットフォームとして使用するチームに適しています。
速度に重点を置いたクラウドCI。CircleCIはDocker、macOS、Androidイメージをサポートし、依存関係を自動的にキャッシュします。料金はクレジットベースで、小規模チームにはGitHub Actionsより高価ですが、最適化されたランナーにより高速です。速度要件のある本番プロジェクトに推奨されます。
GitHub Actionsを使用したAndroidプロジェクトのCIセットアップを考えてみましょう。パイプラインは、mainブランチへのプッシュおよびプルリクエストごとに静的解析、ビルド、テストを実行します。最小構成では15分かかり、外部サービスは必要ありません。
name: Android CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: 17
distribution: temurin
- run: ./gradlew ktlintCheck detekt
unit-tests:
needs: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: 17
distribution: temurin
- uses: gradle/actions/setup-gradle@v4
- run: ./gradlew testDebugUnitTest
- uses: actions/upload-artifact@v4
with:
name: test-results
path: app/build/reports/tests/
パイプラインは2つの並列ジョブで構成されます。lint(静的解析を実行)とunit-tests(lintに依存 — リンティングが失敗した場合、テストは実行されません)。unit-testsジョブはテストレポートをアーティファクトとしてアップロードします。チームはファイルをローカルにダウンロードせずにGitHub Actions UIで確認できます。
些細なエラーによるCIの失敗を防ぐために、Gitのpre-push hookまたはGradleタスクを設定し、同じチェックをローカルで実行します。例:./gradlew ktlintCheck detekt testDebugUnitTest。ローカルチェックに3分以上かかる場合は、高速(リンター)と低速(テスト)に分割し、高速チェックは各コミットの前に、低速チェックはプッシュの前にのみ実行します。
よくある質問
CIはコードの統合と検証(ビルド+テスト)に焦点を当てていますが、CDはデプロイの自動化を追加します。CIはコードが正しいことを確認します。CDはその正しいコードがユーザーに届けられることを保証します。CIはCDの前提条件ですが、CDはCIなしでは機能しません。
最低頻度は開発者1人あたり1日1回です。理想的なプラクティスは、作業の論理的な単位が完了するたび(1~4時間ごと)にリポジトリにプッシュすることです。統合の頻度が高いほど、競合が少なくなり、解決も容易になります。統合の間隔が2日以上空いている場合、CIを使用していません。
AndroidにはGitHub Actions(無料、設定が簡単)またはGitLab CI(独自ランナー)が最適です。iOSにはCircleCI(macOSサポートが最も充実)またはBitrise(モバイルプロジェクト向け特化CI)です。クロスプラットフォームプロジェクトには、2つのランナー(Linux + macOS)を持つGitLab CIです。
はい、ただし条件付きです。UIテストは低速(10~30分)で不安定(flaky)です。最適な戦略は、プッシュごとに高速テスト(ユニット+統合)を実行し、UIテストはプルリクエスト、夜間、またはリリース前に実行することです。UIテストにはDevice FarmまたはCI内のエミュレーターを使用してください。
効果的なCIの指標:ビルド時間が15分未満、グリーンビルドの割合が85%超、障害からの平均復旧時間が30分未満。ビルドが頻繁に失敗する場合、CIは役立たずむしろ妨げになっています。テストを見直し、flakyテストを削除し、依存関係を最適化し、ビルド時間を短縮してください。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。