27 lines
4.3 KiB
Python
27 lines
4.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Generate deterministic browser/performance matrix evidence."""
|
|
|
|
from __future__ import annotations
|
|
import argparse, hashlib, json, subprocess
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
CONTEXT=Path("context-lock.json"); REG03=Path("coverage/recovery-offline-fault-matrix.report.json"); REG01=Path("coverage/full-configuration-startup-matrix.report.json"); BROWSER=Path("coverage/browser-matrix-remediation.report.json"); FE4=Path("coverage/frontend-m4.report.json"); GATE=Path("coverage/release-candidate-gate.report.json"); OUTPUT=Path("coverage/browser-performance-matrix.report.json")
|
|
def canonical(v:Any)->str:return json.dumps(v,ensure_ascii=False,sort_keys=True,separators=(",",":"))
|
|
def digest(v:Any)->str:return hashlib.sha256(canonical(v).encode()).hexdigest()
|
|
def artifact(root:Path,path:Path,role:str)->dict[str,Any]:
|
|
p=root/path
|
|
return {"path":path.as_posix(),"role":role,"status":"present","bytes":p.stat().st_size,"sha256":hashlib.sha256(p.read_bytes()).hexdigest()} if p.is_file() else {"path":path.as_posix(),"role":role,"status":"missing"}
|
|
def run(root:Path):
|
|
outs=[]
|
|
for _ in range(2):
|
|
x=subprocess.run(["node","web/app/test_browser_performance.mjs"],cwd=root,check=False,capture_output=True,text=True); lines=[l.strip() for l in x.stdout.splitlines() if l.lstrip().startswith("{")]; sample=json.loads(lines[-1]) if x.returncode==0 and lines else {}; outs.append({"status":"passed" if x.returncode==0 else "blocked","exit_code":x.returncode,"sample":sample,"stdout_sha256":digest(x.stdout),"stderr_sha256":digest(x.stderr)})
|
|
return outs
|
|
def generate(root:Path,output:Path=OUTPUT)->dict[str,Any]:
|
|
root=root.resolve(); lock=json.loads((root/CONTEXT).read_text()); reg03=json.loads((root/REG03).read_text()); reg01=json.loads((root/REG01).read_text()); browser=json.loads((root/BROWSER).read_text()); fe4=json.loads((root/FE4).read_text()); gate=json.loads((root/GATE).read_text()); runs=run(root); first,second=runs
|
|
checks={"reg01_dependency":{"status":"verified" if reg01.get("implementation_status")=="verified" else "blocked"},"reg03_dependency":{"status":"verified" if reg03.get("implementation_status")=="verified" else "blocked"},"frontend_dependency":{"status":"verified" if fe4.get("implementation_status")=="verified" else "blocked"},"chromium_environment":{"status":"verified" if browser.get("checks",{}).get("chromium_probe",{}).get("status")=="verified" else "blocked"},"firefox_not_in_scope":{"status":"verified","reason":"Firefox is excluded from the current test scope"},"safari_not_in_scope":{"status":"verified","reason":"Safari is excluded from the current test scope"},"repeat_determinism":{"status":"verified" if first==second else "blocked"},"release_stop_preserved":{"status":"verified" if gate.get("release_action")=="STOP_RELEASE" and gate.get("candidate_eligible") is False else "blocked","release_action":gate.get("release_action")}}
|
|
ok=all(v["status"]=="verified" for v in checks.values()); report={"schema":"browser-performance-matrix.v1","context_id":lock.get("context_id"),"task_id":"REG-04","status":"partial" if ok else "blocked","implementation_status":"verified" if ok else "blocked","candidate_eligible":False,"release_action":"STOP_RELEASE","inputs":[artifact(root,CONTEXT,"context_lock"),artifact(root,REG01,"full_configuration_matrix"),artifact(root,REG03,"recovery_offline_fault_matrix"),artifact(root,BROWSER,"browser_matrix_remediation"),artifact(root,FE4,"frontend_m4"),artifact(root,GATE,"release_candidate_gate")],"checks":checks,"runs":runs,"environment":{"scope":["chromium"],"firefox":"out_of_scope","safari":"out_of_scope","minimums":"TBD_in_locked_matrix"},"next_transition":"execute K8-REL-17 release gate refresh after implementation evidence","report_sha256":None}; report["report_sha256"]=digest({k:v for k,v in report.items() if k!="report_sha256"}); dest=output if output.is_absolute() else root/output; dest.parent.mkdir(parents=True,exist_ok=True); dest.write_text(json.dumps(report,ensure_ascii=False,sort_keys=True,indent=2)+"\n"); return report
|
|
def main()->int:
|
|
p=argparse.ArgumentParser();p.add_argument("--repo-root",type=Path,default=Path(__file__).resolve().parents[1]);p.add_argument("--output",type=Path,default=OUTPUT);a=p.parse_args();r=generate(a.repo_root.resolve(),a.output);print(f"browser_performance_matrix={r['status']} scope=chromium");return 0
|
|
if __name__=="__main__":raise SystemExit(main())
|