CI/CD自動化への関心は過去3年間で一貫して高まっており、「CI/CDパイプライン設定」の検索ボリュームは2025年だけで34%増加しました。それにもかかわらず、英国の開発エージェンシーの大半は今なお手動のSSHセッションやアドホックスクリプトでデプロイを行っています。このギャップは大きな競争上の不利を意味します。成熟したCI/CDパイプラインを持つチームは約5倍の頻度でリリースし、デプロイ後の修正と比較して10倍安いコストでバグを発見できます。
このガイドでは、2026年に英国の開発チームがCI/CDパイプラインを構築する際の実践的な現実を取り上げます。プラットフォームの選択、パイプラインステージの正しい構造化、セキュリティスキャンの統合、そして本番環境で実際に機能するデプロイ戦略を扱います。
TL;DR
- CIはすべてのコミットを自動的にビルドしテストする。CDは手動介入なしにステージングまたは本番環境に検証済みコードを届ける
- GitHub Actionsは2026年の英国チームの大半にとって正しいデフォルト選択。セルフホストランナーや強力な監査コントロールが必要な場合はGitLab CIが優れた選択
- 本番対応パイプラインはビルドからポストデプロイモニタリングまで11のステージを持つ。ビルドとテストだけではない
- セキュリティスキャンはパイプラインに組み込むべきで、後付けにすべきではない。SASTと依存関係の監査、シークレットスキャンはすべてのプルリクエストで実行すること
CI/CDとは何か
この用語は曖昧に使われるため、正確に定義する価値があります。継続的インテグレーション(CI)とは、共有ブランチへのすべてのコミットが自動シーケンスをトリガーすることを意味します。コードはビルドされ、リントされ、変更が受け入れられる前にテストされます。目標は、スプリントの終わりに1週間分の分岐したブランチをマージするときではなく、コンテキストがまだ新鮮な間に統合の問題をすぐに発見することです。
継続的デリバリー(CD)はその自動化を拡張し、検証済みコードを最小限またはゼロの手動ステップでステージングまたは本番環境にリリースできるようにします。継続的デプロイ(より強力なバージョン)は、すべての成功したパイプラインが自動的に本番環境にデプロイされることを意味します。ほとんどのチームは継続的デリバリーから始め、本番デプロイ前に手動承認ゲートを追加し、テストカバレッジとロールバックメカニズムへの十分な信頼が得られたら完全な継続的デプロイへと移行します。
実践的な結果として、CI/CDはデプロイを高ストレスで数時間かかるイベントから、週に何十回も行われる日常的なバックグラウンドプロセスに変換します。
プラットフォームの選択
プラットフォームの選択は重要ですが、永続的ではありません。必要があれば後で移行しますが、今すぐコンテキストに合った正しいデフォルトを選んでください。
GitHub Actions は2026年に新プロジェクトを始める英国の開発チームの大半にとって正しい選択です。GitHubと深く統合されており、再利用可能なアクションの最大のエコシステム、公開リポジトリへの寛大な無料分、そしてよく文書化された設定フォーマットを持っています。ホスト型ランナーはLinux、Windows、macOSをカバーしています。すでにGitHubを使用しているチームにとって、最小抵抗パスの利点は本物です。
GitLab CI は、セルフホストランナーが必要(規制上の理由またはプライベートネットワークリソースへのアクセスのため)、より強力な監査ログが必要、またはチームがソースコントロール、CI、コンテナレジストリ、デプロイに単一プラットフォームを好む場合により良い選択です。GitLabの.gitlab-ci.ymlフォーマットは成熟しており、よく理解されています。
CircleCI は強力な並列処理とDockerサポートを持ち、設定は読みやすいです。GitHub Actions以前の市場リーダーであり、多くの英国エージェンシーが今も使用しています。既存のCircleCI設定が機能しているなら、急いで移行する理由はありません。
Jenkins はレガシーです。動作しており、多くの大企業が成功裏に運用していますが、2026年の新プロジェクトではJenkinsサーバーを維持する運用上のオーバーヘッドは割に合いません。Jenkinsを引き継ぐ場合は、長期コミットする前に移行コストを評価してください。
Bitbucket Pipelines は、チームがAtlassianスタックに組み込まれていてソースコントロールを変更できない場合は許容されます。機能セットはGitHub Actionsに後れを取りますが、基本をカバーしています。
パイプラインステージ:何を含めるべきか、そしてその理由
完全な本番対応パイプラインは、ほとんどのチュートリアルがカバーするよりも多くのステージを持ちます。各ステージの理由とともに完全なシーケンスを示します。
ステージ1:ビルド
ソースをコンパイルまたはトランスパイルし、依存関係をインストールし、ビルドアーティファクトを生成します。Node.jsプロジェクトではnpm ci(ciはlockfileを正確に使用するためnpm installではない)とビルドステップを意味します。Pythonサービスでは仮想環境を作成しrequirements.txtからインストールすることを意味します。出力はバージョン管理されたアーティファクトです。コンパイル済みバイナリ、トランスパイル済みJSバンドル、またはwheelファイルです。
ここで依存関係を積極的にキャッシュしてください。package-lock.jsonをキーとするキャッシュを使ったnpm ciは、依存関係を変更していない後続のパイプライン実行がダウンロードを完全にスキップすることを意味します。
ステージ2:リントと静的解析
ESLint、flake8、mypy、厳格モードのPylance、または言語に適した同等ツールです。このステージは高速で、通常30秒以内で、テストが実行される前に広い範囲の問題を検出します。静的型チェック(Pythonのmypy、JS/TSのTypeScriptのtsc --noEmit)は、ユニットテストがしばしば見逃すインターフェースの不一致を検出するために特に価値があります。
ここで速く失敗してください。コードがリントを通過しない場合、10分間のテストスイートを実行する意味はありません。
ステージ3:ユニットテスト
ユニットテストスイートを実行します。ユニットテストは高速であるべきです。完全なユニットテスト実行に5分以上かかる場合は、スイートを分割するか理由を調査してください。テストランナーがサポートしている場合はテストファイル間で並列化してください(Jestの--runInBandをオフ、PythonはpyTest-xdist)。
重要な点:ユニットテストは外部サービスにモックを使用します。このステージでCI環境に実際のデータベース認証情報や外部APIキーがあってはなりません。
ステージ4:インテグレーションテスト
インテグレーションテストは実際のサービスに対して実行されます。テストデータベース、Redisインスタンス、ローカルメッセージキューです。ほとんどのCIプラットフォームはこの目的のためにサービスコンテナをサポートしています。GitHub Actionsでは、テスト実行の期間中PostgreSQLまたはMySQLコンテナを起動するためにジョブの隣にservicesブロックを宣言します。
これがユニットテストが見逃すバグを検出するステージです。意味的に誤ったORMクエリ、トランザクション分離の問題、外部キー制約の失敗です。モックではなく実際のデータベースに対してインテグレーションテストを実行してください。
ステージ5:セキュリティスキャン
セキュリティスキャンはパイプラインに属し、四半期ごとの定期スキャンには属しません。このステージには3つのコンポーネントがあります。
SAST(静的アプリケーションセキュリティテスト)。 Semgrepはポリグロットチームに最も実用的な選択です。Python、JavaScript、TypeScript、Go、Javaなどのルールを持っています。Python専用では、Banditが一般的なセキュリティアンチパターンを検出します。GitHubのCodeQLは公開リポジトリに無料で利用でき、パターンマッチングツールとは異なるクラスの脆弱性を検出します。すべてのプルリクエストでこれらのうち少なくとも1つを実行してください。
依存関係の監査。 Node.jsプロジェクトにはnpm audit --audit-level=high、Pythonにはpip-auditを使用します。これらはOSV(オープンソース脆弱性)データベースに対してインストール済みの依存関係を確認します。高および重大な所見でパイプラインをブロックし、中程度の所見はブロックせずに人間によるレビューのためにフラグを立てます。
シークレットスキャン。 Gitleaksはコミット履歴を誤ってコミットされた認証情報、APIキー、トークンのためにスキャンします。これはシークレットがリモートに到達する前の最後の防衛ラインです。GitHubの組み込みシークレットスキャンを有効にする価値もありますが、パイプラインのGitleaksはプッシュ前に問題を検出します。
ステージ6:Dockerイメージのビルドとプッシュ
デプロイターゲットがコンテナの場合、ここでDockerイメージをビルドし、レジストリにプッシュします。latestだけでなくコミットSHAでタグ付けします。不変のタグにより、本番環境で実行されているコミットを常に正確に特定できます。GitHub Container Registry(ghcr.io)、AWS ECR、または選択したレジストリにプッシュします。
プッシュ前にビルドされたイメージに対してコンテナイメージスキャン(TrivyまたはGrype)を実行します。これにより依存関係の監査が見逃すベースイメージのOSレベルのCVEを検出できます。
ステージ7:ステージングへのデプロイ
本番環境を反映したステージング環境に検証済みアーティファクトをデプロイします。Infrastructure-as-Code(Terraform、Pulumi)により、ステージング環境は本番環境と同じように定義されます。デプロイステップは冪等性を持つべきです。2回実行しても問題が発生しないようにすること。
ステージ8:ステージングに対するスモークテスト
ステージングへのデプロイ後、最小限のエンドツーエンドチェックを実行します。アプリケーションは起動できるか、ヘルスエンドポイントは200を返すか、基本的なログインフローは機能するか。これらのテストは2分以内に実行されるべきです。目標は包括的なカバレッジではなく、分離されたテストでは検出できないデプロイの失敗を検出することです。
ステージ9:手動承認ゲート
本番環境へのデプロイ前に、人間が承認するために一時停止します。GitHub Actionsでは、必須レビュアーを持つ環境保護ルールです。GitLab CIでは手動ジョブトリガーです。このゲートは軽量であるべきです。ステージング環境が正しく見えることを確認する1人のレビュアーであり、長い承認プロセスではありません。
継続的デプロイへと移行しているチームでは、デプロイ頻度とテストカバレッジが十分に高くなれば、このゲートを自動化できますが、ゲートから始めることがより安全なデフォルトです。
ステージ10:本番環境へのデプロイ
ステージングと同じデプロイステップで、本番環境を向いています。コミットSHAでタグ付けされた不変のアーティファクトがあれば、本番デプロイは決定論的です。
ステージ11:ポストデプロイモニタリングチェック
本番デプロイ後、パイプラインはモニタリングが正常であることを確認すべきです。エラーレートが上昇していないか、ヘルスエンドポイントが応答しているか、レイテンシのスパイクがないか。オブザーバビリティプラットフォーム(Datadog、Grafana、または基本的なHTTPヘルスチェック)に対する簡単なチェックにより、デプロイが成功したか、ロールバックをトリガーするアラートかを自動的に示すシグナルが得られます。
現実的なGitHub Actions設定
以下はNode.jsアプリケーションの省略されているが現実的なパイプライン構造です。
1name: CI/CD Pipeline
2
3on:
4 push:
5 branches: [main, develop]
6 pull_request:
7 branches: [main]
8
9jobs:
10 build-and-lint:
11 runs-on: ubuntu-latest
12 steps:
13 - uses: actions/checkout@v4
14 - uses: actions/setup-node@v4
15 with:
16 node-version: '20'
17 cache: 'npm'
18 - run: npm ci
19 - run: npm run lint
20 - run: npx tsc --noEmit
21
22 unit-tests:
23 needs: build-and-lint
24 runs-on: ubuntu-latest
25 steps:
26 - uses: actions/checkout@v4
27 - uses: actions/setup-node@v4
28 with:
29 node-version: '20'
30 cache: 'npm'
31 - run: npm ci
32 - run: npm test -- --coverage
33
34 integration-tests:
35 needs: build-and-lint
36 runs-on: ubuntu-latest
37 services:
38 postgres:
39 image: postgres:16
40 env:
41 POSTGRES_PASSWORD: testpass
42 POSTGRES_DB: testdb
43 options: >-
44 --health-cmd pg_isready
45 --health-interval 10s
46 --health-timeout 5s
47 --health-retries 5
48 steps:
49 - uses: actions/checkout@v4
50 - uses: actions/setup-node@v4
51 with:
52 node-version: '20'
53 cache: 'npm'
54 - run: npm ci
55 - run: npm run test:integration
56 env:
57 DATABASE_URL: postgres://postgres:testpass@localhost:5432/testdb
58
59 security-scan:
60 needs: build-and-lint
61 runs-on: ubuntu-latest
62 steps:
63 - uses: actions/checkout@v4
64 with:
65 fetch-depth: 0
66 - uses: actions/setup-node@v4
67 with:
68 node-version: '20'
69 cache: 'npm'
70 - run: npm ci
71 - run: npm audit --audit-level=high
72 - uses: semgrep/semgrep-action@v1
73 - name: Run Gitleaks
74 uses: gitleaks/gitleaks-action@v2
75
76 deploy-staging:
77 needs: [unit-tests, integration-tests, security-scan]
78 runs-on: ubuntu-latest
79 environment: staging
80 if: github.ref == 'refs/heads/main'
81 steps:
82 - uses: actions/checkout@v4
83 - name: Deploy to staging
84 run: ./scripts/deploy.sh staging
85
86 deploy-production:
87 needs: deploy-staging
88 runs-on: ubuntu-latest
89 environment: production
90 steps:
91 - uses: actions/checkout@v4
92 - name: Deploy to production
93 run: ./scripts/deploy.sh production
unit-tests、integration-tests、security-scanジョブはbuild-and-lintジョブが成功した後に並列で実行されます。この構造はカバレッジを犠牲にすることなくパイプラインの総実行時間を短縮します。
デプロイ戦略
デプロイの方法はデプロイするかどうかと同様に重要です。3つの戦略が英国チームのほとんどのニーズをカバーします。
ローリングデプロイ。 インスタンスを1つずつ置き換えます。ほとんどのオーケストレーター(Kubernetes、ECS)で実装が簡単です。リスク:新バージョンにバグがある場合、ロールアウトウィンドウ中に一部のユーザーは古いインスタンスに、他のユーザーは新しいインスタンスにアクセスします。低トラフィックアプリケーションの良いデフォルトです。
ブルーグリーンデプロイ。 2つの同一の本番環境を維持します。トラフィックはブルーからグリーンにアトミックに切り替わります。新バージョンに不具合がある場合、数秒で切り替えを戻します。コストは2つの環境を同時に実行することであり、データベースにとっては非自明です。ダウンタイムが許容できずロールバック速度が重要なアプリケーションに最適です。
カナリアリリース。 トラフィックの少ない割合(5%または10%)を新バージョンにルーティングし、定められた期間のエラーレートとパフォーマンスを観察し、カナリアを100%に昇格させます。完全なロールアウト前に実際の本番フィードバックが欲しい高トラフィックアプリケーションに最適です。ロードバランサーまたはサービスメッシュがトラフィック分割をサポートする必要があります。
英国チームのほとんどはローリングデプロイから始め、トラフィックと重要性が正当化されたらブルーグリーンを追加し、1日に複数回リリースして各ステップで検証済みの本番フィードバックが必要な場合にカナリアリリースを検討すべきです。
シークレット管理
シークレットはコード、設定ファイル、またはソースコントロールにコミットされた環境固有の.envファイルに属しません。正しいアプローチ:
GitHub Secrets / GitLab CI変数 はパイプラインジョブが必要とするシークレットのためのものです。これらは保存時に暗号化され、ログでマスクされ、環境変数を通じてジョブで利用できます。
環境固有のシークレット はデプロイターゲットレベルで設定されます。AWS Parameter Store、Azure Key Vault、Google Secret Manager、またはより複雑なニーズを持つチームのHashiCorp Vaultです。アプリケーションは起動時にパイプラインを通じて渡される環境変数からではなく、シークレットストアからシークレットを読み取ります。
ローテーション。 APIキー、データベースパスワード、サービス認証情報はスケジュールに従ってローテーションする必要があります。CI/CDパイプラインは、1か所でシークレットを更新すること(シークレットストアまたはCI環境)が次のデプロイに自動的に伝播するため、ローテーションを容易にします。
パイプラインのGitleaksは、開発者が誤ってシークレットをコミットした場合のセーフティネットです。コミットされたシークレットの修復はすぐに無効化し、git履歴をクリーンアップすることです。Gitleaksアラートは、誰かがそれを悪用する前に今すぐそのプロセスを開始する必要があることを伝えます。
パイプラインパフォーマンス
遅いパイプラインは無視されるパイプラインです。開発者がすべてのプッシュに対して15分のフィードバックを待つ場合、小さなコミットをプッシュするのをやめ、作業をバッチ処理し始めます。これはCIの目的を損ないます。
パイプラインを高速に保つための実践的なステップ:
依存関係のインストールをキャッシュします。npmの場合、package-lock.jsonにキャッシュをキーします。pipの場合、requirements.txtにキーされたpipキャッシュアクションを使用します。ウォームキャッシュは2分間のインストールを5秒間の復元に変えます。
独立したジョブを並列で実行します。ビルド、リント、ユニットテスト、インテグレーションテスト、セキュリティスキャンはすべて互いに依存しているわけではありません。適切に構造化されたパイプラインは、共通のビルドステップ後にそれらを並列ジョブとして実行し、総実行時間を大幅に短縮します。
パスフィルターを使用します。複数のサービスを持つモノレポがある場合、サービスディレクトリ内のファイルが変更された場合にのみ関連するパイプラインステージをトリガーします。GitHub Actionsはプッシュトリガーのpathsフィルターをサポートしています。
タイムアウトを設定します。ハングしたジョブはデフォルトの6時間のタイムアウト全体でランナーを占有すべきではありません。各ステージに適したジョブレベルのタイムアウトを設定します。リントは5分、ユニットテストは15分、インテグレーションテストは30分です。
重要なポイント
- CI/CDはデプロイを高リスクイベントからルーティンで自動化されたプロセスに変換する。英国チームのほとんどの最大のボトルネックはツールではなく、構造化されたパイプライン自体の欠如である。
- GitHub Actionsは新プロジェクトの正しい出発点。GitLab CIはセルフホストランナーまたは単一の統合プラットフォームを必要とするチームに。
- 本番グレードのパイプラインは11のステージを持つ。ほとんどのチュートリアルは3で止まる。スキップしたステージが本番インシデントの起源になる。
- セキュリティスキャン(SAST、依存関係監査、シークレットスキャン)はすべてのプルリクエストでパイプラインに属し、月次定期スキャンには属しない。
- デプロイ戦略は互換性がない。シンプルさのためのローリングデプロイ、ゼロダウンタイムの重要性のためのブルーグリーン、本番検証が必要な高頻度リリースのためのカナリア。
- 遅いパイプラインはパイプラインがない場合と同様にダメージを与える。積極的にキャッシュし、独立したジョブを並列化し、すべてのジョブにハードタイムアウトを設定する。
よくある質問(FAQ)
CI/CDパイプラインの実行にはどのくらいかかるべきですか? プッシュからステージングデプロイまでの重要なパスで10分以内を目標にしてください。リントとユニットテストは5分以内に完了すべきです。パイプラインが定期的に長くかかる場合は、キャッシュ、並列化、テストスイートが個別のより少ない頻度の実行に属する遅いテストを積み上げていないかを調査してください。
すべてのコミットで完全なテストスイートを実行すべきか、mainへのプルリクエストのみで実行すべきか? すべてのプッシュで高速チェック(リント、ユニットテスト、セキュリティスキャン)を実行します。mainへのプルリクエストとmainへのマージでインテグレーションテストとステージングデプロイを実行します。これによりフィードバック速度とリソースコストおよびランナー分のバランスが取れます。
CIとCDの違いは何ですか? CI(継続的インテグレーション)とは、すべてのコミットが自動化されたビルドとテストシーケンスをトリガーすることです。CD(継続的デリバリー)はその自動化を拡張して検証済みコードをステージングまたは本番環境にデプロイします。通常は一緒に実装されますが、異なる実践を表しています。
ステージング環境は必要ですか? はい、実際のユーザーがいるすべてのアプリケーションに必要です。ステージングは、デプロイ固有の失敗、環境間の設定の違い、ユニットまたはインテグレーションテストでは現れないスモークテストの問題を検出する場所です。本番環境で直接テストすることは、CI/CDが排除しようとするリスクです。
CI/CDパイプラインでデータベースマイグレーションを処理する最良の方法は何ですか? 新しいアプリケーションバージョンがトラフィックの受信を開始する前に、デプロイステップの一部としてマイグレーションを実行します。ロールバックがスキーマを壊さないように、マイグレーションが前のアプリケーションバージョンとの後方互換性を持つようにしてください。それらを使用する機能と同じマイグレーションで破壊的なスキーマ変更(列の削除、型の変更)を避けてください。
英国のエージェンシーやクライアントにCI/CD投資が価値あることを納得させるにはどうすればよいですか? 最も強力な論拠は財務的なものです。CIで検出されたバグはデプロイ後に見つかったバグよりも修正コストが約10倍安いです。適切に運営されたパイプラインは各リリースのリスクとストレスも軽減し、チームの定着率と速度を直接改善します。ほとんどの英国エージェンシーはCI/CDを採用した最初の四半期以内に時間外緊急デプロイの測定可能な削減を確認しています。
コメント