Blog
Integrate SonarCloud in your DevOps pipeline
This blog post describes how to integrate SonarCloud in your Azure DevOps Pipelines and GitHub Actions to do static analysis and verify code-coverage.
🌟 Intro
This blog post gives a quick intro on SonarCloud. The next chapters describe how to integrate the required SonarCloud steps in your CI/CD pipeline (GitHub Actions and Azure DevOps) in order to enable static analysis and code coverage for .NET projects.
🛡️ SonarCloud
SonarCloud is a cloud-based service that provides automated code analysis to help developers detect and fix quality and security issues in their codebase. It’s a tool widely used in software development for continuous inspection of code quality and code coverage, ensuring that applications are not only functioning but also maintainable, well tested and secure.
SonarCloud offers the following functionality:
- Automated Code Analysis: SonarCloud can automatically review code for bugs, vulnerabilities, and code smells across a wide range of programming languages (HTML, JavaScript, TypeScript, Java, C#, and many more).
- Continuous Integration Support: It easily integrates with CI/CD pipelines, facilitating continuous analysis with each new code commit, and works with popular systems like Azure DevOps, GitHub, GitLab, Bitbucket and more.
- Quality Gates: These are customizable rules that the code must pass before it can be merged into the main branch. This helps ensure that only code that meets certain quality standards is integrated.
- Security Scanning: The tool includes security scanning features to identify vulnerabilities within the code, helping to prevent potential security breaches.
- Reports and Metrics: It provides detailed reports and metrics on code quality, which can help teams monitor improvements over time and identify areas needing attention.
- Code Coverage: SonarCloud can provide insights in code coverage which can help developers maintain a good level of code quality.
⚙️ Create new project in SonarCloud
The following chapter describes how to set up SonarCloud for your (opensource)-project.
Create project in SonarCloud
Creating a new project in SonarCloud can be done in two ways:
- Manually
- Automatically
In this blog I’ll only describe the manual way, because the automatic integration works only with GitHub and not everyone has the project defined in GitHub.
Create Organization
First you need to create an organization in SonarCloud, this can be done like:

Remember the key, this key is the unique identifier of your organization. You will have to include it as a parameter when configuring your analysis.
Analyze new Project
The project key is a unique identifier for your project.
🚀 Integrate with DevOps
Before you can analyse your project, you need to retrieve the secret SonarCloud Token for this project which can be used in the pipelines later on.
Go to the main page from your project and click ‘With GitHub Actions’.
The screen shows the value for this secret token (blurred in this screenshot). Remember this token, it’s required in the next steps.
🛠️ .NET Tools
For analyzing your .NET core with SonarCloud, two dotnet tools are required:
- dotnet-sonarscanner
- dotnet-coverage
These two tools need to be installed during the Build and Test phase in your DevOps stage.
dotnet-sonarscanner
The SonarScanner for .NET is the recommended way to launch a SonarCloud analysis for Clean Code projects/solutions using a dotnet command as a build tool.
For more information see this link.
dotnet-coverage
Enables the cross-platform collection of code coverage data of a .NET unit test.
It is a command-line tool that integrates with the .NET CLI to provide code coverage analysis for .NET applications. It leverages various coverage engines (such as Coverlet) to instrument the code and collect coverage data during test execution.
In order to fully integrate your unit test project some additional libraries (Codecov, coverlet.msbuild and coverlet.collector) should be included in your unit test project:
<ItemGroup>
<PackageReference Include="Codecov" Version="1.13.0" />
<PackageReference Include="coverlet.msbuild" Version="3.2.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.2.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<!-- other libraries -->
</ItemGroup>In addition to adding the required libraries, some settings should be added to the test project collect code coverage in the correct format (opencover) during a test-run:
<PropertyGroup> <CollectCoverage>true</CollectCoverage> <CoverletOutputFormat>opencover</CoverletOutputFormat> </PropertyGroup>
Note that in my projects I still use the older opencover format, however this could also be cobertura.
When the test project is correctly updated and the dotnet-coverage is globally installed, the collect command can be used to collect the code coverage from a running unit-test.
It’s advised to export the code coverage results into xml-format and in case you have multiple test projects and want to include all code coverage results in SonarCloud, it’s recommended to specify a unique filename for the coverage report.
Example:
dotnet-coverage collect "dotnet test ./test/MyProject.Tests/MyProject.Tests.csproj" -f xml -o "my-coverage-1.xml" dotnet-coverage collect "dotnet test ./test/MyOtherProject.Tests/MyOtherProject.Tests.csproj" -f xml -o "my-coverage-2.xml"
🔢 Required steps
For analyzing a project, the following 4 steps are required:
- Begin: Execute a command to begin the analysis via SonarCloud. Note that it’s required to provide the Organization Key, Project Key, SonarCloud Token and Branch Name.
- Build: Build your solution or projects.
- Test: Run unit-tests including code coverage.
- End: Execute a command to end the analysis via SonarCloud and upload the results to SonarCloud.
In the next two chapters I’ll explain how to define these 4 steps in a GitHub Action or Azure DevOps pipeline.
🧩 Integrate with GitHub Actions
🔑 Define secret Sonar Token
Integrating with GitHub is easy, use the token from the previous step and follow the next steps:
- Navigate to your GitHub project and select the ‘Settings’ menu.
- Expand the ‘Secrets and variables’.
- Click ‘Actions’.
- Create a new secret named
SONAR_TOKENwith the correct value (the value you remembered from the “Integrate with DevOps” chapter).
📝 GitHub Actions
Create a new GitHub action named `ci.yml` and define the SonarCloud related tasks:
name: Build with Tests
on:
push:
pull_request:
types: [opened, reopened]
jobs:
build_and_test_Linux:
name: Build and run Tests on Linux
runs-on: ubuntu-latest
# ⭐ Make sure to get the branch name.
# It's required for correct branch analysis (e.g. code coverage)
env:
BranchName: ${69c71ee015543f17f{ github.head_ref || github.ref_name }69c71ee015543f17f}
steps:
# ⭐ Set fetch-depth to 0.
# Shallow clones should be disabled for a better relevancy of analysis.
- uses: actions/checkout@v4
with:
fetch-depth: 0
# ⭐ SonarCloud needs at least Java version 17
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
# ⭐ Install the dotnet-sonarscanner and dotnet-coverage tools
- name: Install dotnet tools
run: |
dotnet tool install --global dotnet-sonarscanner
dotnet tool install --global dotnet-coverage
# 1️⃣ Begin
- name: Begin analysis on SonarCloud
run: |
dotnet sonarscanner begin /k:"stef-test-organization_my-project" /o:"stef-test-organization" /d:sonar.branch.name=$BranchName /d:sonar.host.url="https://sonarcloud.io" /d:sonar.token=${69c71ee015543f17f{ secrets.SONAR_TOKEN }69c71ee015543f17f} /d:sonar.pullrequest.provider=github /d:sonar.dotnet.excludeTestProjects=true /d:sonar.cs.vscoveragexml.reportsPaths=**/my-coverage-*.xml
# 2️⃣ Build
- name: Build
run: |
dotnet build ./src/MyProject/MyProject.csproj -c Debug
# 3️⃣ Run Tests with Coverage
- name: Run Tests (with Coverage)
run: |
dotnet-coverage collect 'dotnet test ./test/MyProject.Tests/MyProject.Tests.csproj --configuration Debug' -f xml -o my-coverage-ef.xml
# 4️⃣ End
- name: End analysis on SonarCloud
run: |
dotnet sonarscanner end /d:sonar.token=${69c71ee015543f17f{ secrets.SONAR_TOKEN }69c71ee015543f17f}
🧩 Integrate with Azure DevOps
🔑 Define secret variable Sonar Token
Also for integrating with Azure DevOps, the token from the previous step is required. This token can be defined in your existing Azure DevOps pipeline as follows:
- Go to your Azure DevOps Pipeline.
- Click the ‘Variables’ button.
- 1. Click the ‘➕’ sign to a add a new variable.
- 2.When adding a new variable
SONAR_TOKENwith the secret value, make sure to add this variable as a secret.
📝 Azure Pipeline
Update your pipeline (`ci.yml`) and define the SonarCloud related tasks:
variables:
buildProjects: '**/src/**/*.csproj'
jobs:
- job: Linux_Build_Test_SonarCloud
pool:
vmImage: 'Ubuntu-latest'
steps:
# ⭐ SonarCloud needs at least Java version 17
# But it's only required to set the JAVA_HOME to the correct version.
# The Azure DevOps Ubuntu-latest vmImage already contains Java 17.
- task: PowerShell@2
displayName: "Use JDK17 by default"
inputs:
targetType: 'inline'
script: |
$jdkPath = $env:JAVA_HOME_17_X64
Write-Host "##vso[task.setvariable variable=JAVA_HOME]$jdkPath"
# ⭐ Install the dotnet-sonarscanner and dotnet-coverage tools
- script: |
dotnet tool install --global dotnet-sonarscanner
dotnet tool install --global dotnet-coverage
displayName: 'Install dotnet tools'
# 1️⃣ Begin
- script: |
dotnet sonarscanner begin /k:"stef-test-organization_my-project" /o:"stef-test-organization" /d:sonar.branch.name=$BranchName /d:sonar.host.url="https://sonarcloud.io" /d:sonar.token=${69c71ee015543f17f{ secrets.SONAR_TOKEN }69c71ee015543f17f} /d:sonar.pullrequest.provider=github /d:sonar.dotnet.excludeTestProjects=true /d:sonar.cs.vscoveragexml.reportsPaths=**/my-coverage-*.xml
displayName: 'Begin analysis on SonarCloud'
# 2️⃣ Build
- task: DotNetCoreCLI@2
displayName: 'Build Unit tests'
inputs:
command: 'build'
projects: './src/MyProject/MyProject.csproj'
arguments: '--configuration Debug --no-incremental'
# 3️⃣ Run Tests with Coverage
- task: CmdLine@2
inputs:
script: 'dotnet-coverage collect "dotnet test ./src/MyProject/MyProject.csproj --configuration Debug --no-build" -f xml -o "my-coverage.xml"'
displayName: 'Execute Unit Tests with Coverage'
# 4️⃣ End
- script: |
dotnet sonarscanner end /d:sonar.token="$(SONAR_TOKEN)"
displayName: 'End analysis on SonarCloud'
⚠️ Deprecated SonarCloud tasks for Azure Pipeline
It was also possible to use these 3 SonarCloud Azure DevOps related tasks:
- SonarCloudPrepare@1
- SonarCloudAnalyze@1
- SonarCloudPublish@1
But since 2024-06-11 and version 2.0.1, this has been deprecated.
For more details see this link.
💻 Demo
When everything is correctly setup in your pipeline, the SonarCloud static and security analysis and .NET Code Coverage should work correct for new branches:
And when clicking a specific branch, you see extra details related to issues, code coverage, duplications and security hotspots:
📌 Conclusion
In conclusion, integrating SonarCloud into your DevOps pipeline, whether GitHub Actions or Azure DevOps, significantly enhances the quality and security of your software projects.
By using SonarCloud’s automated code analysis and code coverage options, developers can ensure the codebase meets the high standards of quality (by enforcing quality gates related to code coverage) and security (by listing known security issues in the code).
My personal interest for writing this blog is that I was surprised last month by the deprecation of the SonarCloud Azure DevOps related tasks which I used in WireMock.Net.
🌐 Examples
GitHub Actions: System.Linq.Dynamic.Core
Azure DevOps: WireMock.Net
📝 Notes
Some content in this blog is created with the help of an AI. I reviewed and revised the content were needed.
Written by: Stef Heyenrath
Stef started writing software for the Microsoft .NET framework in 2007. Over the years, he has developed into a Microsoft specialist with experience in: backend technologies such as .NET, NETStandard, ASP.NET, Ethereum, Azure, and other cloud providers. In addition he worked with several frontend technologies such as Blazor, React, Angular, Vue.js.
He is the author from WireMock.Net.
Mission: Writing quality and structured software with passion in a scrum team for technically challenging projects.
Want to know more about our experts? Contact us!








