JaCoCo coverage your team can actually click
JaCoCo already renders a perfectly good HTML site — per-class drill-down, red and green lines, branch counters. All it needs is a URL. Two lines of YAML and every PR links to live coverage instead of a downloaded zip.
The artifact dead-end
Coverage that lives in a CI artifact is coverage nobody reads. The drill-down — package to class to the exact uncovered branch — is the whole point of the HTML report, and it dies the moment it's zipped.
Self-hosting means standing up a bucket, lifecycle rules and auth for viewers. That's an afternoon of ops work to answer the question 'did this diff get tested?'.
Two lines to a live link
Generate the report like you already do, then hand the folder to the action:
Generate the report (Gradle)
./gradlew test jacocoTestReport.github/workflows/ci.yml
- uses: bitgate/ship-page-action@v1
if: always()
with:
path: build/reports/jacoco/test/html/Omit path entirely and the action auto-detects build/reports/jacoco/test/html/ on its own. The URL lands in the job summary — add comment: true and it lands on the pull request too.
What you get
- The full drill-down works — package → class → line — because the folder is served exactly as JaCoCo wrote it
- Gradle and Maven layouts both auto-detected: build/reports/jacoco/test/html/ and target/site/jacoco/
- With name + api-key, coverage redeploys to the same URL on every push — the PR comment never goes stale
Questions
Does it work with Maven?
Yes. mvn test jacoco:report writes target/site/jacoco/ — point path there, or omit it and let the action find it.
Can I gate the PR on coverage too?
Combine this with jacocoTestCoverageVerification (Gradle) or jacoco:check (Maven) — the gate fails the build, the deployed report shows why.
Who can see the link?
Anyone with the URL. Slugs are long and unguessable; there's no public index. Named drops on paid plans get readable URLs — same rule.
Try it on your next run
Anonymous deploys need no account and no key — paste the step, get a link. When you want stable URLs that redeploy in place, an API key and a name are all it takes.