Closed mwwhited closed 2 years ago
I haven't worked with the other SourceLink versions so I don't know what it does to their URLs.. But for Azure DevOps (Microsoft.SourceLink.AzureRepos.Git) if you select all filename attributes that start with https://
//@filename[starts-with(.,'https://')] and take the path portion of the query string and combined it with the git repository root $(Build.SourcesDirectory) you will get the path to the source files. just updating these attributes to correct path will resolve these files correctly. I'm not sure if people would prefer to rewrite the coverage.cobertura.xml
files or just handle this within the reportgenerator... but I can say that correcting these paths will allow the tool to work as is.
Thanks for reporting this issue. I will have a look within the next days.
I tried to reproduce your issue.
I used this sample project: https://github.com/danielpalme/coveragesample
Then I added Microsoft.SourceLink.AzureRepos.Git
to all projects and changed the origin url to an Azure DevOps repository.
I executed the tests with:
dotnet test --collect:"XPlat Code Coverage"
The coverage.cobertura.xml
file still contains the local path.
What is different in your setup? Can you share a sample project?
That is really weird. I will have to take a look at trying to replicate this for you.
Have you been able to replicate the issue?
Unfortunately my project is in a private repository. It’s caused by using SourceLink for deploying symbols for private nuget packages into Azure DevOps Artifacts.
https://docs.microsoft.com/en-us/azure/devops/pipelines/artifacts/symbols?view=azure-devops
unless you have an azure devops pipeline I’m not sure how you can replicate the build.
I have a work around for me as I just wrote a tool to restore the paths before I the report generator runs. Might just have to mark this as can not replicate for now.
Setting up a DevOps pipeline would not be a problem. If you can share a (minimal) sample project with a YAML pipeline, I would have a look.
I am using Azure DevOps Artifacts for a private Nuget repository. Here is a sanitized version of our internal build script.
I also included a build script at the bottom that I use for local builds. Locally it has the same issue when trying to build the reports without the Internal.FixSourceLinks.Cli
dotnet tool (this is what I use to rewrite the coverage.cobertura.xml
to use local paths.
name: $(Date:yyyyMMdd)_$(Rev:rr)_CI
trigger:
branches:
include:
- main
pool:
vmImage: 'windows-latest'
stages:
- stage: stageBuild
displayName: Build Module
variables:
solution: 'src/SharedFramework/SharedFramework.sln'
buildConfiguration: 'Release'
nugetRepository: 'https://pkgs.dev.azure.com/internal-project/_packaging/Internal.Nuget/nuget/v3/index.json'
jobs:
- job: jobBuildSharedFramework
displayName: Build Shared Framework and Adapters
dependsOn: []
steps:
- checkout: self
clean: true
persistCredentials: true
- task: UseDotNet@2
inputs:
packageType: 'sdk'
version: '3.1.x'
- task: gitversion/setup@0
displayName: Install GitVersion
inputs:
versionSpec: '5.6.0'
- task: gitversion/execute@0
displayName: Use GitVersion
inputs:
useConfigFile: true
configFilePath: 'GitVersion.yml'
- script: |
echo FullSemVer=$(fullSemVer)
echo AssemblySemVer=$(AssemblySemVer)
echo AssemblySemFileVer=$(assemblySemFileVer)
echo InformationalVersion=$(InformationalVersion)
echo ##vso[build.updatebuildnumber]$(fullSemVer)
echo ##vso[task.setvariable variable=fullSemVer]$(fullSemVer)
echo ##vso[task.setvariable variable=InformationalVersion]$(InformationalVersion)
echo ##vso[task.setvariable variable=AssemblySemVer]$(AssemblySemVer)
echo ##vso[task.setvariable variable=assemblySemFileVer]$(assemblySemFileVer)
echo ##vso[task.setvariable variable=buildVersionTag]$(buildConfiguration)-v$(fullSemVer)
displayName: Set Variables
- task: NuGetAuthenticate@0
displayName: 'NuGet Authenticate'
- task: DotNetCoreCLI@2
displayName: Dotnet Restore for API Services and Azure Functions
inputs:
command: restore
projects: $(solution)
feedsToUse: 'select'
vstsFeed: 'INTERNAL-FEED-ID'
- task: DotNetCoreCLI@2
displayName: Dotnet Build for API Services and Azure Functions
inputs:
command: build
projects: $(solution)
arguments: '-c $(buildConfiguration) /p:Version=$(fullSemVer) --no-restore /p:SourceLinkCreate=true /p:ContinuousIntegrationBuild=true'
- task: DotNetCoreCLI@2
displayName: Run Unit Tests and Simulations as $(buildConfiguration)
inputs:
command: test
projects: $(solution)
arguments: '-c $(buildConfiguration) --no-build --no-restore --filter "TestCategory=Unit|TestCategory=Simulate" --collect:"XPlat Code Coverage" --nologo -s "$(Build.SourcesDirectory)\src\SharedFramework\.runsettings"'
publishTestResults: true
- task: DotNetCoreCLI@2
displayName: Package to Staging directory
inputs:
command: custom
custom: 'pack'
projects: $(solution)
arguments: '-c $(buildConfiguration) --no-build --no-restore -o $(Build.ArtifactStagingDirectory)/Packages /p:Version=$(fullSemVer)'
verbosityRestore: Minimal
verbosityPack: Minimal
feedsToUse: select
vstsFeed: personalnugetfeed
nuGetFeedType: internal
includeNuGetOrg: true
- task: NuGetAuthenticate@0
displayName: 'NuGet Authenticate again'
- script: |
dotnet nuget push --skip-duplicate --source $(nugetRepository) --api-key az $(Build.ArtifactStagingDirectory)\Packages\*.nupkg
displayName: 'NuGet Push Packages'
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
- task: DotNetCoreCLI@2
displayName: 'Install dotnet-reportgenerator-globaltool'
inputs:
command: custom
custom: tool
arguments: install --tool-path . dotnet-reportgenerator-globaltool
- task: PublishTestResults@2
displayName: 'Publish Test Results'
condition: always()
inputs:
testRunner: VSTest
testResultsFiles: '$(Agent.TempDirectory)/**/*.trx'
testRunTitle: '$(fullSemVer)'
failTaskOnFailedTests: true
# The reportgenerator is not compatible with SourceLinked coverage reports. This tool fixes the coverage.cobertura.xml so it is compatible with sourcelinked projects
- script: |
dotnet tool install Internal.FixSourceLinks.Cli --add-source=$(Build.ArtifactStagingDirectory)/Packages --version $(Build.BuildNumber)
dotnet fix-sourcelink --include=**\coverage.cobertura.xml --search=$(Agent.TempDirectory) --target=$(Build.SourcesDirectory)
displayName: 'Fix up coverage.cobertura.xml to resolve SourceLinks'
- script: 'reportgenerator "-reports:$(Agent.TempDirectory)/**/coverage.cobertura.xml" "-targetDir:$(Agent.TempDirectory)/TestResults/Coverage/Reports" -tag:$(Build.BuildNumber) -reportTypes:HtmlSummary;Cobertura "-title:Results for API Services & Azure Functions - $(buildConfiguration)-v$(Build.BuildNumber)"'
displayName: 'Create Code Coverage Reports'
- task: PublishCodeCoverageResults@1
displayName: 'Publish Code Coverage Reports'
inputs:
codeCoverageTool: 'cobertura'
summaryFileLocation: $(Agent.TempDirectory)/TestResults/Coverage/Reports/Cobertura.xml
failIfCoverageEmpty: false
- task: PublishSymbols@2
displayName: 'Publish Symbols'
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
inputs:
SearchPattern: '**/bin/**/*.pdb'
IndexSources: false
SymbolServerType: 'TeamServices'
TreatNotIndexedAsWarning: true
- task: tagBuildOrRelease@0
displayName: 'Tag Build'
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
inputs:
type: 'Build'
tags: '$(buildVersionTag)'
- script: |
git config --global user.name "AzureDevOps Agent"
git tag "$(buildVersionTag)" --force
git push origin "$(buildVersionTag)" --force
echo "Tagging $(Build.Repository.Name) with $(buildVersionTag)"
displayName: 'Tag Branch'
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<RunConfiguration>
<MaxCpuCount>10</MaxCpuCount>
</RunConfiguration>
<!--Configurations for data collectors-->
<DataCollectionRunSettings>
<DataCollectors>
<DataCollector friendlyName="XPlat code coverage">
<Configuration>
<!--Obsolete,GeneratedCodeAttribute,-->
<ExcludeByAttribute>ExcludeFromCodeCoverageAttribute</ExcludeByAttribute>
<Exclude>[coverlet.*.tests?]*,[*]Coverlet.Core*,[Internal.*.Contracts?]*,[Internal.*.Entities?]*</Exclude>
<Format>cobertura</Format>
<SingleHit>false</SingleHit>
<UseSourceLink>true</UseSourceLink>
<IncludeTestAssembly>false</IncludeTestAssembly>
<SkipAutoProps>true</SkipAutoProps>
</Configuration>
</DataCollector>
</DataCollectors>
</DataCollectionRunSettings>
<InProcDataCollectionRunSettings>
<InProcDataCollectors>
<InProcDataCollector assemblyQualifiedName="Coverlet.Collector.DataCollection.CoverletInProcDataCollector, coverlet.collector, Version=1.1.0.0, Culture=neutral, PublicKeyToken=null"
friendlyName="XPlat Code Coverage"
enabled="True"
codebase="coverlet.collector.dll" />
</InProcDataCollectors>
</InProcDataCollectionRunSettings>
<LoggerRunSettings>
<Loggers>
<Logger friendlyName="console" enabled="True">
<Configuration>
<Verbosity>normal</Verbosity>
</Configuration>
</Logger>
<Logger friendlyName="trx" enabled="True">
</Logger>
</Loggers>
</LoggerRunSettings>
<!-- MSTest adapter -->
<MSTest>
<MapInconclusiveToFailed>false</MapInconclusiveToFailed>
<CaptureTraceOutput>true</CaptureTraceOutput>
<DeleteDeploymentDirectoryAfterTestRunIsComplete>false</DeleteDeploymentDirectoryAfterTestRunIsComplete>
<DeploymentEnabled>true</DeploymentEnabled>
<DeployTestSourceDependencies>true</DeployTestSourceDependencies>
</MSTest>
</RunSettings>
<Project>
<PropertyGroup>
<NoWarn>NU1603</NoWarn>
<IsTestProject>$(ProjectName.EndsWith('.Tests'))</IsTestProject>
<IsContractProject>$(ProjectName.EndsWith('.Contracts'))</IsContractProject>
</PropertyGroup>
<PropertyGroup Condition="'$(IsTestProject)'!='True'">
<IsPackable>true</IsPackable>
<PackAsTool>false</PackAsTool>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedAllSources>true</EmbedAllSources>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<GenerateDocumentationFile>false</GenerateDocumentationFile>
<Nullable>enable</Nullable>
</PropertyGroup>
<Target Name="isNotTest" BeforeTargets="CoreBuild" Condition="'$(IsTestProject)'!='True'">
<Message Text="===== Project: $(Configuration) - $(ProjectName)" Importance="high"/>
</Target>
<ItemGroup Condition="'$(IsTestProject)'!='True'">
<PackageReference Include="Microsoft.SourceLink.AzureRepos.Git" Version="1.1.0-beta-20204-02" PrivateAssets="All"/>
</ItemGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<DebugType>full</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<Content Include="**\*.md" />
<Content Include="**\*.plantuml" />
<Content Include="**\*.puml" />
<EmbeddedResource Include="**\*.txt" />
<EmbeddedResource Include="**\*.json" />
<EmbeddedResource Include="**\*.html" />
<EmbeddedResource Include="**\*.csv" />
<EmbeddedResource Include="**\*.sql" />
<EmbeddedResource Remove="bin\**\*.*" />
<EmbeddedResource Remove="obj\**\*.*" />
</ItemGroup>
</Project>
assembly-versioning-scheme: MajorMinorPatch
assembly-file-versioning-scheme: MajorMinorPatchTag
assembly-informational-format: '{CommitDate}-{FullSemVer}'
mode: Mainline
branches:
master:
regex: main
increment: Patch
@echo off
SETLOCAL
SET TestProject=SharedFramework.sln
SET Configuration=Release
IF NOT "%1"=="" IF NOT "%TestFilter%"=="" SET TestFilter=
:check_again
IF "%1"=="" GOTO ready_to_run
SET temp_filter=%1
IF "%TestFilter%"=="" (
SET TestFilter=TestCategory=%temp_filter%
) ELSE (
SET TestFilter=%TestFilter%^|TestCategory=%temp_filter%
)
SHIFT
GOTO check_again
:ready_to_run
IF "%TestFilter%"=="" SET TestFilter=TestCategory=Unit^|TestCategory=Simulate
ECHO "%TestFilter%"
dotnet tool install --global dotnet-reportgenerator-globaltool 2>NUL
rmdir /s/q ".\TestResults"
dotnet test "%TestProject%" --configuration %Configuration% -r .\TestResults --nologo -s .runsettings --filter "%TestFilter%"
SET TEST_ERR=%ERRORLEVEL%
dotnet pack "Internal.FixSourceLinks.Cli" --configuration Release -o "Publish\Nuget"
dotnet tool install Internal.FixSourceLinks.Cli --add-source=Publish\Binary --version 1.0.0
dotnet fix-sourcelink --include=.\TestResults\**\coverage.cobertura.xml --target=..\..
dotnet tool uninstall Internal.FixSourceLinks.Cli
reportgenerator "-reports:.\TestResults\**\coverage.cobertura.xml" "-targetDir:.\TestResults\Coverage\Reports" -reportTypes:HtmlSummary;Cobertura "-title:%TestProject% - (%USERNAME%)"
start .\TestResults\Coverage\Reports\summary.html
ECHO TEST_ERR=%TEST_ERR%
IF "%TEST_ERR%"=="0" (
ECHO "No Errors :)"
)
ENDLOCAL
I created a sample project and published it here: https://dev.azure.com/danielpalme/_git/SharedFramework
I'm not able to reproduce the problem, when I run LocalTestRunner.bat
on my machine.
Closing this for now. Feel free to reopen if you can provide further information.
Describe the bug When the csproj files reference SourceLinks the filename attributes in the coverage.cobertura.xml are generated to match the related source control system. This is causing the build to try to access the files a URL instead of a simple filepath which in may receive an internal server error 500.
To Reproduce Add the following to any of the csprog files in your referenced solution