Compare commits

...

16 Commits

Author SHA1 Message Date
irongut 0723132cf6 prepare v1.0.3 2021-09-24 20:41:43 +01:00
irongut 758c38f591 removed short params 2021-09-23 02:08:23 +01:00
irongut 24062a1b2a added changelog to release workflow 2021-09-23 01:48:41 +01:00
irongut dcef09e405 merge PR #7 Handle optional complexity attribute 2021-09-22 22:32:30 +01:00
Jonathan Derrough 9cce3f5374 Handle optional complexity attribute 2021-09-22 18:19:21 +07:00
irongut 20025e7e93 formatting + cleanup 2021-09-20 01:00:33 +01:00
irongut 0bcadffdb9 workflow fixes 2021-09-06 15:06:40 +01:00
irongut 71c6f23d2f use container from GHCR for Action #4 2021-09-06 01:11:36 +01:00
irongut 162def6e89 deploy step needs to checkout again #4 2021-09-06 00:58:20 +01:00
irongut e07628e8aa added deploy to GHCR workflow #4 2021-09-06 00:43:14 +01:00
irongut fc71f6831f merge PR #3 from dependabot/Microsoft.VisualStudio.Azure.Containers.Tools.Targets-1.11.1
Bump Microsoft.VisualStudio.Azure.Containers.Tools.Targets from 1.10.13 to 1.11.1
2021-09-05 23:15:14 +01:00
irongut c4d24d5996 merge PR #5 add empty line after badge from joshjohanning/master
adding empty line after badge so table renders properly
2021-09-05 23:09:40 +01:00
Joshua Johanning f5bcfce861 adding empty line after badge so table formats properly 2021-09-03 15:51:45 -05:00
dependabot[bot] a97b5158b3 Bump Microsoft.VisualStudio.Azure.Containers.Tools.Targets
Bumps Microsoft.VisualStudio.Azure.Containers.Tools.Targets from 1.10.13 to 1.11.1.

