fix: bootstrap.py loads REPO_ROOT/.env so direct invocation matches start.sh (#730) (#791)
Some checks failed
Release & Docker / release (push) Has been cancelled
Some checks failed
Release & Docker / release (push) Has been cancelled
* fix: bootstrap.py loads REPO_ROOT/.env so direct invocation matches start.sh When users run 'python3 bootstrap.py' directly (the primary documented entry point in README), HERMES_WEBUI_HOST, HERMES_WEBUI_PORT and other .env settings were silently ignored because the shell-level 'source .env' in start.sh was never executed. Add _load_repo_dotenv() in bootstrap.py that reads REPO_ROOT/.env into os.environ before DEFAULT_HOST / DEFAULT_PORT are evaluated at module level. Uses unconditional assignment matching 'set -a; source .env' shell semantics. Only loads the repo .env (bootstrap config) — not ~/.hermes/.env, which the server still loads independently at startup for provider credentials. Reported in #730 by @leap233 who had HERMES_WEBUI_HOST=0.0.0.0 and HERMES_WEBUI_PORT=18787 in the webui .env; running bootstrap.py directly caused the server to ignore both settings. Tests: 15 new tests in tests/test_bootstrap_dotenv.py covering the full loader (key=value, comments, blank lines, quoted values, no-file, unreadable-file, overwrite semantics, values with = signs) and structural assertions that _load_repo_dotenv() is called before DEFAULT_HOST/PORT. 1613 tests total. * fix: address review feedback on PR #791 - bootstrap.py: document overwrite semantics and 'export' note in docstring - bootstrap.py: handle 'export FOO=bar' prefix (strip before splitting on =) - bootstrap.py: print warning to stderr on .env parse failure (not silent swallow) - bootstrap.py: add side-effect comment at _load_repo_dotenv() call site - CHANGELOG.md: restore v0.50.124 and v0.50.123 headers (were merged into v0.50.125 section, making three consecutive ### Fixed blocks with no ## header between them) - tests: fix test_noop_when_dotenv_unreadable to assert warning is emitted - tests: tighten test_does_not_set_empty_values with concrete assertion - tests: add test_export_prefix_stripped - tests: remove dead _import_bootstrap_with_env() helper (never called) 1614 tests total --------- Co-authored-by: nesquena-hermes <hermes@nesquena.com>
This commit is contained in:
44
bootstrap.py
44
bootstrap.py
@@ -19,6 +19,50 @@ from pathlib import Path
|
||||
|
||||
INSTALLER_URL = "https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh"
|
||||
REPO_ROOT = Path(__file__).resolve().parent
|
||||
|
||||
|
||||
def _load_repo_dotenv() -> None:
|
||||
"""Load REPO_ROOT/.env into os.environ.
|
||||
|
||||
Mirrors what start.sh does via ``set -a; source .env`` so that running
|
||||
``python3 bootstrap.py`` directly behaves identically to ``./start.sh``.
|
||||
Variables are set unconditionally (matching shell source semantics), so a
|
||||
value in .env overrides one already present in the shell environment.
|
||||
To keep a CLI-supplied value, unset it from .env or launch via start.sh
|
||||
and override there.
|
||||
|
||||
Only loads the webui repo .env — not ~/.hermes/.env, which the server
|
||||
loads independently at startup for provider credentials.
|
||||
|
||||
Note: does not handle the ``export FOO=bar`` prefix — strip ``export``
|
||||
from .env values if copy-pasting from a shell rc file.
|
||||
"""
|
||||
env_path = REPO_ROOT / ".env"
|
||||
if not env_path.exists():
|
||||
return
|
||||
try:
|
||||
for raw_line in env_path.read_text(encoding="utf-8").splitlines():
|
||||
line = raw_line.strip()
|
||||
if not line or line.startswith("#") or "=" not in line:
|
||||
continue
|
||||
k, v = line.split("=", 1)
|
||||
k = k.strip()
|
||||
# Strip optional 'export' prefix (common in copy-pasted shell snippets)
|
||||
if k.startswith("export "):
|
||||
k = k[7:].strip()
|
||||
v = v.strip().strip('"').strip("'")
|
||||
if k:
|
||||
os.environ[k] = v
|
||||
except Exception as exc:
|
||||
import sys as _sys
|
||||
print(f"[bootstrap] Warning: could not load .env — {exc}", file=_sys.stderr)
|
||||
|
||||
|
||||
# Side effect: loads REPO_ROOT/.env into os.environ on import.
|
||||
# Must run before DEFAULT_HOST / DEFAULT_PORT so os.getenv() picks up
|
||||
# values from .env even when bootstrap.py is invoked directly (not via start.sh).
|
||||
_load_repo_dotenv()
|
||||
|
||||
DEFAULT_HOST = os.getenv("HERMES_WEBUI_HOST", "127.0.0.1")
|
||||
DEFAULT_PORT = int(os.getenv("HERMES_WEBUI_PORT", "8787"))
|
||||
# Set HERMES_WEBUI_SKIP_ONBOARDING=1 to bypass the first-run wizard when
|
||||
|
||||
Reference in New Issue
Block a user