mirror of
https://github.com/elder-plinius/OBLITERATUS.git
synced 2026-08-17 16:37:30 +02:00
132 lines
4.5 KiB
Python
132 lines
4.5 KiB
Python
#!/usr/bin/env python3
|
|
"""Run one conditional pytest gate and reject empty or silently skipped evidence."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import importlib.util
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
from datetime import datetime, timezone
|
|
from pathlib import Path
|
|
from xml.etree import ElementTree
|
|
|
|
|
|
GATES = {
|
|
"model-download-runtime": "tests/conditional/test_model_download_runtime.py",
|
|
"external-evaluation": "tests/conditional/test_external_evaluation_runtime.py",
|
|
"network-services": "tests/conditional/test_network_services.py",
|
|
"operator-ui": "tests/conditional/test_operator_ui.py",
|
|
"cuda-runtime": "tests/conditional/test_cuda_runtime.py",
|
|
"bitsandbytes-runtime": "tests/conditional/test_cuda_runtime.py",
|
|
"mps-runtime": "tests/conditional/test_mps_runtime.py",
|
|
"mlx-runtime": "tests/conditional/test_mlx_runtime.py",
|
|
"remote-execution": "tests/conditional/test_remote_runtime.py",
|
|
}
|
|
|
|
|
|
def missing_prerequisites(gate: str) -> list[str]:
|
|
missing: list[str] = []
|
|
if gate in {"cuda-runtime", "bitsandbytes-runtime", "mps-runtime"}:
|
|
import torch
|
|
|
|
if gate.startswith("cuda") or gate.startswith("bitsandbytes"):
|
|
if not torch.cuda.is_available():
|
|
missing.append("a CUDA-capable PyTorch runtime")
|
|
elif not (hasattr(torch.backends, "mps") and torch.backends.mps.is_available()):
|
|
missing.append("an available Apple MPS backend")
|
|
if gate == "bitsandbytes-runtime" and importlib.util.find_spec("bitsandbytes") is None:
|
|
missing.append("bitsandbytes")
|
|
if gate == "mlx-runtime":
|
|
for module in ("mlx", "mlx_lm"):
|
|
if importlib.util.find_spec(module) is None:
|
|
missing.append(module)
|
|
if gate == "remote-execution":
|
|
for variable in (
|
|
"OBLITERATUS_REMOTE_HOST",
|
|
"OBLITERATUS_REMOTE_USER",
|
|
"OBLITERATUS_REMOTE_KEY",
|
|
"OBLITERATUS_REMOTE_KNOWN_HOSTS",
|
|
):
|
|
if not os.environ.get(variable):
|
|
missing.append(variable)
|
|
return missing
|
|
|
|
|
|
def counts(junit_path: Path) -> dict[str, int]:
|
|
root = ElementTree.parse(junit_path).getroot()
|
|
suites = [root] if root.tag == "testsuite" else list(root.findall("testsuite"))
|
|
return {
|
|
key: sum(int(suite.attrib.get(key, "0")) for suite in suites)
|
|
for key in ("tests", "failures", "errors", "skipped")
|
|
}
|
|
|
|
|
|
def write_report(path: Path, gate: str, status: str, **extra: object) -> None:
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
payload = {
|
|
"schema_version": 1,
|
|
"gate": gate,
|
|
"status": status,
|
|
"generated_at": datetime.now(timezone.utc).isoformat(),
|
|
"git_sha": os.environ.get("GITHUB_SHA", "local"),
|
|
**extra,
|
|
}
|
|
path.write_text(json.dumps(payload, indent=2, sort_keys=True) + "\n")
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("gate", choices=sorted(GATES))
|
|
parser.add_argument("--evidence-dir", type=Path, default=Path("conditional-evidence"))
|
|
parser.add_argument("--allow-missing", action="store_true")
|
|
args = parser.parse_args()
|
|
report = args.evidence_dir / f"{args.gate}.json"
|
|
junit = args.evidence_dir / f"{args.gate}.xml"
|
|
|
|
missing = missing_prerequisites(args.gate)
|
|
if missing:
|
|
message = "Missing prerequisites: " + ", ".join(missing)
|
|
write_report(report, args.gate, "not_run", reason=message)
|
|
print(message, file=sys.stderr)
|
|
return 0 if args.allow_missing else 2
|
|
|
|
command = [
|
|
sys.executable,
|
|
"-m",
|
|
"pytest",
|
|
GATES[args.gate],
|
|
"--no-cov",
|
|
"-q",
|
|
f"--junitxml={junit}",
|
|
]
|
|
result = subprocess.run(command, check=False)
|
|
if not junit.is_file():
|
|
write_report(report, args.gate, "failed", exit_code=result.returncode, reason="no JUnit")
|
|
return result.returncode or 1
|
|
|
|
result_counts = counts(junit)
|
|
passed = (
|
|
result.returncode == 0
|
|
and result_counts["tests"] > 0
|
|
and result_counts["failures"] == 0
|
|
and result_counts["errors"] == 0
|
|
and result_counts["skipped"] == 0
|
|
)
|
|
write_report(
|
|
report,
|
|
args.gate,
|
|
"passed" if passed else "failed",
|
|
exit_code=result.returncode,
|
|
counts=result_counts,
|
|
)
|
|
if not passed:
|
|
print(f"conditional gate did not produce unskipped green evidence: {result_counts}")
|
|
return 0 if passed else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|