fix(cli): respect 12-factor env precedence in load_hermes_dotenv() - #18734
fix(cli): respect 12-factor env precedence in load_hermes_dotenv()#18734liuhao1024 wants to merge 14 commits into
Conversation
load_hermes_dotenv() previously used override=True, which caused stale .env values to override runtime-injected secrets (systemd EnvironmentFile=, Docker secrets, k8s env injection). This changes the default to override=False (12-factor compliant) while adding HERMES_DOTENV_OVERRIDE=1 opt-in for users who rely on the legacy override behavior. Fixes NousResearch#18705
|
Hi @liuhao1024 — heads-up that this looks like it'll break three existing tests in
Two ways to handle:
Option 2 keeps coverage of the override path so a future change can't silently regress it. |
…ault behavior test - test_user_env_overrides_stale_shell_values: set HERMES_DOTENV_OVERRIDE=1 to exercise the opt-in override path - test_user_env_takes_precedence_over_project_env: same, set HERMES_DOTENV_OVERRIDE=1 - test_main_import_applies_user_env_over_shell_values: same - Added test_default_does_not_override_shell_values: verifies default behavior (shell env wins over .env file when HERMES_DOTENV_OVERRIDE is not set) - Added test_user_env_fills_missing_shell_values: verifies .env fills missing vars Addresses review feedback from @Tranquil-Flow on NousResearch#18734.
|
Hi @Tranquil-Flow — thanks for the thorough review! I went with Option 2 as you suggested: added Changes pushed:
All 7 tests pass: |
Add the two commit emails used by liuhao1024: - liuhao1024@users.noreply.github.com (GitHub noreply) - sunsky.lau@gmail.com (personal) These were flagged by the Contributor Attribution Check CI on PRs NousResearch#18734, NousResearch#18491, NousResearch#18009, and NousResearch#17761.
|
+1 on this fix. I independently hit the same issue and submitted #19677 before finding this PR. Closing mine as duplicate. The |
|
+1. Adds another use case beyond the systemd/docker scenarios already covered: the Both #36949 (native 1Password backend feature request) and the Cross-link map for anyone arriving from a related thread:
Stack: Hermes 0.14.0, macOS 12.7.6, 1Password CLI 2.34.0 via service-account token, |
The upstream test `test_user_env_overrides_shell` (bf9a048) was added after this PR to pin the old .env-overrides-shell behavior. With the new 12-factor default (override=False), shell env wins unless the user opts in via HERMES_DOTENV_OVERRIDE=1. Split into two tests: - test_shell_env_wins_by_default: verifies 12-factor precedence - test_dotenv_override_opt_in_restores_legacy: verifies opt-in toggle
test_no_managed_env_is_noop asserts that user .env overrides shell env, which requires HERMES_DOTENV_OVERRIDE=1 under the new 12-factor default. Without this, the test expects legacy override=True behavior that no longer applies by default.
Related: this is the canonical 12-factor |
|
Thank you for the focused precedence tests and for documenting the systemd/Docker and This automated hermes-sweeper review is closing this under the standing configuration policy:
If maintainers choose to make dotenv precedence configurable, please re-scope that behavior through the supported Closed as not-planned per standing maintainer policy ( |
What does this PR do?
load_hermes_dotenv()usedoverride=True, causing~/.hermes/.envvalues to silently override runtime-injected secrets from systemdEnvironmentFile=, Docker secrets, or Kubernetes env injection. This breaks credential rotation — stale keys in.envwin over freshly rotated production secrets, causing 401 errors with no obvious cause.Root Cause
In
hermes_cli/env_loader.py:168:override=Truemeans.envalways wins over pre-existing environment variables, violating 12-factor app precedence (env > file).Related Issue
N/A
Type of Change
Changes Made
How to Test
pytest tests/ -q— all tests should passChecklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture and workflows — or N/A