migration: close candidate maintenance audit

This commit is contained in:
leefer
2026-07-31 21:24:37 +08:00
parent faac60b1a6
commit 406118bba6
17 changed files with 844 additions and 120 deletions
+85 -7
View File
@@ -5,10 +5,15 @@ import shutil
import sqlite3
import subprocess
import sys
import time
import urllib.error
import urllib.request
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
FRONTEND_ROOT = ROOT / "frontend"
E2E_URL = "http://127.0.0.1:8876/index.html"
def run(label: str, command: list[str]) -> None:
@@ -28,8 +33,63 @@ def verify_database() -> None:
print(f"\n[database] integrity_check=ok size={database.stat().st_size}")
def url_reachable(url: str) -> bool:
try:
with urllib.request.urlopen(url, timeout=1) as response:
return response.status == 200
except (OSError, urllib.error.URLError):
return False
def start_e2e_server() -> subprocess.Popen[bytes] | None:
if url_reachable(E2E_URL):
print(f"\n[e2e-server] reusing {E2E_URL}")
return None
creation_flags = subprocess.CREATE_NO_WINDOW if sys.platform == "win32" else 0
process = subprocess.Popen(
[
sys.executable,
"-m",
"http.server",
"8876",
"--bind",
"127.0.0.1",
"--directory",
"frontend",
],
cwd=ROOT,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
creationflags=creation_flags,
)
deadline = time.monotonic() + 15
while time.monotonic() < deadline:
if process.poll() is not None:
raise RuntimeError("Playwright static server exited before becoming ready")
if url_reachable(E2E_URL):
print(f"\n[e2e-server] started {E2E_URL}")
return process
time.sleep(0.1)
stop_e2e_server(process)
raise RuntimeError("Playwright static server did not become ready within 15 seconds")
def stop_e2e_server(process: subprocess.Popen[bytes] | None) -> None:
if process is None:
return
process.terminate()
try:
process.wait(timeout=5)
except subprocess.TimeoutExpired:
process.kill()
process.wait(timeout=5)
print("\n[e2e-server] stopped")
def main() -> int:
parser = argparse.ArgumentParser(description="Verify the governance regression baseline")
parser = argparse.ArgumentParser(
description="Verify the modular preservation candidate"
)
parser.add_argument(
"--e2e",
action="store_true",
@@ -38,19 +98,37 @@ def main() -> int:
args = parser.parse_args()
run("python", [sys.executable, "-m", "unittest", "discover", "-s", "tests"])
run(
"api-registry",
[sys.executable, "tools/build_api_registry.py", "--check"],
)
run(
"architecture-inventory",
[sys.executable, "tools/build_architecture_inventory.py", "--check"],
)
node = shutil.which("node")
if not node:
raise RuntimeError("node is required for JavaScript syntax checks")
for script in ("static/app.js", "static/heaven-loading-v2.js"):
run("javascript", [node, "--check", script])
scripts = sorted(FRONTEND_ROOT.rglob("*.js"))
if not scripts:
raise RuntimeError(f"no JavaScript files found under {FRONTEND_ROOT}")
for script in scripts:
run(
"javascript",
[node, "--check", script.relative_to(ROOT).as_posix()],
)
run("patch", ["git", "diff", "--check"])
verify_database()
if args.e2e:
npm = shutil.which("npm.cmd" if sys.platform == "win32" else "npm")
if not npm:
raise RuntimeError("npm is required for the Playwright suite")
run("playwright", [npm, "run", "test:e2e"])
npx = shutil.which("npx.cmd" if sys.platform == "win32" else "npx")
if not npx:
raise RuntimeError("npx is required for the Playwright suite")
server = start_e2e_server()
try:
run("playwright", [npx, "playwright", "test", "--reporter=dot"])
finally:
stop_e2e_server(server)
print("\nBaseline verification passed.")
return 0