目次
- 基本概念
- ソース管理とブランチ戦略
- パイプライン設計
- ビルド
- テスト戦略
- セキュリティ
- アーティファクト管理
- デプロイ戦略
- 環境管理とIaC
- 監視・可観測性とフィードバック
- パフォーマンス最適化
- 指標(DORAメトリクス)
- 文化・運用
- よくあるアンチパターン
- チェックリスト
1. 基本概念
| 用語 | 意味 |
|---|
| CI(継続的インテグレーション) | 開発者の変更を頻繁にメインブランチへ統合し、そのたびに自動でビルド・テストする |
| 継続的デリバリー(Continuous Delivery) | 常にリリース可能な状態を保ち、本番デプロイはボタン一つ(手動承認)で行える |
| 継続的デプロイ(Continuous Deployment) | パイプラインを通過した変更を人手を介さず自動で本番へデプロイする |
根本の原則
- 小さな変更を、頻繁に、自動で検証する
- 問題は早く見つけるほど安く直せる(シフトレフト)
- 「本番に出せる状態」を常に維持する
- 手作業を排除し、再現性を確保する
2. ソース管理とブランチ戦略
すべてをバージョン管理する
- アプリケーションコードだけでなく、パイプライン定義・インフラ定義・設定・DBマイグレーションもリポジトリで管理する
- パイプラインはコード(
.github/workflows/*.yml、.gitlab-ci.yml、Jenkinsfile 等)として定義し、レビュー対象にする
ブランチ戦略
- トランクベース開発を推奨。短命なフィーチャーブランチ(目安: 1〜2日以内)でメインへマージする
- 長期間生きるブランチはマージ地獄の元。避ける
- 未完成の機能はフィーチャーフラグで隠してマージする
メインブランチの保護
- 直接pushを禁止し、Pull Request(Merge Request)経由のみとする
- マージ条件に「CI成功」「レビュー承認」を必須化する
- メインブランチが壊れたら最優先で修正する(Stop the line)
コミットの粒度
- 1コミット・1PRは小さく、目的を一つに絞る
- Conventional Commits などの規約を採用すると、変更履歴やバージョン付けを自動化しやすい
3. パイプライン設計
典型的なステージ構成
コミット
└─ Lint / 静的解析 / フォーマットチェック
└─ ビルド
└─ ユニットテスト
└─ セキュリティスキャン(SAST / 依存関係)
└─ アーティファクト作成・保存
└─ 統合テスト / E2Eテスト(ステージング)
└─ (承認)
└─ 本番デプロイ
└─ スモークテスト / 監視
設計原則
- 速いチェックを先に: Lintやユニットテストなど数秒〜数分で終わるものを前段に置き、早く失敗させる(Fail Fast)
- 並列化: 依存関係のないジョブは並列で実行する
- 冪等性: 同じ入力なら何度実行しても同じ結果になるようにする
- 再現性: ローカルでも同じコマンドでビルド・テストできるようにする(
make test 等の共通エントリポイント)
- パイプラインを単純に保つ: 複雑なロジックはスクリプトに切り出し、YAMLは薄く保つ
- 共通化: 再利用可能なワークフロー/テンプレートを使い、リポジトリ間のコピペを避ける
目標時間の目安
- PRに対するCIフィードバック: 10分以内
- メインマージから本番反映まで: 可能な限り短く(1時間以内を目指す)
4. ビルド
- 一度だけビルドする(Build Once, Deploy Many): 同じアーティファクトを全環境にプロモートする。環境ごとに再ビルドしない
- 依存関係を固定する: ロックファイル(
package-lock.json、poetry.lock、go.sum 等)をコミットする
- ビルド環境を固定する: ベースイメージやツールのバージョンを明示(
latest タグは避ける。ダイジェスト指定が望ましい)
- 環境依存の設定はビルド成果物に埋め込まない: 設定は実行時に環境変数や設定ストアから注入する
- ビルドの決定性: 可能ならタイムスタンプ等を排除し、再現可能ビルドを目指す
- コンテナビルド: マルチステージビルドで最終イメージを小さくし、不要なツールを含めない
5. テスト戦略
テストピラミッド
▲ E2E テスト(少数・遅い・高コスト)
▲▲▲ 統合テスト(中程度)
▲▲▲▲▲▲▲ ユニットテスト(多数・速い・低コスト)
- ユニットテストを厚く、E2Eは重要なユーザーフローに絞る
ベストプラクティス
- フレーキーテスト(不安定なテスト)を放置しない: 検出したら隔離(quarantine)し、期限を決めて修正する。リトライで覆い隠し続けない
- テストは独立させる: 実行順序や共有状態に依存しない
- テストデータを管理する: 各テストが自分でデータを用意・破棄する。コンテナ(Testcontainers 等)で使い捨てのDBを立てる
- カバレッジは目安として使う: 数値目標そのものより、重要なロジックがテストされているかを重視する。カバレッジの低下を検知する仕組みは有効
- 契約テスト: マイクロサービス間ではコンシューマ駆動契約テスト(Pact 等)で互換性を担保する
- 非機能テスト: パフォーマンス・負荷テストを定期実行(夜間ジョブ等)する
- DBマイグレーションのテスト: マイグレーションの適用(と必要ならロールバック)をCIで検証する
6. セキュリティ
シークレット管理
- シークレットをリポジトリにコミットしない。CIのシークレット機能や Vault、クラウドのシークレットマネージャを使う
- ログにシークレットが出力されないようマスキングを確認する
- 可能な限り長期の認証情報を避け、OIDCによる短期トークンでクラウドに認証する
- シークレットスキャン(gitleaks、GitHub Secret Scanning 等)を導入し、push時に検出する
最小権限の原則
- パイプラインのトークン・サービスアカウントの権限は必要最小限にする(例: GitHub Actions の
permissions: を明示)
- 本番デプロイ用の権限は保護されたブランチ/環境からのみ使えるようにする
- フォークからのPRでシークレットが使えないよう設定する
スキャンの組み込み(DevSecOps)
| 種類 | 内容 | ツール例 |
|---|
| SAST | ソースコードの静的解析 | CodeQL, Semgrep, SonarQube |
| SCA | 依存ライブラリの脆弱性 | Dependabot, Renovate, Snyk, Trivy |
| コンテナスキャン | イメージの脆弱性 | Trivy, Grype |
| IaCスキャン | インフラ定義の設定ミス | Checkov, tfsec |
| DAST | 稼働中アプリへの動的検査 | OWASP ZAP |
サプライチェーンセキュリティ
- サードパーティのCIアクション/プラグインはコミットSHAで固定する
- SBOM(ソフトウェア部品表)を生成する
- アーティファクトに署名し(Sigstore / cosign 等)、デプロイ時に検証する
- SLSA などのフレームワークを参考に、ビルドの来歴(provenance)を記録する
- セルフホストランナーは信頼できないコードを実行させない。使い捨て(エフェメラル)にする
7. アーティファクト管理
- ビルド成果物はアーティファクトリポジトリ/コンテナレジストリに保存する
- 不変(immutable)にする: 同じバージョンタグを上書きしない
- トレーサビリティ: アーティファクトからコミットSHA・ビルド番号・PRを辿れるようにする
- バージョニングにはセマンティックバージョニングやコミットSHAを使う
- 保持ポリシーを設定し、古いアーティファクトを自動削除する(ただし本番で動いているものは保持)
8. デプロイ戦略
| 戦略 | 概要 | 長所 | 注意点 |
|---|
| ローリング | インスタンスを順次入れ替える | 追加リソースが少ない | 新旧混在期間がある |
| ブルー/グリーン | 新環境を用意してトラフィックを一括切替 | 即時ロールバック可能 | リソースが2倍必要 |
| カナリア | 一部のトラフィックだけ新版へ流し、段階的に拡大 | 影響範囲を限定できる | 監視・自動判定の仕組みが必要 |
| フィーチャーフラグ | デプロイとリリース(機能公開)を分離 | ユーザー単位で制御可能 | フラグの棚卸しが必要 |
ベストプラクティス
- デプロイとリリースを分離する: コードのデプロイと機能の有効化を別の操作にする
- ロールバックを自動化・訓練する: ロールバック手順は一発で実行できるようにし、定期的に試す
- ロールフォワードも選択肢に: 小さな変更ならすぐ修正版を出すほうが速いこともある
- DBスキーマ変更は後方互換に: Expand/Contract(拡張→移行→縮小)パターンで、新旧両バージョンのアプリが動くようにする
- デプロイ後の自動検証: スモークテストとヘルスチェックを実行し、異常時は自動ロールバック
- 本番デプロイには承認ゲートや保護環境を設定(継続的デリバリーの場合)
- デプロイ頻度を上げ、1回あたりの変更量を小さくする: リスクが下がる
9. 環境管理とIaC
- Infrastructure as Code: Terraform、Pulumi、CloudFormation 等でインフラをコード化し、CIで
plan を確認、レビュー後に apply
- 環境の同等性(Parity): 開発・ステージング・本番の構成差を最小にする
- 設定の外部化: 環境ごとの差分は設定値(環境変数・設定ファイル)だけに留める(Twelve-Factor App)
- プレビュー環境: PRごとに一時環境を自動作成し、マージ・クローズ時に自動削除する
- GitOps: Gitリポジトリを望ましい状態の唯一の情報源とし、Argo CD / Flux 等で自動同期する
- ドリフト検知: 手動変更によるコードとの差異を定期的に検出する
10. 監視・可観測性とフィードバック
- パイプラインの通知: 失敗時はチャットツールなどで即座に関係者へ通知する。成功通知は必要最小限にしてノイズを減らす
- デプロイの可視化: どのバージョンがどの環境にいつデプロイされたかを記録・表示する
- デプロイマーカー: 監視ダッシュボードにデプロイ時刻を表示し、障害との相関を見やすくする
- 本番監視: メトリクス・ログ・トレースを収集し、SLO(サービスレベル目標)に基づいてアラートする
- 自動判定: カナリアのエラー率やレイテンシを自動比較し、閾値超過で自動ロールバック
- パイプライン自体の監視: 実行時間・成功率・キュー待ち時間の推移を追う
11. パフォーマンス最適化
- キャッシュ: 依存関係(npm, pip, Maven 等)やDockerレイヤーをキャッシュする。キャッシュキーにはロックファイルのハッシュを使う
- 差分実行: 変更されたパス・パッケージに関係するジョブだけを実行する(モノレポでは特に重要。Nx、Turborepo、Bazel 等)
- テストの分割(シャーディング): 大きなテストスイートを複数ランナーに分散する
- ジョブの並列化と不要な直列依存の削除
- 同一ブランチの古い実行を自動キャンセル(concurrency 設定)
- 軽量なベースイメージを使い、ランナーの準備時間を短縮する
- 適切なランナーサイズ: 遅いジョブはマシンスペックを上げるほうが総コストが下がる場合がある
12. 指標(DORAメトリクス)
CI/CDの効果は以下の4指標で測るのが一般的です。
| 指標 | 意味 | 改善の方向 |
|---|
| デプロイ頻度 | 本番へデプロイする頻度 | 高いほど良い |
| 変更のリードタイム | コミットから本番稼働までの時間 | 短いほど良い |
| 変更失敗率 | デプロイが障害や修正対応を引き起こす割合 | 低いほど良い |
| サービス復旧時間(MTTR) | 障害発生から復旧までの時間 | 短いほど良い |
- 指標はチームの改善のために使い、個人評価の道具にしない
- 速度(前の2つ)と安定性(後の2つ)は両立できる。片方だけを追わない
13. 文化・運用
- メインブランチが壊れたら全員で直す: 赤いビルドを放置しない
- パイプラインの所有者を明確にする: プラットフォームチームや担当者を決め、継続的に改善する
- ドキュメント化: パイプラインの構成、デプロイ手順、ロールバック手順をREADME等に残す
- ポストモーテム: 障害やデプロイ失敗は非難しない形で振り返り、パイプラインに再発防止策を組み込む
- 開発者体験を重視: CIが遅い・不安定だと、開発者は迂回策を探し始める。速さと信頼性は最優先の品質
- 定期的な依存関係の更新: Renovate / Dependabot で小さく頻繁に更新し、大規模アップデートを避ける
14. よくあるアンチパターン
| アンチパターン | 問題 | 対策 |
|---|
| 環境ごとに再ビルド | 検証したものと本番が異なる | Build Once, Deploy Many |
| 手動デプロイ手順書 | ミス・属人化 | 完全自動化 |
| フレーキーテストのリトライ放置 | CIの信頼性が失われる | 隔離して修正 |
| シークレットのハードコード | 漏洩リスク | シークレットマネージャ・OIDC |
| 長命なフィーチャーブランチ | マージ競合・統合の遅延 | トランクベース+フィーチャーフラグ |
| 30分以上かかるCI | フィードバックが遅く、まとめてコミットされる | キャッシュ・並列化・差分実行 |
latest タグへの依存 | 再現性がない・突然壊れる | バージョン/ダイジェスト固定 |
| ロールバック手順が未検証 | 障害時に機能しない | 定期的に訓練する |
| 失敗通知が多すぎる | アラート疲れで無視される | 通知先と内容を絞る |
| CIでのみ再現する手順 | ローカルでデバッグできない | 共通のビルドスクリプトを用意 |
15. チェックリスト
ソース・ブランチ
パイプライン
品質
セキュリティ
デプロイ
運用