Files

66 lines
2.5 KiB
Python

#!/usr/bin/env python3
"""Combine normalized tool reports into one schema-valid project report."""
import argparse
import json
from pathlib import Path
from jsonschema import Draft202012Validator, FormatChecker
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("inputs", nargs="+", type=Path)
parser.add_argument("--output", type=Path, required=True)
parser.add_argument("--schema", type=Path, default=Path("schemas/test-report.schema.json"))
args = parser.parse_args()
reports = [json.loads(path.read_text(encoding="utf-8")) for path in args.inputs]
if not reports:
parser.error("at least one normalized report is required")
project = reports[0]["project"]
run = reports[0]["run"]
results = []
raw_artifacts = []
for report in reports:
if report["project"]["id"] != project["id"]:
parser.error("all reports must belong to the same project")
tool = report["tool"]
for result in report["results"]:
combined = dict(result)
combined["id"] = f"{tool['id']}:{result['id']}"
combined["category"] = f"{tool['name']} | {result.get('category', '')}".rstrip(" |")
results.append(combined)
raw_artifacts.extend(report.get("raw_artifacts", []))
counts = dict.fromkeys(("passed", "failed", "errors", "skipped", "review"), 0)
for result in results:
counter = "errors" if result["status"] == "error" else result["status"]
counts[counter] += 1
scored = counts["passed"] + counts["failed"]
aggregate = {
"schema_version": "1.0.0",
"run": run,
"project": project,
"tool": {"id": "combined", "name": "Combined test methodologies", "adapter_version": "1.0.0"},
"target": {"id": "project-scope", "type": "test_environment", "groups": []},
"summary": {
"total": len(results),
**counts,
"score": round(counts["passed"] / scored * 100, 2) if scored else 0,
},
"results": results,
"raw_artifacts": sorted(set(raw_artifacts)),
}
schema = json.loads(args.schema.read_text(encoding="utf-8"))
Draft202012Validator(schema, format_checker=FormatChecker()).validate(aggregate)
args.output.parent.mkdir(parents=True, exist_ok=True)
args.output.write_text(json.dumps(aggregate, indent=2) + "\n", encoding="utf-8")
print(f"Aggregated {len(reports)} reports with {len(results)} results")
return 0
if __name__ == "__main__":
raise SystemExit(main())