Absorbs #4412 (tomas-forgac) rebased onto fresh master, plus two Codex-regression-gate fixes: (1) use the scheme that actually answered the probe for the ready/already-up URL + browser-open, (2) honor an explicit HERMES_WEBUI_HEALTH_URL override in the WSL autostart probe. Co-authored-by: tomas-forgac <tomas-forgac@users.noreply.github.com> Closes #4412
110 lines
4.0 KiB
Python
110 lines
4.0 KiB
Python
from __future__ import annotations
|
|
|
|
import re
|
|
import shutil
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
DOC = REPO_ROOT / "docs" / "wsl-autostart.md"
|
|
WSL_SCRIPT = REPO_ROOT / "scripts" / "wsl" / "hermes_webui_autostart.sh"
|
|
POWERSHELL_SCRIPT = REPO_ROOT / "scripts" / "windows" / "setup_webui_autostart.ps1"
|
|
README = REPO_ROOT / "README.md"
|
|
|
|
|
|
def _read(path: Path) -> str:
|
|
return path.read_text(encoding="utf-8")
|
|
|
|
|
|
def test_wsl_autostart_docs_cover_session_and_task_scheduler_options():
|
|
doc = _read(DOC)
|
|
readme = _read(README)
|
|
|
|
assert "docs/wsl-autostart.md" in readme
|
|
assert "WSL session startup" in doc
|
|
assert "Windows Task Scheduler" in doc
|
|
assert "scripts/wsl/hermes_webui_autostart.sh" in doc
|
|
assert "scripts/windows/setup_webui_autostart.ps1" in doc
|
|
assert "HERMES_WEBUI_REPO" in doc
|
|
assert "HERMES_WEBUI_LOG_DIR" in doc
|
|
assert "HERMES_WEBUI_REQUIRE_AGENT_PROCESS" in doc
|
|
assert "/root" not in doc
|
|
assert "C:\\Users\\Michael" not in doc
|
|
|
|
|
|
def test_wsl_autostart_launcher_has_safe_duplicate_prevention_and_exports_runtime_env():
|
|
script = _read(WSL_SCRIPT)
|
|
|
|
assert script.startswith("#!/usr/bin/env bash\n")
|
|
assert "set -euo pipefail" in script
|
|
assert "flock -n" in script
|
|
assert "HERMES_WEBUI_LOCK_FILE" in script
|
|
assert "HERMES_WEBUI_PID_FILE" in script
|
|
assert "hermes_webui_probe_health" in script
|
|
assert "bash \"${HERMES_WEBUI_REPO}/start.sh\" --foreground" in script
|
|
assert "nohup" in script
|
|
|
|
# The launcher documents HERMES_WEBUI_HOST/PORT as runtime knobs; they must
|
|
# be exported so bootstrap.py/server.py receive the selected WSL values.
|
|
assert re.search(r"^export HERMES_WEBUI_HOST HERMES_WEBUI_PORT$", script, re.MULTILINE)
|
|
|
|
assert "/root" not in script
|
|
assert "/home/michael" not in script
|
|
|
|
|
|
def test_wsl_autostart_launcher_passes_bash_syntax_check():
|
|
subprocess.run(["bash", "-n", str(WSL_SCRIPT)], check=True, cwd=REPO_ROOT)
|
|
|
|
|
|
def test_wsl_autostart_honors_explicit_health_url_override():
|
|
"""#4412 regression: an explicitly-set HERMES_WEBUI_HEALTH_URL must remain the
|
|
actual probe target (documented escape hatch), not be silently ignored in
|
|
favor of the TLS-aware HOST/PORT helper after the probe refactor.
|
|
"""
|
|
script = _read(WSL_SCRIPT)
|
|
# The override must be detected and used for the probe, not just for logging.
|
|
assert "_HERMES_WEBUI_HEALTH_URL_EXPLICIT" in script
|
|
# webui_healthy must branch on the explicit flag and probe the exact URL.
|
|
assert re.search(
|
|
r'_HERMES_WEBUI_HEALTH_URL_EXPLICIT.*==.*"1"',
|
|
script,
|
|
)
|
|
assert '"${HERMES_WEBUI_HEALTH_URL}"' in script
|
|
|
|
|
|
def test_windows_task_scheduler_helper_is_idempotent_and_validates_wsl_script_path():
|
|
script = _read(POWERSHELL_SCRIPT)
|
|
|
|
assert "[CmdletBinding(SupportsShouldProcess = $true)]" in script
|
|
assert "Register-ScheduledTask" in script
|
|
assert "-Force" in script
|
|
assert "New-ScheduledTaskSettingsSet" in script
|
|
assert "-MultipleInstances IgnoreNew" in script
|
|
assert "Get-ScheduledTask -TaskName $TaskName" in script
|
|
assert "wsl.exe" in script
|
|
assert '"--exec", "bash", $WslScriptPath' in script
|
|
assert '"--exec", "test", "-f", $WslScriptPath' in script
|
|
assert "Start-ScheduledTask -TaskName $TaskName" in script
|
|
assert "/root" not in script
|
|
assert "C:\\Users\\Michael" not in script
|
|
|
|
|
|
def test_powershell_helper_passes_parser_when_pwsh_is_available():
|
|
pwsh = None
|
|
for candidate in ("pwsh", "powershell"):
|
|
resolved = shutil.which(candidate)
|
|
if resolved:
|
|
pwsh = resolved
|
|
break
|
|
if not pwsh:
|
|
# Linux CI often does not include PowerShell. The source-string tests
|
|
# above still pin the safety/idempotency invariants in that case.
|
|
return
|
|
|
|
subprocess.run(
|
|
[pwsh, "-NoProfile", "-Command", f"$null = [scriptblock]::Create((Get-Content -Raw '{POWERSHELL_SCRIPT.as_posix()}'))"],
|
|
check=True,
|
|
cwd=REPO_ROOT,
|
|
)
|