ariadne/scripts/check_coverage_contract.py

67 lines
2.0 KiB
Python
Raw Permalink Normal View History

#!/usr/bin/env python3
"""Enforce Ariadne's per-file source coverage contract."""
from __future__ import annotations
import argparse
import json
from pathlib import Path
def _source_files(root: Path) -> list[str]:
files: list[str] = []
for path in sorted(root.rglob("*.py")):
if "__pycache__" in path.parts:
continue
files.append(path.as_posix())
return files
def _coverage_percent(file_payload: object) -> float | None:
if not isinstance(file_payload, dict):
return None
summary = file_payload.get("summary")
if not isinstance(summary, dict):
return None
value = summary.get("percent_covered")
if isinstance(value, (int, float)):
return float(value)
return None
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("coverage_json")
parser.add_argument("--source-root", default="ariadne")
parser.add_argument("--threshold", type=float, default=95.0)
args = parser.parse_args()
coverage_path = Path(args.coverage_json)
source_root = Path(args.source_root)
payload = json.loads(coverage_path.read_text(encoding="utf-8"))
files = payload.get("files") if isinstance(payload, dict) else None
if not isinstance(files, dict):
print(f"{coverage_path}: missing files coverage map")
return 1
failures: list[str] = []
for source_file in _source_files(source_root):
percent = _coverage_percent(files.get(source_file))
if percent is None:
failures.append(f"{source_file}: missing from coverage report")
elif percent < args.threshold:
failures.append(f"{source_file}: {percent:.2f}% below {args.threshold:.2f}%")
if failures:
print("coverage contract failed:")
for failure in failures:
print(f" - {failure}")
return 1
print(f"coverage contract passed: {len(_source_files(source_root))} files >= {args.threshold:.2f}%")
return 0
if __name__ == "__main__":
raise SystemExit(main())