forked from molecule-ai/molecule-core
Merge pull request #2560 from Molecule-AI/fix/preflight-smoke-mode-bypass
fix(preflight): skip required_env check in MOLECULE_SMOKE_MODE
This commit is contained in:
commit
bb63e60114
@ -180,16 +180,38 @@ def run_preflight(config: WorkspaceConfig, config_path: str) -> PreflightReport:
|
|||||||
required_env = list(entry.get("required_env") or [])
|
required_env = list(entry.get("required_env") or [])
|
||||||
break
|
break
|
||||||
|
|
||||||
|
# Smoke mode skips the auth-env block: the boot smoke (CI publish-image,
|
||||||
|
# issue #2275) exercises executor.execute() against stub deps, never
|
||||||
|
# hits the real provider, and CI cannot enumerate every adapter's auth
|
||||||
|
# env without forming a maintenance treadmill. Hermes 2026-05-03 outage:
|
||||||
|
# template smoke crashed for two cycles because molecule-ci injected
|
||||||
|
# CLAUDE_CODE_OAUTH_TOKEN/ANTHROPIC_API_KEY/etc. but not HERMES_API_KEY.
|
||||||
|
# Bypass here means new templates can ship without the workflow
|
||||||
|
# learning their env names.
|
||||||
|
smoke_mode = os.environ.get("MOLECULE_SMOKE_MODE", "").strip().lower() in (
|
||||||
|
"1", "true", "yes", "on",
|
||||||
|
)
|
||||||
for env_var in required_env:
|
for env_var in required_env:
|
||||||
if not os.environ.get(env_var):
|
if os.environ.get(env_var):
|
||||||
report.failures.append(
|
continue
|
||||||
|
if smoke_mode:
|
||||||
|
report.warnings.append(
|
||||||
PreflightIssue(
|
PreflightIssue(
|
||||||
severity="fail",
|
severity="warn",
|
||||||
title="Required env",
|
title="Required env",
|
||||||
detail=f"Missing required environment variable: {env_var}",
|
detail=f"Missing {env_var} (skipped — MOLECULE_SMOKE_MODE)",
|
||||||
fix=f"Set {env_var} via the secrets API (global or workspace-level).",
|
fix="",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
continue
|
||||||
|
report.failures.append(
|
||||||
|
PreflightIssue(
|
||||||
|
severity="fail",
|
||||||
|
title="Required env",
|
||||||
|
detail=f"Missing required environment variable: {env_var}",
|
||||||
|
fix=f"Set {env_var} via the secrets API (global or workspace-level).",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# Backward compat: if legacy auth_token_file is set, warn but don't block
|
# Backward compat: if legacy auth_token_file is set, warn but don't block
|
||||||
# if the token is available via required_env or auth_token_env.
|
# if the token is available via required_env or auth_token_env.
|
||||||
|
|||||||
@ -286,6 +286,55 @@ def test_required_env_empty_list_passes(tmp_path):
|
|||||||
assert report.ok is True
|
assert report.ok is True
|
||||||
|
|
||||||
|
|
||||||
|
def test_required_env_skipped_in_smoke_mode(tmp_path, monkeypatch):
|
||||||
|
"""MOLECULE_SMOKE_MODE=1 demotes Required-env failures to warnings.
|
||||||
|
|
||||||
|
Boot smoke (issue #2275) exercises executor.execute() against stub
|
||||||
|
deps and never hits the real provider, so missing auth env is not
|
||||||
|
a real blocker. Without this bypass, every adapter that introduces
|
||||||
|
a new auth env var (HERMES_API_KEY, OPENROUTER_API_KEY, etc.)
|
||||||
|
would silently break the publish-image gate until molecule-ci's
|
||||||
|
fake-env list catches up — the 2026-05-03 hermes outage. The
|
||||||
|
warning still surfaces in the report so unset env doesn't go
|
||||||
|
completely silent.
|
||||||
|
"""
|
||||||
|
monkeypatch.delenv("HERMES_API_KEY", raising=False)
|
||||||
|
monkeypatch.setenv("MOLECULE_SMOKE_MODE", "1")
|
||||||
|
|
||||||
|
config = make_config(
|
||||||
|
runtime_config=RuntimeConfig(required_env=["HERMES_API_KEY"]),
|
||||||
|
)
|
||||||
|
|
||||||
|
report = run_preflight(config, str(tmp_path))
|
||||||
|
|
||||||
|
assert report.ok is True
|
||||||
|
assert any(
|
||||||
|
issue.title == "Required env" and "HERMES_API_KEY" in issue.detail
|
||||||
|
for issue in report.warnings
|
||||||
|
), "smoke-mode bypass should still warn so unset env stays visible"
|
||||||
|
assert not any(
|
||||||
|
issue.title == "Required env" for issue in report.failures
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_required_env_smoke_mode_off_still_fails(tmp_path, monkeypatch):
|
||||||
|
"""Sanity: smoke bypass is OFF when MOLECULE_SMOKE_MODE is unset."""
|
||||||
|
monkeypatch.delenv("HERMES_API_KEY", raising=False)
|
||||||
|
monkeypatch.delenv("MOLECULE_SMOKE_MODE", raising=False)
|
||||||
|
|
||||||
|
config = make_config(
|
||||||
|
runtime_config=RuntimeConfig(required_env=["HERMES_API_KEY"]),
|
||||||
|
)
|
||||||
|
|
||||||
|
report = run_preflight(config, str(tmp_path))
|
||||||
|
|
||||||
|
assert report.ok is False
|
||||||
|
assert any(
|
||||||
|
issue.title == "Required env" and "HERMES_API_KEY" in issue.detail
|
||||||
|
for issue in report.failures
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# ---------- Per-model required_env (models[] override) ----------
|
# ---------- Per-model required_env (models[] override) ----------
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user