-
Notifications
You must be signed in to change notification settings - Fork 12
172 lines (156 loc) · 7.07 KB
/
coverage.yml
File metadata and controls
172 lines (156 loc) · 7.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
name: Coverage
# Maintainer-gated, comment-triggered coverage run for any PR (including forks).
# A maintainer comments `@codecoverage` on a PR; this workflow runs the merged
# unit + selftest coverage recipe from CONTRIBUTING.md and posts the result back
# as a comment.
#
# Security: `issue_comment` workflows run in the base repo with full token
# permissions. Untrusted code from the PR (build scripts, tests) executes here.
# The `author_association` check below limits the trigger to maintainers, who
# are expected to review the diff before commenting.
on:
issue_comment:
types: [created]
permissions:
contents: read
pull-requests: write
jobs:
coverage:
name: Merged coverage
if: |
github.event.issue.pull_request &&
contains(github.event.comment.body, '@codecoverage') &&
contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association)
runs-on: windows-latest
steps:
- name: Acknowledge with reaction
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
await github.rest.reactions.createForIssueComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: context.payload.comment.id,
content: 'eyes',
});
- name: Resolve PR head SHA
id: pr
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const pr = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
});
core.setOutput('sha', pr.data.head.sha);
core.setOutput('ref', `refs/pull/${context.issue.number}/head`);
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ steps.pr.outputs.ref }}
- name: Setup .NET
uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
with:
dotnet-version: 10.0.x
- name: Install dotnet-coverage
run: dotnet tool install -g dotnet-coverage
- name: Build for instrumentation
shell: pwsh
run: |
dotnet build tests/Reactor.Tests -c Debug -p:Platform=x64 -p:Optimize=false -p:DebugType=portable
dotnet build src/Reactor -c Debug -p:Optimize=false -p:DebugType=portable --no-incremental
dotnet build tests/Reactor.AppTests.Host -c Debug -p:Platform=x64 -p:Optimize=false -p:DebugType=portable --no-incremental
- name: Collect unit coverage
shell: pwsh
run: |
dotnet-coverage collect -s coverage.settings.xml `
--output unit.cobertura.xml --output-format cobertura `
-- dotnet test tests/Reactor.Tests --no-build -p:Platform=x64
- name: Instrument Reactor.dll
shell: pwsh
run: |
$dll = Get-ChildItem -Path "tests/Reactor.AppTests.Host/bin" -Recurse -Filter "Reactor.dll" |
Where-Object { $_.FullName -notmatch 'ref[\\/]' } |
Select-Object -First 1
if (-not $dll) { throw "Reactor.dll not found under tests/Reactor.AppTests.Host/bin" }
Write-Host "Instrumenting: $($dll.FullName)"
dotnet-coverage instrument `
$dll.FullName `
-s coverage.settings.xml
- name: Collect selftest coverage
shell: pwsh
run: |
dotnet-coverage collect -s coverage.settings.xml `
--output selftest.cobertura.xml --output-format cobertura `
-- dotnet run --project tests/Reactor.AppTests.Host --no-build -p:Platform=x64 -- --self-test
- name: Merge cobertura reports
shell: pwsh
run: |
dotnet-coverage merge unit.cobertura.xml selftest.cobertura.xml `
--output merged.cobertura.xml --output-format cobertura
- name: Upload coverage artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: coverage-${{ steps.pr.outputs.sha }}
path: |
unit.cobertura.xml
selftest.cobertura.xml
merged.cobertura.xml
- name: Read coverage rates
id: rates
shell: pwsh
run: |
# dotnet-coverage's cobertura output captures per-line branch data in
# `condition-coverage="P% (covered/total)"` attributes but does not
# aggregate them: the root and class `branch-rate` attributes are
# hardcoded to 1. Sum the per-line numerators/denominators ourselves.
[xml]$x = Get-Content merged.cobertura.xml
$line = [math]::Round([double]$x.coverage.'line-rate' * 100, 2)
$covered = 0
$total = 0
foreach ($l in $x.SelectNodes('//line[@condition-coverage]')) {
if ($l.'condition-coverage' -match '\((\d+)/(\d+)\)') {
$covered += [int]$Matches[1]
$total += [int]$Matches[2]
}
}
$branch = if ($total -gt 0) { [math]::Round(100.0 * $covered / $total, 2) } else { 0 }
"line=$line" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
"branch=$branch" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
"branches-covered=$covered" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
"branches-total=$total" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
- name: Comment results
if: always()
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
LINE: ${{ steps.rates.outputs.line }}
BRANCH: ${{ steps.rates.outputs.branch }}
BRANCHES_COVERED: ${{ steps.rates.outputs.branches-covered }}
BRANCHES_TOTAL: ${{ steps.rates.outputs.branches-total }}
SHA: ${{ steps.pr.outputs.sha }}
OUTCOME: ${{ job.status }}
with:
script: |
const { LINE, BRANCH, BRANCHES_COVERED, BRANCHES_TOTAL, SHA, OUTCOME } = process.env;
const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
let body;
if (OUTCOME === 'success') {
body = [
`**Merged coverage** for \`${SHA.slice(0, 7)}\` (unit + selftest)`,
``,
`| Metric | Coverage |`,
`|---|---|`,
`| Line | ${LINE}% |`,
`| Branch | ${BRANCH}% (${BRANCHES_COVERED}/${BRANCHES_TOTAL}) |`,
``,
`Cobertura reports attached to the [workflow run](${runUrl}) as artifacts.`,
].join('\n');
} else {
body = `**Coverage run failed** for \`${SHA.slice(0, 7)}\` — see the [workflow run](${runUrl}) for details.`;
}
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body,
});