main
Drew Owens 0.11.4 source 8889116 1d ago
#!/usr/bin/env python3
"""check-live-report.py <report.json> <version> <last-code-commit-epoch> [--exe-sha <sha256>] [--zip-sha <sha256>]
- the gate behind tools/release.sh --require-live (0.11.0).

Exit 0 only for a tools/cswa-check.py report that ran every CSWA part and passed them all, was made by THIS
bridge version, did not stop, and is NEWER than the last commit that touched code. EVERY part means every spec
shipped in resources/cswa/ (0.11.4): a run narrowed with --only proves nothing about the parts it left out, and a
part may be skipped only for the reason the checker gives a part that needs an op the bridge lacks.

WHICH BUILD RAN (the canary gate): with --exe-sha, the report must say (report.bridge.exeSha256, read back from the
test machine's INSTALLED exe by cswa-check) that it ran exactly that exe - the one inside the zip being published.
With --zip-sha, a report that names the zip it was installed from (report.bridge.zipSha256) must name that zip.
"""
import glob, json, os, sys

ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


def shipped_ids(root=ROOT):
    return sorted(json.load(open(p))["id"] for p in glob.glob(os.path.join(root, "resources", "cswa", "*.json")))


def problems(r, ver, code_at, shipped=None, exe_sha=None, zip_sha=None):
    bad = []
    if r.get("tool") != "cswa-check":
        bad.append(f"it is not a cswa-check report (tool={r.get('tool')!r})")
    if r.get("bridgeVersion") != ver:
        bad.append(f"it was made by bridge {r.get('bridgeVersion')}, not {ver}")
    if not r.get("ran"):
        bad.append("it ran no part")
    if r.get("passed") != r.get("ran") or not r.get("allPassed"):
        bad.append(f"{r.get('summary')} - not 100 %")
    if r.get("stopped"):
        bad.append(f"the run STOPPED ({r.get('stopped')})")
    if int(r.get("whenEpoch") or 0) <= code_at:
        bad.append(f"it is OLDER than the last code commit ({r.get('when')} vs epoch {code_at})")
    if shipped is not None:
        parts = {p.get("id"): p for p in r.get("parts") or [] if isinstance(p, dict)}
        missing = [i for i in shipped if i not in parts]
        if missing:
            bad.append(f"it did not run {len(missing)} of the {len(shipped)} shipped parts ({', '.join(missing)}): a partial run (--only?) proves nothing about them")
        for i, p in parts.items():
            why = p.get("skipped")
            if why and not str(why).startswith("needs ops the bridge does not have yet"):
                bad.append(f"{i} was skipped ({why}) - only a part needing an op the bridge lacks may be")
    b = r.get("bridge") if isinstance(r.get("bridge"), dict) else {}
    if exe_sha:
        got = b.get("exeSha256")
        if not got:
            bad.append("it does not say which build it ran (no bridge.exeSha256: a cswa-check older than the canary gate, or ab "
                       f"could not read the installed exe back: {b.get('exeWhy') or b.get('why') or 'no bridge facts'}) - re-run tools/cswa-check.py")
        elif got.lower() != exe_sha.lower():
            bad.append(f"it ran exe {got[:12]}…, not the one being published ({exe_sha[:12]}…): install the canary on the test machine and run it again")
    if zip_sha and b.get("zipSha256") and b["zipSha256"].lower() != zip_sha.lower():
        bad.append(f"it was installed from zip {b['zipSha256'][:12]}…, not the canary being published ({zip_sha[:12]}…)")
    return bad


def main(argv):
    args, opts = [], {}
    it = iter(argv[1:])
    for a in it:
        if a in ("--exe-sha", "--zip-sha"):
            opts[a] = next(it, "")
        else:
            args.append(a)
    if len(args) != 3:
        print(__doc__)
        return 2
    path, ver, code_at = args[0], args[1], int(args[2] or 0)
    if not os.path.isfile(path):
        print(f"  the report {path} does not exist")
        return 1
    r = json.load(open(path))
    bad = problems(r, ver, code_at, shipped_ids(), opts.get("--exe-sha") or None, opts.get("--zip-sha") or None)
    for b in bad:
        print("  " + b)
    if bad:
        return 1
    which = ""
    if opts.get("--exe-sha"):
        which = f"; it ran exe {opts['--exe-sha'][:12]}…, the one being published"
    print(f"live CSWA report OK: {r.get('summary')} on SOLIDWORKS {(r.get('solidworks') or {}).get('majorVersion')}, {r.get('when')}{which}")
    return 0


if __name__ == "__main__":
    sys.exit(main(sys.argv))