MicrosoftPremier / VstsExtensions

Documentation and issue tracking for Microsoft Premier Services Visual Studio Team Services Extensions
MIT License
59 stars 14 forks source link

Using PublishCodeCoverageResults@2 Causes BuildQualityChecks@9 To Spin #223

Closed aolszowka closed 10 months ago

aolszowka commented 1 year ago

Describe the context

Describe the problem and expected behavior After upgrading to PublishCodeCoverageResults@2 the BuildQualityChecks@9 Spins with the following output:

2023-10-10T21:40:16.1462266Z ##[section]Starting: Code Coverage Gate
2023-10-10T21:40:16.1471221Z ==============================================================================
2023-10-10T21:40:16.1471345Z Task         : Build Quality Checks
2023-10-10T21:40:16.1471440Z Description  : Breaks a build based on quality metrics like number of warnings or code coverage.
2023-10-10T21:40:16.1471649Z Version      : 9.0.1
2023-10-10T21:40:16.1471708Z Author       : Microsoft
2023-10-10T21:40:16.1471790Z Help         : [[Docs]](https://github.com/MicrosoftPremier/VstsExtensions/blob/master/BuildQualityChecks/en-US/overview.md)
2023-10-10T21:40:16.1471911Z ==============================================================================
2023-10-10T21:40:16.8371153Z Using IdentifierJobResolver
2023-10-10T21:40:16.8862506Z Validating code coverage policy...
2023-10-10T21:40:20.0504482Z Waiting for code coverage data...
[Repeats Several Tens of Times]
2023-10-10T21:50:11.2878104Z Waiting for code coverage data...
2023-10-10T21:50:13.6916199Z Waiting for code coverage data...
2023-10-10T21:50:16.1159988Z Waiting for code coverage data...
2023-10-10T21:50:17.4905551Z [WARNING] Unable to get code coverage data within the maximum wait time.
2023-10-10T21:50:17.5018069Z ##[warning]Unable to get code coverage data within the maximum wait time.
2023-10-10T21:50:17.5033083Z Total line: 0
2023-10-10T21:50:17.5035433Z Covered line: 0
2023-10-10T21:50:17.5037561Z Code Coverage (%): 0
2023-10-10T21:50:17.6332274Z [WARNING] The baseline build could not be found. All policies based on the previous build will pass.
2023-10-10T21:50:17.6336621Z ##[warning]The baseline build could not be found. All policies based on the previous build will pass.
2023-10-10T21:50:17.6343324Z [SUCCESS] Code coverage policy passed with 0% (0/0 line).
2023-10-10T21:50:17.6508935Z ##[section]Finishing: Code Coverage Gate

We believe this is the root cause of this persons issue as well; which was previously reported: https://github.com/MicrosoftPremier/VstsExtensions/issues/220 this user was able to work around it because they downgraded to PublishCodeCoverageResults@1.

We're seeing it now after upgrading to PublishCodeCoverageResults@2; we did this because we wanted to use the ability of the new task to combine multiple Cobertura results (See https://github.com/microsoft/azure-pipelines-tasks/issues/10353) without having to use the work around of ReportGenerator (https://github.com/danielpalme/ReportGenerator) to perform the combination ourselves.

However, in doing this we encountered the above.

Consider the following toy project layout (a zipped version is attached to this report and will also be emailed to the address provided) CodeCoverageCheck.zip:

Project Layout

|   azurepipeline.yml
|   CodeCoverageCheck.sln
|
+---CodeCoverageCheck
|       CodeCoverageCheck.csproj
|       CodeCoverageToy.cs
|
+---CodeCoverageCheck.Tests
|       CodeCoverageCheck.Tests.csproj
|       CodeCoverageToyTests.cs
|
+---CodeCoverageCheck.Tests2
|       CodeCoverageCheck.Tests2.csproj
|       CodeCoverageToy2Tests.cs
|
\---CodeCoverageCheck2
        CodeCoverageCheck2.csproj
        CodeCoverageToy2.cs

azurepipeline.yml

# This will be triggered by the gates
trigger: none

pool:
  vmImage: ubuntu-latest

steps:
  - task: DotNetCoreCLI@2
    displayName: 'dotnet test'
    inputs:
      command: 'test'
      projects: CodeCoverageCheck.sln
      arguments: '--collect:"XPlat Code Coverage"'
      publishTestResults: true

  - task: PublishCodeCoverageResults@2
    displayName: 'publish code coverage (dotnet)'
    inputs:
      summaryFileLocation: '$(Agent.TempDirectory)/**/coverage.cobertura.xml'
      failIfCoverageEmpty: true

  # See https://github.com/MicrosoftPremier/VstsExtensions/blob/master/BuildQualityChecks/en-US/CodeCoveragePolicy.md
  - task: BuildQualityChecks@9
    displayName: 'Code Coverage Gate'
    inputs:
      checkCoverage: true
      coverageFailOption: build
      coverageType: line
      treat0of0as100: false
      forceCoverageImprovement: false

CodeCoverageCheck.sln


Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.6.33815.320
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CodeCoverageCheck", "CodeCoverageCheck\CodeCoverageCheck.csproj", "{04596B9F-BE13-4FC3-ABFA-6B633F151487}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CodeCoverageCheck.Tests", "CodeCoverageCheck.Tests\CodeCoverageCheck.Tests.csproj", "{D309ECCB-1FAB-480C-B2AC-E0A7064B759B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCoverageCheck2", "CodeCoverageCheck2\CodeCoverageCheck2.csproj", "{83D8A43C-D1DF-4775-90A3-C513755982AD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCoverageCheck.Tests2", "CodeCoverageCheck.Tests2\CodeCoverageCheck.Tests2.csproj", "{4E49ADC7-8E2B-450A-BCE1-53EEACAF9227}"
EndProject
Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
                Debug|Any CPU = Debug|Any CPU
                Release|Any CPU = Release|Any CPU
        EndGlobalSection
        GlobalSection(ProjectConfigurationPlatforms) = postSolution
                {04596B9F-BE13-4FC3-ABFA-6B633F151487}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {04596B9F-BE13-4FC3-ABFA-6B633F151487}.Debug|Any CPU.Build.0 = Debug|Any CPU
                {04596B9F-BE13-4FC3-ABFA-6B633F151487}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {04596B9F-BE13-4FC3-ABFA-6B633F151487}.Release|Any CPU.Build.0 = Release|Any CPU
                {D309ECCB-1FAB-480C-B2AC-E0A7064B759B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {D309ECCB-1FAB-480C-B2AC-E0A7064B759B}.Debug|Any CPU.Build.0 = Debug|Any CPU
                {D309ECCB-1FAB-480C-B2AC-E0A7064B759B}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {D309ECCB-1FAB-480C-B2AC-E0A7064B759B}.Release|Any CPU.Build.0 = Release|Any CPU
                {83D8A43C-D1DF-4775-90A3-C513755982AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {83D8A43C-D1DF-4775-90A3-C513755982AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
                {83D8A43C-D1DF-4775-90A3-C513755982AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {83D8A43C-D1DF-4775-90A3-C513755982AD}.Release|Any CPU.Build.0 = Release|Any CPU
                {4E49ADC7-8E2B-450A-BCE1-53EEACAF9227}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {4E49ADC7-8E2B-450A-BCE1-53EEACAF9227}.Debug|Any CPU.Build.0 = Debug|Any CPU
                {4E49ADC7-8E2B-450A-BCE1-53EEACAF9227}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {4E49ADC7-8E2B-450A-BCE1-53EEACAF9227}.Release|Any CPU.Build.0 = Release|Any CPU
        EndGlobalSection
        GlobalSection(SolutionProperties) = preSolution
                HideSolutionNode = FALSE
        EndGlobalSection
        GlobalSection(ExtensibilityGlobals) = postSolution
                SolutionGuid = {5D7FE5F3-8CCA-4BE1-ABDD-A6DB744CBD3E}
        EndGlobalSection
EndGlobal

CodeCoverageCheck.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

CodeCoverageToy.cs

namespace CodeCoverageCheck
{
    public class CodeCoverageToy
    {
        public static string ToyFunction(int input)
        {
            if(input == 1)
            {
                return "Case 1";
            }
            else if(input == 2)
            {
                return "Case 2";
            }
            else
            {
                return "All Other Cases";
            }
        }
    }
}

CodeCoverageCheck.Tests.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="coverlet.collector" Version="6.0.0">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
    <PackageReference Include="xunit" Version="2.5.1" />
    <PackageReference Include="xunit.runner.visualstudio" Version="2.5.1">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\CodeCoverageCheck\CodeCoverageCheck.csproj" />
  </ItemGroup>

</Project>

CodeCoverageToyTests.cs

using Xunit;

namespace CodeCoverageCheck.Tests
{
    public class CodeCoverageToyTests
    {
        [Fact]
        public void CodeCoverageToy_ToyFunction_Case1()
        {
            string actual = CodeCoverageToy.ToyFunction(1);
            Assert.Equal("Case 1", actual);
        }
    }
}

CodeCoverageCheck.Tests2.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="coverlet.collector" Version="6.0.0">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
    <PackageReference Include="xunit" Version="2.5.1" />
    <PackageReference Include="xunit.runner.visualstudio" Version="2.5.1">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\CodeCoverageCheck2\CodeCoverageCheck2.csproj" />
  </ItemGroup>

</Project>

CodeCoverageToy2Tests.cs

using CodeCoverageCheck2;
using Xunit;

namespace CodeCoverageCheck.Tests2
{
    public class CodeCoverageToy2Tests
    {
        [Fact]
        public void CodeCoverageToy_AnotherToyFunction_Case1()
        {
            string actual = CodeCoverageToy2.AnotherToyFunction(1);
            Assert.Equal("Case 1", actual);
        }
    }
}

CodeCoverageCheck2.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

CodeCoverageToy2.cs

namespace CodeCoverageCheck2
{
    public class CodeCoverageToy2
    {
        public static string AnotherToyFunction(int input)
        {
            if (input == 1)
            {
                return "Case 1";
            }
            else if (input == 2)
            {
                return "Case 2";
            }
            else
            {
                return "All Other Cases";
            }
        }
    }
}

When running this in the pipeline we do see that coverage is reported (as seen in the screenshot below); however for some reason this extension does not pick up the report:

image

If you look at the output of the publish code coverage (dotnet) task you don't see the summary like you will in the work around below:

Starting: publish code coverage (dotnet)
==============================================================================
Task         : Publish code coverage results v2
Description  : Publish any of the code coverage results from a build
Version      : 2.225.0
Author       : Microsoft Corporation
Help         : https://docs.microsoft.com/azure/devops/pipelines/tasks/test/publish-code-coverage-results
==============================================================================
Found 4 result(s) matching pattern: /home/vsts/work/_temp/**/coverage.cobertura.xml
/home/vsts/work/_temp/8aded273-2586-44fd-a7f3-ace11401ad9c/coverage.cobertura.xml
/home/vsts/work/_temp/91b8cad9-b91a-4fb5-8871-1f5bcc94b4de/coverage.cobertura.xml
/home/vsts/work/_temp/_fv-az428-85_2023-10-10_21_40_06/In/fv-az428-85/coverage.cobertura.xml
/home/vsts/work/_temp/_fv-az428-85_2023-10-10_21_40_10/In/fv-az428-85/coverage.cobertura.xml
/home/vsts/work/_tasks/PublishCodeCoverageResults_2a7ebc54-c13e-490e-81a5-d7561ab7cd97/2.225.0/node_modules/coveragepublisher/CoveragePublisher/linux-x64/CoveragePublisher.Console /home/vsts/work/_temp/8aded273-2586-44fd-a7f3-ace11401ad9c/coverage.cobertura.xml /home/vsts/work/_temp/91b8cad9-b91a-4fb5-8871-1f5bcc94b4de/coverage.cobertura.xml /home/vsts/work/_temp/_fv-az428-85_2023-10-10_21_40_06/In/fv-az428-85/coverage.cobertura.xml /home/vsts/work/_temp/_fv-az428-85_2023-10-10_21_40_10/In/fv-az428-85/coverage.cobertura.xml --reportDirectory /home/vsts/work/_temp/6b029fbd-91e0-4142-a493-5f45929a64ab
2023-10-10T21:40:14: Loading report '/home/vsts/work/_temp/8aded273-2586-44fd-a7f3-ace11401ad9c/coverage.cobertura.xml' 1/4 in memory
2023-10-10T21:40:14: Preprocessing report
2023-10-10T21:40:14: Initiating parser for Cobertura
2023-10-10T21:40:14: Current Assembly: CodeCoverageCheck
2023-10-10T21:40:14: Finished parsing '/home/vsts/work/_temp/8aded273-2586-44fd-a7f3-ace11401ad9c/coverage.cobertura.xml' 1/4
2023-10-10T21:40:14: Loading report '/home/vsts/work/_temp/91b8cad9-b91a-4fb5-8871-1f5bcc94b4de/coverage.cobertura.xml' 2/4 in memory
2023-10-10T21:40:14: Starting merging result 1
2023-10-10T21:40:14: Preprocessing report
2023-10-10T21:40:14: Initiating parser for Cobertura
2023-10-10T21:40:14: Current Assembly: CodeCoverageCheck2
2023-10-10T21:40:14: Finished parsing '/home/vsts/work/_temp/91b8cad9-b91a-4fb5-8871-1f5bcc94b4de/coverage.cobertura.xml' 2/4
2023-10-10T21:40:14: Loading report '/home/vsts/work/_temp/_fv-az428-85_2023-10-10_21_40_06/In/fv-az428-85/coverage.cobertura.xml' 3/4 in memory
2023-10-10T21:40:14: Preprocessing report
2023-10-10T21:40:14: Initiating parser for Cobertura
2023-10-10T21:40:14: Current Assembly: CodeCoverageCheck2
2023-10-10T21:40:14: Finished merging result 1
2023-10-10T21:40:14: Starting merging result 2
2023-10-10T21:40:14: Finished parsing '/home/vsts/work/_temp/_fv-az428-85_2023-10-10_21_40_06/In/fv-az428-85/coverage.cobertura.xml' 3/4
2023-10-10T21:40:14: Loading report '/home/vsts/work/_temp/_fv-az428-85_2023-10-10_21_40_10/In/fv-az428-85/coverage.cobertura.xml' 4/4 in memory
2023-10-10T21:40:14: Finished merging result 2
2023-10-10T21:40:14: Starting merging result 3
2023-10-10T21:40:14: Preprocessing report
2023-10-10T21:40:14: Initiating parser for Cobertura
2023-10-10T21:40:14: Current Assembly: CodeCoverageCheck
2023-10-10T21:40:14: Finished parsing '/home/vsts/work/_temp/_fv-az428-85_2023-10-10_21_40_10/In/fv-az428-85/coverage.cobertura.xml' 4/4
2023-10-10T21:40:14: Parsing of 4 files completed
2023-10-10T21:40:14: Finished merging result 3
2023-10-10T21:40:14: Starting merging result 4
2023-10-10T21:40:14: Finished merging result 4
2023-10-10T21:40:14: Initializing report builders for report types: HtmlInline_AzurePipelines
2023-10-10T21:40:14: Analyzing 2 classes
2023-10-10T21:40:14: Creating report 1/2 (Assembly: CodeCoverageCheck, Class: CodeCoverageCheck.CodeCoverageToy)
2023-10-10T21:40:14: Writing report file 'CodeCoverageCheck_CodeCoverageToy.html'
2023-10-10T21:40:14: Creating report 2/2 (Assembly: CodeCoverageCheck2, Class: CodeCoverageCheck2.CodeCoverageToy2)
2023-10-10T21:40:14: Writing report file 'CodeCoverageCheck2_CodeCoverageToy2.html'
2023-10-10T21:40:14: Creating summary
2023-10-10T21:40:14: Writing report file '/home/vsts/work/_temp/6b029fbd-91e0-4142-a493-5f45929a64ab/index.html'
Publishing file coverage data.
Publishing code coverage HTML report.
Uploading 5 files.
File upload succeed.
Published '/home/vsts/work/_temp/6b029fbd-91e0-4142-a493-5f45929a64ab' as artifact 'Code Coverage Report_23'.
Finishing: publish code coverage (dotnet)

Work Around

While not ideal, you can fall back to the legacy PublishCodeCoverageResults@1, however doing so requires you to convert back to using ReportGenerator to pick up the multiple reports, an example of this working is here:

azurepipeline.yml

# This will be triggered by the gates
trigger: none

pool:
  vmImage: ubuntu-latest

steps:
  - task: DotNetCoreCLI@2
    displayName: 'dotnet test'
    inputs:
      command: 'test'
      projects: CodeCoverageCheck.sln
      arguments: '--collect:"XPlat Code Coverage"'
      publishTestResults: true

################################################################################
# BEGIN HACK Due to limitations in the PublishCodeCoverageResults@1 (see
# https://github.com/microsoft/azure-pipelines-tasks/issues/10353) that only
# allow you to publish a single code coverage file; we must use a third party
# tool ReportGenerator (https://github.com/danielpalme/ReportGenerator) to
# combine the results of the previous cobertura runs.
#
# If Microsoft ever releases PublishCodeCoverageResults@2 (which has support to
# combine reports) we should switch away from this.
################################################################################

  - task: DotNetCoreCLI@2
    displayName: 'Install ReportGenerator'
    inputs:
      command: custom
      custom: tool
      arguments: 'install --global dotnet-reportgenerator-globaltool'

  - task: PowerShell@2
    displayName: 'Use ReportGenerator to Combine Cobertura Results'
    inputs:
      targetType: 'inline'
      script: 'reportgenerator "-reports:$(Agent.TempDirectory)/**/coverage.cobertura.xml" "-targetdir:$(Build.SourcesDirectory)" -reporttypes:Cobertura'
      pwsh: true

  # Last PublishCodeCoverageResults wins; this assumes it is the last one ran
  - task: PublishCodeCoverageResults@1
    displayName: 'publish code coverage (combined)'
    condition: succeededOrFailed()
    inputs:
      codeCoverageTool: Cobertura
      summaryFileLocation: '$(Build.SourcesDirectory)/Cobertura.xml'
      failIfCoverageEmpty: true

################################################################################
# END HACK
################################################################################

  # See https://github.com/MicrosoftPremier/VstsExtensions/blob/master/BuildQualityChecks/en-US/CodeCoveragePolicy.md
  - task: BuildQualityChecks@9
    displayName: 'Code Coverage Gate'
    inputs:
      checkCoverage: true
      coverageFailOption: build
      coverageType: line
      treat0of0as100: false
      forceCoverageImprovement: false

This again is less than ideal; but when ran this way this works; differences seem to come in the publish task (in this version renamed to publish code coverage (combined)):

2023-10-10T22:25:40.9932476Z ##[section]Starting: publish code coverage (combined)
2023-10-10T22:25:40.9937553Z ==============================================================================
2023-10-10T22:25:40.9937696Z Task         : Publish code coverage results
2023-10-10T22:25:40.9937762Z Description  : Publish Cobertura or JaCoCo code coverage results from a build
2023-10-10T22:25:40.9937854Z Version      : 1.228.0
2023-10-10T22:25:40.9937908Z Author       : Microsoft Corporation
2023-10-10T22:25:40.9937971Z Help         : https://docs.microsoft.com/azure/devops/pipelines/tasks/test/publish-code-coverage-results
2023-10-10T22:25:40.9938112Z ==============================================================================
2023-10-10T22:25:41.2727204Z [command]/usr/bin/dotnet /home/vsts/work/_tasks/PublishCodeCoverageResults_2a7ebc54-c13e-490e-81a5-d7561ab7cd97/1.228.0/netcoreapp2.0/ReportGenerator.dll -reports:/home/vsts/work/1/s/Cobertura.xml -targetdir:/home/vsts/work/_temp/cchtml -reporttypes:HtmlInline_AzurePipelines
2023-10-10T22:25:41.4433642Z 2023-10-10T22:25:41: Arguments
2023-10-10T22:25:41.4436613Z 2023-10-10T22:25:41:  -reports:/home/vsts/work/1/s/Cobertura.xml
2023-10-10T22:25:41.4437159Z 2023-10-10T22:25:41:  -targetdir:/home/vsts/work/_temp/cchtml
2023-10-10T22:25:41.4437705Z 2023-10-10T22:25:41:  -reporttypes:HtmlInline_AzurePipelines
2023-10-10T22:25:41.8248420Z 2023-10-10T22:25:41: Writing report file '/home/vsts/work/_temp/cchtml/index.html'
2023-10-10T22:25:41.8729567Z 2023-10-10T22:25:41: Report generation took 0.3 seconds
2023-10-10T22:25:41.8780603Z Generated code coverage html report: /home/vsts/work/_temp/cchtml
2023-10-10T22:25:41.8819699Z Reading code coverage summary from '/home/vsts/work/1/s/Cobertura.xml'
2023-10-10T22:25:42.1017761Z ##[section]Async Command Start: Publish code coverage
2023-10-10T22:25:42.1017995Z Publishing coverage summary data to TFS server.
2023-10-10T22:25:42.1018093Z  Lines- 10 of 20 covered.
2023-10-10T22:25:42.1018183Z  Branches- 2 of 8 covered.
2023-10-10T22:25:42.6018669Z Modifying Cobertura Index file
2023-10-10T22:25:42.6018919Z Publishing code coverage files to TFS server.
2023-10-10T22:25:42.6019017Z Uploading 5 files
2023-10-10T22:25:43.0425721Z File upload succeed.
2023-10-10T22:25:43.0425945Z Published '/home/vsts/work/_temp/cchtml' as artifact 'Code Coverage Report_26'
2023-10-10T22:25:43.0426116Z ##[section]Async Command End: Publish code coverage
2023-10-10T22:25:43.0426880Z ##[section]Finishing: publish code coverage (combined)

With this the reporter seems to be happy (obviously complaining about a lack of baseline):

2023-10-10T22:25:43.0439032Z ##[section]Starting: Code Coverage Gate
2023-10-10T22:25:43.0446541Z ==============================================================================
2023-10-10T22:25:43.0446695Z Task         : Build Quality Checks
2023-10-10T22:25:43.0446778Z Description  : Breaks a build based on quality metrics like number of warnings or code coverage.
2023-10-10T22:25:43.0446899Z Version      : 9.0.1
2023-10-10T22:25:43.0446960Z Author       : Microsoft
2023-10-10T22:25:43.0447050Z Help         : [[Docs]](https://github.com/MicrosoftPremier/VstsExtensions/blob/master/BuildQualityChecks/en-US/overview.md)
2023-10-10T22:25:43.0447190Z ==============================================================================
2023-10-10T22:25:44.3102067Z Using IdentifierJobResolver
2023-10-10T22:25:45.5275573Z Validating code coverage policy...
2023-10-10T22:25:48.7604558Z Successfully read code coverage data from build.
2023-10-10T22:25:48.7632264Z Evaluating coverage data from 1 filtered code coverage data sets...
2023-10-10T22:25:48.7645551Z Total line: 20
2023-10-10T22:25:48.7647341Z Covered line: 10
2023-10-10T22:25:48.7647535Z Code Coverage (%): 50
2023-10-10T22:25:48.8805850Z [WARNING] The baseline build could not be found. All policies based on the previous build will pass.
2023-10-10T22:25:48.8841741Z ##[warning]The baseline build could not be found. All policies based on the previous build will pass.
2023-10-10T22:25:48.8850078Z [SUCCESS] Code coverage policy passed with 50% (10/20 line).
2023-10-10T22:25:48.8897528Z ##[section]Finishing: Code Coverage Gate

However from the GUI perspective there's no way to tell that this is any different:

image

Task logs I have held off providing these in lieu of providing the entire reproducing project above. Should you need these logs I would be happy to provide them.

ReneSchumacher commented 1 year ago

Hi @aolszowka,

thanks for the very good repro steps. I'm going to check this on our side. The biggest difference between v1 and v2 of the publish task seems to be the coverage format. V2 creates a cjson coverage file (see here) and publishes it to Azure DevOps. I don't know what this should prevent the API from returning the correct values, but I'll check with the Azure DevOps testing tools team.

ReneSchumacher commented 1 year ago

First assumption: it seems like v2 of the publish task uploads the cjson file but does not trigger coverage processing in the backend. While the pipeline is running, the coverage API only returns an empty data set:

{
    "coverageData": [],
    "build": {
        "id": "5010",
        "url": "https://dev.azure.com/almtcger/_apis/build/Builds/5010"
    },
    "deltaBuild": null,
    "coverageDetailedSummaryStatus": "codeCoverageSuccess"
}

Coverage processing only starts after the pipeline run has finished, which is way too late for BQC to pick up the data. API results show that even after the build is finished it takes a couple seconds for the coverage job in the backend to run and then the API returns the proper results:

{
    "coverageData": [
        {
            "coverageStats": [
                {
                    "label": "Lines",
                    "position": 2,
                    "total": 53,
                    "covered": 52,
                    "isDeltaAvailable": false,
                    "delta": 0
                }
            ],
            "buildPlatform": "",
            "buildFlavor": ""
        }
    ],
    "build": {
        "id": "5010",
        "url": "https://dev.azure.com/almtcger/_apis/build/Builds/5010"
    },
    "deltaBuild": null,
    "status": "finalized",
    "coverageDetailedSummaryStatus": "finalized"
}

I will talk to the product group and see if they can trigger the job earlier. If not, there is currently no way to make BQC work with v2 of the publish coverage results task. We're also working on a version of the task that does the coverage processing itself, but I cannot say when this will be finished.

aolszowka commented 1 year ago

@ReneSchumacher Thank you for the quick turn around and Root Cause Analysis of this issue.

Is there any publicly posted tracker (IE GitHub Issue) that I can subscribe to, in order to track progress on the external report?

At the end of the day, we'll probably stick with the workaround; but I would like to document why we're stuck on a particular version and still using a workaround. Would it be worth filing documentation change requests as well in order to raise awareness of the issue for other DevOps Engineers attempting to use this combination?

ReneSchumacher commented 1 year ago

Currently, there's no such tracker. We could create something for the task, but some of the work the PG does is not tracked publicly on GitHub but on our internal Azure DevOps project. Thus, I'm not sure if they will update any issue for the task. Nevertheless, I can create an issue in the azure-pipelines-tasks repo, reference this one, and update the issues when I receive more information internally.

ReneSchumacher commented 1 year ago

@aolszowka I have updated an existing issue in the azure-pipelines-tasks repo with a reference to this one. I'll point the PG to both issues.

ReneSchumacher commented 10 months ago

I have received an update from PG regarding the compatibility of PublishCodeCoverageResults@2 and BQC. They have deployed a fixed version (2.231.0) of the task to the cloud service. This works with BQC, but V2 of the task only supports line coverage.

Thus, if you are using line coverage, you can now safely switch to v2 of the publish code coverage results task. If you need other coverage types like branch coverage, you must still use V2 of the publish code coverage results task. PG is also in the process of updating our docs to include this change.