I'm trying to analyze code coverage in SonarQube for a .NET project using GitLab CI/CD. My setup is:
- Windows runner for tests
- Linux container for SonarQube analysis
- ReportGenerator for coverage reports
- dotnet-coverage for test coverage collection
Problem: Even though my tests are running successfully and generating coverage reports, SonarQube shows 0% coverage. In the logs, I see multiple messages like:
DEBUG: The file 'F:\Projects\MyProject\builds\xyz\project\MyFile.cs' does not have a deterministic build path and is either not indexed or does not have a supported language. Will skip this coverage entry.
What I've tried:
- Using different coverage report formats
- Setting various SonarQube properties
- Checking file paths in the coverage report
Configuration:
My .gitlab-ci.yml
test job looks like this:
test:
stage: test
tags:
- windows
script:
- dotnet test --collect:"XPlat Code Coverage"
And my SonarQube job:
sonarqube:
stage: sonar
image: mcr.microsoft/dotnet/sdk:9.0
script:
- dotnet sonarscanner begin
/d:sonar.cs.opencover.reportsPaths="${CI_PROJECT_DIR}/TestResults/coverage.xml"
How can I get SonarQube to correctly recognize and display the code coverage from my Windows runner?
I tried multiple approaches to resolve this issue:
First, I attempted using different coverage report formats (Cobertura, OpenCover) with
dotnet test --collect
, expecting SonarQube to recognize at least one of these formats, but it always showed 0% coverage.Then, I switched to
dotnet-coverage
and ReportGenerator, expecting the combination of these tools to generate a compatible report format. While the reports were generated successfully, SonarQube still couldn't process them correctly due to the Windows/Linux path discrepancy.I also tried various SonarQube configuration properties like:
sonar.cs.opencover.reportsPaths
sonar.sources
sonar.tests
Expected behavior: SonarQube should display the actual code coverage percentage from my tests, which I know are running successfully because I can see the coverage results locally.
Actual result: SonarQube shows 0% coverage and logs show "file is not indexed" errors, apparently due to path incompatibility between Windows runner and Linux container.
I'm trying to analyze code coverage in SonarQube for a .NET project using GitLab CI/CD. My setup is:
- Windows runner for tests
- Linux container for SonarQube analysis
- ReportGenerator for coverage reports
- dotnet-coverage for test coverage collection
Problem: Even though my tests are running successfully and generating coverage reports, SonarQube shows 0% coverage. In the logs, I see multiple messages like:
DEBUG: The file 'F:\Projects\MyProject\builds\xyz\project\MyFile.cs' does not have a deterministic build path and is either not indexed or does not have a supported language. Will skip this coverage entry.
What I've tried:
- Using different coverage report formats
- Setting various SonarQube properties
- Checking file paths in the coverage report
Configuration:
My .gitlab-ci.yml
test job looks like this:
test:
stage: test
tags:
- windows
script:
- dotnet test --collect:"XPlat Code Coverage"
And my SonarQube job:
sonarqube:
stage: sonar
image: mcr.microsoft/dotnet/sdk:9.0
script:
- dotnet sonarscanner begin
/d:sonar.cs.opencover.reportsPaths="${CI_PROJECT_DIR}/TestResults/coverage.xml"
How can I get SonarQube to correctly recognize and display the code coverage from my Windows runner?
I tried multiple approaches to resolve this issue:
First, I attempted using different coverage report formats (Cobertura, OpenCover) with
dotnet test --collect
, expecting SonarQube to recognize at least one of these formats, but it always showed 0% coverage.Then, I switched to
dotnet-coverage
and ReportGenerator, expecting the combination of these tools to generate a compatible report format. While the reports were generated successfully, SonarQube still couldn't process them correctly due to the Windows/Linux path discrepancy.I also tried various SonarQube configuration properties like:
sonar.cs.opencover.reportsPaths
sonar.sources
sonar.tests
Expected behavior: SonarQube should display the actual code coverage percentage from my tests, which I know are running successfully because I can see the coverage results locally.
Actual result: SonarQube shows 0% coverage and logs show "file is not indexed" errors, apparently due to path incompatibility between Windows runner and Linux container.
Share Improve this question asked Mar 19 at 12:08 GreenstuffGreenstuff 315 bronze badges1 Answer
Reset to default 2After a lot of trial and error, I found a solution to this problem. The issue occurs because the coverage report generated on Windows contains Windows-style paths, but SonarQube running in a Linux container expects Linux-style paths.
Solution Overview
- Use
dotnet-coverage
instead ofdotnet test --collect
- Convert the coverage report to OpenCover format using ReportGenerator (requires a license)
- Transform Windows paths to Linux paths in the coverage report
Complete Working Configuration
Here's the working configuration:
stages:
- build
- test
- sonar
variables:
SONAR_HOST_URL: "https://your-sonarqube-url"
SONAR_TOKEN: ${SONAR_TOKEN}
REPORTGENERATOR_LICENSE: ${REPORTGENERATOR_LICENSE}
test:
stage: test
tags:
- windows
script:
# Generate coverage report using dotnet-coverage
- dotnet-coverage collect --output TestResults\coverage.xml --output-format cobertura -- dotnet test
# Convert to OpenCover format using ReportGenerator
- reportgenerator -reports:"TestResults\coverage.xml"
-targetdir:"TestResults\coverage-report"
-reporttypes:"OpenCover"
-sourcepath:"${CI_PROJECT_DIR}"
-license:"$REPORTGENERATOR_LICENSE"
# Convert Windows paths to Linux paths in the coverage report
- $content = Get-Content "TestResults\coverage-report\OpenCover.xml"
- $content = $content -replace 'F:\\Projets\\YourProject\\gitlab-runner-windows-386\\builds\\[^\\]+\\[^\\]+\\your-namespace\\your-project', '/builds/your-namespace/your-project'
- $content | Set-Content "TestResults\coverage-report\OpenCover.xml"
artifacts:
when: always
paths:
- TestResults/
expire_in: 1 week
sonarqube:
stage: sonar
image: mcr.microsoft/dotnet/sdk:9.0
script:
- dotnet sonarscanner begin
/k:"Your-Project-Key"
/d:sonar.token="$SONAR_TOKEN"
/d:"sonar.host.url=$SONAR_HOST_URL"
/d:"sonar.cs.opencover.reportsPaths=${CI_PROJECT_DIR}/TestResults/coverage-report/OpenCover.xml"
/d:sonar.cs.opencover.reportPaths.relative=true
/d:sonar.sources=YourSourceFolder
/d:sonar.tests=YourTestFolder
/d:sonar.exclusions="**/obj/**,**/bin/**,**/*.xaml,**/*.resx,**/*.config,**/*.json,**/*.md,**/*.bat,**/*.ps1,**/.nuget/**,**/packages/**"
/d:sonar.test.exclusions="**/obj/**,**/bin/**,**/.nuget/**,**/packages/**"
/d:sonar.projectBaseDir="${CI_PROJECT_DIR}"
/d:sonar.sourceEncoding=UTF-8
- dotnet build YourProject.csproj -c Debug
- dotnet sonarscanner end /d:sonar.token="$SONAR_TOKEN"
Key Points to Note
1. Prerequisites
- A valid ReportGenerator license
- Windows runner for tests
- Linux container for SonarQube analysis
2. Important Steps
- Use
dotnet-coverage
to generate the initial coverage report - Convert to OpenCover format using ReportGenerator
- Transform Windows paths to Linux paths using PowerShell
- Use relative paths in SonarQube configuration
3. Path Conversion
- Modify the
-replace
regex pattern to match your project's path structure - The pattern should convert from your Windows runner path to the Linux container path
4. SonarQube Configuration
- Set
sonar.cs.opencover.reportPaths.relative=true
- Explicitly specify source and test directories
- Exclude unnecessary files to avoid analysis issues
This solution resolves the "file is not indexed" error and ensures that SonarQube correctly displays code coverage when using a Windows runner for tests and a Linux container for analysis.
Troubleshooting
If you still have issues:
- Verify that your ReportGenerator license is valid
- Check that the path conversion regex matches your project structure
- Ensure the coverage report is correctly generated and converted
- Verify that the paths in the final OpenCover.xml file use Linux-style paths