GitHub Code QualityでCobertura XMLをPRに表示する方法|表示されない原因も解説

CIでCobertura XMLを生成できているのに、プルリクエストのGitHub Code Qualityにカバレッジが表示されない場合は、XMLを作成しただけではGitHubへ登録されていない可能性があります。

表示に必要なのは、Cobertura XMLの生成に加えて、actions/upload-code-coverage@v1によるアップロード、code-quality: write権限、デフォルトブランチとPRブランチの両方での実行、リポジトリでのCode Quality有効化です。

GitHub Code Qualityは2026年7月20日に一般提供となり、GitHub TeamとGitHub Enterprise Cloudで、既存のCobertura XMLレポートをプルリクエスト上に表示できるようになりました。GitHub Enterprise Serverは一般提供開始時点では対象外です。(The GitHub Blog)

目次

結論:Cobertura XMLは生成するだけでは表示されない

PRにカバレッジを表示するには、次の条件をすべて満たす必要があります。(GitHub Docs)

確認項目必要な状態
利用プランGitHub TeamまたはGitHub Enterprise Cloud
Code Quality対象リポジトリで有効
テスト実行環境GitHub Actions
レポート形式Cobertura XML
GitHubへの送信actions/upload-code-coverage@v1を実行
Actions権限code-quality: writeを付与
デフォルトブランチpush時にもカバレッジをアップロード
PRブランチpull_request時にもカバレッジをアップロード

特に間違えやすいのが、actions/upload-artifactとの違いです。

actions/upload-artifactは、XMLファイルをGitHub Actionsの成果物として保存するためのActionです。Code Qualityへカバレッジデータを登録する機能はありません。成果物として保存した後、別ジョブでactions/download-artifactを実行し、最終的にactions/upload-code-coverage@v1へ渡す必要があります。(GitHub)

GitHub Code Qualityがカバレッジを表示する仕組み

GitHub Code Qualityは、各ブランチについて最後にアップロードされたCobertura XMLを保持し、PRブランチのカバレッジをデフォルトブランチと比較します。

たとえば、デフォルトブランチが44%、PRブランチが65%なら、PRでは「21ポイント増加」として扱われます。変更されたファイルごとの増減も表示されます。(GitHub Docs)

そのため、PR側のワークフローだけを実行しても不十分です。比較元となるデフォルトブランチ側でも、一度はカバレッジレポートをアップロードする必要があります。

PRにCobertura XMLのカバレッジを表示する手順

Code Qualityをリポジトリで有効にする

リポジトリの管理権限を持つユーザーが、次の順番で設定します。

  1. 対象リポジトリを開く
  2. Settingsを開く
  3. 左側のSecurityからCode qualityを選択する
  4. Enable code qualityをクリックする
  5. 言語やRunnerの設定を確認する
  6. Save changesをクリックする

Enterprise環境では、先にEnterprise ownerがCode Qualityの利用を許可している必要があります。また、Code Qualityの処理にはGitHub Actionsが使われるため、Actionsも有効でなければなりません。(GitHub Docs)

Cobertura XMLを生成する

GitHub Code Qualityへ送信できるのはCobertura XML形式です。テストツールが別形式を出力する場合は、Cobertura XMLへ変換します。

GitHub公式ドキュメントで示されている代表的な生成方法は次のとおりです。(GitHub Docs)

言語ツール生成例
Pythonpytest、pytest-covpytest --cov=. --cov-report=xml
JavaScript/TypeScriptIstanbul、nycnyc report --reporter=cobertura
Gogo test、gocover-coberturago test -coverprofile=cover.out && gocover-cobertura < cover.out > coverage.xml
JavaJaCoCocover2cover.pyや変換用Gradle/Mavenプラグインを使用
RubySimpleCovCobertura用Formatterを設定

生成後は、ファイル名だけで判断せず、中身と保存場所を確認してください。たとえば、次のステップを一時的に追加すると、ファイルが存在し、空ではなく、Cobertura XMLらしい内容を持っているかを確認できます。

- name: Verify Cobertura XML
  run: |
    test -s coverage.xml
    grep -q "<coverage" coverage.xml
    ls -lh coverage.xml

テストコマンドがreports/coverage.xmlへ出力しているのに、アップロード側でcoverage.xmlを指定していると失敗します。モノレポでは、実行ディレクトリの違いにも注意が必要です。

GitHub Actionsへアップロード処理を追加する

Pythonプロジェクトを例にすると、基本構成は次のようになります。

name: Code Coverage

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

