#!/usr/bin/env python3 import sys import json import logging from pathlib import Path logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s") def validate_step(step, idx): required_keys = { "id": str, "name": str, "enabled": bool, "status": str, "exit_code": int, "duration_ms": int, "started_at": str, "ended_at": str, "command": str } for key, expected_type in required_keys.items(): if key not in step: raise ValueError(f"Step[{idx}] missing required key: '{key}'") if not isinstance(step[key], expected_type): raise ValueError(f"Step[{idx}] '{key}' must be {expected_type.__name__}, got {type(step[key]).__name__}") def validate_report(report_path: Path): if not report_path.exists(): raise FileNotFoundError(f"Report file not found: {report_path}") try: report = json.loads(report_path.read_text(encoding="utf-8")) except json.JSONDecodeError as e: raise ValueError(f"Invalid JSON format: {e}") # Root Level if "schema_version" not in report or report["schema_version"] != "1.0": raise ValueError("Invalid or missing schema_version. Expected '1.0'") if "generated_at" not in report or not isinstance(report["generated_at"], str): raise ValueError("Missing or invalid 'generated_at' string") # Git if "git" not in report or not isinstance(report["git"], dict): raise ValueError("Missing or invalid 'git' object") if "sha" not in report["git"] or not isinstance(report["git"]["sha"], str): raise ValueError("Missing or invalid 'git.sha'") if "branch" not in report["git"] or not isinstance(report["git"]["branch"], str): raise ValueError("Missing or invalid 'git.branch'") # Overall if "overall" not in report or not isinstance(report["overall"], dict): raise ValueError("Missing or invalid 'overall' object") for key in ["duration_ms", "passed", "failed", "skipped", "total"]: if key not in report["overall"] or not isinstance(report["overall"][key], int): raise ValueError(f"Missing or invalid integer 'overall.{key}'") if "status" not in report["overall"] or not isinstance(report["overall"]["status"], str): raise ValueError("Missing or invalid string 'overall.status'") # Steps if "steps" not in report or not isinstance(report["steps"], list): raise ValueError("Missing or invalid 'steps' array") for idx, step in enumerate(report["steps"]): validate_step(step, idx) logging.info(f"Report {report_path} passed schema validation (v1.0).") if __name__ == '__main__': if len(sys.argv) < 2: logging.error("Usage: validate_regression_report.py ") sys.exit(1) try: validate_report(Path(sys.argv[1])) except Exception as e: logging.error(f"Validation failed: {e}") sys.exit(1)