Skip to content

Commit

Permalink
Publish coverage report as pipelne artifact on GitHub Actions
Browse files Browse the repository at this point in the history
  • Loading branch information
ap0llo committed Dec 21, 2024
1 parent 4022446 commit 2729ed7
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 9 deletions.
54 changes: 45 additions & 9 deletions src/SharedBuild/Tasks/TestTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
using Cake.Core.Diagnostics;
using Cake.Core.IO;
using Cake.Frosting;
using Grynwald.SharedBuild.Tools.TemporaryFiles;
using Microsoft.VisualBasic;

namespace Grynwald.SharedBuild.Tasks;

Expand All @@ -26,7 +28,7 @@ public override async Task RunAsync(IBuildContext context)

if (context.TestSettings.CollectCodeCoverage)
{
GenerateCoverageReport(context);
await GenerateCoverageReportAsync(context);
}
}

Expand Down Expand Up @@ -139,7 +141,7 @@ await context.GitHubActions().Commands.UploadArtifact(
}
}

private void GenerateCoverageReport(IBuildContext context)
private async Task GenerateCoverageReportAsync(IBuildContext context)
{
context.EnsureDirectoryDoesNotExist(context.Output.CodeCoverageReportDirectory, new() { Force = true, Recursive = true });

Expand Down Expand Up @@ -168,21 +170,55 @@ private void GenerateCoverageReport(IBuildContext context)
}
);

var coverageReportPath = context.Output.CodeCoverageReportDirectory.CombineWithFilePath("Cobertura.xml");

//
// Publish Code coverage report
//
if (context.AzurePipelines.IsActive)
{
context.Log.Information("Publishing Code Coverage Results to Azure Pipelines");
context.AzurePipelines.Commands.PublishCodeCoverage(new()
{
CodeCoverageTool = AzurePipelinesCodeCoverageToolType.Cobertura,
SummaryFileLocation = context.Output.CodeCoverageReportDirectory.CombineWithFilePath("Cobertura.xml"),
ReportDirectory = context.Output.CodeCoverageReportDirectory
});
PublishCodeCoverageToAzurePipelines(context, coverageReportPath);
}
else if (context.GitHubActions.IsActive)
{
await PublishCodeCoverageToGitHubActionsAsync(context, coverageReportPath);
}
}

protected virtual void PublishCodeCoverageToAzurePipelines(IBuildContext context, FilePath coverageReportPath)
{
context.Log.Information("Publishing Code Coverage Results to Azure Pipelines");
context.AzurePipelines.Commands.PublishCodeCoverage(new()
{
CodeCoverageTool = AzurePipelinesCodeCoverageToolType.Cobertura,
SummaryFileLocation = coverageReportPath,
ReportDirectory = context.Output.CodeCoverageReportDirectory
});
}

protected virtual async Task PublishCodeCoverageToGitHubActionsAsync(IBuildContext context, FilePath coverageReportPath)
{
context.Log.Information("Publishing Code Coverage Results to GitHub Actions");

using var temporaryDirectory = context.CreateTemporaryDirectory();

// Generate Markdown coverage report
context.ReportGenerator(
reports: [coverageReportPath],
targetDir: temporaryDirectory.Path,
settings: new ReportGeneratorSettings()
{
ReportTypes = [ReportGeneratorReportType.MarkdownSummaryGithub],
HistoryDirectory = context.Output.CodeCoverageHistoryDirectory,
}
);
var markdownSummaryPath = context.FileSystem.GetFilePaths(temporaryDirectory.Path, "*.md").Single();

// Publish coverage file and Summary are artifacts
await context.GitHubActions().Commands.UploadArtifact(coverageReportPath, context.GitHubActions.ArtifactNames.TestResults);
await context.GitHubActions().Commands.UploadArtifact(markdownSummaryPath, context.GitHubActions.ArtifactNames.TestResults);
}

private static IReadOnlyDictionary<FilePath, string> GetTestRunNames(IBuildContext context, IEnumerable<FilePath> testResultPaths)
{
var testRunNamer = new TestRunNamer(context.Log, context.Environment, context.FileSystem);
Expand Down
17 changes: 17 additions & 0 deletions src/SharedBuild/Tools/TemporaryFiles/TemporaryDirectory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using Cake.Core.IO;

namespace Grynwald.SharedBuild.Tools.TemporaryFiles;

public class TemporaryDirectory(DirectoryPath path, IFileSystem fileSystem) : IDisposable
{
public DirectoryPath Path { get; } = path ?? throw new ArgumentNullException(nameof(path));

public void Dispose()
{
if (fileSystem.GetDirectory(Path).Exists)
{
fileSystem.GetDirectory(Path).Delete(recursive: true);
}
}
}
17 changes: 17 additions & 0 deletions src/SharedBuild/Tools/TemporaryFiles/TemporaryDirectoryAliases.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using Cake.Core;
using Cake.Core.IO;

namespace Grynwald.SharedBuild.Tools.TemporaryFiles;

public static class TemporaryDirectoryAliases
{
public static TemporaryDirectory CreateTemporaryDirectory(this ICakeContext context)
{
var path = context.Environment
.GetSpecialPath(SpecialPath.LocalTemp)
.Combine($"{Guid.NewGuid():n}");

return new TemporaryDirectory(path, context.FileSystem);
}
}

0 comments on commit 2729ed7

Please sign in to comment.