Skip to content

Commit

Permalink
Collect code coverage on CI (#471)
Browse files Browse the repository at this point in the history
* Update CI

* Use NetCorePublic-Pool

* Rename to Build.cmd

* Collect code coverage

* Suppress ContinuousIntegrationBuild

* Add debug messages

* Upload code coverage

* Suppress DeterministicSourcePaths instead

* Publish code coverage reports per job

* Remove single quotes
  • Loading branch information
nxtn authored and leculver committed Dec 27, 2019
1 parent 652aeb6 commit 6480630
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 6 deletions.
30 changes: 30 additions & 0 deletions .config/dotnet-tools.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"version": 1,
"isRoot": true,
"tools": {
"coverlet.console": {
"version": "1.6.0",
"commands": [
"coverlet"
]
},
"powershell": {
"version": "6.2.3",
"commands": [
"pwsh"
]
},
"codecov.tool": {
"version": "1.9.0",
"commands": [
"codecov"
]
},
"dotnet-reportgenerator-globaltool": {
"version": "4.3.9",
"commands": [
"reportgenerator"
]
}
}
}
File renamed without changes.
3 changes: 2 additions & 1 deletion Directory.Build.targets
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<Import Project="$(RepositoryEngineeringDir)Coverage.targets" Condition="'$(Coverage)' == 'true'" />
<Import Project="Sdk.targets" Sdk="Microsoft.DotNet.Arcade.Sdk" />
</Project>
</Project>
41 changes: 36 additions & 5 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,21 +51,36 @@ jobs:
-prepareMachine
$(_SignArgs)
$(_OfficialBuildIdArgs)
/p:Coverage=true
/p:DeterministicSourcePaths=false # tonerdo/coverlet#363
name: Build
displayName: Build
condition: succeeded()
- task: PublishBuildArtifacts@1
displayName: Publish Packages
inputs:
PathtoPublish: '$(Build.SourcesDirectory)/artifacts/packages'
PublishLocation: Container
ArtifactName: Packages_$(Agent.Os)_$(Agent.JobName)
pathtoPublish: '$(Build.SourcesDirectory)\artifacts\packages\$(_BuildConfig)'
artifactName: Packages_$(Agent.Os)_$(Agent.JobName)
continueOnError: true
condition: always()
- script: .dotnet\dotnet.exe tool run reportgenerator
"-reports:$(Build.SourcesDirectory)\src\*\coverage.cobertura.xml"
"-targetdir:$(Build.SourcesDirectory)\artifacts\coverage"
displayName: Generate Code Coverage Reports
- task: PublishBuildArtifacts@1
displayName: Publish Code Coverage Reports
inputs:
pathToPublish: '$(Build.SourcesDirectory)\artifacts\coverage'
artifactName: Coverage_$(Agent.Os)_$(Agent.JobName)
- task: PublishCodeCoverageResults@1
displayName: Publish Code Coverage
inputs:
codeCoverageTool: cobertura
summaryFileLocation: '$(Build.SourcesDirectory)\src\*\coverage.cobertura.xml'
- job: Linux
container: LinuxContainer
pool:
name: Hosted Ubuntu 1604
name: NetCorePublic-Pool
queue: BuildPool.Ubuntu.1604.Amd64.Open
strategy:
matrix:
debug:
Expand All @@ -76,6 +91,22 @@ jobs:
- script: eng/common/cibuild.sh
--configuration $(_BuildConfig)
--prepareMachine
/p:Coverage=true
/p:DeterministicSourcePaths=false # tonerdo/coverlet#363
name: Build
displayName: Build
condition: succeeded()
- script: .dotnet/dotnet tool run reportgenerator
"-reports:$(Build.SourcesDirectory)/src/*/coverage.cobertura.xml"
"-targetdir:$(Build.SourcesDirectory)/artifacts/coverage"
displayName: Generate Code Coverage Reports
- task: PublishBuildArtifacts@1
displayName: Publish Code Coverage Reports
inputs:
pathToPublish: '$(Build.SourcesDirectory)/artifacts/coverage'
artifactName: Coverage_$(Agent.Os)_$(Agent.JobName)
- task: PublishCodeCoverageResults@1
displayName: Publish Code Coverage
inputs:
codeCoverageTool: cobertura
summaryFileLocation: '$(Build.SourcesDirectory)/src/*/coverage.cobertura.xml'
98 changes: 98 additions & 0 deletions eng/Coverage.targets
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<Project>

