# 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 - this code sleeps well at night 😴 |', '| 🟡 B | 60-79% | Good - almost there, don\'t stop now 😉 |', '| 🟠 C | 40-59% | Acceptable - your code is wearing a seatbelt, but no airbags 😬 |', '| 🔴 D | 20-39% | Marginal - boldly shipping where no test has gone before 🖖 |', '| ⛔ F | < 20% | Failing - tests? what tests? 🔥 |', '', '> 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');