-
Notifications
You must be signed in to change notification settings - Fork 4
75 lines (65 loc) · 2.68 KB
/
Copy pathmutation.yml
File metadata and controls
75 lines (65 loc) · 2.68 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
name: Mutation
# 100% branch coverage proves every line runs; mutation testing asks whether any
# assertion would notice if it changed. It runs out of band — the signal is a
# slowly-moving score, not a per-commit gate — so it is never a required check
# on a pull request.
on:
schedule:
- cron: '0 4 * * 1' # Mondays, 04:00 UTC
workflow_dispatch:
permissions:
contents: read
jobs:
mutmut:
name: Mutation score
runs-on: ubuntu-latest
env:
# The floor, as in extras-min: compatibility is the matrix's job in ci.yml,
# and a mutation score is about what the tests assert, not about the
# interpreter. Pinning one keeps the number reproducible.
UV_PYTHON: '3.11'
# The survivors left are equivalent mutants, enumerated in CONTRIBUTING.md.
# Every new one is a test that would not have noticed the change; raise
# this only together with the list.
SURVIVOR_BUDGET: '23'
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Install uv
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
enable-cache: true
- name: Install dependencies
run: uv sync --frozen
- name: Run mutation testing
run: uv run mutmut run
- name: Collect the score
if: ${{ !cancelled() }}
run: |
uv run mutmut export-cicd-stats
python - <<'PY' >> "$GITHUB_STEP_SUMMARY"
import json, os, pathlib
stats = json.loads(pathlib.Path('mutants/mutmut-cicd-stats.json').read_text())
killed, survived, total = stats['killed'], stats['survived'], stats['total']
budget = int(os.environ['SURVIVOR_BUDGET'])
print('## Mutation score\n')
print(f'**{killed / total:.1%}** — {killed} killed, {survived} survived of {total}.\n')
print(f'Survivor budget: {survived}/{budget}.')
with pathlib.Path(os.environ['GITHUB_ENV']).open('a') as env:
env.write(f'SURVIVED={survived}\n')
PY
- name: Upload the report
if: ${{ !cancelled() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: mutmut-stats
path: mutants/mutmut-cicd-stats.json
- name: Fail if new mutants survive
if: ${{ !cancelled() }}
run: |
if [ "$SURVIVED" -gt "$SURVIVOR_BUDGET" ]; then
echo "::error::$SURVIVED mutants survived, budget is $SURVIVOR_BUDGET."
echo 'Run `uv run mutmut results` and `uv run mutmut show <mutant>` locally.'
exit 1
fi