File size: 2,385 Bytes
4d10530
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
from __future__ import annotations

import subprocess
import shutil
import sys
from dataclasses import dataclass
from pathlib import Path
from typing import Sequence


REPO_ROOT = Path(__file__).resolve().parent.parent


@dataclass(frozen=True)
class Check:
    name: str
    command: tuple[str, ...]


def _run_check(check: Check) -> int:
    printable = " ".join(check.command)
    print(f"\n[verify] {check.name}: {printable}", flush=True)
    command = _resolve_command(check.command)
    completed = subprocess.run(command, cwd=REPO_ROOT, check=False)
    if completed.returncode == 0:
        print(f"[verify] PASS: {check.name}", flush=True)
        return 0
    print(f"[verify] FAIL: {check.name} (exit {completed.returncode})", flush=True)
    return completed.returncode


def _resolve_command(command: tuple[str, ...]) -> tuple[str, ...]:
    executable = shutil.which(command[0])
    if executable is None:
        return command
    return (executable, *command[1:])


def build_checks() -> Sequence[Check]:
    python = sys.executable
    return (
        Check(
            "backend unittest discover",
            (python, "-m", "unittest", "discover", "-s", "backend", "-p", "test_*.py"),
        ),
        Check(
            "script unittest test_scratch_cleanup.py",
            (python, "scripts/test_scratch_cleanup.py"),
        ),
        Check(
            "backend and scripts compileall",
            (python, "-m", "compileall", "-q", "backend", "scripts"),
        ),
        Check(
            "npm run check:frontend",
            ("npm", "run", "check:frontend"),
        ),
        Check(
            "pip check",
            (python, "-m", "pip", "check"),
        ),
        Check(
            "npm audit --audit-level=moderate",
            ("npm", "audit", "--audit-level=moderate"),
        ),
        Check(
            "git diff --check",
            ("git", "diff", "--check"),
        ),
    )


def main() -> int:
    failed: list[str] = []
    for check in build_checks():
        if _run_check(check) != 0:
            failed.append(check.name)

    if failed:
        print("\n[verify] Failed checks:", flush=True)
        for name in failed:
            print(f"  - {name}", flush=True)
        return 1

    print("\n[verify] All local checks passed.", flush=True)
    return 0


if __name__ == "__main__":
    raise SystemExit(main())