The jacoco-badge-generator is a GitHub Action, which can also be used locally as a command-line utility. Its functionality includes parsing JaCoCo test coverage csv files, generating coverage badges that can be displayed within the READMEs of GitHub repositories, generating a JSON summary file with the coverage percentages, and can optionally be used for pull-request coverage checks (e.g., validating if coverage is above a target minimum and/or ensuring that coverage did not decrease). It is customizable in a variety of ways (see its GitHub repository and/or the other posts in this series for details).
I just release version v2.9.0, which enhanced the existing functionality associated with using the jacoco-badge-generator GitHub Action with multi-module projects. Specifically, prior to this release, for a multi-module project, the paths to all of the JaCoCo csv reports had to be listed in the inputs to the action. Now, as of v2.9.0, you can use a glob pattern to specify the paths to the JaCoCo csv reports. This can actually now also work for the more common single module project, but the glob functionality is likely most useful in the multi-module case. Note that the CLI mode already implicitly supported globs since your shell will expand any globs you specify on the command line. But as a GitHub Action this previously was not the case as GitHub Actions doesn't expand globs in the inputs to an Action. The jacoco-badge-generator v2.9.0 now handles glob expansion internally.
This post focuses on workflows for the multi-module case, including introducing the new approach to using a glob to specify the JaCoCo reports. The README in the GitHub repository, as well as other posts in this series here on DEV, cover other functionality along with additional sample workflows.
Table of Contents: The remainder of this post is organized as follows:
- Preliminaries
- Workflow Specifying Paths to JaCoCo Reports Without Globs
- Workflow Specifying Paths to JaCoCo Reports With Globs
- Workflow Generating Separate Badges for Each Module
- Multi-Module Examples with the CLI Utility
- More Information
- Where You Can Find Me
Preliminaries
Before you can use the jacoco-badge-generator, your workflow must generate a JaCoCo csv coverage report. Here are a couple examples of how to do this for different build tools.
Running JaCoCo with Maven
The example workflows in this post assume that you are using Maven to build and test a Java project, and that you have the jacoco-maven-plugin configured in your pom.xml in the test phase with something along the lines of the following:
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.10</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>generate-code-coverage-report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Running JaCoCo with Gradle
If you use gradle as your build tool, then you can configure JaCoCo to generate the csv report in build.gradle.kts
with:
plugins {
jacoco
}
tasks.jacocoTestReport {
reports {
csv.isEnabled = true
}
}
Or the equivalent in build.gradle
:
plugins {
id 'jacoco'
}
jacocoTestReport {
reports {
csv.enabled true
}
}
Note that the workflows in the remainder of this post assume that Maven is in use, including Maven's default location and filename for the coverage report. You will need to alter the jacoco-csv-file
input if you are using Gradle to the appropriate location and filename.
Workflow Specifying Paths to JaCoCo Reports Without Globs
This example workflow generates both badges (instructions coverage percentage and branches coverage percentage) for a multi-module project. The badges that are generated are computed over all modules. To do so, simply pass the paths to all of the JaCoCo reports that you want to include via the jacoco-csv-file input. The >
is just Yaml's way of writing a string across multiple lines. You can also just list all on a single space-separated line, but your workflow file will be easier to read if you put them one per line. In this example, there are three subprojects: module1
, module2
, and module3
. This workflow assumes that you are using Maven as your build tool, and that you have configured JaCoCo to run during the test phase.
name: build
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up the Java JDK
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'adopt'
- name: Build with Maven
run: mvn -B test
- name: Generate JaCoCo Badge
id: jacoco
uses: cicirello/jacoco-badge-generator@v2
with:
generate-branches-badge: true
jacoco-csv-file: >
module1/target/site/jacoco/jacoco.csv
module2/target/site/jacoco/jacoco.csv
module3/target/site/jacoco/jacoco.csv
- name: Log coverage percentage
run: |
echo "coverage = ${{ steps.jacoco.outputs.coverage }}"
echo "branch coverage = ${{ steps.jacoco.outputs.branches }}"
- name: Commit the badge (if it changed)
run: |
if [[ `git status --porcelain` ]]; then
git config --global user.name 'YOUR NAME HERE'
git config --global user.email 'YOUR-GITHUB-USERID@users.noreply.github.com'
git add -A
git commit -m "Autogenerated JaCoCo coverage badge"
git push
fi
Workflow Specifying Paths to JaCoCo Reports With Globs
This next example workflow is just like the previous, except that now a glob is used to to find all JaCoCo reports named jacoco.csv
regardless of where they appear within your project. This will actually also work if you have a single module project, with a single jacoco.csv
but without the need to specify its path. We'll pass the glob pattern to the jacoco-csv-file
input with the following: jacoco-csv-file: "**/jacoco.csv"
. Note that the quotes around the pattern are necessary. Without the quotes, the wildcard characters will lead to an "invalid workflow" error from GitHub Actions. We're essentially passing the glob as a string to the action, and the action then processes the glob internally.
name: build
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up the Java JDK
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'adopt'
- name: Build with Maven
run: mvn -B test
- name: Generate JaCoCo Badge
id: jacoco
uses: cicirello/jacoco-badge-generator@v2
with:
generate-branches-badge: true
jacoco-csv-file: "**/jacoco.csv"
- name: Log coverage percentage
run: |
echo "coverage = ${{ steps.jacoco.outputs.coverage }}"
echo "branch coverage = ${{ steps.jacoco.outputs.branches }}"
- name: Commit the badge (if it changed)
run: |
if [[ `git status --porcelain` ]]; then
git config --global user.name 'YOUR NAME HERE'
git config --global user.email 'YOUR-GITHUB-USERID@users.noreply.github.com'
git add -A
git commit -m "Autogenerated JaCoCo coverage badge"
git push
fi
Workflow Generating Separate Badges for Each Module
If you prefer to generate separate coverage badges for each of the modules of a multi-module project, then just include multiple steps of the jacoco-badge-generator in your workflow, such as in this example. Be sure to use the inputs to specify names for the badge files, otherwise with the defaults the subsequent steps will overwrite the previous. This example assumes that there are two modules. You also will likely want to use the coverage-label
and branches-label
inputs to change the text on the left side of the badges if you are displaying badges for multiple modules in the README of the same repository. This example demonstrates that as well.
name: build
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up the Java JDK
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'adopt'
- name: Build with Maven
run: mvn -B test
- name: Generate JaCoCo Badges for Module 1
id: jacocoMod1
uses: cicirello/jacoco-badge-generator@v2
with:
generate-branches-badge: true
jacoco-csv-file: module1/target/site/jacoco/jacoco.csv
coverage-badge-filename: jacoco1.svg
branches-badge-filename: branches1.svg
coverage-label: coverage (module 1)
branches-label: branches (module 1)
- name: Generate JaCoCo Badges for Module 2
id: jacocoMod2
uses: cicirello/jacoco-badge-generator@v2
with:
generate-branches-badge: true
jacoco-csv-file: module2/target/site/jacoco/jacoco.csv
coverage-badge-filename: jacoco2.svg
branches-badge-filename: branches2.svg
coverage-label: coverage (module 2)
branches-label: branches (module 2)
- name: Commit the badges (if they changed)
run: |
if [[ `git status --porcelain` ]]; then
git config --global user.name 'YOUR NAME HERE'
git config --global user.email 'YOUR-GITHUB-USERID@users.noreply.github.com'
git add -A
git commit -m "Autogenerated JaCoCo coverage badge"
git push
fi
Multi-Module Examples with the CLI Utility
For those using the jacoco-badge-generator
as a CLI tool, the following commands will accomplish the equivalent of the above three workflows. First, to install the CLI tool with pip from PyPI.
On Linux and MacOS:
python3 -m pip install jacoco-badge-generator
On Windows:
py -m pip install jacoco-badge-generator
Note that all examples below assume Linux (e.g., Python command is python3
). If on Windows, just change python3
to py
in all of the examples below.
Three Modules Without Globs:
Generate both instructions coverage and branches coverage badges for combination of three modules:
python3 -m jacoco_badge_generator --generate-branches-badge true --jacoco-csv-file module1/target/site/jacoco/jacoco.csv module2/target/site/jacoco/jacoco.csv module3/target/site/jacoco/jacoco.csv
Three Modules With Globs:
Generate both instructions coverage and branches coverage badges for combination of three modules:
python3 -m jacoco_badge_generator --generate-branches-badge true --jacoco-csv-file **/jacoco.csv
Two Modules with Separate Badges for Each:
python3 -m jacoco_badge_generator --generate-branches-badge true --jacoco-csv-file module1/target/site/jacoco/jacoco.csv --coverage-badge-filename jacoco1.svg --branches-badge-filename branches1.svg --coverage-label "coverage (module 1)" --branches-label "branches (module 1)"
python3 -m jacoco_badge_generator --generate-branches-badge true --jacoco-csv-file module2/target/site/jacoco/jacoco.csv --coverage-badge-filename jacoco2.svg --branches-badge-filename branches2.svg --coverage-label "coverage (module 2)" --branches-label "branches (module 2)"
More Information
For more information, see the GitHub Repository:
cicirello / jacoco-badge-generator
Coverage badges, and pull request coverage checks, from JaCoCo reports in GitHub Actions
jacoco-badge-generator
Check out all of our GitHub Actions: https://actions.cicirello.org/
About
The jacoco-badge-generator can be used in one of two ways: as a GitHub Action or as a command-line
utility (e.g., such as part of a local build script). The jacoco-badge-generator parses a jacoco.csv
from a JaCoCo coverage report, computes coverage percentages
from JaCoCo's Instructions and Branches counters, and
generates badges for one or both of these (user configurable) to provide an easy
to read visual summary of the code coverage of your test cases. The default behavior directly
generates the badges internally with no external calls, but the action also provides an option
to instead generate Shields JSON endpoints. It supports
both the basic case of a single jacoco.csv
, as well as multi-module projects in which
case the action can produce coverage badges from the combination of…
You can also check out a website about this action as well as other GitHub Actions that I maintain:
Where You Can Find Me
Follow me here on DEV and on GitHub:
Or visit my website:
Top comments (0)