fedora-csb-system-manager
 1#!/usr/bin/env -S uv run --script
 2# /// script
 3# requires-python = ">=3.11"
 4# dependencies = [
 5#     "ruff>=0.8.0",
 6#     "mypy>=1.13.0",
 7#     "pytest>=8.0.0",
 8#     "pytest-cov>=6.0.0",
 9# ]
10# ///
11"""Run all Python quality checks: lint, type check, and tests.
12
13This comprehensive check runs:
141. ruff check (linting)
152. ruff format --check (formatting)
163. mypy (type checking)
174. pytest with coverage (testing)
18"""
19
20import subprocess
21import sys
22from pathlib import Path
23
24
25def run_check(name: str, cmd: list[str]) -> tuple[bool, int]:
26    """Run a check command.
27
28    Args:
29        name: Name of the check
30        cmd: Command and arguments to run
31
32    Returns:
33        Tuple of (success, exit_code)
34    """
35    print(f"\n{'='*60}")
36    print(f"Running: {name}")
37    print(f"{'='*60}")
38    print(f"Command: {' '.join(cmd)}\n")
39
40    result = subprocess.run(cmd, check=False)
41    success = result.returncode == 0
42
43    if success:
44        print(f"\n✓ {name} passed")
45    else:
46        print(f"\n✗ {name} failed")
47
48    return success, result.returncode
49
50
51def main() -> int:
52    """Run all quality checks.
53
54    Returns:
55        Exit code (0 if all checks pass, 1 if any fail)
56    """
57    target = Path(sys.argv[1]) if len(sys.argv) > 1 else Path(".")
58
59    if not target.exists():
60        print(f"Error: {target} does not exist", file=sys.stderr)
61        return 1
62
63    checks: list[tuple[str, list[str]]] = [
64        ("Linting (ruff check)", ["ruff", "check", str(target)]),
65        ("Formatting (ruff format)", ["ruff", "format", "--check", str(target)]),
66        ("Type checking (mypy)", ["mypy", str(target)]),
67        ("Tests (pytest)", ["pytest", "--cov", str(target)]),
68    ]
69
70    results: list[tuple[str, bool, int]] = []
71
72    for name, cmd in checks:
73        success, code = run_check(name, cmd)
74        results.append((name, success, code))
75
76    # Print summary
77    print(f"\n{'='*60}")
78    print("Summary")
79    print(f"{'='*60}")
80
81    all_passed = True
82    for name, success, code in results:
83        status = "✓ PASS" if success else "✗ FAIL"
84        print(f"{status} - {name}")
85        if not success:
86            all_passed = False
87
88    print(f"{'='*60}\n")
89
90    if all_passed:
91        print("✓ All checks passed!")
92        return 0
93    else:
94        print("✗ Some checks failed")
95        return 1
96
97
98if __name__ == "__main__":
99    sys.exit(main())