diff --git a/scripts/smoke_nemo_relay_shared_metrics.py b/scripts/smoke_nemo_relay_shared_metrics.py index 93f4562a99de..38a42641d1b1 100644 --- a/scripts/smoke_nemo_relay_shared_metrics.py +++ b/scripts/smoke_nemo_relay_shared_metrics.py @@ -5,6 +5,7 @@ from __future__ import annotations import argparse import json import os +import shutil import sqlite3 import subprocess import sys @@ -21,6 +22,23 @@ MODEL_CANARY = "gpt-relay-smoke-sensitive-model" RESPONSE_CANARY = "relay-smoke-sensitive-response" +def _resolve_hermes_executable(hermes_repo: Path) -> Path: + for relative_path in ( + Path(".venv") / "bin" / "hermes", + Path(".venv") / "Scripts" / "hermes.exe", + ): + candidate = hermes_repo / relative_path + if candidate.is_file(): + return candidate + discovered = shutil.which("hermes") + if discovered: + return Path(discovered) + raise SystemExit( + "Hermes executable not found in the repository virtual environment " + "or on PATH" + ) + + class _ModelHandler(BaseHTTPRequestHandler): """Minimal OpenAI-compatible model server for one deterministic turn.""" @@ -321,9 +339,7 @@ def main() -> int: args = _arguments() hermes_repo = args.hermes_repo.resolve() relay_python = args.relay_python.resolve() if args.relay_python else None - hermes = hermes_repo / ".venv" / "bin" / "hermes" - if not hermes.is_file(): - raise SystemExit(f"Hermes executable not found: {hermes}") + hermes = _resolve_hermes_executable(hermes_repo) if relay_python is not None and not any( (relay_python / "nemo_relay").glob("_native.*") ): diff --git a/tests/scripts/test_smoke_nemo_relay_shared_metrics.py b/tests/scripts/test_smoke_nemo_relay_shared_metrics.py new file mode 100644 index 000000000000..d31a90bb4395 --- /dev/null +++ b/tests/scripts/test_smoke_nemo_relay_shared_metrics.py @@ -0,0 +1,41 @@ +"""Tests for the shared-metrics smoke artifact.""" + +from pathlib import Path + +import pytest + +from scripts import smoke_nemo_relay_shared_metrics as smoke + + +@pytest.mark.parametrize( + "relative_path", + [ + Path(".venv") / "bin" / "hermes", + Path(".venv") / "Scripts" / "hermes.exe", + ], +) +def test_resolve_hermes_executable_from_repository_venv( + tmp_path, + monkeypatch, + relative_path, +): + executable = tmp_path / relative_path + executable.parent.mkdir(parents=True) + executable.touch() + monkeypatch.setattr(smoke.shutil, "which", lambda _name: None) + + assert smoke._resolve_hermes_executable(tmp_path) == executable + + +def test_resolve_hermes_executable_falls_back_to_path(tmp_path, monkeypatch): + executable = tmp_path / "bin" / "hermes" + monkeypatch.setattr(smoke.shutil, "which", lambda _name: str(executable)) + + assert smoke._resolve_hermes_executable(tmp_path / "repo") == executable + + +def test_resolve_hermes_executable_reports_missing_binary(tmp_path, monkeypatch): + monkeypatch.setattr(smoke.shutil, "which", lambda _name: None) + + with pytest.raises(SystemExit, match="or on PATH"): + smoke._resolve_hermes_executable(tmp_path)