#!/usr/bin/env python3 from __future__ import annotations import os import subprocess import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[1] if hasattr(sys.stdout, "reconfigure"): sys.stdout.reconfigure(encoding="utf-8", errors="replace") if hasattr(sys.stderr, "reconfigure"): sys.stderr.reconfigure(encoding="utf-8", errors="replace") def command_text(command: list[str]) -> str: parts: list[str] = [] for part in command: if any(ch.isspace() for ch in part): parts.append(f'"{part}"') else: parts.append(part) return " ".join(parts) def run_step(name: str, command: list[str]) -> bool: print(f"\n== {name} ==", flush=True) print(f"$ {command_text(command)}", flush=True) env = os.environ.copy() env["PYTHONIOENCODING"] = "utf-8" env["PYTHONUTF8"] = "1" env["PIO_FORCE_COLOR"] = "0" result = subprocess.run(command, cwd=ROOT, env=env) if result.returncode != 0: print(f"FAILED: {name} exited with {result.returncode}", flush=True) return False print(f"PASSED: {name}", flush=True) return True def main() -> int: python = sys.executable steps = [ ("repository formatting check", [python, "tools/check_format.py"]), ("dependency and PlatformIO policy check", [python, "tools/check_dependencies.py"]), ("production build", [python, "-m", "platformio", "run", "-e", "production"]), ("debug build", [python, "-m", "platformio", "run", "-e", "debug"]), ("test firmware build", [python, "-m", "platformio", "run", "-e", "test"]), ( "compile-only embedded Unity tests", [python, "-m", "platformio", "test", "-e", "test", "--without-uploading", "--without-testing"], ), ("static analysis", [python, "-m", "platformio", "check", "-e", "production", "--fail-on-defect=high"]), ("documentation consistency check", [python, "tools/check_docs.py"]), ("firmware size check", [python, "tools/check_size.py"]), ] failures: list[str] = [] for name, command in steps: if not run_step(name, command): failures.append(name) if failures: print("\nVerification failed:") for failure in failures: print(f"- {failure}") return 1 print("\nVerification passed.") return 0 if __name__ == "__main__": raise SystemExit(main())