66 lines
2.5 KiB
Python
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()) |