from __future__ import annotations import re from pathlib import Path PROJECT_ROOT = Path(__file__).resolve().parents[1] def read_project_file(name: str) -> str: return (PROJECT_ROOT / name).read_text(encoding="utf-8") def requirement_names(text: str) -> set[str]: names: set[str] = set() for raw_line in text.splitlines(): line = raw_line.strip() if not line or line.startswith(("#", "-r")): continue match = re.match(r"([A-Za-z0-9_.-]+)", line) if match: names.add(match.group(1).casefold().replace("_", "-")) return names def test_no_development_secret_is_committed_in_runtime_config() -> None: files = [ read_project_file("docker-compose.yml"), read_project_file("app/main.py"), ] assert all("dev-secret" not in text for text in files) def test_compose_uses_env_file_and_keeps_chunk_configuration() -> None: compose = read_project_file("docker-compose.yml") assert "env_file:" in compose assert ".env" in compose assert "CHUNK_MAX_TOKENS" in compose assert "CHUNK_OVERLAP_TOKENS" in compose assert "CHUNK_MIN_TOKENS" in compose assert "CHUNK_TOKEN_ENCODING" in compose assert "./data:/app/data" in compose assert "../zpwiki:/zpwiki" in compose def test_secrets_are_ignored_by_git_and_docker() -> None: gitignore = read_project_file(".gitignore") dockerignore = read_project_file(".dockerignore") assert re.search(r"(?m)^\.env$", gitignore) assert re.search(r"(?m)^\.env$", dockerignore) def test_runtime_requirements_contain_only_direct_dependencies() -> None: names = requirement_names(read_project_file("requirements.txt")) required = { "fastapi", "pydantic", "python-frontmatter", "rich", "tiktoken", "uvicorn", } forbidden = { "gitpython", "gitdb", "smmap", "starlette", "pydantic-core", "annotated-types", } assert required <= names assert names.isdisjoint(forbidden) def test_all_application_python_files_compile() -> None: targets = [PROJECT_ROOT / "app", PROJECT_ROOT / "scripts"] for directory in targets: for path in directory.rglob("*.py"): source = path.read_text(encoding="utf-8") compile(source, str(path), "exec")