fix: preserve webui launcher environment
(cherry picked from commit 2297ab4db854b52b20cdd34731cd82e8cc5bdb72)
This commit is contained in:
12
bootstrap.py
12
bootstrap.py
@@ -28,8 +28,8 @@ def _load_repo_dotenv() -> None:
|
||||
``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.
|
||||
``ctl.sh`` sets HERMES_WEBUI_PRESERVE_ENV=1 when it has already resolved
|
||||
launcher-specific values such as HERMES_HOME or HERMES_WEBUI_STATE_DIR.
|
||||
|
||||
Only loads the webui repo .env — not ~/.hermes/.env, which the server
|
||||
loads independently at startup for provider credentials.
|
||||
@@ -41,6 +41,12 @@ def _load_repo_dotenv() -> None:
|
||||
if not env_path.exists():
|
||||
return
|
||||
try:
|
||||
preserve_existing = os.getenv("HERMES_WEBUI_PRESERVE_ENV", "").strip().lower() in {
|
||||
"1",
|
||||
"true",
|
||||
"yes",
|
||||
"on",
|
||||
}
|
||||
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:
|
||||
@@ -52,6 +58,8 @@ def _load_repo_dotenv() -> None:
|
||||
k = k[7:].strip()
|
||||
v = v.strip().strip('"').strip("'")
|
||||
if k:
|
||||
if preserve_existing and k in os.environ:
|
||||
continue
|
||||
os.environ[k] = v
|
||||
except Exception as exc:
|
||||
import sys as _sys
|
||||
|
||||
4
ctl.sh
4
ctl.sh
@@ -219,7 +219,9 @@ start_cmd() {
|
||||
: >> "${LOG_FILE}"
|
||||
(
|
||||
cd "${REPO_ROOT}"
|
||||
exec "${python_exe}" "${REPO_ROOT}/bootstrap.py" --no-browser --foreground --host "${CTL_HOST}" "${CTL_PORT}" ${CTL_BOOTSTRAP_ARGS[@]+"${CTL_BOOTSTRAP_ARGS[@]}"}
|
||||
trap '' HUP
|
||||
export HERMES_WEBUI_PRESERVE_ENV=1
|
||||
exec nohup "${python_exe}" "${REPO_ROOT}/bootstrap.py" --no-browser --foreground --host "${CTL_HOST}" "${CTL_PORT}" ${CTL_BOOTSTRAP_ARGS[@]+"${CTL_BOOTSTRAP_ARGS[@]}"}
|
||||
) >> "${LOG_FILE}" 2>&1 &
|
||||
pid=$!
|
||||
|
||||
|
||||
@@ -112,6 +112,18 @@ class TestLoadRepoDotenv:
|
||||
self._run(tmp_path, "HERMES_WEBUI_HOST=0.0.0.0\n")
|
||||
assert os.environ.get("HERMES_WEBUI_HOST") == "0.0.0.0"
|
||||
|
||||
def test_preserve_existing_env_keeps_ctl_overrides(self, tmp_path):
|
||||
"""ctl.sh can ask bootstrap.py to keep wrapper-provided env values."""
|
||||
os.environ["HERMES_WEBUI_PRESERVE_ENV"] = "1"
|
||||
os.environ["HERMES_HOME"] = "/runtime/hermesOne"
|
||||
os.environ["HERMES_WEBUI_PASSWORD"] = ""
|
||||
self._run(
|
||||
tmp_path,
|
||||
"HERMES_HOME=/repo/default\nHERMES_WEBUI_PASSWORD=repo-password\n",
|
||||
)
|
||||
assert os.environ.get("HERMES_HOME") == "/runtime/hermesOne"
|
||||
assert os.environ.get("HERMES_WEBUI_PASSWORD") == ""
|
||||
|
||||
def test_does_not_set_empty_values(self, tmp_path):
|
||||
"""A key whose value is empty after stripping is not set to a non-empty string."""
|
||||
os.environ.pop("HERMES_EMPTY_KEY", None)
|
||||
|
||||
@@ -138,6 +138,13 @@ def test_start_writes_pid_under_hermes_home_runs_foreground_no_browser_and_logs(
|
||||
assert not pid_file.exists()
|
||||
|
||||
|
||||
def test_start_uses_nohup_so_daemon_survives_launcher_exit():
|
||||
ctl_text = CTL.read_text(encoding="utf-8")
|
||||
|
||||
assert "trap '' HUP" in ctl_text
|
||||
assert 'exec nohup "${python_exe}"' in ctl_text
|
||||
|
||||
|
||||
def test_start_loads_dotenv_but_inline_overrides_win(tmp_path):
|
||||
repo_root = tmp_path / "repo"
|
||||
repo_root.mkdir()
|
||||
|
||||
Reference in New Issue
Block a user