SourceLink breaks coverage report generation

ALM used

GitHub

CI system used

GitHub Actions

Scanner command used when applicable (private details masked)

Installed dotnet version is:

dotnet-install: Installed version is 7.0.100

Relevant workflow config:

    - name: Install sonar scanners
      run: |
        dotnet tool install --global dotnet-sonarscanner
    - name: Sonarqube begin
      run: |
        dotnet-sonarscanner begin \
        -o:myorg \
        -k:${{ env.SONAR_KEY }} \
        -d:sonar.login=${{ secrets.SONAR_TOKEN }} \
        -d:sonar.verbose=true \
        -v:${{ env.GITVERSION_FULLSEMVER }} \
        -s:${{ github.workspace }}/SonarQube.Analysis.xml
    - name: Build
      run: |
        dotnet build \
        --no-restore \
        --no-incremental \
        --configuration Release \
        -p:ContinuousIntegrationBuild=true \
        -p:DeterministicSourcePaths=true
    - name: Test
      run: |
        dotnet test \
        --no-restore \
        --settings coverlet.runsettings \
        --logger trx
    - name: Sonarqube end
      run: |
        dotnet-sonarscanner end \
        -d:sonar.login="${{ secrets.SONAR_TOKEN }}"

Scanner config

<?xml version="1.0" encoding="utf-8" ?>
<SonarQubeAnalysisProperties xmlns="http://www.sonarsource.com/msbuild/integration/2015/1">
  <Property Name="sonar.host.url">https://sonarcloud.io</Property>
  <Property Name="sonar.cs.vstest.reportsPaths">**/*.trx</Property>
  <Property Name="sonar.cs.opencover.reportsPaths">**/coverage.opencover.xml</Property>
</SonarQubeAnalysisProperties>

Languages of the repository

  • C#

Error observed

Coverage is skipped and no test and coverage results are uploaded to sonarcloud.io

11:11:23.407 INFO: Sensor C# Tests Coverage Report Import [csharp]
11:11:23.408 DEBUG: Analyzing coverage with wildcardPatternFileProvider with base dir '/home/runner/work/my-project/my-project/.' and file separator '/'.
11:11:23.409 DEBUG: Pattern matcher extracted prefix/absolute path '/home/runner/work/my-project/my-project/.' from the given pattern '**/*opencover.xml'.
11:11:23.410 DEBUG: Gathering files for wildcardPattern '**/*opencover.xml'.
11:11:23.423 DEBUG: Pattern matcher returns '2' files.
11:11:23.423 DEBUG: The current user dir is '/home/runner/work/my-project/my-project'.
11:11:23.424 INFO: Parsing the OpenCover report /home/runner/work/my-project/my-project/./CodeCoverage/_fv-az438-772_2023-03-07_11_10_50/In/fv-az438-772/coverage.opencover.xml
11:11:23.457 DEBUG: Did not find deterministic source path in 'https://raw.githubusercontent.com/my-org/my-project/8c4d6ca1c493abf9f9547f22b152e4b843271480/My.Proj/Entry.cs'. Will skip this coverage entry. Verify sonar.sources in .sonarqube\out\sonar-project.properties.
11:11:23.458 DEBUG: CoveredFile created: (ID '1', path 'https://raw.githubusercontent.com/my-org/my-project/8c4d6ca1c493abf9f9547f22b152e4b843271480/My.Proj/Entry.cs', NO INDEXED PATH).
11:11:23.459 DEBUG: Did not find deterministic source path in 'https://raw.githubusercontent.com/my-org/my-project/8c4d6ca1c493abf9f9547f22b152e4b843271480/My.Proj/Book.cs'. Will skip this coverage entry. Verify sonar.sources in .sonarqube\out\sonar-project.properties.
11:11:23.460 DEBUG: CoveredFile created: (ID '2', path 'https://raw.githubusercontent.com/my-org/my-project/8c4d6ca1c493abf9f9547f22b152e4b843271480/My.Proj/Book.cs', NO INDEXED PATH).
11:11:23.461 DEBUG: Did not find deterministic source path in 'https://raw.githubusercontent.com/my-org/my-project/8c4d6ca1c493abf9f9547f22b152e4b843271480/My.Proj/Side.cs'. Will skip this coverage entry. Verify sonar.sources in .sonarqube\out\sonar-project.properties.
11:11:23.462 DEBUG: CoveredFile created: (ID '3', path 'https://raw.githubusercontent.com/my-org/my-project/8c4d6ca1c493abf9f9547f22b152e4b843271480/My.Proj/Side.cs', NO INDEXED PATH).
11:11:23.463 DEBUG: Skipping the file (ID '1', path 'https://raw.githubusercontent.com/my-org/my-project/8c4d6ca1c493abf9f9547f22b152e4b843271480/My.Proj/Entry.cs', NO INDEXED PATH), line '66', visitCount '3' because file is not indexed or does not have the supported language.
11:11:23.464 DEBUG: Skipping the file (ID '1', path 'https://raw.githubusercontent.com/my-org/my-project/8c4d6ca1c493abf9f9547f22b152e4b843271480/My.Proj/Entry.cs', NO INDEXED PATH), line '67', visitCount '3' because file is not indexed or does not have the supported language.
11:11:23.465 DEBUG: Skipping the file (ID '1', path 'https://raw.githubusercontent.com/my-org/my-project/8c4d6ca1c493abf9f9547f22b152e4b843271480/My.Proj/Entry.cs', NO INDEXED PATH), line '68', visitCount '2' because file is not indexed or does not have the supported language.
11:11:23.465 DEBUG: Skipping the file (ID '1', path 'https://raw.githubusercontent.com/my-org/my-project/8c4d6ca1c493abf9f9547f22b152e4b843271480/My.Proj/Entry.cs', NO INDEXED PATH), line '69', visitCount '1' because file is not indexed or does not have the supported language.
11:11:23.466 DEBUG: Skipping the file (ID '1', path 'https://raw.githubusercontent.com/my-org/my-project/8c4d6ca1c493abf9f9547f22b152e4b843271480/My.Proj/Entry.cs', NO INDEXED PATH), line '70', visitCount '3' because file is not indexed or does not have the supported language.
11:11:23.467 DEBUG: OpenCover parser: Skipping branch hits for file (ID '1', path 'https://raw.githubusercontent.com/my-org/my-project/8c4d6ca1c493abf9f9547f22b152e4b843271480/My.Proj/Entry.cs', NO INDEXED PATH), line '67', offset '14', visitCount '2' because file is not indexed or does not have the supported language.
11:11:23.467 DEBUG: OpenCover parser: Skipping branch hits for file (ID '1', path 'https://raw.githubusercontent.com/my-org/my-project/8c4d6ca1c493abf9f9547f22b152e4b843271480/My.Proj/Entry.cs', NO INDEXED PATH), line '67', offset '14', visitCount '1' because file is not indexed or does not have the supported language.
.
.
.

