69 lines
3.9 KiB
Python
Executable File
69 lines
3.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Compiler-independent source-size and test-isolation contracts for non-Rust modules."""
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
import os
|
|
import re
|
|
import shutil
|
|
import subprocess
|
|
import tempfile
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
MAX_LINES = 500
|
|
|
|
|
|
def lines(path: Path) -> int:
|
|
return len(path.read_text(encoding="utf-8").splitlines())
|
|
|
|
# Browser implementation modules are bounded. QA harnesses under tools/checks are checked separately.
|
|
for path in sorted((ROOT / "src/admin/web").rglob("*.js")):
|
|
assert lines(path) <= MAX_LINES, f"{path.relative_to(ROOT)} has {lines(path)} lines (max {MAX_LINES})"
|
|
|
|
# Docker Agent implementation and Go tests are separate files and all remain bounded.
|
|
for path in sorted((ROOT / "docker-agent").glob("*.go")):
|
|
assert lines(path) <= MAX_LINES, f"{path.relative_to(ROOT)} has {lines(path)} lines (max {MAX_LINES})"
|
|
if not path.name.endswith("_test.go"):
|
|
text = path.read_text(encoding="utf-8")
|
|
assert not re.search(r"(?m)^func\s+Test[A-Z]", text), f"Go test remains in implementation file: {path.relative_to(ROOT)}"
|
|
|
|
# Application-coupled Python entry points are split from external QA/dev tooling.
|
|
for directory in ("scripts/runtime", "scripts/build", "scripts/deploy", "scripts/migration"):
|
|
for path in sorted((ROOT / directory).glob("*.py")):
|
|
assert lines(path) <= MAX_LINES, f"{path.relative_to(ROOT)} has {lines(path)} lines (max {MAX_LINES})"
|
|
|
|
for old in (ROOT / "src/admin/web/app.js", ROOT / "src/admin/web/vhosts.js"):
|
|
assert not old.exists(), f"oversized browser monolith returned: {old.relative_to(ROOT)}"
|
|
for required in (
|
|
"src/admin/web/app/core.js", "src/admin/web/app/session-resume.js", "src/admin/web/app/preferences.js", "src/admin/web/app/config-history.js", "src/admin/web/app/runtime.js", "src/admin/web/app/settings.js",
|
|
"src/admin/web/vhosts/core.js", "src/admin/web/vhosts/protocol.js", "src/admin/web/vhosts/rates.js", "src/admin/web/vhosts/health.js", "src/admin/web/vhosts/editor.js", "src/admin/web/vhosts/render.js",
|
|
"docker-agent/model.go", "docker-agent/docker.go", "docker-agent/network.go",
|
|
"docker-agent/certificate.go", "docker-agent/server.go",
|
|
"scripts/deploy/deploy_core.py", "scripts/deploy/deploy_runtime.py",
|
|
"scripts/migration/migrate_npm_core.py", "scripts/migration/migrate_npm_api.py",
|
|
):
|
|
assert (ROOT / required).is_file(), f"missing split source module: {required}"
|
|
|
|
|
|
# When Node is available, parse every standalone browser module and both assembled public bundles.
|
|
node = shutil.which("node")
|
|
if node:
|
|
env = dict(os.environ, TERM=os.environ.get("TERM", "xterm"))
|
|
standalone = list((ROOT / "src/admin/web").rglob("*.js"))
|
|
for path in sorted(standalone):
|
|
subprocess.run([node, "--check", str(path)], check=True, env=env, stdout=subprocess.DEVNULL)
|
|
from web_assets import read_app_js, read_vhosts_js
|
|
browser_markup = (ROOT / "src/admin/web/index.html").read_text(encoding="utf-8")
|
|
assert browser_markup.count('<script defer="" src="/assets/') == 1, "one private JS bundle prevents module race"
|
|
assert '/assets/app___RUSTPROXY_ASSET_ID__.js' in browser_markup
|
|
with tempfile.TemporaryDirectory(prefix="rustproxy-js-contract-") as directory:
|
|
temporary = Path(directory)
|
|
for name, content in (("app.js", read_app_js(ROOT)), ("vhosts.js", read_vhosts_js(ROOT))):
|
|
target = temporary / name
|
|
target.write_text(content, encoding="utf-8")
|
|
subprocess.run([node, "--check", str(target)], check=True, env=env, stdout=subprocess.DEVNULL)
|
|
# The public vhosts asset wraps three individually valid source modules in one private IIFE.
|
|
# Every source part is parsed above; this additional check keeps the assembled browser asset valid.
|
|
|
|
print(f"PASS: browser, Docker Agent and application-coupled Python modules are <= {MAX_LINES} lines, tooling is separated, tests are isolated, and browser source boundaries parse cleanly.")
|