Brain-5D-Space / scripts /generate_baseline.py
github-actions[bot]
Sync: publish Space API fix
5e0b58b
Raw History Blame Contribute Delete
4.38 kB
"""Generate tests/test_baseline.json from a completed full-suite run.
Usage:
python -m pytest tests/ -q
python scripts/generate_baseline.py
The script reads the pytest output from the last run (or you can pipe it),
computes the canonical source digest, and writes tests/test_baseline.json.
This is the ONLY canonical baseline writer. Never manually patch the digest.
"""
from __future__ import annotations
import json
import re
import subprocess
import sys
import time
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parent.parent
BASELINE_PATH = REPO_ROOT / "tests" / "test_baseline.json"
# Ensure src/ is importable
sys.path.insert(0, str(REPO_ROOT))
def current_git_head() -> str | None:
try:
result = subprocess.run(
["git", "rev-parse", "HEAD"],
capture_output=True,
text=True,
timeout=10,
cwd=str(REPO_ROOT),
)
return result.stdout.strip() if result.returncode == 0 else None
except Exception:
return None
def main() -> int:
from src.dashboard.verification import compute_source_tree_digest
# Compute canonical digest
digest = compute_source_tree_digest(REPO_ROOT)
if digest is None:
print("ERROR: Failed to compute source tree digest")
return 1
head = current_git_head()
print(f"Canonical digest: {digest}")
print(f"HEAD: {head}")
print()
# Run the full suite
print("Running full test suite...")
result = subprocess.run(
[sys.executable, "-m", "pytest", "tests/", "-q"],
capture_output=True,
text=True,
timeout=600,
cwd=str(REPO_ROOT),
)
output = result.stdout + result.stderr
# Parse results
passed = 0
failed = 0
skipped = 0
xfailed = 0
xpassed = 0
collection_errors = 0
match = re.search(r"(\d+) passed", output)
if match:
passed = int(match.group(1))
match = re.search(r"(\d+) failed", output)
if match:
failed = int(match.group(1))
match = re.search(r"(\d+) skipped", output)
if match:
skipped = int(match.group(1))
match = re.search(r"(\d+) xfailed", output)
if match:
xfailed = int(match.group(1))
match = re.search(r"(\d+) xpassed", output)
if match:
xpassed = int(match.group(1))
# Detect collection errors
if "errors" in output and "collection" in output.lower():
match = re.search(r"(\d+) error", output)
if match:
collection_errors = int(match.group(1))
print(
f" {passed} passed, {failed} failed, {skipped} skipped, {xfailed} xfailed, {xpassed} xpassed, {collection_errors} collection errors"
)
print()
# Build baseline
baseline: dict[str, object] = {
"tested_commit": head,
"tested_tree_digest": digest,
"tree_digest_paths": [
"src/",
"configs/",
"research/schemas/",
"pyproject.toml",
"tests/",
],
"tree_digest_excludes": ["tests/test_baseline.json"],
"timestamp": time.strftime("%Y-%m-%dT%H:%M:%S%z"),
"python": f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}",
"full_collection": {
"status": "passed" if collection_errors == 0 else "failed",
"collection_errors": collection_errors,
},
"full_suite": {
"command": "python -m pytest tests/ -q",
"passed": passed,
"failed": failed,
"skipped": skipped,
"xfailed": xfailed,
"xpassed": xpassed,
},
}
# Add skipped reasons if any
if skipped > 0:
reasons: list[str] = []
for line in output.split("\n"):
if "SKIPPED" in line:
reasons.append(
line.split("SKIPPED")[-1].strip().lstrip("[").rstrip("]")
)
if reasons:
baseline["full_suite"]["skipped_reasons"] = reasons # type: ignore[typeddict-item]
# Write baseline
BASELINE_PATH.write_text(
json.dumps(baseline, indent=2, ensure_ascii=False) + "\n",
encoding="utf-8",
)
print(f"Baseline written to: {BASELINE_PATH}")
print(f" tested_tree_digest = {digest}")
return 0
if __name__ == "__main__":
sys.exit(main())