As mentioned in the linked blog post and in the official SonarCloud docs, code coverage reporting works out of the box if and only if your .NET build is running on Windows agents. If you are running your .NET build on Linux agents, some adjustments are required.
To make SonarCloud code coverage reporting work on Azure DevOps Microsoft-hosted linux agents, I will make use of .NET tool scanner variant dotnet-coverage (for more details, see here).
I will reuse the YAML pipeline files of the blog post linked above and highlight the necessary adjustments in the code snippets.
ArbitrarySolution-quality.yml
Due to the usage of dotnet-coverage, it’s no longer possible to use Azure DevOps pipeline task UseDotNet@2 for executing the tests. And because dotnet-coverage does not support multiple projects nor wildcards, I pass the solution folder instead.
name: ArbitrarySolution Quality Pipeline
# pipeline gets triggered on every commit to dev or main branch, if there are changes in src and/or deploy directory
trigger:
branches:
include:
- dev
- main
paths:
include:
- src
- deploy
# as we are using yarn (v3.6.3), we specify the folder for the yarn cache
variables:
YARN_CACHE_FOLDER: "$(Pipeline.Workspace)/.yarn"
CI: true
stages:
- stage: Quality
displayName: Quality Build
pool:
vmImage: ubuntu-latest
jobs:
- template: jobs-build-quality.yml
parameters:
dotNetBuildProjects: "**/*.sln"
dotNetSolutionFolder: "/home/vsts/work/1/s/"
jobs-build-quality.yml
The solution folder is the referred as base path for sonar.cs.vscoveragexml.reportsPaths and as directory in the dotnet test command. Note that the dotnet test command is now passed as an argument to the dotnet-coverage collect command.
parameters:
- name: dotNetBuildProjects
type: string
default: "**/*.sln"
- name: dotNetSolutionFolder
type: string
- name: buildConfiguration
type: string
default: "Release"
- name: "clientPath"
type: string
default: "src/Client"
jobs:
- job: Build
displayName: Quality Build ArbitrarySolution
pool:
vmImage: ubuntu-latest
steps:
- checkout: self
fetchDepth: 0 # disable shallow fetch to avoid SCM warnings in SonarCloud (see https://learn.microsoft.com/en-us/azure/devops/pipelines/yaml-schema/steps-checkout?view=azure-pipelines#shallow-fetch)
- task: UseDotNet@2
displayName: Get DotNet SDK
inputs:
packageType: sdk
useGlobalJson: true # .NET version is specified in global.json file which resides in the repository root
- task: SonarCloudPrepare@2
displayName: "Prepare analysis configuration"
inputs:
SonarCloud: "AZ_DEVOPS_SERVICE_CONNECTION_NAME_HERE"
organization: NAME_OF_THE_SONARCLOUD_ORGANIZATION_HERE
projectKey: SONARCLOUD_PROJECT_KEY_HERE # if project already exists in SonarCloud, get the project key from the project settings
extraProperties: |
scm.provider=git
sonar.cs.vscoveragexml.reportsPaths=${{parameters.dotNetSolutionFolder}}/coverage.xml
- task: DotNetCoreCLI@2
displayName: Build ArbitrarySolution Backend
inputs:
command: build
projects: ${{parameters.dotNetBuildProjects}}
arguments: "--configuration ${{parameters.buildConfiguration}}"
- script: dotnet tool install --global dotnet-coverage
displayName: Install dotnet-coverage
- script: dotnet-coverage collect "dotnet test ${{parameters.dotNetSolutionFolder}} --configuration ${{parameters.buildConfiguration}}" -f xml -o "coverage.xml"
displayName: Test ArbitrarySolution Backend
- task: NodeTool@0
inputs:
versionSpec: "18.17.x"
- task: Bash@3
displayName: Yarn - Install
inputs:
targetType: inline
workingDirectory: ${{parameters.clientPath}}
script: |
yarn set version 3.6.3
- task: Bash@3
displayName: Yarn - Install NPM packages
inputs:
targetType: inline
workingDirectory: ${{parameters.clientPath}}
script: |
yarn install --immutable
- task: Bash@3
displayName: Yarn - Run jest
inputs:
targetType: inline
workingDirectory: ${{parameters.clientPath}}
script: |
yarn test-ci
- task: SonarCloudAnalyze@2
displayName: SonarCloud - Run code analysis
- task: SonarCloudPublish@2
displayName: SonarCloud - Publish quality gate result
That’s it. Please note that only the changed or added lines of code are taken into account for the calculation of code coverage in pull request analyses!


Leave a Reply