SimpleChatbot / scripts /verify_repository_metadata.py
Amin
Deploy: HermesFace finalized project to HF Space
2e658e7
Raw
History Blame Contribute Delete
3.93 kB
#!/usr/bin/env python3
"""Verify repository packaging, documentation references, and safe templates."""
from __future__ import annotations
import re
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
REQUIRED = (
".env.example", ".gitignore", ".gitattributes", ".python-version",
"VERSION", "BUILD_MANIFEST.md", "requirements.lock", "requirements-ci.lock", "package.json", "package-lock.json", "README.md",
"scripts/check_migrations.py", "scripts/validate_startup_configuration.py",
"scripts/generate_dependency_inventory.py", "docs/dependency_inventory.json", "docs/dependency_licenses.json",
)
SECRET_TEMPLATE_KEYS = {
"HF_TOKEN", "HERMES_ADMIN_PASSWORD", "HERMES_SESSION_SECRET",
"FUTURES_API_KEY", "FUTURES_API_SECRET", "FUTURES_API_PASSPHRASE",
"OPENROUTER_API_KEY", "GOOGLE_API_KEY", "TELEGRAM_BOT_TOKEN",
"TELEGRAM_WEBHOOK_SECRET", "TELEGRAM_BOOTSTRAP_SECRET",
}
def verify(root: Path = ROOT) -> list[str]:
errors: list[str] = []
for rel in REQUIRED:
if not (root / rel).is_file():
errors.append(f"required repository file missing: {rel}")
readme_path = root / "README.md"
if readme_path.is_file():
readme = readme_path.read_text(encoding="utf-8")
for target in re.findall(r"\[[^]]+\]\(([^)]+)\)", readme):
if "://" in target or target.startswith("#"):
continue
if not (root / target).exists():
errors.append(f"README link target missing: {target}")
for required_command in (
"python scripts/validate_startup_configuration.py",
"python scripts/check_migrations.py",
"python -m pytest hermes_overlay/tests -q",
"docker build",
):
if required_command not in readme:
errors.append(f"README command missing: {required_command}")
package_path = root / "package.json"
lock_path = root / "package-lock.json"
if package_path.is_file() and lock_path.is_file():
import json
try:
package = json.loads(package_path.read_text(encoding="utf-8"))
lock = json.loads(lock_path.read_text(encoding="utf-8"))
except (OSError, ValueError) as exc:
errors.append(f"invalid Node metadata: {exc.__class__.__name__}")
else:
if package.get("engines", {}).get("node") != "22.16.0":
errors.append("package.json must pin Node 22.16.0")
if not lock.get("lockfileVersion"):
errors.append("package-lock.json must declare lockfileVersion")
root_package = lock.get("packages", {}).get("", {})
if root_package.get("engines", {}).get("node") != "22.16.0":
errors.append("package-lock.json must preserve the Node engine pin")
env_path = root / ".env.example"
if env_path.is_file():
entries: dict[str, str] = {}
for raw in env_path.read_text(encoding="utf-8").splitlines():
line = raw.strip()
if not line or line.startswith("#") or "=" not in line:
continue
key, value = line.split("=", 1)
entries[key.strip()] = value.strip()
for key in SECRET_TEMPLATE_KEYS:
if entries.get(key):
errors.append(f"secret template key must be blank: {key}")
if entries.get("TRADING_MODE") != "paper":
errors.append("TRADING_MODE template must default to paper")
if entries.get("HERMES_EXECUTION_ENABLED", "").lower() != "false":
errors.append("HERMES_EXECUTION_ENABLED template must default false")
return errors
def main() -> int:
errors = verify()
for error in errors:
print(f"ERROR: {error}")
print(f"repository_metadata={'PASS' if not errors else 'FAIL'}")
return 1 if errors else 0
if __name__ == "__main__":
raise SystemExit(main())