permissions:
  contents: read
  code-quality: write

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source
        uses: actions/checkout@v6
        with:
          ref: ${{ github.event.pull_request.head.sha || github.sha }}

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.x"

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
          pip install pytest pytest-cov

      - name: Run tests with coverage
        run: pytest --cov=. --cov-report=xml

      - name: Verify Cobertura XML
        run: |
          test -s coverage.xml
          grep -q "<coverage" coverage.xml

      - name: Upload coverage report
        if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
        uses: actions/upload-code-coverage@v1
        with:
          file: coverage.xml
          language: Python
          label: code-coverage/pytest

この構成には、表示に必要な重要ポイントが含まれています。(GitHub Docs)

pushとpull_requestの両方で実行する

pushはデフォルトブランチの基準値を登録するために必要です。pull_requestはPRブランチの値を登録するために必要です。

リポジトリのデフォルトブランチがmasterdevelopの場合は、例のmainを実際のブランチ名へ変更してください。

code-quality: writeを付与する

カバレッジデータのアップロードには、次の権限が必要です。

permissions:
  contents: read
  code-quality: write

ワークフロー全体ではなく、アップロードを行うジョブだけに設定しても構いません。code-quality: writeはAction自身では追加できないため、呼び出し側のワークフローまたはジョブで明示する必要があります。(GitHub)

PRのhead commitをチェックアウトする

通常のPRワークフローでは、GitHubが作成したマージコミットがチェックアウトされる場合があります。公式例では、カバレッジの行番号とPR差分を正しく対応させるため、PRのhead SHAを明示的に指定しています。(GitHub Docs)

- uses: actions/checkout@v6
  with:
    ref: ${{ github.event.pull_request.head.sha || github.sha }}

カバレッジ率は表示されるものの、ファイル単位の差分や対象行が不自然な場合は、この設定を確認してください。

file、language、labelを正しく指定する

actions/upload-code-coverage@v1では、次の入力を指定します。

with:
  file: coverage.xml
  language: Python
  label: code-coverage/pytest

fileにはCobertura XMLの実際のパスを指定します。languageにはPythonJavaGoなど、GitHub Linguistで使われる言語名を設定します。

公式Actionのメタデータでは、filelanguagelabelはいずれも必須入力として定義されています。ドキュメント上の説明にかかわらず、labelも省略せず設定するのが確実です。(GitHub)

CI成果物を別ジョブからアップロードする場合

テストとカバレッジアップロードを別ジョブに分離している場合は、XMLをジョブ間で引き継ぐ必要があります。

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read

    steps:
      - uses: actions/checkout@v6

      - name: Run tests
        run: |
          # テストを実行し、cobertura.xmlを生成する
          ./run-tests.sh

      - name: Store Cobertura report
        uses: actions/upload-artifact@v4
        with:
          name: cobertura-report
          path: cobertura.xml

  upload-coverage:
    needs: build
    runs-on: ubuntu-latest

    permissions:
      contents: read
      code-quality: write

    steps:
      - name: Download Cobertura report
        uses: actions/download-artifact@v4
        with:
          name: cobertura-report

      - name: Upload coverage to Code Quality
        uses: actions/upload-code-coverage@v1
        with:
          file: cobertura.xml
          language: Java
          label: code-coverage/tests

この場合、upload-artifactはジョブ間の受け渡しに使い、upload-code-coverageがCode Qualityへの登録を担当します。前者だけではPRにカバレッジは表示されません。(GitHub)

表示されないときは、この順番で確認する

Cobertura XMLの出力形式を確認する

最初に、生成されたファイルが本当にCobertura XMLかを確認します。

確認するポイントは次のとおりです。

  • XMLファイルが空ではない
  • ルート要素にcoverageがある
  • テスト終了後もファイルが残っている
  • JaCoCo XML、LCOV、OpenCoverなど別形式のままではない
  • ソースファイルのパスが現在のリポジトリ構成と対応している

拡張子を.xmlにしただけではCobertura形式にはなりません。JavaのJaCoCoなど、標準出力が別形式のツールでは変換処理が必要です。(GitHub Docs)

CI成果物とアップロードステップを確認する

次に、Actionsの実行ログでUpload coverage reportステップを開きます。

確認するポイントは次のとおりです。

  • actions/upload-code-coverage@v1が実行されている
  • fileで指定したパスにXMLが存在する
  • テスト失敗によりアップロードステップがスキップされていない
  • 別ジョブの場合はdownload-artifactが成功している
  • code-quality: writeが設定されている
  • アップロード後の処理が成功している