11:11:23.660 INFO: Adding this code coverage report to the cache for later reuse: /home/runner/work/my-project/my-project/./CodeCoverage/ff090159-017d-437e-9b70-355c09cf120d/coverage.opencover.xml
11:11:23.660 DEBUG: Analyzing coverage after aggregate found '0' coverage files.
11:11:23.661 DEBUG: The total number of file count statistics is '0'.
11:11:23.661 INFO: Sensor C# Tests Coverage Report Import [csharp] (done) | time=254ms
11:11:23.661 INFO: Sensor C# Unit Test Results Import [csharp]
11:11:23.662 DEBUG: Pattern matcher extracted prefix/absolute path '/home/runner/work/my-project/my-project/.' from the given pattern '**/*.trx'.
11:11:23.662 DEBUG: Gathering files for wildcardPattern '**/*.trx'.
11:11:23.670 DEBUG: Pattern matcher returns '1' files.
11:11:23.679 DEBUG: The current user dir is '/home/runner/work/my-project/my-project'.
11:11:23.680 INFO: Parsing the Visual Studio Test Results file '/home/runner/work/my-project/my-project/./CodeCoverage/_fv-az438-772_2023-03-07_11_10_50.trx'.
11:11:23.682 DEBUG: Parsed Visual Studio Test Times - duration: 6497.
11:11:23.684 DEBUG: Parsed Visual Studio Test Counters - total: 29, failed: 0, errors: 0, timeout: 0, aborted: 0, executed: 29.
11:11:23.687 INFO: Sensor C# Unit Test Results Import [csharp] (done) | time=26ms
11:11:23.688 INFO: Sensor Zero Coverage Sensor
11:11:23.707 INFO: Sensor Zero Coverage Sensor (done) | time=19ms

Steps to reproduce

Run the command while Microsoft.SourceLink.GitHub is installed

      <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1">
        <PrivateAssets>all</PrivateAssets>
        <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      </PackageReference>

Potential workaround

Remove the SourceLink package from the reproduce step.
Setting -p:DeterministicSourcePaths=true to false does not fix the problem.

Additional information

Hello @mrt181 - this path seems very strange.

We expect _ to appear in the path of deterministic source paths.

Essentially, the path is a web URL and it’s not a file on disk, thus our scanner gets confused.

Can you create a small reproducer project that we can clone and reproduce this behavior locally?

This reproduces: Danek Duvall / sonar-sourcelink · GitLab. I just followed https://learn.microsoft.com/en-us/dotnet/core/testing/unit-testing-code-coverage?tabs=linux for the source, and added the CI config.

For now, I’m just using sed to remove the portion of the URL which is GitLab-specific, and that seems to be enough for Sonar. But I’d love not to have to do that.

1 Like

Hello @dhduvall,

Thank you for the reproducer, unfortunately, it seems we cannot access or see the source code.
Can you make sure we can access it?

Thank you,

Whoops. I got confused by one of the project settings. It should be fully accessible now.

Thanks,
Danek

Hello @dhduvall,

I was able to reproduce the issue with your reproducer; thank you for that.

You used the option --use-source-link when invoking Coverlet. From my understanding, this will generate the coverage report using source link URIs instead of system paths, as mentioned in their documentation here.

Today, sonar-scanner does not support URIs as the source input for file coverage.

If possible, I suggest you drop the option --use-source-link when using Coverlet to generate the coverage report. It will generate the coverage report with file system paths instead of URIs.

I hope this will resolve your issue.

1 Like

You used the option --use-source-link when invoking Coverlet.

I see. I had conflated source link and deterministic source paths. And after much wrangling, I discover that coverlet doesn’t support deterministic paths with an opencover report format, so it’s kind of moot for Sonar, AFAIK.

Thanks,
Danek

Hello @dhduvall - did you open an issue to coverlet about this?

I did not (somewhat surprisingly). I’ve now found an existing one, though, which seems to be the right fit for this issue: Support deterministic reports · Issue #1075 · coverlet-coverage/coverlet · GitHub

Also: Switch to use relative paths in OpenCover report · Issue #1315 · coverlet-coverage/coverlet · GitHub. Those were the top two hits in issues, and sufficiently relevant I didn’t dig further.

2 Likes