{"meta":{"title":"CI テストエラーの診断","intro":"Copilot CLIを使用して CI ログをプルし、エラーをローカル コードに関連付け、ターミナルを離れることなく問題を修正します。","product":"GitHub Copilot","breadcrumbs":[{"href":"/ja/copilot","title":"GitHub Copilot"},{"href":"/ja/copilot/tutorials","title":"チュートリアル"},{"href":"/ja/copilot/tutorials/copilot-cookbook","title":"GitHub Copilot クックブック"},{"href":"/ja/copilot/tutorials/copilot-cookbook/debug-errors","title":"エラーをデバッグする"},{"href":"/ja/copilot/tutorials/copilot-cookbook/debug-errors/diagnose-ci-test-failures","title":"CI テストの失敗を診断する"}],"documentType":"article"},"body":"# CI テストエラーの診断\n\nCopilot CLIを使用して CI ログをプルし、エラーをローカル コードに関連付け、ターミナルを離れることなく問題を修正します。\n\nCopilot CLIは、GitHub MCP サーバーに付属しており、GitHub Actionsワークフローの実行、ジョブ ログ、状態の確認に直接アクセスできます。 ローカル ファイルへのアクセスと組み合わせることで、CI エラーの詳細をフェッチし、コードに関連付け、ターミナルから修正プログラムを提案できます。\n\n## シナリオ 1 の例: テストはローカルで成功しますが、CI では失敗します\n\nローカル コンピューターで成功するが、CI で失敗するテストがあります。 このテストの失敗を直接調査するように Copilot CLI に依頼できます。\n\nこの例では、テスト対象のコードは単純な注文サービス (`order.py`) を定義し、注文が今日作成されたかどうかを確認する対応するテスト (`test_order_service.py`) があります。\n\n### プロンプトの例\n\n```copilot copy\nMy CI is failing on this branch. Can you pull the latest workflow run \nlogs, figure out what is failing, and help me fix it? The relevant files \nare @order.py and @test_order_service.py\n```\n\n### 応答の例\n\n> \\[!NOTE] 次の応答は例です。 Copilot Chat の応答は非決定的であるため、ここで示したものとは異なる応答が返される可能性があります。\n\nCopilot CLI は、GitHub MCP サーバーを使用して、現在のブランチで最新のワークフロー実行をフェッチし、失敗したジョブを識別し、そのログを取得します。 次のエラーが検出されます。\n\n```text\n___ TestOrderService.test_order_created_today ___\n>       assert order[\"created_date\"] == date.today()\nE       AssertionError: assert datetime.date(2024, 1, 15) == datetime.date(2024, 1, 16)\n\ntest_order_service.py:45: AssertionError\n```\n\n両方のローカル ファイルを読み取った後、 Copilot CLI は日付が正確に 1 日離れていることに気付き、これを **タイムゾーン境界の問題**として識別します。 CI ランナーは UTC を使用し、ローカル コンピューターでは別のタイムゾーンを使用します。 テストが午前 0 時近くに実行されると、 `date.today()` は環境ごとに異なる日付を返します。\n\nCopilot CLI は、クロック依存関係を挿入するか、タイムゾーンをピン留めすることで、 `today` の計算方法を標準化することを提案します。\n\n```python\nfrom datetime import timezone, datetime\n\ndef get_today():\n    return datetime.now(timezone.utc).date()\n```\n\n`order.py`と`test_order_service.py`の両方に修正プログラムが適用され、新しい`get_today()` ヘルパーを使用するようにすべての参照が更新されます。\n\n修正後、変更を確認し、テストをローカルで実行できます。\n\n1. `/diff`を実行して、Copilot CLIによる変更内容を正確に確認します。\n2. `!pytest test_order_service.py`を実行して、テストがローカルで成功することを確認します。\n3. 修正をプッシュし、CI を再実行します。\n\n## シナリオ例 2: 競合状態での断続的なテストエラー\n\nテストは、同じコンピューターで成功し、失敗する場合があります。\nCopilot CLI成功した実行と失敗した実行のログを比較して、原因を特定したい。\n\nこの例では、テスト対象のコードは `order_service.py` のバックグラウンド ジョブを使用して注文の状態を非同期的に更新し、 `test_order_service.py` のテストでは最終的な状態が `\"processed\"`であることをアサートします。\n\n### 競合状態向けの例示用プロンプト\n\n```copilot copy\nThis test passes sometimes and fails sometimes. Can you pull the logs \nfrom the last passing and failing CI runs for test_order_processed \non this branch, compare them, and figure out what is going wrong? \nRelevant files: @order_service.py @test_order_service.py\n```\n\n### 競合状態のレスポンス例\n\n> \\[!NOTE] 次の応答は例です。 Copilot Chat の応答は非決定的であるため、ここで示したものとは異なる応答が返される可能性があります。\n\nCopilot CLI は、GitHub MCP サーバーを使用して、現在のブランチでの最近のワークフロー実行を一覧表示し、1 つのパスと 1 つの失敗した実行を識別し、両方のログを取得します。 それらを比較します。\n\n**成功した実行:**\n\n```text\n[DEBUG] Created order #1234\n[DEBUG] Background job started for order #1234\n[DEBUG] Background job completed (52ms)\n[DEBUG] Checking order status\n[DEBUG] Order #1234 status: processed\n```\n\n**失敗した実行:**\n\n```text\n[DEBUG] Created order #1234\n[DEBUG] Background job started for order #1234\n[DEBUG] Checking order status\n[DEBUG] Order #1234 status: pending\n```\n\nCopilot CLI は、成功した実行で、バックグラウンド ジョブが状態チェックの前に完了したことを確認します。失敗した実行では、ジョブの実行中に状態がチェックされました。 テストがバックグラウンドジョブの終了を待たないため、これは **競合状態** と判断されます。\n\nCopilot CLI は、アサートする前に明示的な待機メカニズムを追加することを提案し、ポーリング ヘルパーを使用して修正を提案します。\n\n```python\nimport time\n\ndef wait_for_status(order_id, expected, timeout=5):\n    start = time.time()\n    while time.time() - start < timeout:\n        order = get_order(order_id)\n        if order.status == expected:\n            return order\n        time.sleep(0.1)\n    raise TimeoutError(\n        f\"Order {order_id} did not reach '{expected}' within {timeout}s\"\n    )\n```\n\n## 詳細については、次を参照してください。\n\n* *\n\n[GitHub Copilot CLI](/ja/copilot/how-tos/copilot-cli)"}