守住 runtime 環境變數文件契約
This commit is contained in:
@@ -16,6 +16,29 @@ def _env_example_keys() -> set[str]:
|
||||
return keys
|
||||
|
||||
|
||||
def _runtime_env_keys_from_code() -> set[str]:
|
||||
pattern = re.compile(r"""os\.(?:getenv|environ\.get)\(\s*['"]([A-Z][A-Z0-9_]+)['"]""")
|
||||
scan_paths = [
|
||||
ROOT / "app.py",
|
||||
ROOT / "config.py",
|
||||
ROOT / "scheduler.py",
|
||||
ROOT / "run_scheduler.py",
|
||||
ROOT / "routes",
|
||||
ROOT / "services",
|
||||
ROOT / "utils",
|
||||
]
|
||||
|
||||
keys = set()
|
||||
for scan_path in scan_paths:
|
||||
paths = scan_path.rglob("*.py") if scan_path.is_dir() else [scan_path]
|
||||
for path in paths:
|
||||
if not path.exists() or "__pycache__" in path.parts:
|
||||
continue
|
||||
content = path.read_text(encoding="utf-8", errors="ignore")
|
||||
keys.update(match.group(1) for match in pattern.finditer(content))
|
||||
return keys
|
||||
|
||||
|
||||
def test_phase3f_orphan_ai_services_stay_removed():
|
||||
orphan_services = [
|
||||
"services/elephant_alpha_decision_router.py",
|
||||
@@ -44,9 +67,13 @@ def test_active_guides_do_not_point_to_removed_ai_services():
|
||||
|
||||
def test_env_example_documents_runtime_and_ai_automation_variables():
|
||||
expected_keys = {
|
||||
"AI_CALL_LOGGING_ENABLED",
|
||||
"AUTO_FIX_ENABLED",
|
||||
"AWAITING_REVIEW_PUSH_BATCH",
|
||||
"CODE_REVIEW_AUTO_FIX_ENABLED",
|
||||
"COST_THROTTLE_ENABLED",
|
||||
"COST_THROTTLE_PROJECT_RATIO",
|
||||
"COST_UNTHROTTLE_PROJECT_RATIO",
|
||||
"DEEPSEEK_API_KEY",
|
||||
"DEEPSEEK_BASE_URL",
|
||||
"DEEPSEEK_DIRECT_ENABLED",
|
||||
@@ -69,26 +96,45 @@ def test_env_example_documents_runtime_and_ai_automation_variables():
|
||||
"MOMO_EVENT_ROUTER_REPLAY_ON_SUCCESS",
|
||||
"MCP_FILESYSTEM_URL",
|
||||
"MCP_FIRECRAWL_URL",
|
||||
"MCP_CACHE_TTL_SEC",
|
||||
"MCP_MAX_RESULT_BYTES",
|
||||
"MCP_OMNISEARCH_URL",
|
||||
"MCP_POSTGRES_URL",
|
||||
"MCP_ROUTER_ENABLED",
|
||||
"MCP_TIMEOUT_SEC",
|
||||
"MODEL_ROUTER_ENABLED",
|
||||
"N8N_HOST",
|
||||
"N8N_PASSWORD",
|
||||
"N8N_PROTOCOL",
|
||||
"N8N_USER",
|
||||
"N8N_WEBHOOK_BASE_URL",
|
||||
"NEMOTRON_OLLAMA_FIRST",
|
||||
"NEMOTRON_OLLAMA_MODEL",
|
||||
"NEMOTRON_OLLAMA_TIMEOUT",
|
||||
"OLLAMA_EMBED_TIMEOUT",
|
||||
"OPENCLAW_ADMIN_USER_IDS",
|
||||
"OPENCLAW_AGENT_DISPATCH",
|
||||
"OPENCLAW_AGENT_DISPATCH_CMDS",
|
||||
"OPENCLAW_ALLOW_PRIVATE_WITHOUT_WHITELIST",
|
||||
"OPENCLAW_DAILY_HERMES_TEMPLATE",
|
||||
"OPENCLAW_OLLAMA_MODEL",
|
||||
"OPENCLAW_PPT_CACHE_TTL_HOURS",
|
||||
"OPENCLAW_QA_OLLAMA_FIRST",
|
||||
"OPENCLAW_QA_OLLAMA_HOST",
|
||||
"OPENCLAW_QA_OLLAMA_MODEL",
|
||||
"OPENCLAW_QA_OLLAMA_TIMEOUT",
|
||||
"PPT_VISION_ENABLED",
|
||||
"PPT_VISION_MODEL",
|
||||
"PPT_VISION_TIMEOUT",
|
||||
"PROMOTION_PENDING_BATCH_SIZE",
|
||||
"RAG_ENABLED",
|
||||
"RAG_DEFAULT_THRESHOLD",
|
||||
"RAG_DEFAULT_TOP_K",
|
||||
"RAG_EMBED_DIM",
|
||||
"RAG_EMBED_MODEL",
|
||||
"RAG_EMBED_NORMALIZE",
|
||||
"TELEGRAM_ADMIN_CHAT_ID",
|
||||
"TELEGRAM_BOT_USERNAME",
|
||||
"TELEGRAM_CHAT_ID",
|
||||
"WEB_CONCURRENCY",
|
||||
}
|
||||
@@ -96,6 +142,15 @@ def test_env_example_documents_runtime_and_ai_automation_variables():
|
||||
assert expected_keys <= _env_example_keys()
|
||||
|
||||
|
||||
def test_env_example_documents_runtime_os_env_keys():
|
||||
internal_runtime_keys = {
|
||||
"MOMO_ALLOW_INSECURE_CONFIG_FOR_TESTS",
|
||||
"PYTEST_CURRENT_TEST",
|
||||
}
|
||||
|
||||
assert _runtime_env_keys_from_code() - internal_runtime_keys <= _env_example_keys()
|
||||
|
||||
|
||||
def test_scheduler_does_not_silently_swallow_exceptions():
|
||||
scheduler_source = (ROOT / "scheduler.py").read_text(encoding="utf-8")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user