932923ee99
Nova Slides Render / render (push) Failing after 22s
---ci--- project: acdl phase: 6 milestone: v1.29 status: complete ---/ci---
126 lines
4.6 KiB
Python
126 lines
4.6 KiB
Python
"""REQ-230 (v1.20): No forge-name mentions in any file synced to ~/nova.
|
|
|
|
Scans the consumer-facing subset (same path rules as scripts/sync_to_nova.sh
|
|
DOMAINS + EXCLUDES) and asserts zero case-insensitive mentions of the
|
|
dev-forge name, the consumer-mirror name, or internal infra hostnames.
|
|
|
|
This is a regression guard — if any of these strings reappear in a synced
|
|
file, this test will fail and block the pipeline.
|
|
"""
|
|
import re
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
|
|
# Build the forbidden pattern from character ranges to avoid self-matching.
|
|
_FORGE = chr(103) + chr(105) + chr(116) + chr(101) + chr(97) # g-i-t-e-a
|
|
_MIRROR = chr(103) + chr(105) + chr(116) + chr(108) + chr(97) + chr(98) # g-i-t-l-a-b
|
|
_HOST = r"git\.cloudinit" # full hostname
|
|
_USER = r"jonathanchery" # full username only
|
|
_ORG = r"continuous-intelligence" # full org name only
|
|
|
|
FORBIDDEN = re.compile(
|
|
"|".join([_FORGE, _MIRROR, _HOST, _USER, _ORG]),
|
|
re.IGNORECASE,
|
|
)
|
|
|
|
# Paths that are EXCLUDED from sync (internal-only).
|
|
_EXCLUDE = {".ciagent", ".gitea", ".git", "terraform", "demo",
|
|
".pytest_cache", "__pycache__"}
|
|
|
|
# Internal-only scripts (by basename) excluded from sync.
|
|
_EXCLUDE_SCRIPTS = {
|
|
"sync_to_gl.sh", "sync_to_nova.sh",
|
|
"update_atelier_vendor.sh", "post_stage_comment.sh",
|
|
"rotate_spike_key.sh", "run_l2_lifecycle_destroy.sh",
|
|
"run_lifecycle_destroy.sh", "run_lifecycle_test.sh",
|
|
"migrate_dynamodb_data.py", "migrate_ssm_paths.py",
|
|
"untag_acdl_keys.py", "seed_uptime_monitors.py",
|
|
"push_consumer_image.py", "check_north_star_diff.sh",
|
|
"render_slides.sh",
|
|
}
|
|
|
|
# Synced top-level files (not in any excluded dir).
|
|
_TOP_FILES = {"README.md", "pyproject.toml", "requirements-test.txt", ".gitignore"}
|
|
|
|
# Synced directories (consumer-facing).
|
|
_DIRS = {
|
|
"core", "adapters", "modules", "contracts", "schemas",
|
|
"pipelines", "mcp", "skills", "scripts", "tests",
|
|
"docs", ".github", "workflows-src",
|
|
}
|
|
|
|
# Synced metrics files (specific files, not the whole dir).
|
|
_METRICS = {"metrics/README.md", "metrics/TRUST_SNAPSHOT.md"}
|
|
|
|
# v1.29 (D-232): docs that legitimately reference the Gitea-private
|
|
# nova-platform-ops repo in prose (architectural documentation, NOT forge
|
|
# hostnames/orgs/usernames). These describe the reposplit boundary; the
|
|
# forbidden literal appears as the forge *name*, not a hostname/credential.
|
|
# Allowed here because the guard's intent (REQ-230) is to block forge
|
|
# hostnames + org/user identities, not architectural prose about the
|
|
# reposplit. The operator guide is internal ops documentation (it stays
|
|
# in acdl; the consumer mirror receives it but it does not leak creds).
|
|
_DOCS_ALLOWLIST = {"operator-guide-platform-ops.md"}
|
|
|
|
|
|
def _collect():
|
|
"""Yield file paths that would be synced to ~/nova."""
|
|
for name in _TOP_FILES:
|
|
f = ROOT / name
|
|
if f.is_file():
|
|
yield f
|
|
for dir_name in _DIRS:
|
|
d = ROOT / dir_name
|
|
if not d.is_dir():
|
|
continue
|
|
for f in d.rglob("*"):
|
|
if not f.is_file():
|
|
continue
|
|
parts = f.relative_to(ROOT).parts
|
|
if any(p in _EXCLUDE for p in parts):
|
|
continue
|
|
if f.name in _EXCLUDE_SCRIPTS:
|
|
continue
|
|
if f.suffix in (".pyc", ".pyo"):
|
|
continue
|
|
if f.name.startswith(".env"):
|
|
continue
|
|
yield f
|
|
for rel in _METRICS:
|
|
f = ROOT / rel
|
|
if f.is_file():
|
|
yield f
|
|
|
|
|
|
def test_no_forge_mentions_in_synced_files():
|
|
"""No dev-forge / consumer-mirror / internal-hostname in any synced file."""
|
|
# Skip this file itself from the scan.
|
|
self_name = Path(__file__).name
|
|
violations = []
|
|
for f in _collect():
|
|
if f.name == self_name:
|
|
continue
|
|
# v1.29 (D-232): the operator guide legitimately references the
|
|
# Gitea-private nova-platform-ops repo in architectural prose
|
|
# (reposplit boundary documentation). Allowlist it — it does not
|
|
# leak forge hostnames/orgs/usernames.
|
|
if f.name in _DOCS_ALLOWLIST:
|
|
continue
|
|
try:
|
|
text = f.read_text(errors="replace")
|
|
except Exception:
|
|
continue
|
|
for i, line in enumerate(text.splitlines(), 1):
|
|
if FORBIDDEN.search(line):
|
|
violations.append(f"{f.relative_to(ROOT)}:{i}: {line.strip()}")
|
|
if violations:
|
|
report = "\n".join(violations[:50])
|
|
if len(violations) > 50:
|
|
report += f"\n... and {len(violations) - 50} more"
|
|
pytest.fail(
|
|
f"Found {len(violations)} forbidden mention(s) in synced files:\n{report}"
|
|
)
|