publish-unit-test-result-action

repository·master·Indexed 20 days ago

https://github.com/enricomi/publish-unit-test-result-action

A GitHub Action that parses test result files in JUnit XML, NUnit XML, XUnit XML, TRX, or JSON formats and publishes the results as GitHub Checks, Pull Request comments, annotations, and job summaries. It supports various runners including Ubuntu, ARM Linux, macOS, and Windows, with specific sub-actions for environments without Docker.

Tokens
7.1K
Snippets
11
Records
24
Agent score
23%

What's inside publish-unit-test-result-action

  1. Where test results are published

    master

    The action publishes test results to several configurable locations on GitHub:

    • Pull request comments: A comment is posted on related pull requests. Subsequent runs update this existing comment. If failures occur, the comment includes a link to the check summary.
    • Commit and pull request checks: A summary (e.g., 1 fail, 1 skipped) is listed in the checks section of commits and pull requests, with a link to the check summary.
    • Annotations: Failing tests produce annotations in the checks section of a commit and the 'changed files' section of pull requests.
    • GitHub Actions job summary: Results are added to the workflow's job summary page (requires GitHub Actions runner v2.288.0 or above).
    • GitHub Actions check summary: Results are published in the check summary of the respective commit.
  2. Install and use the Publish Test Results action

    master

    The publish-unit-test-result-action analyzes test result files (JSON, TRX, or XML) and publishes them to GitHub. Depending on your runner and environment, you should use different entry points.

    Ubuntu or ARM Linux (with Docker)

    Use the default action for Ubuntu or ARM Linux runners that have Docker installed.

    macOS (no Docker needed)

    Use the /macos sub-action for macOS runners.

    Windows (no Docker needed)

    Use the /windows sub-action for Windows runners. If PowerShell is not available, use the /windows/bash variant.

    Linux (without Docker)

    For self-hosted Linux runners that do not have Docker installed, use the /linux sub-action.

    Best Practices

    • Use if: (!cancelled()) to ensure the action runs even if your test step fails.
    • If running the action multiple times in a single workflow, you must set a unique check_name for each instance to prevent them from overwriting each other.
    # Ubuntu / ARM Linux with Docker
    - name: Publish Test Results
      uses: EnricoMi/publish-unit-test-result-action@v2
      if: (!cancelled())
      with:
        files: |
          test-results/**/*.xml
          test-results/**/*.trx
          test-results/**/*.json
    
    # macOS
    - name: Publish Test Results
      uses: EnricoMi/publish-unit-test-result-action/macos@v2
      if: (!cancelled())
      with:
        files: ...
    
    # Windows
    - name: Publish Test Results
      uses: EnricoMi/publish-unit-test-result-action/windows@v2
      if: (!cancelled())
      with:
        files: ...
    
    # Windows without PowerShell
    - name: Publish Test Results
      uses: EnricoMi/publish-unit-test-result-action/windows/bash@v2
      if: (!cancelled())
      with:
        files: ...
    
    # Linux without Docker
    - name: Publish Test Results
      uses: EnricoMi/publish-unit-test-result-action/linux@v2
      if: (!cancelled())
      with:
        files: ...
  3. Use the action with a GitHub Actions matrix strategy

    master

    When running tests in a matrix (e.g., multiple Python versions), you should not run the publishing action within the matrix job itself, as this would create multiple separate comments/checks. Instead:

    1. In the matrix job: Run your tests and use actions/upload-artifact to upload the resulting XML files. Use a unique name for each artifact (e.g., Test Results (Python ${{ matrix.python-version }})).
    2. In a separate publish job: Create a new job that needs the matrix job. Use actions/download-artifact to download all artifacts into a single directory, then run the publish-unit-test-result-action pointing to that directory.

    Required Permissions for the publish job:

    • checks: write (to post check results)
    • pull-requests: write (if using comment_mode to comment on PRs)
    • contents: read (for private repositories)
    • issues: read (for private repositories)
    jobs:
      build-and-test:
        strategy:
          matrix:
            python-version: [3.6, 3.7, 3.8]
        steps:
          - name: PyTest
            run: python -m pytest test --junit-xml pytest.xml
          - name: Upload Test Results
            if: (!cancelled())
            uses: actions/upload-artifact@v7
            with:
              name: Test Results (Python ${{ matrix.python-version }})
              path: pytest.xml
    
      publish-test-results:
        name: "Publish Tests Results"
        needs: build-and-test
        runs-on: ubuntu-latest
        permissions:
          checks: write
          pull-requests: write
          contents: read
          issues: read
        if: (!cancelled())
        steps:
          - name: Download Artifacts
            uses: actions/download-artifact@v7
            with:
              path: artifacts
          - name: Publish Test Results
            uses: EnricoMi/publish-unit-test-result-action@v2
            with:
              files: "artifacts/**/*.xml"
  4. Support fork repositories and Dependabot branches

    master

    When running tests on pull requests from fork repositories or Dependabot, the action may fail with a "Resource not accessible by integration" error due to permission restrictions.

    To resolve this, do not run the action directly in your CI workflow. Instead, use a two-step approach:

    1. CI Workflow: Upload the GitHub event file (${{ github.event_path }}) and your test result files as artifacts.
    2. Separate Workflow: Create a new workflow triggered by workflow_run events (on completion of your CI workflow). This workflow downloads the artifacts and runs the action. This ensures the action runs with the necessary permissions in the context of the main repository.
    # 1. In your CI workflow, upload the event file
    event_file:
      name: "Event File"
      runs-on: ubuntu-latest
      steps:
      - name: Upload
        uses: actions/upload-artifact@v7
        with:
          name: Event File
          path: ${{ github.event_path }}
    
    # 2. In your CI workflow, upload test results
    - name: Upload Test Results
      if: (!cancelled())
      uses: actions/upload-artifact@v7
      with:
        name: Test Results
        path: "test-results/*.xml"
    
    # 3. Create a separate workflow triggered by workflow_run
    name: Test Results
    on:
      workflow_run:
        workflows: ["CI"]
        types: [completed]
    
    jobs:
      test-results:
        runs-on: ubuntu-latest
        if: github.event.workflow_run.conclusion == 'success' || github.event.workflow_run.conclusion == 'failure'
        permissions:
          checks: write
          pull-requests: write
          actions: read
        steps:
          - name: Download and Extract Artifacts
            uses: dawidd6/action-download-artifact@v21
            with:
               run_id: ${{ github.event.workflow_run.id }}
               path: artifacts
    
          - name: Publish Test Results
            uses: EnricoMi/publish-unit-test-result-action@v2
            with:
              commit: ${{ github.event.workflow_run.head_sha }}
              event_file: artifacts/Event File/event.json
              event_name: ${{ github.event.workflow_run.event }}
              files: "artifacts/**/*.xml"
  5. Migration guide from version 1 to version 2

    master

    If you are upgrading from version 1 to version 2, be aware of the following breaking changes:

    Default Naming Changes

    • check_name: The default changed from "Unit Test Results" to "Test Results". Existing checks with the old name will not be updated. To maintain version 1 behavior, explicitly set check_name: "Unit Test Results".
    • comment_title: The default changed from "Unit Test Results" to "Test Results". To maintain version 1 behavior, set the title explicitly.

    Removed Options

    • comment_mode: The modes create new and update last have been removed. The action now always updates the most recent pull request comment (equivalent to the old update last behavior).
    • hiding_comments: Removed because the action now always updates existing comments.
    • comment_on_pr: Removed. To achieve similar behavior, use comment_mode: always or off.
  6. Run with absolute paths or non-Docker environments

    master

    The standard Docker variant (EnricoMi/publish-unit-test-result-action@v2) works best with relative paths. If you must use absolute paths, you have two options:

    1. Copy to relative path: Use a shell command to copy files from the absolute path to a relative directory before running the action.
    2. Use non-Docker variants: Use the OS-specific actions which run directly on the runner. These require a Python 3 environment.

    Non-Docker variants

    • Linux: EnricoMi/publish-unit-test-result-action/linux@v2
    • macOS: EnricoMi/publish-unit-test-result-action/macos@v2
    • Windows: EnricoMi/publish-unit-test-result-action/windows@v2
    • Windows (Bash): EnricoMi/publish-unit-test-result-action/windows/bash@v2

    Note: The composite@v2 variant is deprecated.

    # Option 1: Copy to relative path for Docker variant
    - name: Copy Test Results
      if: (!cancelled())
      run: cp -Lpr /tmp/test-results test-results
      shell: bash
    
    - name: Publish Test Results
      uses: EnricoMi/publish-unit-test-result-action@v2
      with:
         files: "test-results/**/*.xml"
    
    # Option 2: Use non-Docker variant (requires Python 3)
    - name: Publish Test Results
      uses: EnricoMi/publish-unit-test-result-action/linux@v2
      with:
        files: "/tmp/test-results/**/*.xml"
  7. Handle multiple event types to avoid overwriting results

    master

    The action comments on pull requests for every event type it runs. If you run it for multiple event types (e.g., push, pull_request, schedule), subsequent runs will overwrite previous pull request comments.

    To prevent this, you can use one of two strategies:

    1. Use unique check_name per event type

    Append the event name to the check_name so each event type creates its own check.

    2. Disable pull request comments for non-PR events

    Use the comment_mode option to set it to always for pull_request events and off for all other events.

    # Strategy 1: Unique check names
    - name: Publish Test Results
      uses: EnricoMi/publish-unit-test-result-action@v2
      with:
        check_name: "Test Results (${{ github.event.workflow_run.event || github.event_name }})"
        files: "test-results/**/*.xml"
    
    # Strategy 2: Conditional comment_mode
    - name: Publish Test Results
      uses: EnricoMi/publish-unit-test-result-action@v2
      with:
        comment_mode: ${{ (github.event.workflow_run.event == 'pull_request' || github.event_name == 'pull_request') && 'always' || 'off' }}
        files: "test-results/**/*.xml"
  8. Configure required GitHub permissions

    master

    To avoid the "Resource not accessible by integration" error, you must grant the following permissions to your workflow job.

    Public Repositories

    Minimal required permissions:

    • checks: write
    • pull-requests: write

    Private Repositories

    Minimal required permissions:

    • contents: read
    • issues: read
    • checks: write
    • pull-requests: write

    Note: If you set comment_mode: off, the pull-requests: write permission is not required.

    # Example for a private repository
    permissions:
      contents: read
      issues: read
      checks: write
      pull-requests: write
  9. Configure Pull Request comments

    master

    The action posts a comment on pull requests related to the commit.

    • Updating comments: Subsequent runs of the action will update the same comment rather than creating new ones. You can view previous results via the comment's edit history.
    • Test vs Run distinction: The results distinguish between individual tests and test runs (useful if tests run in multiple environments). If tests only run once, run information is hidden.
    • Highlighting test removals: To highlight unintended test removals in the comment, set check_run_annotations to all tests, skipped tests.
    • Disabling: Use comment_mode: off to disable pull request comments.
  10. Configure pull request comment behavior

    master

    The comment_mode option controls how the action posts comments to pull requests.

    Available modes:

    • always: Always post a comment.
    • changes: Post a comment only when changes exist relative to the target branch.
    • changes in failures: Post a comment only when the number of failures or errors changes.
    • changes in errors: Post a comment only when the number of errors changes.
    • failures: Post a comment if failures or errors exist.
    • errors: Post a comment if only errors exist.
    • off: Do not create pull request comments.