Azure DevOps and SonarQube Enterprise code coverage problems

Hi,

I have some troubles setting up the code coverage in SonarQube (Enterprise edition). Previously we have been using the community edition and that has been working fine, but now when are migrating to Enterprise we seem to get some problems with the reports.

  • CI system used: Azure DevOps
  • Languages of the repository: Java

We have setup a token based service connection and a YAML pipeline where we use Gradle to handle the build.

name: $(SourceBranchName)_$(Date:yyyyMMdd)$(Rev:.r)

pool:
  vmImage: 'Ubuntu 16.04'

steps:
- task: SonarQubePrepare@4
  displayName: 'SonarQube prepare'
  inputs:
    SonarQube: 'Sonar Test Enterprise'
    scannerMode: 'Other'

- task: Gradle@2
  displayName: 'Build'
  inputs:
    workingDirectory: ''
    gradleWrapperFile: 'gradlew'
    options: -Pversion=$(Build.BuildNumber) --stacktrace
    gradleOptions: -Xmx3072m
    javaHomeOption: 'JDKVersion'
    jdkVersionOption: '1.8'
    jdkArchitectureOption: 'x64'
    publishJUnitResults: true
    testResultsFiles: '**/TEST-*.xml'
    testRunTitle: 'Unit Tests'
    tasks: 'webpackProd build'
    codeCoverageToolOption: 'jaCoCo'
    codeCoverageClassFilesDirectories: 'build/classes/java/main/'
    codeCoverageFailIfEmpty: true
    checkStyleRunAnalysis: true
    findBugsRunAnalysis: true
    pmdRunAnalysis: true
    sonarQubeRunAnalysis: true
    sqGradlePluginVersionChoice: 'specify'
    sonarQubeGradlePluginVersion: '2.6.1'

- task: SonarQubePublish@4
  displayName: 'SonarQube publish'
  inputs:
     pollingTimeoutSec: 300

- task: CopyFiles@2
  displayName: 'Copy web.config file to /build/libs'
  inputs:
    sourceFolder: '$(build.sourcesDirectory)/azure/app-service/'
    contents: 'web.config'
    targetFolder: '$(build.sourcesDirectory)/build/libs/'
- task: PublishBuildArtifacts@1
  displayName: 'Publish artifact: webapp'
  inputs:
    pathtoPublish: '$(build.sourcesDirectory)/build/libs/'
    artifactName: 'WebApp'
  inputs:
    pathtoPublish: '$(build.sourcesDirectory)/build/reports/'
    artifactName: 'BuildReports'
