Zero-config test reporting for GitHub Actions. Never breaks your CI.
- Zero config — auto-detects test report files; no
report-pathrequired - Rich CI summaries — failed tests with stack traces, slowest tests, per-suite breakdowns
- PR comments — multi-job test summaries posted directly on pull requests
- Inline annotations — failed tests annotated directly on the PR diff (opt-in)
- Non-blocking — guaranteed exit code 0, your builds are always safe
No signup, no account, no outbound calls to TestGlance.
- uses: testglance/action@v1That's it. TestGlance auto-detects your test reports and generates a CI summary.
Most agents (Claude Code, Cursor, Windsurf, ...) will set this up end-to-end if you point them at the install prompt:
Install TestGlance in this project — instructions and per-framework guides at https://www.testglance.dev/install/index.md
The agent fetches the matching https://www.testglance.dev/install/<framework>.md page (vitest, jest, playwright, mocha, cypress, pytest, go, rspec, phpunit, junit5, dotnet, or other), wires up the JUnit reporter, and adds the workflow step. The copy-pasteable prompt is on the TestGlance landing page.
permissions:
contents: read
pull-requests: write
steps:
- uses: testglance/action@v1
with:
github-token: ${{ github.token }}Requires pull-requests: write permission. See Permissions for details.
The hosted TestGlance dashboard — health scores, flaky test detection, and trend tracking — is in development. The api-key input is reserved for this integration but is not yet active.
- uses: testglance/action@v1
with:
api-key: ${{ secrets.TESTGLANCE_API_KEY }} # reserved — SaaS coming soon- Failed Test Details — up to 30 lines of stack traces per failure, formatted in collapsible sections
- Slowest Tests — configurable top-N ranking to spot performance bottlenecks
- Suite Breakdown — per-suite pass/fail/skip counts and durations
- Auto-Detection — finds
**/test-results/*.xml,**/junit.xml,**/ctrf/*.json, and more - Multi-File Merge — glob patterns merge multiple report files into a single summary
- Inline Annotations — opt-in failure annotations on the PR diff at the exact file:line
- PR Comments — multi-job summaries merged into a single comment, updated on re-runs
- SaaS Dashboard (coming soon) — optional health scores, flaky test detection, and trend tracking
| Feature | TestGlance | dorny/test-reporter | ctrf-io/github-test-reporter | mikepenz/action-junit-report | EnricoMi/publish-unit-test-result-action |
|---|---|---|---|---|---|
| Zero Config | ✅ | ❌ | ❌ | ❌ | ❌ |
| JUnit + CTRF | Both | JUnit only | CTRF only | JUnit only | JUnit only |
| Failed Test Details | ✅ | ✅ | ✅ | ✅ | ✅ |
| Slowest Tests | ✅ | ❌ | ❌ | ❌ | ❌ |
| Suite Breakdown | ✅ | ❌ | ❌ | ❌ | ✅ |
| Check Runs | ✅ | ✅ | ✅ | ✅ | ✅ |
| PR Comments | ✅ | ❌ | ✅ | ❌ | ✅ |
| Never Fails CI | ✅ | ❌ | Configurable | Configurable | Configurable |
| Multi-File Merge | ✅ | ✅ | ❌ | ✅ | ✅ |
| Auto-Detect Files | ✅ | ❌ | ❌ | ❌ | ❌ |
| SaaS Dashboard | Coming soon | ❌ | ❌ | ❌ | ❌ |
- uses: testglance/action@v1- uses: testglance/action@v1
with:
github-token: ${{ github.token }}permissions:
checks: write
steps:
- uses: testglance/action@v1
with:
github-token: ${{ github.token }}
annotate-failures: true
check-name: Unit Tests- uses: testglance/action@v1
with:
api-key: ${{ secrets.TESTGLANCE_API_KEY }} # reserved — SaaS coming soon
github-token: ${{ github.token }}Each GitHub Actions job runs on its own runner with its own filesystem and Job Summary. Add the TestGlance step to every job that produces test reports — results are automatically merged into a single PR comment.
jobs:
unit:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
checks: write
steps:
- uses: actions/checkout@v4
- run: pnpm install && pnpm test
- uses: testglance/action@v1
if: always()
with:
github-token: ${{ github.token }}
e2e:
needs: unit
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
checks: write
steps:
- uses: actions/checkout@v4
- run: pnpm install && pnpm test:e2e
- uses: testglance/action@v1
if: always()
with:
github-token: ${{ github.token }}Use if: always() so results are reported even when tests fail. Use test-job-name to disambiguate jobs in the merged PR comment if the default job name isn't clear enough.
See examples/reusable-workflow.yml for a workflow_call template you can deploy across your organization. More examples in the examples/ directory.
| Input | Required | Default | Description |
|---|---|---|---|
report-path |
No | '' (auto-detect) |
Path to test report file(s). Supports glob patterns. |
api-key |
No | '' |
TestGlance project API key (reserved — SaaS coming soon) |
api-url |
No | https://www.testglance.dev |
TestGlance API URL (reserved — SaaS coming soon) |
report-format |
No | auto |
Format: junit, ctrf, or auto (detect from extension) |
test-job-name |
No | '' |
Override the display name for this test job |
slowest-tests |
No | 10 |
Number of slowest tests to show in CI summary (0 to disable) |
send-results |
No | true |
Send results to TestGlance API. Automatically forced to false when no api-key is provided. |
github-token |
No | '' |
GitHub token for PR comments and Check Runs |
annotate-failures |
No | false |
Annotate failed tests inline on the PR diff (creates a Check Run) |
check-name |
No | Test Results |
Name of the Check Run created by annotate-failures |
annotation-level |
No | failure |
Severity for inline failure annotations: failure, warning, or notice. warning/notice keep the check advisory. |
summary-template |
No | '' |
Path to a Handlebars template that replaces the default CI summary. See Custom Templates. |
comment-template |
No | '' |
Path to a Handlebars template that replaces the default PR comment body. See Custom Templates. |
Note on
annotation-level: The Check Run'sconclusionis stillfailurewhenever tests fail, regardless ofannotation-level. Settingwarningornoticeonly changes the severity of the inline annotations — it does not change the check outcome. This is the dial for teams who want inline failure annotations without those annotations tripping required-checks branch protection.
TestGlance's core functionality (CI summaries, auto-detection) requires no special permissions. Additional features degrade gracefully when permissions are missing — they log a warning and skip, never failing your build.
| Permission | Feature | Behavior if Missing |
|---|---|---|
contents: read |
Baseline (checkout code) | Required for all modes |
pull-requests: write |
PR comments | Skipped with warning log, CI stays green |
checks: write |
Check Runs + inline annotations | Skipped with warning log, CI stays green |
permissions:
contents: readpermissions:
contents: read
pull-requests: write
checks: writeAdd a permissions block at the job level or workflow level:
jobs:
test:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
checks: write
steps:
- uses: testglance/action@v1
with:
github-token: ${{ github.token }}
annotate-failures: trueImportant: When you add a
permissionsblock, GitHub removes all default permissions and grants only what you list. If your job needs other permissions (e.g.,contents: readto check out code), you must include them explicitly.
For the full reference, see docs/permissions.md.
Output from most test frameworks:
- JavaScript/TypeScript: Jest, Vitest, Mocha, Playwright
- Python: pytest, unittest
- Go:
go test -vwith gotestsum - Java/Kotlin: JUnit 5, Maven Surefire, Gradle
- Ruby: RSpec, Minitest
- C#/.NET: xUnit, NUnit, MSTest
Common Test Report Format — a standardized JSON schema supported by many test frameworks.
After each CI run, TestGlance adds a Job Summary:
## TestGlance Results
| Metric | Value |
|-----------|--------|
| Total | 142 |
| Passed | 138 |
| Failed | 3 |
| Skipped | 1 |
| Duration | 12.3s |
### Failed Tests
| Suite | Test | Error |
|--------------|------------------------------|-------------------------------|
| auth.login | should reject expired token | Expected 401 but received 200 |
| api.users | should validate email format | Invalid email was accepted |
### Slowest Tests
| Test | Duration |
|--------------------------------|----------|
| e2e.checkout full flow | 4.2s |
| api.users bulk import | 2.8s |
| auth.login rate limiting | 1.9s |
### Suite Breakdown
| Suite | Passed | Failed | Skipped | Duration |
|-------------|--------|--------|---------|----------|
| auth | 42 | 1 | 0 | 3.1s |
| api | 89 | 2 | 1 | 7.8s |
| utils | 7 | 0 | 0 | 1.4s |
## TestGlance Test Summary
### ci/test (unit tests)
**142 tests** | 12.3s | Health: 94/100
| Signal | Details |
|--------|---------|
| | Health Score: 94 -> 91 |
| | 2 new test(s) added |
View Run ->
Multiple test jobs are merged into a single comment. Subsequent runs update the existing comment.
Deploy TestGlance across your organization with a single reusable workflow:
- Copy
examples/reusable-workflow.ymlinto your org's shared workflow repo - Each repo calls it with minimal config:
jobs:
report:
uses: your-org/.github/.github/workflows/testglance.yml@main
secrets:
api-key: ${{ secrets.TESTGLANCE_API_KEY }}See the examples/ directory for more usage patterns.
Per-framework install instructions are hosted at https://www.testglance.dev/install/index.md — also served as agent-friendly markdown so any AI coding agent can fetch them directly.
- Vitest
- Jest
- Playwright
- Mocha
- Cypress
- pytest
- Go
- RSpec
- PHPUnit
- JUnit 5 (Maven & Gradle)
- .NET (xUnit / NUnit / MSTest)
- Other / generic JUnit XML
This Action never fails your CI pipeline. If anything goes wrong — file not found, parse error, API timeout, PR comment failure — the Action logs a warning and exits with code 0. Your builds are safe.
- No
core.setFailed()calls anywhere in the codebase - No repository permissions required for core functionality
- Optional
github-tokenfor PR comments and Check Runs only (never affects exit code) - Only outbound HTTPS to the TestGlance API and GitHub API
Add a single step to any workflow that produces test reports:
- uses: testglance/action@v1The hosted dashboard is in development. Once available, you'll be able to:
- Sign up at testglance.dev
- Create a project and connect your repository
- Copy your project API key
- Add it as a repository secret:
Settings > Secrets > TESTGLANCE_API_KEY - Add the Action to your workflow (see Quick Start)
Until then, the api-key input is accepted but inactive — all core features (CI summaries, PR comments, annotations) work without it.
Standard workflow (pnpm):
pnpm install
pnpm test # vitest
pnpm lint # eslint
pnpm typecheck # tsc --noEmit
pnpm build # bundle to dist/index.js (gitignored; CI rebuilds it)pnpm e2e:act runs the bundled Action (dist/index.js + action.yml) against
real report fixtures inside Docker via act, then
asserts it parses JUnit/CTRF, handles edge cases (malformed/empty/missing) with a
warning, and exits 0. This catches packaging/runtime breakage that unit tests
can't, before you push.
pnpm e2e:actPrerequisites:
- Docker running (the script skips with exit 0 if the daemon is unavailable).
actinstalled. First run only, seed the runner image:act --pull(subsequent runs use--pull=false).- Don't run two
actinvocations against the same Docker daemon concurrently —actuses host networking and the containers race.
Caveat: act cannot create real GitHub Check Run annotations or PR
comments (no live GitHub API). Those are covered by the vitest suite (mocked
octokit) and by the authoritative hosted e2e (.github/workflows/e2e.yml). The
Check Run code path is still smoke-exercised here — with a dummy token it warns
gracefully and exits 0, but no annotation is created.
MIT