fix(cron): null-safe deliver in cron list + re-resolve BSM secrets per run

Two live cron bugs, both surfaced by @banditburai in #35616 (whose larger
watchdog/supervisor work is already superseded by the CronScheduler provider
refactor on main):

- #32896: `cron list` crashed on a present-but-null `deliver` field —
  `job.get("deliver", ["local"])` returns None for an explicit null, which
  then hit `", ".join(None)`. Coalesce with `or ["local"]` (same pitfall
  the sibling `repeat` line already guards against).

- #33465: cron jobs 401'd on Bitwarden/BSM-backed secrets. The per-run env
  reload used a bare `load_dotenv(override=True)`, which re-applied only the
  .env placeholder — startup had already recorded this HERMES_HOME in
  env_loader._APPLIED_HOMES, so the external-secret re-pull no-oped. Route the
  reload through load_hermes_dotenv() and call reset_secret_source_cache()
  first to force the re-pull (Bitwarden's 300s value-cache keeps it off the
  network; override honours secrets.bitwarden.override_existing, mirroring
  startup).

Tests: null-deliver regression guard in test_cron.py; reset-before-reload
ordering guard in test_scheduler.py. Migrated 31 scheduler-reload test seams
from patching dotenv.load_dotenv to the new load_hermes_dotenv /
reset_secret_source_cache seam.
This commit is contained in:
teknium1 2026-07-01 00:39:00 -07:00 committed by Teknium
parent cf427ccf08
commit 836732f54f
5 changed files with 148 additions and 38 deletions

View file

@ -122,6 +122,23 @@ class TestCronCommandLifecycle:
out = capsys.readouterr().out
assert "Repeat: ∞" in out
def test_list_does_not_crash_when_deliver_is_null(self, tmp_cron_dir, capsys):
"""A job can be persisted with ``"deliver": null`` (present-but-null).
`cron list` must fall back to the default channel rather than crashing
on ``", ".join(None)`` same dict-default pitfall as ``repeat`` (#32896).
"""
from cron.jobs import load_jobs, save_jobs
create_job(prompt="No deliver", schedule="every 1h")
jobs = load_jobs()
jobs[0]["deliver"] = None
save_jobs(jobs)
cron_command(Namespace(cron_command="list", all=True))
out = capsys.readouterr().out
assert "Deliver: local" in out
class TestGatewayNotRunningWarning:
"""`cron create` / `cron list` must warn when the gateway (and thus the