<PropertyGroup>
<CoverageFormat Condition="'$(CoverageFormat)' == ''">cobertura</CoverageFormat>
<CoverageOutputPath Condition="'$(CoverageOutputPath)' == ''">coverage.cobertura.xml</CoverageOutputPath>
</PropertyGroup>

<PropertyGroup>
<CoverletId />
</PropertyGroup>

<Target Name="BeforeCollectCodeCoverage" BeforeTargets="RunTests">
<BeforeCollectCodeCoverageTask TestAssembly="%(TestToRun.Identity)" PipeName="%(TestToRun.Filename)">
<Output TaskParameter="CoverletId" PropertyName="CoverletId" />
</BeforeCollectCodeCoverageTask>
</Target>

<Target Name="AfterCollectCodeCoverage" AfterTargets="RunTests">
<AfterCollectCodeCoverageTask PipeName="%(TestToRun.Filename)" CoverletId="$(CoverletId)" />
<!-- <Exec Command="$(DotNetTool) tool run codecov -f '$(CoverageOutputPath)'" /> -->
</Target>

<UsingTask
TaskName="BeforeCollectCodeCoverageTask"
TaskFactory="RoslynCodeTaskFactory"
AssemblyName="Microsoft.Build.Tasks.Core">

<ParameterGroup>
<TestAssembly ParameterType="System.String" Required="true" />
<PipeName ParameterType="System.String" Required="true" />
<CoverletId ParameterType="System.Int32" Output="true" />
</ParameterGroup>

<Task>
<Using Namespace="System.Diagnostics" />
<Using Namespace="System.IO.Pipes" />
<Code>
Log.LogMessage(MessageImportance.High, $"Collecting code coverage for {PipeName} .");

using var coverlet = Process.Start(
@"$(DotNetTool)",
$@"tool run coverlet ""{TestAssembly}"" " +
@"--format $(CoverageFormat) " +
@"--output ""$(CoverageOutputPath)"" " +
@"--target ""$(DotNetTool)"" " +
@"--targetargs ""tool run pwsh " +
$"$server = [System.IO.Pipes.NamedPipeServerStream]::new('{PipeName}');" +
"$server.WaitForConnection();" +
"$server.ReadByte();" +
"$server.Disconnect();" +
"$server.WaitForConnection();" +
"$server.Disconnect();" +
@"""");
CoverletId = coverlet.Id;

Log.LogMessage(MessageImportance.High, $"Collecting code coverage for {PipeName} ..");

using var client = new NamedPipeClientStream(PipeName);
client.Connect();
client.WriteByte(0);

Log.LogMessage(MessageImportance.High, $"Collecting code coverage for {PipeName} ...");
</Code>
</Task>

</UsingTask>

<UsingTask
TaskName="AfterCollectCodeCoverageTask"
TaskFactory="RoslynCodeTaskFactory"
AssemblyName="Microsoft.Build.Tasks.Core">

<ParameterGroup>
<PipeName ParameterType="System.String" Required="true" />
<CoverletId ParameterType="System.Int32" Required="true" />
</ParameterGroup>

<Task>
<Using Namespace="System.Diagnostics" />
<Using Namespace="System.IO.Pipes" />
<Code>
Log.LogMessage(MessageImportance.High, $"Collecting code coverage for {PipeName} ....");

using var client = new NamedPipeClientStream(PipeName);
client.Connect();

Log.LogMessage(MessageImportance.High, $"Collecting code coverage for {PipeName} .....");

using var coverlet = Process.GetProcessById(CoverletId);
coverlet.WaitForExit();

Log.LogMessage(MessageImportance.High, $"Collecting code coverage for {PipeName} ......");
</Code>
</Task>

</UsingTask>

</Project>

0 comments on commit 6480630

Please sign in to comment.