fix(ci): repair JSON validation syntax, add repo-truth guard, copy robots.txt/index.html in Dockerfile
This commit is contained in:
@@ -52,7 +52,7 @@ jobs:
|
||||
run: |
|
||||
FAIL=0
|
||||
for f in $(find . -name '*.json' -not -path './venv/*'); do
|
||||
if ! python3 -c "import json; json.load(open('$f'))"; then
|
||||
if ! python3 -c "import json; json.load(open('$f'))" 2>/dev/null; then
|
||||
echo "FAIL: $f"
|
||||
FAIL=1
|
||||
else
|
||||
@@ -60,11 +60,10 @@ jobs:
|
||||
fi
|
||||
done
|
||||
exit $FAIL
|
||||
else
|
||||
echo "OK: $f"
|
||||
fi
|
||||
done
|
||||
exit $FAIL
|
||||
|
||||
- name: Repo Truth Guard
|
||||
run: |
|
||||
python3 scripts/repo_truth_guard.py
|
||||
|
||||
- name: Validate YAML
|
||||
run: |
|
||||
|
||||
@@ -6,6 +6,8 @@ WORKDIR /app
|
||||
COPY nexus/ nexus/
|
||||
COPY server.py .
|
||||
COPY portals.json vision.json ./
|
||||
COPY robots.txt ./
|
||||
COPY index.html help.html ./
|
||||
|
||||
RUN pip install --no-cache-dir websockets
|
||||
|
||||
|
||||
112
scripts/repo_truth_guard.py
Normal file
112
scripts/repo_truth_guard.py
Normal file
@@ -0,0 +1,112 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Repo Truth Guard for the-nexus
|
||||
==============================
|
||||
Machine-checkable validation that current `main` matches the canonical
|
||||
deployment truth. Prevents migration-era ambiguity from re-entering audits.
|
||||
|
||||
Exit 0 = truth validated
|
||||
Exit 1 = drift detected
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
REPO_ROOT = Path(__file__).parent.parent
|
||||
|
||||
# Canonical truth: what main currently IS and IS NOT
|
||||
CANONICAL_TRUTH = {
|
||||
"description": (
|
||||
"the-nexus main is a Python bridge/gateway (server.py) plus "
|
||||
"infrastructure-as-code (branch protection, workflows, fleet configs). "
|
||||
"It is NOT the browser-world visualization surface (not yet restored)."
|
||||
),
|
||||
"required_paths": [
|
||||
"server.py",
|
||||
"Dockerfile",
|
||||
"docker-compose.yml",
|
||||
"deploy.sh",
|
||||
"nexus/morning_report.py",
|
||||
".gitea/workflows/ci.yml",
|
||||
"gitea_api/branch_protection.py",
|
||||
"robots.txt",
|
||||
],
|
||||
"forbidden_paths": [
|
||||
# Migration-era browser-world artifacts that should not be in main
|
||||
"browser-world/index.html",
|
||||
"src/frontend",
|
||||
"vite.config.ts",
|
||||
"package-lock.json",
|
||||
],
|
||||
"required_in_dockerfile": [
|
||||
"server.py",
|
||||
"nexus/",
|
||||
],
|
||||
"required_py_deps": [
|
||||
"websockets",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def check_required_paths() -> list[str]:
|
||||
failures = []
|
||||
for p in CANONICAL_TRUTH["required_paths"]:
|
||||
if not (REPO_ROOT / p).exists():
|
||||
failures.append(f"MISSING required path: {p}")
|
||||
return failures
|
||||
|
||||
|
||||
def check_forbidden_paths() -> list[str]:
|
||||
failures = []
|
||||
for p in CANONICAL_TRUTH["forbidden_paths"]:
|
||||
if (REPO_ROOT / p).exists():
|
||||
failures.append(f"UNEXPECTED forbidden path found: {p}")
|
||||
return failures
|
||||
|
||||
|
||||
def check_dockerfile() -> list[str]:
|
||||
failures = []
|
||||
dockerfile = REPO_ROOT / "Dockerfile"
|
||||
if not dockerfile.exists():
|
||||
failures.append("MISSING Dockerfile")
|
||||
return failures
|
||||
content = dockerfile.read_text()
|
||||
for token in CANONICAL_TRUTH["required_in_dockerfile"]:
|
||||
if token not in content:
|
||||
failures.append(f"Dockerfile missing required reference: {token}")
|
||||
return failures
|
||||
|
||||
|
||||
def check_py_deps() -> list[str]:
|
||||
failures = []
|
||||
dockerfile = REPO_ROOT / "Dockerfile"
|
||||
if not dockerfile.exists():
|
||||
return failures
|
||||
content = dockerfile.read_text()
|
||||
for dep in CANONICAL_TRUTH["required_py_deps"]:
|
||||
if dep not in content:
|
||||
failures.append(f"Dockerfile missing Python dependency: {dep}")
|
||||
return failures
|
||||
|
||||
|
||||
def main() -> int:
|
||||
failures = []
|
||||
failures.extend(check_required_paths())
|
||||
failures.extend(check_forbidden_paths())
|
||||
failures.extend(check_dockerfile())
|
||||
failures.extend(check_py_deps())
|
||||
|
||||
report = {
|
||||
"canonical_truth": CANONICAL_TRUTH["description"],
|
||||
"repo_root": str(REPO_ROOT),
|
||||
"status": "PASS" if not failures else "FAIL",
|
||||
"failures": failures,
|
||||
}
|
||||
|
||||
print(json.dumps(report, indent=2))
|
||||
return 0 if not failures else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user