Skip to main content

CI テストエラーの診断

Copilot CLI (コパイロット CLI)を使用して CI ログをプルし、エラーをローカル コードに関連付け、ターミナルを離れることなく問題を修正します。

Copilot CLI (コパイロット CLI)は、GitHub MCP サーバーに付属しており、GitHub Actionsワークフローの実行、ジョブ ログ、状態の確認に直接アクセスできます。 ローカル ファイルへのアクセスと組み合わせることで、CI エラーの詳細をフェッチし、コードに関連付け、ターミナルから修正プログラムを提案できます。

シナリオ 1 の例: テストはローカルで成功しますが、CI では失敗します

ローカル コンピューターで成功するが、CI で失敗するテストがあります。 このテストの失敗を直接調査するように Copilot CLI (コパイロット CLI) に依頼できます。

この例では、テスト対象のコードは単純な注文サービス (order.py) を定義し、注文が今日作成されたかどうかを確認する対応するテスト (test_order_service.py) があります。

プロンプトの例

Copilot prompt
My CI is failing on this branch. Can you pull the latest workflow run 
logs, figure out what is failing, and help me fix it? The relevant files 
are @order.py and @test_order_service.py

応答の例

メモ

次の応答は例です。 コパイロットチャット の応答は非決定的であるため、ここで示したものとは異なる応答が返される可能性があります。

Copilot CLI (コパイロット CLI) は、GitHub MCP サーバーを使用して、現在のブランチで最新のワークフロー実行をフェッチし、失敗したジョブを識別し、そのログを取得します。 次のエラーが検出されます。

___ TestOrderService.test_order_created_today ___
>       assert order["created_date"] == date.today()
E       AssertionError: assert datetime.date(2024, 1, 15) == datetime.date(2024, 1, 16)

test_order_service.py:45: AssertionError

両方のローカル ファイルを読み取った後、 Copilot CLI (コパイロット CLI) は日付が正確に 1 日離れていることに気付き、これを タイムゾーン境界の問題として識別します。 CI ランナーは UTC を使用し、ローカル コンピューターでは別のタイムゾーンを使用します。 テストが午前 0 時近くに実行されると、 date.today() は環境ごとに異なる日付を返します。

Copilot CLI (コパイロット CLI) は、クロック依存関係を挿入するか、タイムゾーンをピン留めすることで、 today の計算方法を標準化することを提案します。

from datetime import timezone, datetime

def get_today():
    return datetime.now(timezone.utc).date()

order.pytest_order_service.pyの両方に修正プログラムが適用され、新しいget_today() ヘルパーを使用するようにすべての参照が更新されます。

修正後、変更を確認し、テストをローカルで実行できます。

  1. /diffを実行して、Copilot CLI (コパイロット CLI)による変更内容を正確に確認します。
  2. !pytest test_order_service.pyを実行して、テストがローカルで成功することを確認します。
  3. 修正をプッシュし、CI を再実行します。

シナリオ例 2: 競合状態での断続的なテストエラー

テストは、同じコンピューターで成功し、失敗する場合があります。 Copilot CLI (コパイロット CLI)成功した実行と失敗した実行のログを比較して、原因を特定したい。

この例では、テスト対象のコードは order_service.py のバックグラウンド ジョブを使用して注文の状態を非同期的に更新し、 test_order_service.py のテストでは最終的な状態が "processed"であることをアサートします。

競合状態向けの例示用プロンプト

Copilot prompt
This test passes sometimes and fails sometimes. Can you pull the logs 
from the last passing and failing CI runs for test_order_processed 
on this branch, compare them, and figure out what is going wrong? 
Relevant files: @order_service.py @test_order_service.py

競合状態のレスポンス例

メモ

次の応答は例です。 コパイロットチャット の応答は非決定的であるため、ここで示したものとは異なる応答が返される可能性があります。

Copilot CLI (コパイロット CLI) は、GitHub MCP サーバーを使用して、現在のブランチでの最近のワークフロー実行を一覧表示し、1 つのパスと 1 つの失敗した実行を識別し、両方のログを取得します。 それらを比較します。

成功した実行:

[DEBUG] Created order #1234
[DEBUG] Background job started for order #1234
[DEBUG] Background job completed (52ms)
[DEBUG] Checking order status
[DEBUG] Order #1234 status: processed

失敗した実行:

[DEBUG] Created order #1234
[DEBUG] Background job started for order #1234
[DEBUG] Checking order status
[DEBUG] Order #1234 status: pending

Copilot CLI (コパイロット CLI) は、成功した実行で、バックグラウンド ジョブが状態チェックの前に完了したことを確認します。失敗した実行では、ジョブの実行中に状態がチェックされました。 テストがバックグラウンドジョブの終了を待たないため、これは 競合状態 と判断されます。

Copilot CLI (コパイロット CLI) は、アサートする前に明示的な待機メカニズムを追加することを提案し、ポーリング ヘルパーを使用して修正を提案します。

import time

def wait_for_status(order_id, expected, timeout=5):
    start = time.time()
    while time.time() - start < timeout:
        order = get_order(order_id)
        if order.status == expected:
            return order
        time.sleep(0.1)
    raise TimeoutError(
        f"Order {order_id} did not reach '{expected}' within {timeout}s"
    )

詳細については、次を参照してください。

GitHub Copilot CLI(コマンドラインインターフェース)