Load coverage data for Java using SonarScanner CLI

  • ALM used: GitHub
  • CI system used: Github Actions
  • Scanner command used:
    $ sonar-scanner -Dsonar.projectVersion=1.64.4 -X -Dsonar.branch.name=feature/foo-bar
    
  • Languages of the repository: primarily Java
  • Error observed:
    1. Branch scan results are displaying A few extra steps are needed for SonarCloud to analyze your code coverage instead of the coverage numbers in web UI
    2. PR scan results are displaying No data about Coverage

I have a Maven-based Java product that is already set up to produce JaCoCo XML coverage report. I’m trying to use SonarScanner CLI to pick up / process that report and reflect the data in the Sonarcloud web UI.

I know that SonarScanner for Maven is the recommended way in this case.

We have a big portfolio of products using different ecosystems so I’m trying to reuse a generic language-agnostic approach in order to integrate each product with SonarCloud in a similar way (reusing common dev-automation that invokes SonarScanner CLI)

Here is the sonar-project.properties content:

sonar.organization=foo
sonar.projectKey=bar
sonar.host.url=https://sonarcloud.io
sonar.projectName=BAR

sonar.sources=src/main/java
sonar.tests=src/test
sonar.exclusions=**/*.json, **/*.js, **/*.xml, **/*.html
sonar.sourceEncoding=UTF-8

# =====================================================
#   Properties specific to Java
# =====================================================

sonar.java.source=17
sonar.java.binaries=.build/classes/
sonar.java.libraries=.build/lib/*.jar
sonar.java.test.binaries=.build/test-classes/
sonar.coverage.jacoco.xmlReportPaths=dist/coverage/jacoco.xml

and this is how I am invoking SonarScanner CLI:

$ sonar-scanner -Dsonar.projectVersion=1.64.4 -X -Dsonar.branch.name=feature/foo-bar

From the logs I get the impression that SonarScanner detects the report, but no processing occurs on it:

09:07:34.537 INFO: Sensor JaCoCo XML Report Importer [jacoco]
09:07:34.542 INFO: Importing 1 report(s). Turn your logs in debug mode in order to see the exhaustive list.
09:07:34.542 DEBUG: Reading report '/data/work/foo/git/bar/dist/coverage/jacoco.xml'
09:07:34.721 INFO: Sensor JaCoCo XML Report Importer [jacoco] (done) | time=184ms

Here is a sample of the JaCoCo report:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE report PUBLIC "-//JACOCO//DTD Report 1.1//EN" "report.dtd">
<report name="bar">
    <sessioninfo id="6c34987f2ba9-a7b6f54b" start="1715165817971" dump="1715165827782" />
    <sessioninfo id="6c34987f2ba9-c3584840" start="1715165828086" dump="1715165872093" />
    <package name="net/foo/bar/multiplexer">
        <class name="net/foo/bar/multiplexer/TranslatorJSON" sourcefilename="TranslatorJSON.java">
            <method name="&lt;init&gt;"
                desc="(Lnet/foo/bar/protocol/Protocol;Lnet/foo/bar/log/RequestContext;Lnet/foo/bar/mapping/Mappings;)V"
                line="16">
                <counter type="INSTRUCTION" missed="0" covered="6" />
                <counter type="LINE" missed="0" covered="2" />
                <counter type="COMPLEXITY" missed="0" covered="1" />
                <counter type="METHOD" missed="0" covered="1" />
            </method>
            <method name="multiplexQueryFrom" desc="(Ljava/util/HashMap;)Ljava/util/HashMap;" line="21">
                <counter type="INSTRUCTION" missed="69" covered="0" />
                <counter type="BRANCH" missed="2" covered="0" />
                <counter type="LINE" missed="12" covered="0" />
                <counter type="COMPLEXITY" missed="2" covered="0" />
                <counter type="METHOD" missed="1" covered="0" />
            </method>
            ...
            <counter type="INSTRUCTION" missed="84" covered="17" />
            <counter type="BRANCH" missed="2" covered="0" />
            <counter type="LINE" missed="16" covered="5" />
            <counter type="COMPLEXITY" missed="4" covered="2" />
            <counter type="METHOD" missed="3" covered="2" />
            <counter type="CLASS" missed="0" covered="1" />
        </class>
...

This is how JaCoCo is configured (in case it is relevant):

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.8.8</version>
    <configuration>
        <rules>
            <rule>
                <element>BUNDLE</element>
                <limits>
                    <limit>
                        <counter>LINE</counter>
                        <value>COVEREDRATIO</value>
                        <minimum>0.45</minimum>
                    </limit>
                </limits>
            </rule>
        </rules>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
        </execution>
        <execution>
            <id>jacoco-report</id>
            <goals>
                <goal>report</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Any ideas what am I missing here? Is this again the issue with relative paths where paths from JaCoCo report don’t line up with SonarScanner’s view of the sources?

Hi,

Based on your log snippet, I would expect this to be working.

Since you insist on using SonarScanner CLI, for this Maven-based project, can you provide the version you’re using?

And to eliminate variables, can you try this

  • with the normal, SonarScanner for Maven
  • with the coverage report generated to the default path: target/site/jacoco/jacoco.xml
  • with the normal scanner and the default path

?

And if all of that fails, can you add -Dsonar.log.level=TRACE and see fi that adds anything useful to the log?

 
Ann

My bad:

14:21:05.991 INFO: SonarScanner 5.0.1.3006
14:21:05.991 INFO: Java 17.0.7 Eclipse Adoptium (64-bit)
14:21:05.991 INFO: Linux 6.8.0-76060800daily20240311-generic amd64

Will provide the rest of the information shortly.

1 Like

I tried other suggestions but didn’t get anywhere with any of them.

I did however figure out the root of the issue by accident.

Apparently, if the branch/PR has no source/test changes compared to the base branch (develop), then a very confusing message is displayed suggesting that the project configuration is incomplete:

With code changes:
image

Without code changes:
image

Btw, with code changes present it works well with both SonarScanner CLI and SonarScanner for Maven.

If the above behaviour is expected, it should be documented clearer. But to be honest, I see no reason not to make user life easier and improve the UI by distinguishing between these 2 scenarios:

  1. Coverage setup is incomplete (no JaCoCo report found or report is empty)
  2. Coverage setup is complete but the diff between the head and the base is empty (equivalent of “0 new lines to cover”)
1 Like

Hi,

I’m glad you worked through this.

I agree with you. I’m going to refer this internally.

Thanks for following up!

 
Ann

Thank you @Ivan_Ribakov for your feedback!
We confirmed that this is an internal issue on our side, and we created a ticket for the fix.

2 Likes