#!/usr/bin/env python3 """Run repository validation commands for the Harness template.""" from __future__ import annotations import json import os import subprocess import sys from pathlib import Path DEFAULT_NPM_ORDER = ("lint", "build", "test") def load_env_commands() -> list[str]: raw = os.environ.get("HARNESS_VALIDATION_COMMANDS", "") return [line.strip() for line in raw.splitlines() if line.strip()] def load_npm_commands(root: Path) -> list[str]: package_json = root / "package.json" if not package_json.exists(): return [] try: payload = json.loads(package_json.read_text(encoding="utf-8")) except json.JSONDecodeError: return [] scripts = payload.get("scripts", {}) if not isinstance(scripts, dict): return [] commands = [] for name in DEFAULT_NPM_ORDER: value = scripts.get(name) if isinstance(value, str) and value.strip(): commands.append(f"npm run {name}") return commands def discover_commands(root: Path) -> list[str]: env_commands = load_env_commands() if env_commands: return env_commands return load_npm_commands(root) def run_command(command: str, root: Path) -> subprocess.CompletedProcess: return subprocess.run( command, cwd=root, shell=True, capture_output=True, text=True, ) def emit_stream(prefix: str, content: str, *, stream) -> None: text = content.strip() if not text: return print(prefix, file=stream) print(text, file=stream) def main() -> int: root = Path(__file__).resolve().parent.parent commands = discover_commands(root) if not commands: print("No validation commands configured.") print("Set HARNESS_VALIDATION_COMMANDS or add npm scripts for lint/build/test.") return 0 for command in commands: print(f"$ {command}") result = run_command(command, root) emit_stream("[stdout]", result.stdout, stream=sys.stdout) emit_stream("[stderr]", result.stderr, stream=sys.stderr) if result.returncode != 0: print(f"Validation failed: {command}", file=sys.stderr) return result.returncode print("Validation succeeded.") return 0 if __name__ == "__main__": raise SystemExit(main())