reticiulum-specification/tools/verify_all.py

110 lines
3.3 KiB
Python

#!/usr/bin/env python3
"""
Run the complete verifier suite against the versions pinned in requirements.txt.
This is the repository's Tier 2 baseline gate. It refuses to run individual
verifiers when the active Python environment does not contain the exact pinned
RNS and LXMF versions, then runs every tools/verify_*.py script in isolation.
Exit code 0 means every verifier passed. Exit code 1 means the environment
does not match the pins or at least one verifier failed.
"""
from __future__ import annotations
import importlib.metadata
import pathlib
import re
import subprocess
import sys
TOOLS_DIR = pathlib.Path(__file__).resolve().parent
REQUIREMENTS_PATH = TOOLS_DIR / "requirements.txt"
PIN_PATTERN = re.compile(r"^(rns|lxmf)==([A-Za-z0-9_.+-]+)$", re.IGNORECASE)
def load_pins() -> dict[str, str]:
pins: dict[str, str] = {}
for raw_line in REQUIREMENTS_PATH.read_text(encoding="utf-8").splitlines():
line = raw_line.strip()
match = PIN_PATTERN.match(line)
if match:
pins[match.group(1).lower()] = match.group(2)
missing = {"rns", "lxmf"} - pins.keys()
if missing:
names = ", ".join(sorted(missing))
raise RuntimeError(f"missing required pins in {REQUIREMENTS_PATH}: {names}")
return pins
def installed_versions(names: list[str]) -> dict[str, str]:
versions: dict[str, str] = {}
for name in names:
try:
versions[name] = importlib.metadata.version(name)
except importlib.metadata.PackageNotFoundError:
versions[name] = "<not installed>"
return versions
def verifier_paths() -> list[pathlib.Path]:
return sorted(
path
for path in TOOLS_DIR.glob("verify_*.py")
if path.name != pathlib.Path(__file__).name
)
def main() -> int:
try:
pins = load_pins()
except (OSError, RuntimeError) as exc:
print(f"FAIL baseline configuration: {exc}")
return 1
installed = installed_versions(sorted(pins))
mismatches = [
f"{name}: installed {installed[name]}, pinned {pins[name]}"
for name in sorted(pins)
if installed[name] != pins[name]
]
print(f"Python: {sys.executable}")
print("Pinned environment: " + ", ".join(
f"{name}=={pins[name]}" for name in sorted(pins)
))
if mismatches:
print("FAIL environment does not match tools/requirements.txt:")
for mismatch in mismatches:
print(f" - {mismatch}")
return 1
verifiers = verifier_paths()
if not verifiers:
print("FAIL no verifier scripts found")
return 1
failures: list[tuple[str, int]] = []
for index, path in enumerate(verifiers, start=1):
print(f"\n=== [{index}/{len(verifiers)}] {path.name} ===", flush=True)
result = subprocess.run([sys.executable, str(path)], cwd=TOOLS_DIR.parent)
if result.returncode != 0:
failures.append((path.name, result.returncode))
print("\n=== Verification summary ===")
print(f"Passed: {len(verifiers) - len(failures)}")
print(f"Failed: {len(failures)}")
if failures:
for name, returncode in failures:
print(f" - {name}: exit {returncode}")
return 1
print("ALL VERIFIERS PASS")
return 0
if __name__ == "__main__":
raise SystemExit(main())