Code Coverage percentage not uploading to SonarCloud

I am trying to upload the code coverage of a project for a C# project using the yaml file below. When the pipeline runs it ends in a success, and shows the code in the Sonar Cloud UI online, but the coverage report does not show up and says " A few extra steps are needed for SonarCloud to analyze your code coverage.

Set up coverage analysis".

I know the coverage is working properly as the coverage report shows up in Azure under the specific Pipeline run but does not show in Sonar Cloud. I have been through all of the documentation but can’t find anything that helps. Below is the yaml file, please let me know how I can get this to work.

trigger:
  - develop

pool:
  vmImage: 'ubuntu-latest'

variables:
  buildConfiguration: 'Debug'

steps:
  # Use .NET Core v8
  - task: UseDotNet@2
    displayName: 'Use .NET Core SDK 8.x'
    inputs:
      version: 8.x
      performMultiLevelLookup: true

  # Install NuGet
  - task: NuGetToolInstaller@0
    displayName: 'Install NuGet'
    inputs:
      versionSpec: '6.8.0'

  # restore all nuget packages. this task is dependant on the nuget.config file in the repository.
  # the nuget.config file is needed to include the tempworks application framework nuget feed.
  - task: NuGetCommand@2
    displayName: 'Restore project dependencies'
    inputs:
      command: 'restore'
      restoreSolution: '**/src/*.sln'
      feedsToUse: config
      nugetConfigPath: 'nuget.config'

  # Prepare SonarCloud using the Azure DevOps connection to SonarCloud
  - task: SonarCloudPrepare@2
    displayName: 'Prepare analysis configuration'
    inputs:
      SonarCloud: 'SonarCloud'
      organization: ******
      scannerMode: 'MSBuild'
      projectKey: ******
      projectName: ******
      extraProperties: |
        sonar.cs.vstest.reportsPaths='$(Agent.TempDirectory)/**/coverage.cobertura.xml'
        sonar.cs.vscoveragexml.reportsPaths='$(Agent.TempDirectory)/**/coverage.cobertura.xml
        sonar.verbose=true

  # build the project(s)
  - task: DotNetCoreCLI@2
    displayName: 'Build the projects - $(buildConfiguration)'
    inputs:
      command: 'build'
      arguments: '--configuration $(buildConfiguration)'
      #projects: '**/*.csproj'
      projects: '**/src/Webhooks/*.csproj'

  # The projects argument is set to '**/*.UnitTests.csproj'. This is because the unit test projects
  # are named with the convention of 'ProjectName.UnitTests.csproj'.
  # Collect code coverage data while running the tests
  # Specify in the runsettings file which DLLs to include and exclude
  - task: DotNetCoreCLI@2
    displayName: 'Execute Unit Tests'
    inputs:
      command: 'test'
      projects: '**/src/Webhooks.Tests/*.csproj'
      arguments: '--collect "XPlat Code Coverage"'
      
  # Run the SonarCloud Analyzer
  - task: SonarCloudAnalyze@2
    displayName: 'Run SonarCloud Analysis'

  #Publish SonarCloud results
  - task: SonarCloudPublish@2
    displayName: 'Publish results on build summary'
    inputs:
      pollingTimeoutSec: '300'

  # Publish the 'coverlet.collector' code coverage results from the build
  - task: PublishCodeCoverageResults@2
    inputs:
      summaryFileLocation: '$(Agent.TempDirectory)/**/coverage.cobertura.xml'

  # Ensure the code has enough test case coverage.
  - task: BuildQualityChecks@9
    displayName: 'Check build quality'
    inputs:
      checkCoverage: true
      coverageType: lines
      coverageThreshold: 0

  # veracode sca scan
  - task: Bash@3
    displayName: 'Veracode SCA scan'
    inputs:
      targetType: 'inline'
      script: |
          export SRCCLR_API_TOKEN=******
          export DEBUG="1"
          export SRCCLR_SKIP_DOTNET_RESTORE="true"
          curl -sSL https://download.sourceclear.com/ci.sh | bash -s -- scan --update-advisor
1 Like

Hey there.

I think you’re facing a bug that was already reported:

It only affects PRs/short-lived branches with no lines of code that can be covered by tests (0 new lines)

A fix is scheduled for an upcoming hardening sprint. You should be able to verify that coverage is read correctly by running an analysis (with coverage generated and passed to the scanner) on your main branch.

Not sure this is the same issue that I am facing. We were able to get this working by switching from ubuntu-latest to 'windows-latest`. We still want to be able to run this on ubuntu so I am working to try and get the .coverage files into .coveragexml files that can be uploaded to SonarCloud.

If the issue I am facing is the bug you described above I want to call out that it was logged and scheduled in April and it is almost September? Is there a time frame on that being fixed if this is the issue that you are speaking of.

I just confirmed this. We merged our pipeline into the main branch and ran the pipeline and the coverage is still only showing in Azure and not SonarCloud. When searching for the .coveragexml files I do not find any, so I believe this is an issue with running these tasks on Ubuntu and not on Windows. However, we want to run on Ubuntu due to the fact that Veracode can not run on Windows based Images.