---
updated-dependencies:
- dependency-name: Microsoft.VisualStudio.Azure.Containers.Tools.Targets
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-10 23:11:27 +00:00
irongut e67bf0d2d1 updated documentation 2021-05-13 23:06:38 +01:00
irongut 1c05e17f24 updated readme 2021-05-10 23:30:39 +01:00
9 changed files with 197 additions and 103 deletions
+14 -11
View File
@@ -1,15 +1,18 @@
# Assign PR to Author # Assign PR to Author
# https://github.com/samspills/assign-pr-to-author # https://github.com/samspills/assign-pr-to-author
name: Auto Assign PR # Disabled due to #14 HttpError: Resource not accessible by integration:
on: [pull_request] # https://github.com/samspills/assign-pr-to-author/issues/14
jobs: #name: Auto Assign PR
assignAuthor: #on: [pull_request]
runs-on: ubuntu-latest
steps: #jobs:
- name: Auto Assign PR # assignAuthor:
uses: samspills/assign-pr-to-author@v1.0 # runs-on: ubuntu-latest
if: github.event_name == 'pull_request' && github.event.action == 'opened' # steps:
with: # - name: Auto Assign PR
repo-token: '${{ secrets.GITHUB_TOKEN }}' # uses: samspills/assign-pr-to-author@v1.0
# if: github.event_name == 'pull_request' && github.event.action == 'opened'
# with:
# repo-token: '${{ secrets.GITHUB_TOKEN }}'
+5 -9
View File
@@ -11,8 +11,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: CI Build name: CI Build
steps: steps:
- uses: actions/checkout@v2 - name: Checkout
- name: Setup .NET uses: actions/checkout@v2
- name: Setup .Net
uses: actions/setup-dotnet@v1 uses: actions/setup-dotnet@v1
with: with:
dotnet-version: 5.0.x dotnet-version: 5.0.x
@@ -23,11 +25,5 @@ jobs:
- name: Build CodeCoverageSummary - name: Build CodeCoverageSummary
run: dotnet build src/CodeCoverageSummary.sln --configuration Release --no-restore run: dotnet build src/CodeCoverageSummary.sln --configuration Release --no-restore
- name: Run CodeCoverageSummary with sample file - name: Test with sample file
run: dotnet src/CodeCoverageSummary/bin/Release/net5.0/CodeCoverageSummary.dll src/coverage.cobertura.xml --badge true run: dotnet src/CodeCoverageSummary/bin/Release/net5.0/CodeCoverageSummary.dll src/coverage.cobertura.xml --badge true
- name: Test Action
uses: irongut/CodeCoverageSummary@master
with:
filename: '/app/sample.coverage.xml'
badge: 'true'
+87
View File
@@ -0,0 +1,87 @@
name: Build + Deploy to GHCR
on:
release:
types: [published]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
name: Test Build
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Setup .Net
uses: actions/setup-dotnet@v1
with:
dotnet-version: 5.0.x
- name: Restore Dependencies
run: dotnet restore src/CodeCoverageSummary.sln
- name: Build CodeCoverageSummary
run: dotnet build src/CodeCoverageSummary.sln --configuration Release --no-restore
- name: Test with sample file
run: dotnet src/CodeCoverageSummary/bin/Release/net5.0/CodeCoverageSummary.dll src/coverage.cobertura.xml --badge true
- name: Get Previous Tag
id: get_previous_tag
run: |
PREV_TAG=$(git describe --abbrev=0 --tags "${{ github.ref }}^")
echo "::set-output name=baseRef::${PREV_TAG}"
- name: Generate Changelog
id: generate_changelog
uses: nblagoev/pull-release-notes-action@v1.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
base-ref: ${{ steps.get_previous_tag.outputs.baseRef }}
head-ref: ${{ github.ref }}
- name: Add Changelog to Release
uses: irongut/EditRelease@v1.0.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
id: ${{ github.event.release.id }}
body: ${{ steps.generate_changelog.outputs.result }}
deploy:
name: Deploy to GHCR
needs: [build]
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v3
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build + Push Docker image
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
+5 -5
View File
@@ -1,8 +1,8 @@
# Code Coverage Summary # Code Coverage Summary
A GitHub Action that reads Cobertura format code coverage files and outputs a text or markdown summary. Other Actions can then post the summary as a pull request comment, include it in release notes, etc. A GitHub Action that reads Cobertura format code coverage files from your test suite and outputs a text or markdown summary. This summary can then be posted as a Pull Request comment, included in Release Notes, etc by another action to give you an immediate insight into the health of your code without using a third-party site.
Written for use with [Coverlet](https://github.com/coverlet-coverage/coverlet) and .Net but it should work with any tests that output coverage in Cobertura format. Code Coverage Summary was designed for use with [Coverlet](https://github.com/coverlet-coverage/coverlet) and .Net but it should work with any test framework that outputs coverage in Cobertura format.
## Inputs ## Inputs
@@ -52,7 +52,7 @@ Company.Example.Library: Line Rate = 27%, Branch Rate = 100%, Complexity = 11
```yaml ```yaml
name: Code Coverage Summary Report name: Code Coverage Summary Report
uses: irongut/CodeCoverageSummary@v1 uses: irongut/CodeCoverageSummary@v1.0.3
with: with:
filename: coverage/coverage.cobertura.xml filename: coverage/coverage.cobertura.xml
``` ```
@@ -94,7 +94,7 @@ jobs:
run: cp coverage/**/coverage.cobertura.xml coverage/coverage.cobertura.xml run: cp coverage/**/coverage.cobertura.xml coverage/coverage.cobertura.xml
- name: Code Coverage Summary Report - name: Code Coverage Summary Report
uses: irongut/CodeCoverageSummary@v1 uses: irongut/CodeCoverageSummary@v1.0.3
with: with:
filename: coverage/coverage.cobertura.xml filename: coverage/coverage.cobertura.xml
badge: true badge: true
@@ -115,7 +115,7 @@ jobs:
Please make sure the bug is not already reported by searching existing [issues]. Please make sure the bug is not already reported by searching existing [issues].
If you're unable to find an existing issue addressing the problem [open a new one][new-issue]. Be sure to include a title and clear description, as much relevant information as possible, a workflow sample and any logs demonstrating the problem. If you're unable to find an existing issue addressing the problem please [open a new one][new-issue]. Be sure to include a title and clear description, as much relevant information as possible, a workflow sample and any logs demonstrating the problem.
### Suggest an Enhancement ### Suggest an Enhancement
+1 -1
View File
@@ -22,7 +22,7 @@ inputs:
default: 'console' default: 'console'
runs: runs:
using: 'docker' using: 'docker'
image: 'Dockerfile' image: 'docker://ghcr.io/irongut/codecoveragesummary:v1.0.2'
args: args:
- ${{ inputs.filename }} - ${{ inputs.filename }}
- '--badge' - '--badge'
@@ -6,19 +6,20 @@
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS> <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<Company>Taranis Software</Company> <Company>Taranis Software</Company>
<Authors>Irongut</Authors> <Authors>Irongut</Authors>
<Description>A GitHub Action that reads Cobertura format code coverage files and outputs a summary.</Description> <Description>A GitHub Action that reads Cobertura format code coverage files and outputs a text or markdown summary.</Description>
<Copyright>Copyright © 2021 Taranis Software</Copyright> <Copyright>Copyright © 2021 Taranis Software</Copyright>
<PackageId>Taranis.CodeCoverageSummary</PackageId> <PackageId>Taranis.CodeCoverageSummary</PackageId>
<PackageLicenseExpression>MIT</PackageLicenseExpression> <PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/irongut/CodeCoverageSummary</PackageProjectUrl> <PackageProjectUrl>https://github.com/irongut/CodeCoverageSummary</PackageProjectUrl>
<RepositoryUrl>https://github.com/irongut/CodeCoverageSummary</RepositoryUrl> <RepositoryUrl>https://github.com/irongut/CodeCoverageSummary</RepositoryUrl>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<PackageTags>code-coverage cobertura coverlet</PackageTags> <PackageTags>coverage test-coverage cobertura action code-coverage coverlet github-actions</PackageTags>
<Version>1.0.3</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.8.0" /> <PackageReference Include="CommandLineParser" Version="2.8.0" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.13" /> <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.11.1" />
</ItemGroup> </ItemGroup>
</Project> </Project>
@@ -7,13 +7,13 @@ namespace CodeCoverageSummary
[Value(index: 0, Required = true, HelpText = "Code coverage file to analyse.")] [Value(index: 0, Required = true, HelpText = "Code coverage file to analyse.")]
public string Filename { get; set; } public string Filename { get; set; }
[Option(shortName: 'b', longName: "badge", Required = false, HelpText = "Include a badge in the output - true / false.", Default = false)] [Option(longName: "badge", Required = false, HelpText = "Include a badge reporting the Line Rate coverage in the output using shields.io - true or false.", Default = false)]
public bool Badge { get; set; } public bool Badge { get; set; }
[Option(shortName: 'f', longName: "format", Required = false, HelpText = "Output Format - markdown or text.", Default = "text")] [Option(longName: "format", Required = false, HelpText = "Output Format - markdown or text.", Default = "text")]
public string Format { get; set; } public string Format { get; set; }
[Option(shortName: 'o', longName: "output", Required = false, HelpText = "Output Type - console, file or both.", Default = "console")] [Option(longName: "output", Required = false, HelpText = "Output Type - console, file or both.", Default = "console")]
public string Output { get; set; } public string Output { get; set; }
} }
} }
@@ -0,0 +1,8 @@
// This file is used by Code Analysis to maintain SuppressMessage
// attributes that are applied to this project.
// Project-level suppressions either have no target or are given
// a specific target and scoped to a namespace, type, member, etc.
using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage("Performance", "RCS1197:Optimize StringBuilder.Append/AppendLine call.", Scope = "type", Target = "~T:CodeCoverageSummary.Program")]
+70 -71
View File
@@ -9,83 +9,81 @@ namespace CodeCoverageSummary
{ {
internal static class Program internal static class Program
{ {
// test file: /Dev/Csharp/CodeCoverageSummary/coverage.cobertura.xml
private static int Main(string[] args) private static int Main(string[] args)
{ {
return Parser.Default.ParseArguments<CommandLineOptions>(args) return Parser.Default.ParseArguments<CommandLineOptions>(args)
.MapResult(o => .MapResult(o =>
{ {
try try
{ {
if (!File.Exists(o.Filename)) if (!File.Exists(o.Filename))
{ {
Console.WriteLine("Error: Code coverage file not found."); Console.WriteLine("Error: Code coverage file not found.");
return -2; // error return -2; // error
} }
// parse code coverage file // parse code coverage file
Console.WriteLine($"Code Coverage File: {o.Filename}"); Console.WriteLine($"Code Coverage File: {o.Filename}");
CodeSummary summary = ParseTestResults(o.Filename); CodeSummary summary = ParseTestResults(o.Filename);
if (summary == null) if (summary == null)
{ {
Console.WriteLine("Error: Parsing code coverage file."); Console.WriteLine("Error: Parsing code coverage file.");
return -2; // error return -2; // error
} }
else else
{ {
// generate badge // generate badge
string badgeUrl = o.Badge ? GenerateBadge(summary) : null; string badgeUrl = o.Badge ? GenerateBadge(summary) : null;
// generate output // generate output
string output; string output;
string fileExt; string fileExt;
if (o.Format.Equals("text", StringComparison.OrdinalIgnoreCase)) if (o.Format.Equals("text", StringComparison.OrdinalIgnoreCase))
{ {
fileExt = "txt"; fileExt = "txt";
output = GenerateTextOutput(summary, badgeUrl); output = GenerateTextOutput(summary, badgeUrl);
} }
else if (o.Format.Equals("md", StringComparison.OrdinalIgnoreCase) || o.Format.Equals("markdown", StringComparison.OrdinalIgnoreCase)) else if (o.Format.Equals("md", StringComparison.OrdinalIgnoreCase) || o.Format.Equals("markdown", StringComparison.OrdinalIgnoreCase))
{ {
fileExt = "md"; fileExt = "md";
output = GenerateMarkdownOutput(summary, badgeUrl); output = GenerateMarkdownOutput(summary, badgeUrl);
} }
else else
{ {
Console.WriteLine("Error: Unknown output format."); Console.WriteLine("Error: Unknown output format.");
return -2; // error return -2; // error
} }
// output // output
if (o.Output.Equals("console", StringComparison.OrdinalIgnoreCase)) if (o.Output.Equals("console", StringComparison.OrdinalIgnoreCase))
{ {
Console.WriteLine(output); Console.WriteLine(output);
} }
else if (o.Output.Equals("file", StringComparison.OrdinalIgnoreCase)) else if (o.Output.Equals("file", StringComparison.OrdinalIgnoreCase))
{ {
File.WriteAllText($"code-coverage-results.{fileExt}", output); File.WriteAllText($"code-coverage-results.{fileExt}", output);
} }
else if (o.Output.Equals("both", StringComparison.OrdinalIgnoreCase)) else if (o.Output.Equals("both", StringComparison.OrdinalIgnoreCase))
{ {
Console.WriteLine(output); Console.WriteLine(output);
File.WriteAllText($"code-coverage-results.{fileExt}", output); File.WriteAllText($"code-coverage-results.{fileExt}", output);
} }
else else
{ {
Console.WriteLine("Error: Unknown output type."); Console.WriteLine("Error: Unknown output type.");
return -2; // error return -2; // error
} }
return 0; // success return 0; // success
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine($"Error: {ex.GetType()} - {ex.Message}"); Console.WriteLine($"Error: {ex.GetType()} - {ex.Message}");
return -3; // unhandled error return -3; // unhandled error
} }
}, },
errs => -1); // invalid arguments _ => -1); // invalid arguments
} }
private static CodeSummary ParseTestResults(string filename) private static CodeSummary ParseTestResults(string filename)
@@ -143,7 +141,7 @@ namespace CodeCoverageSummary
Name = item.Attribute("name").Value, Name = item.Attribute("name").Value,
LineRate = double.Parse(item.Attribute("line-rate").Value), LineRate = double.Parse(item.Attribute("line-rate").Value),
BranchRate = double.Parse(item.Attribute("branch-rate").Value), BranchRate = double.Parse(item.Attribute("branch-rate").Value),
Complexity = int.Parse(item.Attribute("complexity").Value) Complexity = int.Parse(item.Attribute("complexity")?.Value ?? "0")
}; };
summary.Packages.Add(packageCoverage); summary.Packages.Add(packageCoverage);
summary.Complexity += packageCoverage.Complexity; summary.Complexity += packageCoverage.Complexity;
@@ -204,6 +202,7 @@ namespace CodeCoverageSummary
if (!string.IsNullOrWhiteSpace(badgeUrl)) if (!string.IsNullOrWhiteSpace(badgeUrl))
{ {
markdownOutput.AppendLine($"![Code Coverage]({badgeUrl})"); markdownOutput.AppendLine($"![Code Coverage]({badgeUrl})");
markdownOutput.AppendLine("");
} }
markdownOutput.AppendLine("Package | Line Rate | Branch Rate | Complexity") markdownOutput.AppendLine("Package | Line Rate | Branch Rate | Complexity")