Actionは初期設定では、アップロードまたはGitHub側の処理に失敗するとステップを失敗させます。また、処理完了を最大160秒待機します。(GitHub)

次のようにfail-on-error: falseを設定している場合は、アップロードに失敗してもステップ自体が成功扱いになります。

- uses: actions/upload-code-coverage@v1
  with:
    file: coverage.xml
    language: Python
    label: code-coverage/pytest
    fail-on-error: false

この設定を使っているときは、緑色のチェックだけで成功と判断せず、ログ内のerrorアノテーションも確認してください。

対象ブランチと実行イベントを確認する

その次に、デフォルトブランチとPRブランチの両方でアップロードされているかを確認します。

よくある設定ミスは次のとおりです。

  • pull_requestしか設定していない
  • push対象が実際のデフォルトブランチと異なる
  • branches: [main]のままだが、実際はmasterを使用している
  • PRのマージ先がワークフローの対象外になっている
  • ワークフロー変更後、デフォルトブランチ側の処理を一度も実行していない

まずデフォルトブランチへワークフローを反映し、pushイベントでカバレッジを登録します。その後、PRへ新しいコミットをpushして再実行すると、比較元と比較先の両方をそろえられます。GitHub Code Qualityは各ブランチの最新アップロードを使って比較します。(GitHub Docs)

pushイベントだけでPRへの関連付けも行う構成では、Actionがgh pr listを使ってPR番号を検索します。その場合は、追加でpull-requests: readが必要です。(GitHub)

permissions:
  contents: read
  pull-requests: read
  code-quality: write

Code Qualityの有効化状態を確認する

最後に、対象リポジトリがCode Qualityの適用対象になっているかを確認します。

リポジトリでは次の画面を開きます。

Settings
└ Security
  └ Code quality

組織単位でCode Qualityを管理している場合は、組織のSettingsにあるCode qualityから、対象リポジトリがRepository accessの範囲に含まれているかも確認してください。

組織側で特定リポジトリのみを選択している場合や、フィルター条件で対象を限定している場合、リポジトリ管理者が設定を変更できないことがあります。大規模な組織では、設定変更の反映に数分かかる場合もあります。(GitHub Docs)

ForkからのPRでは表示されないことがある

公式のactions/upload-code-coverageは、Forkリポジトリから作成されたPRをサポートしていません。

Fork側のPRにはベースリポジトリへの書き込み権限がないため、Actionはカバレッジのアップロードをスキップします。この場合、ワークフロー全体を失敗させず、ログにスキップした旨を出力して正常終了します。(GitHub)

公式例にある次の条件は、Fork PRでアップロード処理を実行しないためのものです。

if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository

社内の同一リポジトリ内で作成したブランチでは表示されるのに、外部ForkからのPRだけ表示されない場合は、設定不良ではなくこの制限に該当している可能性があります。

また、merge queueのmerge_groupイベントでもカバレッジアップロードはスキップされます。カバレッジはPRとデフォルトブランチで登録する構成にしてください。(GitHub)

設定後にPRで確認する内容

設定が正しければ、ワークフロー完了後にgithub-code-quality[bot]がPRへコメントを投稿します。

コメントでは主に次の内容を確認できます。

  • PRブランチ全体のカバレッジ率
  • デフォルトブランチのカバレッジ率
  • カバレッジの増減
  • 変更ファイルごとのカバレッジ差分

カバレッジ率は、テストで実行された行数を対象行数で割って計算されます。PRでは単純な現在値だけでなく、デフォルトブランチに対して改善したか、低下したかを判断できます。(GitHub Docs)

まず確認すべきチェックリスト

CIでCobertura XMLが作成されているのにPRへ表示されない場合は、次の順番で切り分けると原因を見つけやすくなります。

  • Cobertura XMLが実際に生成され、空ではない
  • actions/upload-artifactだけで終わっていない
  • actions/upload-code-coverage@v1が実行されている
  • fileが実際のXMLパスと一致している
  • code-quality: writeが設定されている
  • デフォルトブランチのpushでもアップロードしている
  • PRではhead commitをチェックアウトしている
  • 対象リポジトリでCode Qualityが有効になっている
  • Fork PRやmerge queueによるスキップではない
  • Actionsログにアップロードや処理エラーがない

最初にXMLの形式、次にCI成果物の受け渡し、続いて対象ブランチ、最後にCode Qualityの有効化状態を確認してください。特に、XMLをActionsの成果物として保存することと、Code Qualityへアップロードすることは別処理である点が重要です。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次