Files
go-omni/scripts/verifyErrorInheritanceRelease.py

81 lines
4.5 KiB
Python

#!/usr/bin/env python3
"""Install the released CLI in a fresh cache, then test its generated consumer.
The fixture tests Go-owned App catalogs on generated routes, early middleware, raw responses,
body limits, independent route policies and regeneration protection. Only local temporary resources
are used; the framework and CLI are fetched from the specified remote version.
"""
import argparse
import hashlib
import json
import os
from pathlib import Path
import re
import subprocess
import tempfile
import time
ROOT = Path(__file__).resolve().parents[1]
MODULE = "git.yuntuo.hk/k2safe/go-omni"
def run(args, cwd, env, timeout=300):
result = subprocess.run([str(arg) for arg in args], cwd=cwd, env=env,
capture_output=True, text=True, timeout=timeout)
output = re.sub(r"https://[^/@\s]+:[^/@\s]+@", "https://", result.stdout + result.stderr)
if result.returncode:
raise RuntimeError(f"{args[0]} failed ({result.returncode}):\n{output}")
return output
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--version", required=True)
parser.add_argument("--report", type=Path, default=ROOT / "performance/errorInheritanceRemote.json")
args = parser.parse_args()
if not re.fullmatch(r"v\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?", args.version):
parser.error("a fixed release version is required")
env = {k: v for k, v in os.environ.items() if not k.startswith("GO_OMNI_")}
env.update(GOWORK="off", GOFLAGS="", GOPRIVATE="git.yuntuo.hk", GONOSUMDB="git.yuntuo.hk")
start = time.monotonic()
with tempfile.TemporaryDirectory(prefix="goOmniErrorInheritanceRelease-") as directory:
temp = Path(directory)
(temp / "bin").mkdir()
env.update(GOBIN=str(temp / "bin"), GOMODCACHE=str(temp / "modcache"))
print(f"Installing CLI {args.version} in an empty module cache", flush=True)
run(["go", "install", MODULE + "/cmd/go-omni@" + args.version], temp, env)
cli = temp / "bin/go-omni"
run([cli, "api", "validate", "--api", ROOT / "examples/contracts/errorInheritance.api"], temp, env)
env.update(GO_OMNI_SCAFFOLD_INTEGRATION="1", GO_OMNI_RELEASE_CLI=str(cli), GO_OMNI_RELEASE_VERSION=args.version)
print("Testing remote App catalog inheritance on generated handlers and early middleware", flush=True)
output = run(["go", "test", "-race", "-count=1", "-json", "-timeout=180s",
"./cmd/go-omni/apigen", "-run", "^TestErrorInheritanceConsumer$"], ROOT, env)
events = [json.loads(line) for line in output.splitlines() if line.startswith("{")]
passed = [e["Test"] for e in events if e.get("Action") == "pass" and "Test" in e]
assert passed == ["TestErrorInheritanceConsumer"], output
evidence = "".join(e.get("Output", "") for e in events)
checksum = re.search(r"checksum (h1:\S+); no local replace", evidence)
assert checksum, "consumer did not verify its remote dependency"
report = {
"passed": True, "frameworkVersion": args.version, "frameworkSum": checksum.group(1),
"freshModuleCache": True, "noLocalReplace": True,
"durationSeconds": round(time.monotonic() - start, 2),
"checks": ["remoteCLIInstall", "noAPICatalogRequired", "ordinaryAndGeneratedResponseEquality",
"typedMessageParameters", "configuredUnknownFallback", "independentRouteCatalog",
"rawSuccess", "dataNull", "earlyMiddlewareInheritance", "routeBodyLimit",
"handwrittenServicesPreserved", "generatedConsumerRaceTests", "fixedRemoteModuleChecksum"],
"sourceHashes": {name: hashlib.sha256((ROOT / name).read_bytes()).hexdigest() for name in
("scripts/verifyErrorInheritanceRelease.py", "cmd/go-omni/apigen/errorInheritance_test.go", "cmd/go-omni/apigen/errorCatalog_test.go",
"examples/contracts/errorInheritance.api",
"cmd/go-omni/apigen/testdata/errorInheritance/consumer_test.go",
"cmd/go-omni/apigen/testdata/errorInheritance/service.go",
"cmd/go-omni/apigen/testdata/errorInheritance/emptyService.go",
"cmd/go-omni/apigen/testdata/errorInheritance/bounded.go")},
}
args.report.write_text(json.dumps(report, ensure_ascii=False, indent=2) + "\n")
print(f"PASS remote App error catalog inheritance {args.version}; temporary files removed", flush=True)
if __name__ == "__main__":
main()