#!/usr/bin/env python3 """Check that all env vars used in the codebase are documented in .env.example.""" import os import re import sys REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) def find_env_vars_in_code(): """Find all os.Getenv() and import.meta.env.VITE_* calls in the codebase.""" env_vars = set() # Search backend Go files for os.Getenv("VAR_NAME") go_dir = os.path.join(REPO_ROOT, 'backend') for root, dirs, files in os.walk(go_dir): dirs[:] = [d for d in dirs if d not in ('vendor', '.git', 'node_modules')] for f in files: if f.endswith('.go'): path = os.path.join(root, f) with open(path) as fh: for line in fh: m = re.findall(r'os\.Getenv\(["\']([A-Z_][A-Z0-9_]*)["\']', line) env_vars.update(m) # Search frontend files for import.meta.env.VITE_* frontend_dir = os.path.join(REPO_ROOT, 'frontend') for root, dirs, files in os.walk(frontend_dir): dirs[:] = [d for d in dirs if d not in ('.git', 'node_modules', 'build')] for f in files: if f.endswith(('.ts', '.svelte', '.js')): path = os.path.join(root, f) with open(path) as fh: for line in fh: m = re.findall(r'import\.meta\.env\.([A-Z_][A-Z0-9_]*)', line) env_vars.update(m) return sorted(env_vars) def find_documented_vars(): """Find all env vars documented in .env.example.""" env_path = os.path.join(REPO_ROOT, '.env.example') documented = set() if os.path.exists(env_path): with open(env_path) as fh: for line in fh: line = line.strip() if line and not line.startswith('#') and '=' in line: var_name = line.split('=')[0].strip() if var_name: documented.add(var_name) return documented def main(): code_vars = find_env_vars_in_code() documented = find_documented_vars() undocumented = [v for v in code_vars if v not in documented] if undocumented: print("ERROR: The following env vars are used in code but not documented in .env.example:\n") for v in undocumented: print(f" {v}") print(f"\nTotal: {len(undocumented)} undocumented vars out of {len(code_vars)} total") sys.exit(1) else: print(f"OK: All {len(code_vars)} env vars used in code are documented in .env.example") sys.exit(0) if __name__ == '__main__': main()