|
3 | 3 | push: |
4 | 4 | branches: ["**"] |
5 | 5 |
|
| 6 | +permissions: |
| 7 | + contents: write |
| 8 | + pull-requests: write |
| 9 | + |
6 | 10 | jobs: |
7 | 11 | tests: |
8 | 12 | runs-on: ubuntu-latest |
|
24 | 28 | - name: Install project (editable) |
25 | 29 | run: uv pip install -e . |
26 | 30 |
|
27 | | - - name: Run pytest |
28 | | - run: uv run pytest -v tests/ |
| 31 | + - name: Run tests with coverage |
| 32 | + run: uv run pytest -v --cov=openhands --cov-report=xml:coverage.xml --cov-report=term-missing tests/ |
| 33 | + |
| 34 | + - name: Code Coverage Summary |
| 35 | + if: always() |
| 36 | + uses: irongut/CodeCoverageSummary@v1.3.0 |
| 37 | + with: |
| 38 | + filename: coverage.xml |
| 39 | + badge: true |
| 40 | + fail_below_min: false |
| 41 | + format: markdown |
| 42 | + hide_branch_rate: false |
| 43 | + hide_complexity: true |
| 44 | + indicators: true |
| 45 | + output: both |
| 46 | + |
| 47 | + - name: Add Coverage PR Comment |
| 48 | + if: ${{ always() && github.event_name == 'pull_request' }} |
| 49 | + continue-on-error: true |
| 50 | + uses: marocchino/sticky-pull-request-comment@v2 |
| 51 | + with: |
| 52 | + recreate: true |
| 53 | + path: code-coverage-results.md |
| 54 | + |
| 55 | + - name: Upload coverage artifacts |
| 56 | + if: always() |
| 57 | + uses: actions/upload-artifact@v4 |
| 58 | + with: |
| 59 | + name: coverage-artifacts |
| 60 | + path: | |
| 61 | + coverage.xml |
| 62 | + code-coverage-results.md |
| 63 | + if-no-files-found: ignore |
| 64 | + - name: Parse coverage percent |
| 65 | + if: always() |
| 66 | + id: parsecov |
| 67 | + run: | |
| 68 | + python - << 'PY' |
| 69 | + import xml.etree.ElementTree as ET |
| 70 | + import math |
| 71 | + p = 'coverage.xml' |
| 72 | + try: |
| 73 | + root = ET.parse(p).getroot() |
| 74 | + lr = root.attrib.get('line-rate') |
| 75 | + pct = int(round(float(lr) * 100)) if lr is not None else 0 |
| 76 | + except Exception: |
| 77 | + pct = 0 |
| 78 | + print(f"coverage_percent={pct}") |
| 79 | + with open("coverage_percent.txt", "w") as f: |
| 80 | + f.write(str(pct)) |
| 81 | + PY |
| 82 | +
|
| 83 | + - name: Determine badge color |
| 84 | + if: always() |
| 85 | + id: color |
| 86 | + run: | |
| 87 | + PCT=$(cat coverage_percent.txt || echo 0) |
| 88 | + if [ "$PCT" -ge 90 ]; then COLOR=brightgreen; |
| 89 | + elif [ "$PCT" -ge 75 ]; then COLOR=green; |
| 90 | + elif [ "$PCT" -ge 60 ]; then COLOR=yellowgreen; |
| 91 | + elif [ "$PCT" -ge 50 ]; then COLOR=yellow; |
| 92 | + else COLOR=red; fi |
| 93 | + echo "color=$COLOR" >> $GITHUB_OUTPUT |
| 94 | + echo "pct=$PCT" >> $GITHUB_OUTPUT |
| 95 | +
|
| 96 | + - name: Ensure badges directory |
| 97 | + if: always() |
| 98 | + run: mkdir -p badges |
| 99 | + |
| 100 | + - name: Generate coverage badge |
| 101 | + if: always() |
| 102 | + uses: emibcn/badge-action@v2.0.2 |
| 103 | + with: |
| 104 | + label: coverage |
| 105 | + status: "${{ steps.color.outputs.pct }}%" |
| 106 | + color: "${{ steps.color.outputs.color }}" |
| 107 | + path: badges/coverage.svg |
| 108 | + |
| 109 | + - name: Upload badge artifact (PRs) |
| 110 | + if: ${{ always() && github.event_name == 'pull_request' }} |
| 111 | + uses: actions/upload-artifact@v4 |
| 112 | + with: |
| 113 | + name: coverage-badge |
| 114 | + path: badges/coverage.svg |
| 115 | + |
| 116 | + - name: Commit coverage badge (push builds) |
| 117 | + if: ${{ always() && github.event_name == 'push' }} |
| 118 | + uses: EndBug/add-and-commit@v9 |
| 119 | + with: |
| 120 | + add: "badges/coverage.svg" |
| 121 | + message: "docs: update coverage badge [skip ci]" |
| 122 | + default_author: github_actions |
0 commit comments