trigger:
  - master
  - release/*

This setup has been working fine while using the community edition, but now when we have updated the service connection to point to the new enterprise edition SonarQube we see the code coverage as 0%. We are using the same project key, but have updated the URL and token in the service connection.
We also get this in our logs when building a successful build:

:sonarqube
SonarScanner will require Java 11 to run starting in SonarQube 8.x
No coverage report can be found with sonar.coverage.jacoco.xmlReportPaths='build/reports/jacoco'. Using default locations: target/site/jacoco/jacoco.xml,target/site/jacoco-it/jacoco.xml,build/reports/jacoco/test/jacocoTestReport.xml

When I read the documentation, I understand it as Java 8 should be ok to use for the scanner:


Supported Platforms

Java

SonarQube scanners require version 8 or 11 of the JVM and the SonarQube server requires version 11. Versions beyond Java 11 are not officially supported.


This is how it looks in SonarQube Enterprise, as you can see we get some data, but are missing the code coverage:

Compared to the same branch in SonarQube Community:

Any idea on what do we need to do to get the code coverage working?

Hi @dwal and welcome to the community !

I’m not sure that this is related to the move to the Enterprise Edition, but from what i know, there’s a problem with the gradle task that doesn’t set the correct property for coverage (it will be corrected soon), so i suggest that you add it as a additionalProperties into your YAML file with
sonar.coverage.jacoco.xmlReportPaths

Let me know if that solves your problem.

Thanks !

Thanks for the reply, could you provide me with an example of this. Not sure on how to add additional properties and what to set the paths value to?

You can modify the SonarQubePrepare task as the following in your YAML

I have added this now:

steps:
- task: SonarQubePrepare@4
  displayName: 'SonarQube prepare'
  inputs:
    SonarQube: 'Sonar Test Enterprise'
    scannerMode: 'Other'
    extraProperties: |
      sonar.coverage.jacoco.xmlReportPaths=build/reports/jacoco/test/jacocoTestReport.xml

but still doesn’t seems to work, I get the same path problem message.

:sonarqube
SonarScanner will require Java 11 to run starting in SonarQube 8.x
No coverage report can be found with sonar.coverage.jacoco.xmlReportPaths='build/reports/jacoco/test/jacocoTestReport.xml'. Using default locations: target/site/jacoco/jacoco.xml,target/site/jacoco-it/jacoco.xml,build/reports/jacoco/test/jacocoTestReport.xml

When I build it locally this is how my build folder looks
image

When I look at the published artifacts in Azure DevOps I can’t seem to find the jacoco folder in build/reports/.
image

When I look in previous builds, when we used SonarQube Community Edititon v7.6, we also didn’t have a jacoco folder present in the published artifacts but then we got the code coverage reports in Sonar. Has something changed on how this integration works in SonarQube Enterprise Edititon v8.3.1?

The only thing that has changed is, i think, the fact that we do not support binary file (exec) for jacoco coverage anymore, you must now provide XML format.

Can you try maybe wildcard or an Agent env variable that may direct the search to the proper folder ? Like $(System.DefaultWorkingDirectory) for example.

I can see that we have a coverage report in Azure DevOps and that there is a folder created with a summary.xml that looks like the coverage xml

image

As you can see in the screenshot it is referring to the Code Coverage Report_125121 folder, so it seems to be created but not under the build/reports/ folder. Is this the expected way when showing it in Azure DevOps, that it is published under a specific folder?

I can see these lines in the build log:

:check
:build
:sonarqube
SonarScanner will require Java 11 to run starting in SonarQube 8.x
No coverage report can be found with sonar.coverage.jacoco.xmlReportPaths='build/reports/jacoco/test/jacocoTestReport.xml'. Using default locations: target/site/jacoco/jacoco.xml,target/site/jacoco-it/jacoco.xml,build/reports/jacoco/test/jacocoTestReport.xml

Deprecated Gradle features were used in this build, making it incompatible with Gradle 5.0.
See https://docs.gradle.org/4.6/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 2m 47s
20 actionable tasks: 19 executed, 1 up-to-date
Reading code coverage summary from '/home/vsts/work/1/s/CCReport43F6D5EF/summary.xml'
Async Command Start: Upload Artifact
Uploading 3 files
File upload succeed.
Upload '/home/vsts/work/1/a/.codeAnalysis/CA' to file container: '#/9939294/Code Analysis Results'
Associated artifact 129005 with build 125121
Async Command End: Upload Artifact
Async Command Start: Publish test results
Publishing test results to test run '1129562'
Test results remaining: 164. Test run id: 1129562
Published Test Run : https://tfsprodweu3.visualstudio.com/XXXX/_TestManagement/Runs?runId=1129562&_a=runCharts
Async Command End: Publish test results
Async Command Start: Publish code coverage
Publishing coverage summary data to TFS server.
 Instruction- 5216 of 8313 covered.
 Branch- 364 of 674 covered.
 Line- 1165 of 1907 covered.
 Complexity- 480 of 941 covered.
 Method- 369 of 601 covered.
 Class- 96 of 124 covered.
Modifying Cobertura Index file
Publishing code coverage files to TFS server.
Uploading 308 files
Total file: 308 ---- Processed file: 81 (26%)
Total file: 308 ---- Processed file: 246 (79%)
File upload succeed.

As you can see it manages to publish it to Azure DevOps.

Ok, so now I think I have got it to work. I’m not so sure about the “hacky” solution, but seems to do the trick for now.

In short summary I found this line in the logs, which seems to refer to from where Azure DevOps is finding the summary.

Reading code coverage summary from '/home/vsts/work/1/s/CCReport43F6D5EF/summary.xml'

So I then set the property you referred to to this path, and then I got the code coverage visible in SonarQube Enterprise Edition

steps:
- task: SonarQubePrepare@4
  displayName: 'SonarQube prepare'
  inputs:
    SonarQube: 'Sonar Test Enterprise'
    scannerMode: 'Other'
    extraProperties: |
      sonar.coverage.jacoco.xmlReportPaths=$(System.DefaultWorkingDirectory)/CCReport43F6D5EF/summary.xml

Maybe you (@mickaelcaro) have an idea of why this works, and if it will work going forward? Seems like the local vs the Azure paths differ in regards to where the code coverage summary is placed by default…

Yes this will not change, since the path is hardcoded, this is the default place when you are using the Gradle task.

Glad it works then !

Thanks for the pointers and tips, helped me to pinpoint the issue :slight_smile:

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.