[Feature] Window - needs DPI aware size, need to support multiple windows #35
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.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, | |
| }); |