ci-cd-integration について
ci-cd-integrationは、テストパイプラインの設計を支援するQAスキルで、CI/CDでの効率的なテスト実行を目指すチーム向けです。トリガーに応じたテスト選択、分割実行、成果物の保存、不安定なテストの隔離、品質ゲートを扱い、GitHub ActionsとGitLab CIのテンプレートを提供します。
主な機能
- 01トリガーに応じたテスト実行の設計
- 02複数のランナーへのテスト分割
- 03レポートとトレースの成果物保存
- 04不安定なテストの隔離
- 05カバレッジとマージのゲート設定
- 06GitHub Actions・GitLab CIのテンプレート
活用シーン
- 01時間のかかるCIテストを短縮
- 02Pull Requestにテストレポートを公開
- 03不安定なテストによるマージ阻止を回避
- 04テストとカバレッジの結果でリリースを制御
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ petrkindlmann/ qa-skills --skill ci-cd-integrationインストール後、Claude Code で/ci-cd-integrationを入力して読み込まれたか確認します。
同梱ファイルreferences/github-actions-templates.mdreferences/gitlab-ci-template.md
詳細
確認事項
まず .agents/qa-project-context.md を確認してください。存在する場合はその内容を使い、すでに回答されている項目(特に team_maturity と既存の CI の規約)は確認を省略してください。その後、次の項目を確認します。
- どの CI プラットフォームを使用していますか? GitHub Actions、GitLab CI、CircleCI、Jenkins などです。このスキルには GitHub Actions と GitLab CI のテンプレートが用意されています。
- どの種類のテストを実行する必要がありますか? ユニットテスト、統合テスト、E2E、ビジュアルテスト、パフォーマンステストなどです。それぞれ必要なリソースと実行時間が異なります。
- 現在の CI の実行時間はどれくらいですか? 10分を超える場合、並列化とシャーディングは任意ではなく必須です。
- 開発者は1日に何回プッシュしますか? プッシュ頻度の高いチームでは、並行実行の積極的なキャンセルとキャッシュが必要です。
- どのトリガーでどのテストを実行しますか? すべてのプッシュで完全な E2E スイートを実行する必要はありません。YAML を記述する前に、トリガーとテストスイートの対応を決めてください。
チームの成熟度に合わせて調整する
.agents/qa-project-context.md で team_maturity を設定し、該当するパイプライン構成を選択してください。
- startup — 1つのジョブで、PR 時に lint、ユニットテスト、E2E スモークテストを実行します。網羅性より迅速なフィードバックを優先します。
- growing — ユニットテスト、統合テスト、E2E を別々のジョブに分けます。並列化、アーティファクトのアップロード、結果の公開、フレークテストの隔離を行います。
- established — 完全なマトリックス構成です。シャーディングした E2E、複数環境への昇格ゲート、パフォーマンスおよびセキュリティのスキャン、デプロイゲート付きチェック、SLA に裏付けられたパイプラインを含みます。
基本原則
- 迅速なフィードバック:適切なタイミングで適切なテストを実行します。 プッシュごとにユニットテストを実行します(2分未満)。PR では E2E を実行します(10分未満)。マージ後と夜間には完全なスイートを実行します。以下のトリガーとテストスイートの対応が、この契約となります。
- まず並列化:テストをワーカー間でシャーディングします。 20分かかるシリアルテストスイートは、4つのシャードに分ければ5分で完了します。ランナーのコストをかける価値は常にあります。
- アーティファクトは証拠です。 すべての実行でトレース、スクリーンショット、カバレッジ、HTML レポートを保存します。アーティファクトがなければ、CI の失敗は「ローカルで再現してください」というデバッグ不能なループになります。
- フレークするテストにはリトライではなく隔離が必要です。 リトライは問題を隠します。リトライ後にテストが成功し、レポートはグリーンになっても、競合状態は残ります。フレークするテストをブロッキング対象外のジョブに移し、追跡して、根本原因を修正してください。
- 品質ゲートは本番環境に近づくほど厳しくします。 各段階で合格が必要な条件を定義します。PR ゲートは迅速かつ低コストに、デプロイゲートは包括的にします。
- しきい値は bash ではなく設定から読み込みます。 テストランナー自身の
coverageThreshold/thresholdsでカバレッジを適用し、失敗時にはゼロ以外の終了コードを返すようにします。正規表現で stdout からパーセンテージを抽出する方法は、ランナーのバージョン間で動作が不安定です。
パイプラインのアーキテクチャ
Push to branch: lint+types (30s) → unit (1-2m)
PR opened: + integration (2-3m) → E2E sharded (5-8m) → merge report
Merge to main: full E2E ∥ visual ∥ perf budget → deploy (OIDC)
Nightly (cron): full suite + npm audit + axe a11y + flaky quarantine
何をいつ実行するか
| トリガー | テスト | 最大実行時間 |
|---|---|---|
| ブランチへのプッシュ | lint、型チェック、ユニットテスト | 2分 |
| PR のオープン/更新 | + 統合テスト、E2E スモークテスト | 10分 |
| main へのマージ | + 完全な E2E、ビジュアルテスト、パフォーマンス予算 | 15分 |
| 夜間スケジュール | 完全なテストスイート、セキュリティ、a11y、フレークテストの隔離 | 30分 |
| リリースタグ | 完全なテストスイート、ステージング環境に対するスモークテスト | 20分 |
GitHub Actions
ユニットテスト、Playwright によるシャーディング済み E2E、完全なパイプライン、夜間実行、PR ゲート向けの、コピーしてそのまま使える完全なワークフローファイルについては、references/github-actions-templates.md を参照してください。
アクションのバージョン(2026年6月)
現在のメジャーバージョンに固定し、Dependabot に更新を任せます。actions/* ファミリーは Node 24 ランナーで実行されます。Node 20 は GH ホストランナーでは非推奨です。
| アクション | 現在のメジャーバージョン | 備考 |
|---|---|---|
actions/checkout | @v6 | |
actions/setup-node | @v6 | v5 以降は packageManager が設定されている場合のみ自動でキャッシュします。明示するには cache: npm を使用してください |
actions/cache | @v5 | 新しいキャッシュサービス v2 バックエンド |
actions/upload-artifact | @v7 | v7 では未圧縮(archive: false)でアップロードできます |
actions/download-artifact | @v7 | upload-artifact と同じメジャーバージョンを使用してください |
dorny/test-reporter | @v3 | v3 では Node 24 ランナーが必要です。レポーターキーに変更はありません |
dorny/paths-filter | @v3 | |
marocchino/sticky-pull-request-comment | @v3 | |
slackapi/slack-github-action | @v2 | メジャーバージョンは固定されていません。v3 を採用する前に通知に関する注記を確認してください |
サプライチェーンに配慮が必要なパイプラインでは、サードパーティ製アクション(dorny、marocchino、slackapi、knapsack)をバージョンコメント付きの完全なコミット SHA に固定し、Dependabot に SHA の更新を任せます。uses: dorny/test-reporter@<40-char-sha> # v3.0.0。ファーストパーティの actions/* はリスクが低いため、タグを使用しても問題ありません。
重要な概念
並行実行グループは、ブランチに複数のプッシュがあったときに、無駄な実行をキャンセルします。
concurrency:
group: tests-${{ github.ref }}
cancel-in-progress: true
マトリックス分割を複数のランナーで行います。
strategy:
fail-fast: false
matrix:
shard: [1, 2, 3, 4]
steps:
- run: npx playwright test --shard=${{ matrix.shard }}/4
キャッシュを利用して、ブラウザーを実行のたびに再ダウンロードしないようにします。
- uses: actions/setup-node@v6
with: { node-version: 22, cache: npm }
- name: Cache Playwright browsers
id: playwright-cache
uses: actions/cache@v5
with:
path: ~/.cache/ms-playwright
key: playwright-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
- name: Install Playwright browsers
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: npx playwright install --with-deps chromium
レポートやトレース用のアーティファクトと、分割したレポートを 1 つの HTML レポートに統合する方法については、references/github-actions-templates.md(E2E ワークフロー)を参照してください。統合ジョブでは、pattern: test-results-* を指定して actions/download-artifact@v7 を使用し、その後 npx playwright merge-reports --reporter=html を実行します。
大規模環境での、より効率的な分割
10〜15 個を超えるシャードでは、単純なハッシュベースの分割はシャード間の偏りによってランナーの時間を無駄にします。実行時間を考慮したバランサーを使用してください。
knapsack-pro— 実行時間データに基づき、Playwright/Jest/Cypress/RSpec に対応します。過去の所要時間に基づいて分散します。- CloudBees Smart Tests(旧 Launchable)— ML による優先順位付けと Test Impact Analysis に対応します。差分をもとに、失敗する可能性が高いテストのみを実行します。
- Datadog Test Optimization — TIA と不安定なテストの管理に対応し、過去の実行時間に基づいてシャードを分割します。
- Trunk Flaky Tests — 不安定なテストを考慮した隔離と、再試行回数の割り当てに対応します。
有料のバランサーを導入する前に、Playwright の --shard はファイル単位で分散し、過去の実行時間に基づいてすでにバランスを調整しています。カスタムの実行時間データを確認または取り込むには、次のように自分で出力します。npx playwright test --reporter=json | jq '[.suites[].specs[] | {file: .file, duration: .tests[].results[].duration}]'。Jest では、jest-slow-test-reporter を使うと実行時間が最も長いスペックがわかるため、分割または修正できます。
Kubernetes 上のセルフホストランナーには、Actions Runner Controller(arc-runner-set/gha-runner-scale-set)を使用してください。Helm でインストールでき、ワークフローごとにランナーポッドを自動スケーリングします。非推奨となった runner-deployment CRD の代替です。
必須のステータスチェック
Settings → Branches → Branch protection rules で main を保護します。「Require status checks to pass before merging」を有効にし、lint、unit-tests、e2e(すべてのシャード)を必須チェックに追加して、「Require branches to be up to date」も有効にします。
GitLab CI
パイプライン全体については、references/gitlab-ci-template.md を参照してください。重要なポイントは次のとおりです。
- ステージは
[validate, test, e2e, deploy]。lint/unit にはnode:22-alpine、E2E にはmcr.microsoft.com/playwright:v1.60.0-nobleを使用します(インストール済みの@playwright/testのマイナーバージョンに合わせて固定してください)。 - 並列分割:
parallel: 4によりCI_NODE_INDEX/CI_NODE_TOTALが利用可能になります。npx playwright test --shard=$CI_NODE_INDEX/$CI_NODE_TOTALを実行してください。 - カバレッジ:cobertura の
coverage_reportアーティファクトとjunitレポートを出力します。GitLab はそれらから割合とテスト結果を読み取ります。従来のcoverage:stdout 正規表現は Jest のバージョンによって不安定な代替手段です。cobertura レポートを推奨します。
高度なパターン
PR コメントへのテスト結果の公開
- name: Publish test results
uses: dorny/test-reporter@v3
if: ${{ !cancelled() }}
with:
name: Test Results
path: test-results/junit.xml
reporter: jest-junit # use java-junit for a Playwright JUnit report
スティッキーなカバレッジ PR コメント(marocchino/sticky-pull-request-comment@v3)については、references/github-actions-templates.md(PR 品質ゲート)を参照してください。
条件付きテスト実行
変更された箇所だけをテストします。dorny/paths-filter@v3 を使って出力を設定し、それらの出力に応じてステップを制御します。詳しくは references/github-actions-templates.md(条件付き実行)を参照してください。
不安定なテストの隔離
不安定なテストをブロックしないジョブに分け、CI では実行しつつ、マージを妨げないようにします。
e2e-stable: # required for merge
steps:
- run: npx playwright test --grep-invert @flaky
e2e-quarantine: # non-blocking
continue-on-error: true
steps:
- run: npx playwright test --grep @flaky
- if: failure()
run: echo "::warning::Quarantined tests failed. Review and fix or remove."
grep で振り分けられるよう、不安定なテストにはソースコードでタグを付けます。
test('sometimes fails due to race condition @flaky', async ({ page }) => {
// runs in CI but doesn't block merges
});
隔離したテストが10回連続で成功したら、@flaky タグを削除します。単一の不安定なテストを実行時に自己修復する場合(セレクターの回復、自動再試行ポリシー)は、test-reliability を使用してください。
キャッシュ戦略
| レイヤー | パス | キャッシュキー |
|---|---|---|
| Node モジュール | (setup-node の cache: npm で処理) | 自動 |
| Playwright ブラウザー | ~/.cache/ms-playwright | pw-{os}-{hash(package-lock.json)} |
| ビルドキャッシュ(Next.js) | .next/cache | nextjs-{os}-{hash(lockfile)}-{hash(src)} |
| テストフィクスチャ | e2e/fixtures/.cache | test-data-{hash(seed.sql)} |
レイヤー2〜4には actions/cache@v5 を使用し、部分一致に備えてビルドキャッシュに restore-keys を追加します。
OIDC によるキーレスデプロイ
長期間有効な DEPLOY_TOKEN を保存しないでください。GitHub Actions OIDC を使ってクラウドロールを引き受け、短期間有効な認証情報を取得します。漏えいやローテーションが必要な静的な情報はありません。
deploy:
permissions:
id-token: write # request the OIDC JWT
contents: read
steps:
- uses: aws-actions/configure-aws-credentials@v6
with:
role-to-assume: arn:aws:iam::123456789012:role/gha-deploy
aws-region: eu-central-1
- run: ./deploy.sh production # uses short-lived STS creds, no static secret
IAM ロールの信頼ポリシーでは、sub クレームをリポジトリとブランチに固定します。GCP(google-github-actions/auth)と Azure(azure/login)にも同等の OIDC フローがあります。
失敗時の Slack/Teams 通知
slackapi/slack-github-action@v2 を webhook-type: incoming-webhook とともに使用し、if: failure() && github.ref == 'refs/heads/main' で制御して、main ブランチでの失敗だけを通知します。@v3 に移行する前に、v3 ではワークフロー起動 Webhook のペイロード処理が変更された点(フラット化/文字列化されなくなった点)に注意してください。まず v3 のドキュメントに照らしてペイロードを確認してください。完全な例は references/github-actions-templates.md(夜間フルスイート)を参照してください。
品質ゲート
| ゲート | タイミング | 必須チェック | ブロックするか |
|---|---|---|---|
| PR ゲート | PR の作成/更新時 | lint、型チェック、ユニットテスト、カバレッジしきい値 | はい |
| マージゲート | main へのマージ前 | + E2E スモークスイート | はい |
| デプロイゲート | 本番環境へのデプロイ前 | + フル E2E、ビジュアル、パフォーマンス予算 | はい |
| 夜間ゲート | 毎日午前2時にスケジュール実行 | フルスイート、npm audit、axe a11y | アラートのみ |
PR ゲート(3分未満)
カバレッジの最低基準は bash ではなく、テストランナーの設定で適用します。jest.config.js(または vitest.config.ts の coverage.thresholds)に設定します。
coverageThreshold: { global: { lines: 80, statements: 80, branches: 70 } }
これにより、カバレッジが低下すると jest --coverage がゼロ以外で終了するため、追加のスクリプトなしでジョブが失敗します。CI で数値を読み取る必要がある場合(たとえば表示する場合)は、Jest に json-summary を出力させてファイルを読み取ります。coverage-summary CLI はありません。
- run: npm test -- --ci --coverage # exits 1 if below coverageThreshold
- name: Print coverage (optional)
run: |
PCT=$(jq '.total.lines.pct' coverage/coverage-summary.json)
echo "Line coverage: ${PCT}%"
(json-summary レポーターは coverage/coverage-summary.json に書き込みます。nyc/c8 プロジェクトでは nyc report --reporter=text-summary を使用します。単独の istanbul CLI は非推奨です。istanbul report は使用しないでください。)
マージゲート(10分未満)
PR ゲート + E2E スモーク。ブランチ保護で必須のステータスチェックとして設定します。
デプロイゲート(15分未満)
[unit-tests, e2e-tests, visual-tests] が必要です。その後、上記の OIDC デプロイステップの前に、パフォーマンス予算をチェックします(npx lhci autorun / lhci assert --config=lighthouserc.json)。
夜間ゲート(最大30分)
すべてのブラウザーでのフル E2E、セキュリティスキャン、a11y 監査、不安定なテストの隔離を実行します。セキュリティと a11y のステップは、説明文だけでなく実際のジョブとして組み込みます。
- run: npm audit --audit-level=high # fails on high/critical advisories
- run: npx playwright test --grep @a11y # specs that call @axe-core/playwright
@a11y タグ付きの仕様では @axe-core/playwright を使用します。
import AxeBuilder from '@axe-core/playwright';
test('home page has no a11y violations @a11y', async ({ page }) => {
await page.goto('/');
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);
});
結果は Slack に送信し、ブロックするチェックにはしません。
アンチパターン
1. すべてのコミットで全テストを実行する
プッシュのたびに20分かかるフルスイートを実行すると、開発速度が大きく損なわれます。トリガーとテストスイートの対応表を使い、プッシュでは高速なテストを、PR とマージでは包括的なテストを実行します。
2. アーティファクトの保存がない
トレース、スクリーンショット、ログがなければ、CI の失敗のたびに「ローカルで再現する」作業が発生し、何時間も浪費します。if: ${{ !cancelled() }} でアーティファクトをアップロードしてください。
3. 不安定なテストを追跡せずに再試行する
retries: 3 は不安定さを隠します。レポートは成功になっても、競合状態は残ったままです。隔離し、追跡し、根本原因を修正してください。
4. CI でのみ発生する失敗をローカルで再現できない
テストが CI でのみ失敗する場合は、その理由(タイムゾーン、環境変数の欠落、画面解像度など)を記録し、CI で実行しているものと同じPlaywright イメージを使って、CI をローカルで再現するスクリプトを追加してください。古いイメージに固定しないでください。references/github-actions-templates.md(ローカルでの再現)を参照してください。
5. CI ジョブ間で状態を共有する
アーティファクトや needs を使わずに、兄弟ジョブのファイルを読み込むジョブがあります。各ジョブはまっさらな状態で開始するため、upload-artifact/download-artifact でデータを受け渡してください。
6. 同時実行の制御がない
同じブランチで複数の実行を行うと、ランナーが無駄になります。必ず cancel-in-progress: true を指定した同時実行グループを使ってください。
7. ワークフローファイルにシークレットをハードコードする
トークン、パスワード、キーを YAML に記述しないでください。リポジトリのシークレット(${{ secrets.X }})または GitLab CI/CD 変数を使い、長期間有効なデプロイトークンよりも OIDC によるキーレス認証を優先してください。
8. ジョブのタイムアウトを無視する
停止したテストがランナーを何時間も占有することがあります。すべてのジョブに timeout-minutes を、Playwright の設定に actionTimeout/navigationTimeout を設定してください。
検証
パイプラインに依存する前に、正常に動作することを確認してください。まずは最小限のチェックから始めます。
- ワークフローの構文をリントする —
actionlint .github/workflows/*.ymlを実行すると、実行時に失敗する前に、式、needs、シェルのクォートに関するエラーを検出できます。インデントを確認するため、yamllint .github/workflows/も実行してください。actionlint もジョブとして実行します。 - ジョブをローカルでドライランする —
act -j unit-testsを実行すると、コンテナー内でジョブが動作するため、プッシュせずに反復できます。 - 必須チェックが表示されることを確認する — 使い捨てブランチにプッシュしてドラフト PR を開き、想定されるチェック(
lint、unit-tests、e2e)が表示されること、またカバレッジをしきい値未満にするとカバレッジゲートが失敗することを確認します。 - アーティファクトを確認する — Actions UI(または
gh run download <id>)から実行のアーティファクトをダウンロードし、playwright-report/とトレースが含まれていることを確認します。
完了条件
- トリガーマップが存在すること:push では lint と unit のみが実行され、PR ワークフローでは
if: github.event_name == 'pull_request'によって E2E がゲートされていること(「どこかで統合テストが実行されている」ではなく、YAML を確認します)。 actionlint .github/workflows/*.ymlが終了コード 0 で終了すること。- ブロックしない隔離ジョブが
continue-on-error: trueを指定して--grep @flakyを実行し、安定ジョブが--grep-invert @flakyを実行して必須チェック一覧に含まれていること。 - テストのアーティファクト(レポート、スクリーンショット、トレース)が
if: ${{ !cancelled() }}でアップロードされ、retention-days/expire_inが明示的に設定されていること。 - PR/テストワークフローに、
cancel-in-progress: trueを指定した同時実行グループが設定されていること。 - カバレッジがランナーの
coverageThreshold/thresholdsによって強制されていること(しきい値未満でジョブが 0 以外の終了コードになること)。coverage-summaryの CLI スクレイピングは使用しないでください。 - ブランチ保護で、
lint、unit-tests、e2eが必須ステータスチェックとして指定されていること。 - YAML に長期間有効なデプロイトークンがないこと。デプロイには OIDC(
id-token: writeとクラウドロール)を使うか、最低限でもシークレットストアへの参照を使います。
関連スキル
- playwright-automation — E2E テスト、ページオブジェクトモデル、およびこのパイプラインがシャーディング/タイムアウトを制御する
playwright.config.tsの作成に使用します。 - test-reliability — 不安定なテスト 1 件の実行時セルフヒーリング(セレクターの復旧、再試行ポリシー)に使用します。不安定なテストを修正する場合はこちらを参照し、CI で隔離する場合はこちらを参照してください。
- qa-metrics — このパイプラインが生成する JUnit/カバレッジのアーティファクトを、ダッシュボードや不安定さの傾向に反映します。
- release-readiness — ゲートの結果をもとに、人がリリース可否を判断し、リリースチェックリストを確認します。このスキルはゲートを構築し、そちらのスキルはゲートの結果に基づいて判断します。
- coverage-analysis — カバレッジの不足箇所を見つけ、このスキルの PR ゲートが強制するしきい値を設定します。
参考ファイル(references/ 内)
- github-actions-templates.md — コピーしてそのまま使えるユニットテスト、シャーディング対応の Playwright E2E(レポートのマージを含む)、フルパイプライン、夜間実行(Slack + audit + axe)、PR 品質ゲートのワークフローに加え、条件付き実行とローカルでの再現用スニペット。
- gitlab-ci-template.md — 並列シャーディング、cobertura カバレッジ、JUnit による MR レポートに対応した完全な
.gitlab-ci.yml。