Files
soft_quay/scripts/check_core_boundaries.py
T

124 lines
3.2 KiB
Python

#!/usr/bin/env python3
"""Reject UI, Windows, SQLite, and app-layer imports from the core module."""
import json
import os
import pathlib
import subprocess
import sys
FORBIDDEN_IMPORT_PREFIXES = (
"gioui.org",
"golang.org/x/sys/windows",
"github.com/mattn/go-sqlite3",
"modernc.org/sqlite",
"softbox.local/app-modern",
"softbox.local/app-win7",
)
def is_forbidden(import_path):
return any(
import_path == prefix or import_path.startswith(prefix + "/")
for prefix in FORBIDDEN_IMPORT_PREFIXES
)
def decode_json_stream(text):
decoder = json.JSONDecoder()
index = 0
while index < len(text):
while index < len(text) and text[index].isspace():
index += 1
if index >= len(text):
return
value, index = decoder.raw_decode(text, index)
yield value
def list_core_packages(repo_root):
environment = os.environ.copy()
environment["GOWORK"] = "off"
result = subprocess.run(
["go", "list", "-json", "./..."],
cwd=str(repo_root / "core"),
env=environment,
check=False,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True,
)
if result.returncode != 0:
print(result.stderr, file=sys.stderr, end="")
raise SystemExit(result.returncode)
return list(decode_json_stream(result.stdout))
def run_self_test():
cases = (
("gioui.org/layout", True),
("golang.org/x/sys/windows/registry", True),
("modernc.org/sqlite/lib", True),
("softbox.local/app-modern/ui/gio", True),
("context", False),
("crypto/sha256", False),
)
failures = [
import_path
for import_path, expected in cases
if is_forbidden(import_path) != expected
]
if failures:
print(
"ERROR: boundary matcher self-test failed for {}".format(
", ".join(failures)
),
file=sys.stderr,
)
raise SystemExit(1)
print("core boundary matcher self-test passed.")
def main():
if sys.argv[1:] == ["--self-test"]:
run_self_test()
return
if len(sys.argv) != 1:
print(
"usage: python scripts/check_core_boundaries.py [--self-test]",
file=sys.stderr,
)
raise SystemExit(2)
repo_root = pathlib.Path(__file__).resolve().parents[1]
violations = []
for package in list_core_packages(repo_root):
imports = set(package.get("Imports", []))
imports.update(package.get("TestImports", []))
imports.update(package.get("XTestImports", []))
for import_path in sorted(imports):
if is_forbidden(import_path):
violations.append((package["ImportPath"], import_path))
if violations:
for package, import_path in violations:
print(
"ERROR: {} imports forbidden dependency {}".format(
package, import_path
),
file=sys.stderr,
)
raise SystemExit(1)
print(
"core boundary check passed: {} forbidden prefixes absent.".format(
len(FORBIDDEN_IMPORT_PREFIXES)
)
)
if __name__ == "__main__":
main()