triage-ci-flake について
CI の E2E テスト失敗、特に不安定な Playwright テストの診断と修正を支援するワークフロースキルです。修正案を出す前に対象テストを再現し、必要に応じて開発コードとバンドル済みの本番コードを確認します。
主な機能
- 01PR チェックとログの確認
- 02個別テストの再現
- 03開発環境と本番環境の確認
- 04不安定なテストのパターン指針
- 05修正の検証手順
活用シーン
- 01マージ済み PR の CI 失敗調査
- 02CI のみで発生する Playwright のタイムアウト再現
- 03バンドルがテストに影響するかの確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ payloadcms/ payload --skill triage-ci-flakeインストール後、Claude Code で/triage-ci-flakeを入力して読み込まれたか確認します。
詳細
CI 障害のトリアージ
概要
CI におけるエンドツーエンド (e2e) テストの障害、特にローカルでは成功するものの CI では失敗する不安定な Playwright テストをトリアージして修正するために特別に設計された体系的なワークフローです。main に到達した e2e テストは、通常、タイミング、バンドル、または環境の違いにより不安定です。
重要なルール: 修正を提案する前に、必ず再現ワークフローを実行する必要があります。例外はありません。
使用する状況
- PR がマージされた後、
mainブランチで CI テストが失敗する - テストはローカルでは成功するが CI では失敗する
- テスト障害が「不安定」または断続的とラベル付けされている
- CI でのみ e2e テストがタイムアウトする
- ユーザーが失敗したチェックを含む PR URL/番号を提供する
PR ベースのワークフロー (PR URL/番号が提供された場合)
ユーザーが PR URL (例: https://github.com/payloadcms/payload/pull/16701) または PR 番号を提供した場合:
ステップ 1: PR ステータスチェックの取得
まず、tool_search をクエリ "github pull request status checks" で使用して GitHub ツールを読み込みます。
次に github-pull-request_pullRequestStatusChecks ツールを使用して、失敗しているすべてのチェックを取得します:
Tool: github-pull-request_pullRequestStatusChecks
Parameters:
pullRequestNumber: <extracted from URL or provided>
repo: { owner: "payloadcms", name: "payload" }
ステップ 2: 失敗したテストの集約
ステータスチェックのレスポンスを解析し、サマリーテーブルを作成します:
| スイート | チェックのステータス | ターゲット URL |
|---|---|---|
| admine2elist-view | failed | [link] |
| plugin-import-export | failed | [link] |
失敗した各チェックについて、context フィールドにテストスイート名 (例: admin__e2e__list-view) が含まれています。
ステップ 3: 各チェックから障害の詳細を抽出
失敗した各チェックについて:
targetUrlにアクセスして詳細な障害ログを取得します- 特定のテスト名とエラーメッセージを抽出します
- 集約された障害リストに追加します
統合されたサマリーを提示します:
## Failing Tests Summary
### 1. admin**e2e**list-view (3/4)
- **Test**: "should use custom pagination limit"
- **Error**: Locator `.per-page__button` not found
- **File**: test/admin/e2e/list-view/e2e.spec.ts:1495
### 2. plugin-import-export
- **Test**: "should inherit limit from list view URL"
- **Error**: Locator `.per-page__button` not found
- **File**: test/plugin-import-export/e2e.spec.ts:150
ステップ 4: 共通パターンの特定
障害全体にわたるパターンを探します:
- 同じセレクターエラー → テストの更新が必要なコンポーネントの変更である可能性が高い
- 同じテストファイル → 局所的な問題
- 同じスイート内の異なるエラー → テスト汚染の可能性
ステップ 5: トリアージの続行
一意の各障害について、以下の標準的な再現ワークフローに従います。
必須の最初のステップ
これらのコマンドを実行する必要があります。コードを読んだりログを分析したりすることは再現とはみなされません。
- CI ログからスイート名、テスト名、エラーを抽出します
- 実行: 競合を避けるためポート 3000 を強制終了します
- 実行:
pnpm dev $SUITE_NAME(run_in_background=true を使用) - 実行: サーバーが準備完了になるまで待機します (curl または sleep で確認)
- 実行: 失敗している特定のテストを Playwright で直接実行します (npx playwright test test/TEST_SUITE_NAME/e2e.spec.ts:31:3 --headed -g "TEST_DESCRIPTION_TARGET_GOES_HERE")
- テストが成功した場合、実行:
pnpm prepare-run-test-against-prod - 実行:
pnpm dev:prod $SUITE_NAMEを実行し、テストを再度実行します
これらのコマンドを実行し、その出力を確認した後にのみ、分析と修正に進むことができます。
「ログからの分析」は再現ではありません。コマンドを実行する必要があります。
コアワークフロー
digraph triage_ci {
"CI failure reported" [shape=box];
"Extract details from CI logs" [shape=box];
"Identify suite and test name" [shape=box];
"Run dev server: pnpm dev $SUITE" [shape=box];
"Run specific test by name" [shape=box];
"Did test fail?" [shape=diamond];
"Debug with dev code" [shape=box];
"Run prepare-run-test-against-prod" [shape=box];
"Run: pnpm dev:prod $SUITE" [shape=box];
"Run specific test again" [shape=box];
"Did test fail now?" [shape=diamond];
"Debug bundling issue" [shape=box];
"Unable to reproduce - check logs" [shape=box];
"Fix and verify" [shape=box];
"CI failure reported" -> "Extract details from CI logs";
"Extract details from CI logs" -> "Identify suite and test name";
"Identify suite and test name" -> "Run dev server: pnpm dev $SUITE";
"Run dev server: pnpm dev $SUITE" -> "Run specific test by name";
"Run specific test by name" -> "Did test fail?";
"Did test fail?" -> "Debug with dev code" [label="yes"];
"Did test fail?" -> "Run prepare-run-test-against-prod" [label="no"];
"Run prepare-run-test-against-prod" -> "Run: pnpm dev:prod $SUITE";
"Run: pnpm dev:prod $SUITE" -> "Run specific test again";
"Run specific test again" -> "Did test fail now?";
"Did test fail now?" -> "Debug bundling issue" [label="yes"];
"Did test fail now?" -> "Unable to reproduce - check logs" [label="no"];
"Debug with dev code" -> "Fix and verify";
"Debug bundling issue" -> "Fix and verify";
}
ステップバイステップのプロセス
1. CI の詳細を抽出
CI ログまたは GitHub Actions URL から以下を特定します:
- スイート名: ディレクトリ名 (例:
i18n、fields、lexical) - テストファイル: 完全なパス (例:
test/i18n/e2e.spec.ts) - テスト名: 正確なテストの説明
- エラーメッセージ: 完全なスタックトレース
- テストタイプ: E2E (Playwright)
2. 開発コードで再現
重要: 常にスイート全体ではなく、名前で特定のテストを実行してください。
サーバー管理のルール:
- 新しいサーバーを起動する前に、常にすべてのサーバーを強制終了する
- ポートが空いていると決して想定しない
- テストを実行する前に、常にサーバー準備完了の確認を待つ
# ========================================
# STEP 2A: STOP ALL SERVERS
# ========================================
lsof -ti:3000 | xargs kill -9 2>/dev/null || echo "Port 3000 clear"
# ========================================
# STEP 2B: START DEV SERVER
# ========================================
# Start dev server with the suite (in background with run_in_background=true)
pnpm dev $SUITE_NAME
# ========================================
# STEP 2C: WAIT FOR SERVER READY
# ========================================
# Wait for server to be ready (REQUIRED - do not skip)
until curl -s http://localhost:3000/admin > /dev/null 2>&1; do sleep 1; done && echo "Server ready"
# ========================================
# STEP 2D: RUN SPECIFIC TEST
# ========================================
# Run ONLY the specific failing test using Playwright directly
# For E2E tests (DO NOT use pnpm test:e2e as it spawns its own server):
pnpm exec playwright test test/$SUITE_NAME/e2e.spec.ts -g "exact test name"
テストは失敗しましたか?
- ✅ はい: 再現できました! 開発コードでデバッグに進みます。
- ❌ いいえ: ステップ 3 (バンドルされたコードでのテスト) に進みます。
3. バンドルされたコードで再現する
開発コードでテストが通った場合、問題はバンドル済み/本番コードにある可能性が高いです。
重要: 本番サーバーを起動する前に、必ず開発サーバーを停止する必要があります。
# ========================================
# STEP 3A: STOP ALL SERVERS (INCLUDING DEV SERVER FROM STEP 2)
# ========================================
lsof -ti:3000 | xargs kill -9 2>/dev/null || echo "Port 3000 clear"
# ========================================
# STEP 3B: BUILD AND PACK FOR PROD
# ========================================
# Build all packages and pack them (this takes time - be patient)
pnpm prepare-run-test-against-prod
# ========================================
# STEP 3C: START PROD SERVER
# ========================================
# Start prod dev server (in background with run_in_background=true)
pnpm dev:prod $SUITE_NAME
# ========================================
# STEP 3D: WAIT FOR SERVER READY
# ========================================
# Wait for server to be ready (REQUIRED - do not skip)
until curl -s http://localhost:3000/admin > /dev/null 2>&1; do sleep 1; done && echo "Server ready"
# ========================================
# STEP 3E: RUN SPECIFIC TEST
# ========================================
# Run the specific test again using Playwright directly
pnpm exec playwright test test/$SUITE_NAME/e2e.spec.ts -g "exact test name"
今度はテストが失敗しましたか?
- ✅ はい: バンドルまたは本番ビルドの問題です。以下を確認してください:
- package.json にエクスポートが不足している
- ビルド設定の問題
- バンドル時に動作が変わるコード
- ❌ いいえ: ローカルで再現できません。ステップ 4 に進んでください。
4. 再現できない場合
両方の試行の後もローカルで再現できない場合:
- 環境の違いについて CI ログをより注意深く確認する
- 競合状態がないか確認する(テストを複数回実行:
for i in {1..10}; do pnpm test:e2e...; done) - CI 固有の制約(メモリ、CPU、タイミング)を確認する
- タイミングに非常に依存する真の競合状態かどうかを検討する
よくある不安定なテストのパターン
競合状態
- アサーションの実行中にページがナビゲートされる
- アサーションの前にネットワークリクエストが完了していない
- 状態の更新が完了していない
修正パターン:
- Playwright の Web ファーストアサーション(
toBeVisible()、toHaveText())を使用する - 任意のタイムアウトではなく、特定の条件を待機する
- 条件チェックを伴う
waitForFunction()を使用する
テスト汚染
- テストがデータベースにデータを残す
- テスト間で状態が共有される
afterEachでのクリーンアップが欠けている
修正パターン:
- 作成された ID を追跡し、
afterEachでクリーンアップする - 分離されたテストデータを使用する
- 他のテストに影響を与える
deleteAllを使用しない
タイミングの問題
- 条件ベースの待機ではなく
setTimeout/sleepを使用している - ページの安定性を待機していない
- アニメーション/トランジションが完了していない
修正パターン:
waitForPageStability()ヘルパーを使用する- 特定の DOM 状態を待機する
- Playwright の組み込みの待機メカニズムを使用する
リンティングに関する考慮事項
e2e テストを修正する際は、以下の eslint ルールに注意してください:
playwright/no-networkidle-waitForLoadState('networkidle')を避ける(代わりに条件ベースの待機を使用してください)payload/no-wait-function- カスタムのwait()関数を避ける(Playwright の組み込みの待機を使用してください)payload/no-flaky-assertions- リトライ不可能なアサーションを避けるplaywright/prefer-web-first-assertions- Playwright の組み込みアサーションを使用する
既存のコードはこれらのルールに違反している可能性があります - 新しいコードを追加する際は、既存のコードが違反していてもルールに従ってください。
検証
修正後:
# Ensure dev server is running on port 3000
# Run test multiple times to confirm stability
for i in {1..10}; do
pnpm exec playwright test test/$SUITE_NAME/e2e.spec.ts -g "exact test name" || break
done
# Run full suite
pnpm exec playwright test test/$SUITE_NAME/e2e.spec.ts
# If you modified bundled code, test with prod build
lsof -ti:3000 | xargs kill -9 2>/dev/null
pnpm prepare-run-test-against-prod
pnpm dev:prod $SUITE_NAME
until curl -s http://localhost:3000/admin > /dev/null; do sleep 1; done
pnpm exec playwright test test/$SUITE_NAME/e2e.spec.ts
鉄の掟
再現なしに修正なし
ワークフローのステップ 1〜3 を完了する前に修正を提案した場合、このスキルに違反しています。
これは以下の場合にも適用されます:
- ログから修正が明らかなように見える
- 以前にこのエラーを見たことがある
- チームからの時間的プレッシャーがある
- 根本原因に確信がある
- ログに明確なスタックトレースが表示されている
例外はありません。まず再現ワークフローを実行してください。
合理化の表
再現をスキップするあらゆる言い訳と、それがなぜ間違っているか:
| 合理化 | 現実 |
|---|---|
| 「ログに正確なエラーが表示されている」 | ログは症状を示すもので、根本原因ではありません。再現してください。 |
| 「コードの問題がわかる」 | あなたは推測しています。確認するために再現してください。 |
| 「これは明らかに競合状態だ」 | おそらくそうでしょう。確実にするために再現してください。 |
| 「以前にこのエラーを見たことがある」 | 今回は異なるかもしれません。再現してください。 |
| 「スタックトレースは明確だ」 | スタックトレースはどこでを示すもので、なぜを示しません。再現してください。 |
| 「時間的プレッシャー - 早く修正する必要がある」 | 再現することこそが迅速です。推測は時間を浪費します。 |
| 「テストファイルが問題を示している」 | 読むこと ≠ 実行すること。コマンドを実行してください。 |
| 「まずコードを分析しよう」 | コード分析は再現の後に来ます。 |
| 「根本原因を調査させてください」 | 再現こそが調査です。 |
| 「エラーを理解する必要がある」 | 理解は、それが失敗するのを見ることから生まれます。 |
危険信号 - 停止
これらの思考は、あなたがスキルに違反しようとしていることを意味します。
- 「明らかな問題をちょっと直そう」→ 停止。まず再現を実行してください。
- 「タイムアウトを増やそう」→ 停止。再現によって根本原因を突き止めてください。
- 「ログからすると X のようだ」→ 停止。テストを実行してください。
- 「フルスイートを実行しよう」→ 停止。まず特定のテストを実行してください。
- 「コードを確認しよう」→ 停止。まず再現を実行してください。
- 「スタックトレースで問題がわかる」→ 停止。再現して確認してください。
- 「ログは十分明確だ」→ 停止。コマンドを実行してください。
- 「分析しよう...」→ 停止。分析は再現の後です。
これらはすべて次を意味します: 直ちに停止してください。再現コマンドを実行してください。実行なしに分析はありません。
セッション例
正しいアプローチ - まずコマンドを実行する:
User: CI failed on i18n suite - https://github.com/.../actions/runs/XXX
Agent:
1. Extracted details from CI logs:
- Suite: i18n
- Test: "ensure translations update correctly when switching language"
- File: test/i18n/e2e.spec.ts:124
- Error: "Error loading language: en" TypeError: network error
2. Executing reproduction workflow:
[Uses Bash tool to kill ports]
$ lsof -ti:3000 | xargs kill -9 2>/dev/null || echo "Port 3000 clear"
[Uses Bash tool with run_in_background=true]
$ pnpm dev i18n
[Waits for server to start with curl check]
$ until curl -s http://localhost:3000/admin > /dev/null; do sleep 1; done && echo "Server ready"
[Uses Bash tool to run Playwright directly]
$ pnpm exec playwright test test/i18n/e2e.spec.ts -g "ensure translations update correctly when switching language"
Output shows: Test PASSED locally
3. Test passed with dev code, trying bundled code:
[Kills ports again]
$ lsof -ti:3000 | xargs kill -9 2>/dev/null
[Uses Bash tool]
$ pnpm prepare-run-test-against-prod
[Uses Bash tool with run_in_background=true]
$ pnpm dev:prod i18n
[Waits for server]
$ until curl -s http://localhost:3000/admin > /dev/null; do sleep 1; done
[Uses Bash tool]
$ pnpm exec playwright test test/i18n/e2e.spec.ts -g "ensure translations update correctly when switching language"
Output shows: Test FAILED - reproduced!
4. Now that I've reproduced it, analyzing the failure...
[Code analysis, root cause identification]
5. Implementing fix: [specific changes]
6. Verification:
[Uses Bash tool]
$ for i in {1..10}; do pnpm test:e2e i18n -g "exact test"; done
All 10 runs passed!
誤ったアプローチ - 実行せずに分析する:
User: CI failed on i18n suite
Agent: Looking at the error logs, I can see this is a race condition...
[Analyzes code, proposes fix without running any commands]
❌ WRONG - This violates the skill. Must execute reproduction commands first.
よくある間違い
| 間違い | 修正 |
|---|---|
| 最初にフルテストスイートを実行する | 名前で特定のテストを実行する |
| dev コードでの再現をスキップする | 常にまず dev コードを試す |
| バンドルされたコードでテストしない | dev が通ったら、prepare-run-test-against-prod でテストする |
| 再現せずに修正を提案する | ワークフローに従う - まず再現する |
新しいコードで networkidle を使う | waitForFunction() を使った条件ベースの待機を使う |
恣意的な wait() 呼び出しを追加する | Playwright の組み込みアサーションと待機を使う |
主要な原則
- 修正の前に再現: 問題を再現せずに修正を提案してはいけません
- 具体的にテスト: フルスイートではなく、失敗している正確なテストを実行してください
- まず dev、次に prod: バンドルされたコードの前に dev コードを確認してください
- ワークフローに従う: 近道はなし - これらの手順は時間を節約するために存在します
- 安定性を検証: 修正を確認するためにテストを複数回実行してください
完了: PR の作成
次のことを行った後:
- ✅ 問題を再現した
- ✅ 修正を実装した
- ✅ 修正がローカルで通ることを検証した(複数回の実行)
- ✅ prod ビルドでテストした(該当する場合)
ユーザーに PR を作成するよう促さなければなりません:
The fix has been verified and is ready for review. Would you like me to create a PR with these changes?
Summary of changes:
- [List files modified]
- [Brief description of the fix]
- [Verification results]
重要:
- PR を自動的に作成しないでください - 常にまずユーザーに尋ねてください
- 何がなぜ変更されたかの明確な要約を提供してください
- 検証結果(テスト実行回数、合格率)を含めてください
- PR をすぐに作成するか、先に追加の変更を行うかはユーザーに決めさせてください
これにより、ユーザーはレビューのために提出される内容を把握し、制御できるようになります。