Add code coverage grading workflow #20170
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
| # Licensed to the Apache Software Foundation (ASF) under one | |
| # or more contributor license agreements. See the NOTICE file | |
| # distributed with this work for additional information | |
| # regarding copyright ownership. The ASF licenses this file | |
| # to you under the Apache License, Version 2.0 (the | |
| # "License"); you may not use this file except in compliance | |
| # with the License. You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, | |
| # software distributed under the License is distributed on an | |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| # KIND, either express or implied. See the License for the | |
| # specific language governing permissions and limitations | |
| # under the License. | |
| name: Coverage Check | |
| on: [pull_request, push] | |
| permissions: | |
| contents: read | |
| pull-requests: write # required to post/update the grade comment on PRs | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| build: | |
| if: github.repository == 'apache/cloudstack' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) | |
| name: codecov | |
| runs-on: ubuntu-22.04 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up JDK 17 | |
| uses: actions/setup-java@v5 | |
| with: | |
| distribution: 'temurin' | |
| java-version: '17' | |
| cache: 'maven' | |
| - name: Build CloudStack with Quality Checks | |
| run: | | |
| git clone https://github.com/shapeblue/cloudstack-nonoss.git nonoss | |
| cd nonoss && bash -x install-non-oss.sh && cd .. | |
| mvn -P quality -Dsimulator -Dnoredist clean install -T$(nproc) | |
| - uses: codecov/codecov-action@v6 | |
| with: | |
| files: ./client/target/site/jacoco-aggregate/jacoco.xml | |
| fail_ci_if_error: true | |
| flags: unittests | |
| verbose: true | |
| name: codecov | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| - name: Compute Coverage Grade | |
| id: grade | |
| run: bash scripts/coverage-grade.sh client/target/site/jacoco-aggregate/jacoco.xml | |
| # Posts a new comment on every push so coverage history is preserved across the PR timeline. | |
| # On push events (no PR number) this step is skipped automatically. | |
| - name: Post Coverage Grade Comment on PR | |
| if: github.event_name == 'pull_request' | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const grade = '${{ steps.grade.outputs.coverage_grade }}'; | |
| const label = '${{ steps.grade.outputs.coverage_grade_label }}'; | |
| const linePct = '${{ steps.grade.outputs.line_coverage }}'; | |
| const branchPct = '${{ steps.grade.outputs.branch_coverage }}'; | |
| const emojiMap = { A: '🟢', B: '🟡', C: '🟠', D: '🔴', F: '⛔' }; | |
| const emoji = emojiMap[grade] ?? '❓'; | |
| const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; | |
| const branchRow = branchPct !== 'N/A' | |
| ? `| Branch coverage | **${branchPct}%** |` | |
| : ''; | |
| const body = [ | |
| `## ${emoji} Test Coverage Grade: \`${grade}\` — ${label}`, | |
| '', | |
| '| Metric | Value |', | |
| '|--------|-------|', | |
| `| Line coverage | **${linePct}%** |`, | |
| branchRow, | |
| '', | |
| '### Grade Scale', | |
| '| Grade | Line Coverage | Meaning |', | |
| '|-------|--------------|---------|', | |
| '| 🟢 A | ≥ 80% | Excellent |', | |
| '| 🟡 B | 60–79% | Good |', | |
| '| 🟠 C | 40–59% | Acceptable |', | |
| '| 🔴 D | 20–39% | Marginal — meets minimum gate |', | |
| '| ⛔ F | < 20% | Failing — below minimum gate |', | |
| '', | |
| '> Branch coverage is shown as a secondary signal. Grade is determined by **line coverage**.', | |
| `> [View full Actions run](${runUrl})`, | |
| ].filter(l => l !== undefined).join('\n'); | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body: body, | |
| }); | |
| console.log('Posted coverage grade comment'); |