Skip to content

Commit 36225b9

Browse files
coverage report workflow
- Added script .github/scripts/check_pyrefly_coverage.py to check for regressions in type annotations by comparing baseline coverage report to newly generated coverage report. - Added actions workflow to automatically call type coverage regression test. - Added unit tests for coverage report script. - Checked in baseline report to track current type annotation state.
1 parent 2ab1dc5 commit 36225b9

5 files changed

Lines changed: 8725 additions & 1 deletion

File tree

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
from argparse import ArgumentParser
2+
from difflib import unified_diff
3+
from pathlib import Path
4+
import pprint
5+
import json
6+
import sys
7+
8+
if __name__ == "__main__":
9+
parser = ArgumentParser()
10+
parser.add_argument(
11+
"--baseline_report_path",
12+
type=str,
13+
required=False,
14+
default=".pyrefly-baseline-report.json",
15+
)
16+
parser.add_argument(
17+
"--current_report_path",
18+
type=str,
19+
required=False,
20+
default="pyrefly-current-report.json",
21+
)
22+
args = parser.parse_args()
23+
baseline = json.loads(Path(args.baseline_report_path).read_text())
24+
current = json.loads(Path(args.current_report_path).read_text())
25+
26+
baseline_reports = {}
27+
current_reports = {}
28+
29+
for report in baseline["module_reports"]:
30+
baseline_reports[report["name"]] = report
31+
32+
for report in current["module_reports"]:
33+
current_reports[report["name"]] = report
34+
35+
failures = []
36+
37+
for module_name, current_module_report in current_reports.items():
38+
baseline_module_report = baseline_reports.get(module_name)
39+
40+
# File does not exist in baseline yet
41+
if baseline_module_report is None:
42+
completeness = current_module_report["coverage"]
43+
44+
if completeness < 100:
45+
failures.append(
46+
f"New file {module_name} is only " f"{completeness:.1f}% annotated"
47+
)
48+
continue
49+
50+
old_n_untpyed = baseline_module_report["n_untyped"]
51+
new_n_untpyed = current_module_report["n_untyped"]
52+
53+
if new_n_untpyed > old_n_untpyed:
54+
dict1_lines = pprint.pformat(
55+
baseline_module_report, sort_dicts=True
56+
).splitlines()
57+
dict2_lines = pprint.pformat(
58+
current_module_report, sort_dicts=True
59+
).splitlines()
60+
61+
diff = unified_diff(
62+
dict1_lines, dict2_lines, fromfile="dict1", tofile="dict2", lineterm=""
63+
)
64+
65+
failures.append(
66+
f"{module_name}: Untyped count increased "
67+
f"from {old_n_untpyed} to {new_n_untpyed}\n"
68+
f"\n{'\n'.join(diff)}"
69+
)
70+
71+
if failures:
72+
print("Pyrefly coverage regression detected:")
73+
74+
for failure in failures:
75+
print(f"- {failure}\n\n")
76+
77+
sys.exit(1)
78+
79+
print("No pyrefly coverage regressions detected.")
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: Pyrefly Coverage Check
2+
3+
on:
4+
push:
5+
branches: [ "main" ]
6+
pull_request:
7+
branches: [ "main" ]
8+
9+
jobs:
10+
check-type-coverage:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout repository
15+
uses: actions/checkout@v4
16+
17+
- name: Set up Python
18+
uses: actions/setup-python@v5
19+
with:
20+
python-version: "3.13"
21+
22+
- name: Install dependencies
23+
run: |
24+
python -m pip install --upgrade pip
25+
pip install pyrefly
26+
27+
- name: Generate current Pyrefly coverage report
28+
run: |
29+
pyrefly coverage report > pyrefly-current-report.json
30+
31+
- name: Compare against baseline
32+
run: |
33+
python .github/scripts/check_pyrefly_coverage.py

0 commit comments

Comments
 (0)