feat: Publish test coverage summaries to PRs (#513)

This commit is contained in:
Allen Hutchison 2025-05-27 12:45:28 -07:00 committed by GitHub
parent 9595e98db8
commit 4e3c539f5e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 184 additions and 11 deletions

View File

@ -0,0 +1,102 @@
name: 'Post Coverage Comment Action'
description: 'Prepares and posts a code coverage comment to a PR.'
inputs:
cli_json_file:
description: 'Path to CLI coverage-summary.json'
required: true
server_json_file:
description: 'Path to Server coverage-summary.json'
required: true
cli_full_text_summary_file:
description: 'Path to CLI full-text-summary.txt'
required: true
server_full_text_summary_file:
description: 'Path to Server full-text-summary.txt'
required: true
node_version:
description: 'Node.js version for context in messages'
required: true
github_token:
description: 'GitHub token for posting comments'
required: true
runs:
using: 'composite'
steps:
- name: Prepare Coverage Comment
id: prep_coverage_comment
shell: bash
run: |
cli_json_file="${{ inputs.cli_json_file }}"
server_json_file="${{ inputs.server_json_file }}"
cli_full_text_summary_file="${{ inputs.cli_full_text_summary_file }}"
server_full_text_summary_file="${{ inputs.server_full_text_summary_file }}"
comment_file="coverage-comment.md"
# Extract percentages using jq for the main table
if [ -f "$cli_json_file" ]; then
cli_lines_pct=$(jq -r '.total.lines.pct' "$cli_json_file")
cli_statements_pct=$(jq -r '.total.statements.pct' "$cli_json_file")
cli_functions_pct=$(jq -r '.total.functions.pct' "$cli_json_file")
cli_branches_pct=$(jq -r '.total.branches.pct' "$cli_json_file")
else
cli_lines_pct="N/A"; cli_statements_pct="N/A"; cli_functions_pct="N/A"; cli_branches_pct="N/A"
echo "CLI coverage-summary.json not found at: $cli_json_file" >&2 # Error to stderr
fi
if [ -f "$server_json_file" ]; then
server_lines_pct=$(jq -r '.total.lines.pct' "$server_json_file")
server_statements_pct=$(jq -r '.total.statements.pct' "$server_json_file")
server_functions_pct=$(jq -r '.total.functions.pct' "$server_json_file")
server_branches_pct=$(jq -r '.total.branches.pct' "$server_json_file")
else
server_lines_pct="N/A"; server_statements_pct="N/A"; server_functions_pct="N/A"; server_branches_pct="N/A"
echo "Server coverage-summary.json not found at: $server_json_file" >&2 # Error to stderr
fi
echo "## Code Coverage Summary" > "$comment_file"
echo "" >> "$comment_file"
echo "| Package | Lines | Statements | Functions | Branches |" >> "$comment_file"
echo "|---|---|---|---|---|" >> "$comment_file"
echo "| CLI | ${cli_lines_pct}% | ${cli_statements_pct}% | ${cli_functions_pct}% | ${cli_branches_pct}% |" >> "$comment_file"
echo "| Server | ${server_lines_pct}% | ${server_statements_pct}% | ${server_functions_pct}% | ${server_branches_pct}% |" >> "$comment_file"
echo "" >> "$comment_file"
# CLI Package - Collapsible Section (with full text summary from file)
echo "<details>" >> "$comment_file"
echo "<summary>CLI Package - Full Text Report</summary>" >> "$comment_file"
echo "" >> "$comment_file"
echo '```text' >> "$comment_file"
if [ -f "$cli_full_text_summary_file" ]; then
cat "$cli_full_text_summary_file" >> "$comment_file"
else
echo "CLI full-text-summary.txt not found at: $cli_full_text_summary_file" >> "$comment_file"
fi
echo '```' >> "$comment_file"
echo "</details>" >> "$comment_file"
echo "" >> "$comment_file"
# Server Package - Collapsible Section (with full text summary from file)
echo "<details>" >> "$comment_file"
echo "<summary>Server Package - Full Text Report</summary>" >> "$comment_file"
echo "" >> "$comment_file"
echo '```text' >> "$comment_file"
if [ -f "$server_full_text_summary_file" ]; then
cat "$server_full_text_summary_file" >> "$comment_file"
else
echo "Server full-text-summary.txt not found at: $server_full_text_summary_file" >> "$comment_file"
fi
echo '```' >> "$comment_file"
echo "</details>" >> "$comment_file"
echo "" >> "$comment_file"
echo "_For detailed HTML reports, please see the 'coverage-reports-${{ inputs.node_version }}' artifact from the main CI run._" >> "$comment_file"
- name: Post Coverage Comment
uses: thollander/actions-comment-pull-request@v3
if: always()
with:
file-path: coverage-comment.md # Use the generated file directly
comment-tag: code-coverage-summary
github-token: ${{ inputs.github_token }}

View File

@ -87,11 +87,8 @@ jobs:
- name: Install dependencies for testing
run: npm ci # Install fresh dependencies using the downloaded package-lock.json
- name: Run tests (generate JUnit XML)
run: npm run test:ci --workspaces --if-present
- name: Collect coverage
run: npm run coverage # This will run tests again, but also generate coverage
- name: Run tests and generate reports
run: NO_COLOR=true npm run test:ci
- name: Publish Test Report
uses: dorny/test-reporter@v1
@ -108,3 +105,35 @@ jobs:
with:
name: coverage-reports-${{ matrix.node-version }}
path: packages/*/coverage
post_coverage_comment:
name: Post Coverage Comment
runs-on: ubuntu-latest
needs: test
if: always()
continue-on-error: true
permissions:
contents: read # For checkout
pull-requests: write # For commenting
strategy:
matrix:
node-version: [20.x] # Should match the test job's matrix
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Download coverage reports artifact
uses: actions/download-artifact@v4
with:
name: coverage-reports-${{ matrix.node-version }}
path: coverage_artifact # Download to a specific directory
- name: Post Coverage Comment using Composite Action
uses: ./.github/actions/post-coverage-comment # Path to the composite action directory
with:
cli_json_file: coverage_artifact/cli/coverage/coverage-summary.json
server_json_file: coverage_artifact/server/coverage/coverage-summary.json
cli_full_text_summary_file: coverage_artifact/cli/coverage/full-text-summary.txt
server_full_text_summary_file: coverage_artifact/server/coverage/full-text-summary.txt
node_version: ${{ matrix.node-version }}
github_token: ${{ secrets.GITHUB_TOKEN }}

View File

@ -12,7 +12,7 @@
"clean": "scripts/clean.sh",
"prepare": "npm run bundle",
"test": "npm run test --workspaces",
"coverage": "npm run coverage --workspaces --if-present",
"test:ci": "npm run test:ci --workspaces --if-present",
"start": "NODE_ENV=development scripts/start.sh",
"debug": "NODE_ENV=development DEBUG=1 scripts/start.sh",
"lint:fix": "eslint . --fix",

View File

@ -18,8 +18,7 @@
"lint": "eslint . --ext .ts,.tsx",
"format": "prettier --write .",
"test": "vitest run",
"test:ci": "vitest run --reporter=junit --outputFile=junit.xml",
"coverage": "vitest run --coverage",
"test:ci": "vitest run --coverage",
"typecheck": "tsc --noEmit",
"prerelease:version": "node ../../scripts/bind_package_version.js",
"prerelease:deps": "node ../../scripts/bind_package_dependencies.js",

View File

@ -10,6 +10,22 @@ import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
environment: 'jsdom',
globals: true, // Optional: enables global APIs like describe, it, expect
globals: true,
reporters: ['default', 'junit'],
outputFile: {
junit: 'junit.xml',
},
coverage: {
provider: 'v8',
reportsDirectory: './coverage',
reporter: [
['text', { file: 'full-text-summary.txt' }],
'html',
'json',
'lcov',
'cobertura',
['json-summary', { outputFile: 'coverage-summary.json' }],
],
},
},
});

View File

@ -11,8 +11,7 @@
"lint": "eslint . --ext .ts,.tsx",
"format": "prettier --write .",
"test": "vitest run",
"test:ci": "vitest run --reporter=junit --outputFile=junit.xml",
"coverage": "vitest run --coverage",
"test:ci": "vitest run --coverage",
"typecheck": "tsc --noEmit",
"prerelease:version": "node ../../scripts/bind_package_version.js",
"prerelease:deps": "node ../../scripts/bind_package_dependencies.js",

View File

@ -0,0 +1,28 @@
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
reporters: ['default', 'junit'],
outputFile: {
junit: 'junit.xml',
},
coverage: {
provider: 'v8',
reportsDirectory: './coverage',
reporter: [
['text', { file: 'full-text-summary.txt' }],
'html',
'json',
'lcov',
'cobertura',
['json-summary', { outputFile: 'coverage-summary.json' }],
],
},
},
});