feat(ws): release generic WebSocket client and server v0.31.0-preview
This commit is contained in:
91
scripts/verifyWebsocketRelease.py
Normal file
91
scripts/verifyWebsocketRelease.py
Normal file
@@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Verify a fixed WebSocket release and generated routes from an empty module cache."""
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
from verifyErrorInheritanceRelease import run
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
MODULE = "git.yuntuo.hk/k2safe/go-omni"
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--version", required=True)
|
||||
parser.add_argument("--report", type=Path, default=ROOT / "reports/websocket-remote.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")
|
||||
started = time.monotonic()
|
||||
with tempfile.TemporaryDirectory(prefix="goOmniWebsocketRelease-") as directory:
|
||||
temp = Path(directory)
|
||||
(temp / "bin").mkdir()
|
||||
env.update(GOBIN=str(temp / "bin"), GOMODCACHE=str(temp / "modcache"))
|
||||
print(f"Installing remote CLI {args.version} in an empty cache", flush=True)
|
||||
run(["go", "install", MODULE + "/cmd/go-omni@" + args.version], temp, env)
|
||||
cli = temp / "bin/go-omni"
|
||||
starter = temp / "starter"
|
||||
# Verify the installed default, without --framework-version or a local replace.
|
||||
run([cli, "new", "--module", "example.com/websocketRelease", starter], temp, env)
|
||||
run(["go", "mod", "tidy"], starter, env)
|
||||
dependency = json.loads(run(["go", "list", "-m", "-json", MODULE], starter, env))
|
||||
assert dependency["Version"] == args.version and dependency.get("Sum") and not dependency.get("Replace")
|
||||
downloaded = Path(dependency["Dir"])
|
||||
# Add the optional WS dependency only after checking the CLI's default.
|
||||
run(["go", "get", MODULE + "/ws@" + args.version], starter, env)
|
||||
print("Testing downloaded WS, Hub, RPC, observation and App integration with race detection", flush=True)
|
||||
output = run(["go", "test", "-mod=mod", "-race", "-count=1", "-json", "-timeout=180s",
|
||||
MODULE + "/ws/...", MODULE + "/examples/websocketRPC"], starter, env)
|
||||
events = [json.loads(line) for line in output.splitlines() if line.startswith("{")]
|
||||
packages = sorted({e["Package"] for e in events if e.get("Action") == "pass" and "Test" not in e})
|
||||
expected = [MODULE + "/ws" + suffix for suffix in ("", "/hub", "/observe", "/omni", "/rpc")]
|
||||
assert set(expected + [MODULE + "/examples/websocketRPC"]) == set(packages), output
|
||||
tests = sorted(e["Package"] + ":" + e["Test"] for e in events
|
||||
if e.get("Action") == "pass" and "Test" in e and "/" not in e["Test"])
|
||||
echo = run(["go", "run", "-mod=mod", MODULE + "/examples/websocket"], starter, env)
|
||||
assert "hello websocket" in echo and "hello group" in echo, echo
|
||||
rpc = run(["go", "run", "-mod=mod", MODULE + "/examples/websocketRPC"], starter, env)
|
||||
for generation in (1, 2):
|
||||
assert f'connection {generation}: double=42, remote callback="generic Go client", restored=1, event={generation}' in rpc, rpc
|
||||
env.update(GO_OMNI_SCAFFOLD_INTEGRATION="1", GO_OMNI_RELEASE_CLI=str(cli), GO_OMNI_RELEASE_VERSION=args.version)
|
||||
print("Testing generated custom routes and failure cleanup against the fixed remote release", flush=True)
|
||||
output = run(["go", "test", "-race", "-count=1", "-json", "-timeout=180s", "./cmd/go-omni/apigen",
|
||||
"-run", "^TestGeneratedCustomRoutesConsumer$"], downloaded, env)
|
||||
events = [json.loads(line) for line in output.splitlines() if line.startswith("{")]
|
||||
assert any(e.get("Action") == "pass" and e.get("Test") == "TestGeneratedCustomRoutesConsumer" for e in events), output
|
||||
evidence = "".join(e.get("Output", "") for e in events)
|
||||
assert f'checksum {dependency["Sum"]}; no local replace' in evidence, evidence
|
||||
final_dependency = json.loads(run(["go", "list", "-m", "-json", MODULE], starter, env))
|
||||
assert final_dependency["Version"] == args.version and final_dependency["Sum"] == dependency["Sum"]
|
||||
assert not final_dependency.get("Replace")
|
||||
report = {
|
||||
"passed": True, "frameworkVersion": args.version, "frameworkSum": dependency["Sum"],
|
||||
"toolchain": run(["go", "version"], temp, env).strip(),
|
||||
"freshModuleCache": True, "noLocalReplace": True,
|
||||
"durationSeconds": round(time.monotonic() - started, 2),
|
||||
"packages": packages, "tests": tests,
|
||||
"checks": ["remoteCLIInstall", "installedVersionDefault", "fixedRemoteModuleChecksum",
|
||||
"downloadedWebsocketRaceTests", "remoteEchoAndGroupExample", "remoteBidirectionalRPCExample",
|
||||
"remoteTwoConnectionSubscriptionRestore", "generatedCustomRoutesConsumer",
|
||||
"oldServiceWithoutHook", "handwrittenHookPreserved", "customRouteFailureCleanup"],
|
||||
"examples": {"websocket": echo.strip(), "websocketRPC": rpc.strip()},
|
||||
"sourceHashes": {name: hashlib.sha256((downloaded / name).read_bytes()).hexdigest() for name in
|
||||
("scripts/verifyWebsocketRelease.py", "cmd/go-omni/apigen/customRoutes_test.go")},
|
||||
"limitations": ["Functional release acceptance; not a vulnerability scan or browser UI test.",
|
||||
"Known framework HTTP/2 dependency vulnerabilities remain documented in the validation report."],
|
||||
}
|
||||
args.report.parent.mkdir(parents=True, exist_ok=True)
|
||||
args.report.write_text(json.dumps(report, ensure_ascii=False, indent=2) + "\n")
|
||||
print(f"PASS remote WebSocket release {args.version}; temporary files removed", flush=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user