In that case, what do the logs say about importing code coverage?

The logs say that in the SonarCloudPublish step SonarCloud is unable to find the the coverage files that are needed. We looked into this further and have found that .coverage files are being created, but there are not files that are created that are .coveragexml files which is what SonarCloudPublish uses to actually upload to SonarCloud. This is only occurring on ubuntu-latest, when we run the pipeline on windows-latest everything works and is created successfully. I can send you the logs we are seeing specifically but was wondering if based on our .yaml file above if you are able to recreate this issue.

We fixed it with the below changes. You should really add documentation on ubuntu-latest images and not just windows-latest. Having to dig around all of the community.sonarsource.com to find a random persons answer is not a good user experience at all.

trigger:
  - develop

pool:
  vmImage: 'ubuntu-latest'

variables:
  buildConfiguration: 'Release'

steps:
  # Use .NET Core v8
  - task: UseDotNet@2
    displayName: 'Use .NET Core SDK 8.x'
    inputs:
      version: 8.x
      performMultiLevelLookup: true

  # Install NuGet
  - task: NuGetToolInstaller@0
    displayName: 'Install NuGet'
    inputs:
      versionSpec: '6.8.0'

  # restore all nuget packages. this task is dependant on the nuget.config file in the repository.
  # the nuget.config file is needed to include the tempworks application framework nuget feed.
  - task: NuGetCommand@2
    displayName: 'Restore project dependencies'
    inputs:
      command: 'restore'
      restoreSolution: '**/src/*.sln'
      feedsToUse: config
      nugetConfigPath: 'nuget.config'

  # Prepare SonarCloud using the Azure DevOps connection to SonarCloud
  - task: SonarCloudPrepare@2
    displayName: 'Prepare analysis configuration'
    inputs:
      SonarCloud: ***
      organization: ***
      scannerMode: ***
      projectKey: ***
      projectName: ***
      extraProperties: |
        sonar.cs.vstest.reportsPaths=$(Agent.TempDirectory)/**/*.trx
        sonar.cs.opencover.reportsPaths = $(Agent.TempDirectory)/**/coverage.opencover.xml
        sonar.verbose=true

  # build the project(s)
  - task: DotNetCoreCLI@2
    displayName: 'Build the projects - $(buildConfiguration)'
    inputs:
      command: 'build'
      arguments: '--configuration $(buildConfiguration)'
      projects: '**/src/Webhooks/*.csproj'

  # The projects argument is set to '**/*.UnitTests.csproj'. This is because the unit test projects
  # are named with the convention of 'ProjectName.UnitTests.csproj'.
  # Collect code coverage data while running the tests
  # Specify in the runsettings file which DLLs to include and exclude
  - task: DotNetCoreCLI@2
    displayName: 'Execute Unit Tests'
    inputs:
      command: 'test'
      projects: '**/src/Webhooks.Tests/*.csproj'
      arguments: --collect:"XPlat Code Coverage" -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=opencover

      
  # Run the SonarCloud Analyzer
  - task: SonarCloudAnalyze@2
    displayName: 'Run SonarCloud Analysis'

  #Publish SonarCloud results
  - task: SonarCloudPublish@2
    displayName: 'Publish results on build summary'
    inputs:
      pollingTimeoutSec: '300'

  # Publish the 'coverlet.collector' code coverage results from the build
  - task: PublishCodeCoverageResults@2
    inputs:
      summaryFileLocation: $(Agent.TempDirectory)/**/coverage.opencover.xml

  # veracode sca scan
  - task: Bash@3
    displayName: 'Veracode SCA scan'
    inputs:
      targetType: 'inline'
      script: |
          export SRCCLR_API_TOKEN=***
          export SRCCLR_SKIP_DOTNET_RESTORE="true"
          curl -sSL https://download.sourceclear.com/ci.sh | bash -s -- scan --update-advisor```

Hey Thomas.

Thanks for the feedback. Are you referring to documentation in the product (the analysis tutorials) or in the docs? Basically – where did you get the windows-latest example from you’d expect to see a ubuntu-latest example?

Hey Colin,

The place I think that would be best suited for a second example would be here. .NET test coverage (sonarsource.com) This describes how to set up a basic windows-latest pipeline but does not have anything relating to the fact that if you want ubuntu-latest that there will be more changes required. I get that things may not work out of the box on a Linux operating system. At least describing that there are ways to get it running.

We also spun our wheels trying to look into why cobertura was not working successfully with Sonar Cloud. We finally found something in this community pages that said cobertura would not work with Sonar Cloud. Obviously, we ended up getting everything working so we have a pattern to use going forward. We were just frustrated with the lack of documentation and having to do multiple days of searching for a resolution. I would also suggest updating some of the documentation to use current Tasks. Most of the tasks listed use version 1, when in reality they are on newer versions now.

Hi Thomas,
Thanks for your input. We’ve created a documentation ticket internally to improve the documentation on the points you raised.