Java coverage
Generate JaCoCo XML with Maven or Gradle, then upload the report directly from GitHub Actions.
Install dependencies
Add the JaCoCo Maven plugin or Gradle jacoco plugin to your build so CI writes a JaCoCo XML report.
Generate coverage
mvn test jacoco:report
./gradlew test jacocoTestReport
Maven GitHub Actions workflow
For Maven, upload target/site/jacoco/jacoco.xml. The action uses the default upload endpoint unless you provide an optional endpoint override.
name: coverage
on:
pull_request:
push:
jobs:
coverage:
if: github.event_name == 'pull_request' || github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "21"
cache: maven
- run: mvn -B test jacoco:report
- name: Upload coverage
uses: 9to5/9to5-coverage-action@v1
with:
token: ${{ secrets.COVERAGE_UPLOAD_TOKEN }}
path: target/site/jacoco/jacoco.xml
Maven: attach the JaCoCo test agent
Add this plugin under build/plugins
in your pom.xml. The agent records execution during tests; the report goal writes XML for upload.
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.14</version>
<executions>
<execution>
<goals><goal>prepare-agent</goal></goals>
</execution>
</executions>
</plugin>
Gradle: enable XML and upload the report
For a single-module JVM project, add this to build.gradle.kts and commit the Gradle wrapper. Multi-module and Android builds require their own report tasks and paths.
plugins {
java
jacoco
}
jacoco {
toolVersion = "0.8.14"
}
tasks.jacocoTestReport {
dependsOn(tasks.test)
reports {
xml.required.set(true)
}
}
name: coverage
on:
pull_request:
push:
jobs:
coverage:
if: github.event_name == 'pull_request' || github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "21"
- run: ./gradlew test jacocoTestReport
- name: Upload coverage
uses: 9to5/9to5-coverage-action@v1
with:
token: ${{ secrets.COVERAGE_UPLOAD_TOKEN }}
path: build/reports/jacoco/test/jacocoTestReport.xml
See the Gradle JaCoCo documentation for custom report locations.
Pull request behavior
JaCoCo reports behave like other uploads: project and patch checks are attached to the pull request commit.
Troubleshooting
If upload fails, confirm the JaCoCo XML path. Gradle projects usually write build/reports/jacoco/test/jacocoTestReport.xml.