hermes: recover interrupted provider CLI installs
This commit is contained in:
parent
0192ef8ee8
commit
364d1b3503
@ -475,7 +475,21 @@ spec:
|
||||
# which self-heals after the pod has run on the other architecture.
|
||||
case "$(uname -m)" in x86_64) nodearch=x64 ;; aarch64) nodearch=arm64 ;; *) nodearch=unknown ;; esac
|
||||
codex_native="${tools}/lib/node_modules/@openai/codex-linux-${nodearch}"
|
||||
if [ ! -f "${tools}/.cli-versions-0.154.0-2.1.226-${arch}" ] || [ ! -d "${codex_native}" ]; then
|
||||
codex_version="$("${tools}/bin/codex" --version 2>/dev/null || true)"
|
||||
claude_version="$("${tools}/bin/claude" --version 2>/dev/null || true)"
|
||||
case "${codex_version}" in *0.154.0*) codex_ready=1 ;; *) codex_ready=0 ;; esac
|
||||
case "${claude_version}" in *2.1.226*) claude_ready=1 ;; *) claude_ready=0 ;; esac
|
||||
if [ ! -f "${tools}/.cli-versions-0.154.0-2.1.226-${arch}" ] || [ ! -d "${codex_native}" ] \
|
||||
|| [ "${codex_ready}" != "1" ] || [ "${claude_ready}" != "1" ]; then
|
||||
# Interrupted npm global installs leave only these private
|
||||
# staging directories; never follow or remove other entries.
|
||||
for scope in "${tools}/lib/node_modules/@anthropic-ai" "${tools}/lib/node_modules/@openai"; do
|
||||
[ -d "${scope}" ] && [ ! -L "${scope}" ] || continue
|
||||
case "${scope}" in
|
||||
*/@anthropic-ai) find "${scope}" -mindepth 1 -maxdepth 1 -type d -name '.claude-code-*' -exec rm -rf -- {} + ;;
|
||||
*/@openai) find "${scope}" -mindepth 1 -maxdepth 1 -type d -name '.codex-*' -exec rm -rf -- {} + ;;
|
||||
esac
|
||||
done
|
||||
npm install --global --omit=dev --no-audit --no-fund --prefix "${tools}" \
|
||||
@openai/codex@0.154.0 \
|
||||
@anthropic-ai/claude-code@2.1.226
|
||||
|
||||
@ -2,6 +2,9 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from testing.tests.test_hermes_cli_support import (
|
||||
HERMES,
|
||||
Path,
|
||||
@ -61,6 +64,13 @@ def test_owner_agent_installs_the_pinned_operator_toolchain():
|
||||
)
|
||||
assert "/bin/sh /opt/coordinator/install_agent_tools.sh" in installer["command"][2]
|
||||
assert any(mount["name"] == "coordinator" for mount in installer["volumeMounts"])
|
||||
install = installer["command"][2]
|
||||
assert 'codex_version="$("${tools}/bin/codex" --version' in install
|
||||
assert 'claude_version="$("${tools}/bin/claude" --version' in install
|
||||
assert "@anthropic-ai" in install and "-name '.claude-code-*'" in install
|
||||
assert "@openai" in install and "-name '.codex-*'" in install
|
||||
assert "-mindepth 1 -maxdepth 1 -type d" in install
|
||||
assert "[ ! -L \"${scope}\" ]" in install
|
||||
init_config = next(
|
||||
item
|
||||
for item in deployment["spec"]["template"]["spec"]["initContainers"]
|
||||
@ -72,6 +82,60 @@ def test_owner_agent_installs_the_pinned_operator_toolchain():
|
||||
assert 'chmod 0644 "${profile_file}"' in init_command
|
||||
|
||||
|
||||
def test_npm_reinstall_removes_only_known_interrupted_staging_directories(tmp_path):
|
||||
"""A stale npm rename target is cleared before the pinned reinstall only."""
|
||||
installer = next(
|
||||
item
|
||||
for item in _agent_deployment()["spec"]["template"]["spec"]["initContainers"]
|
||||
if item["name"] == "install-agent-tools"
|
||||
)
|
||||
tools = tmp_path / "tools"
|
||||
bin_dir = tools / "bin"
|
||||
bin_dir.mkdir(parents=True)
|
||||
for name, output in {
|
||||
"ttyd": "ttyd 1.7.7\n",
|
||||
"kubectl": '{"gitVersion":"v1.33.3"}\n',
|
||||
"codex": "codex 0.154.0\n",
|
||||
"claude": "2.1.226\n",
|
||||
}.items():
|
||||
path = bin_dir / name
|
||||
path.write_text(f"#!/bin/sh\nprintf '%s' '{output}'\n", encoding="utf-8")
|
||||
path.chmod(0o755)
|
||||
for scope, stale in (("@anthropic-ai", ".claude-code-aborted"), ("@openai", ".codex-aborted")):
|
||||
path = tools / "lib/node_modules" / scope / stale
|
||||
path.mkdir(parents=True)
|
||||
(path / "partial").write_text("incomplete", encoding="utf-8")
|
||||
preserved = tools / "lib/node_modules/@anthropic-ai/keep-me"
|
||||
preserved.mkdir(parents=True)
|
||||
(preserved / "data").write_text("preserve", encoding="utf-8")
|
||||
fake_npm = tmp_path / "fake-bin/npm"
|
||||
fake_npm.parent.mkdir()
|
||||
fake_npm.write_text(
|
||||
"#!/bin/sh\n"
|
||||
"test ! -e \"$HERMES_TEST_TOOLS/lib/node_modules/@anthropic-ai/.claude-code-aborted\"\n"
|
||||
"test ! -e \"$HERMES_TEST_TOOLS/lib/node_modules/@openai/.codex-aborted\"\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
fake_npm.chmod(0o755)
|
||||
command = installer["command"][2]
|
||||
command = command.replace("tools=/opt/data/tools", f"tools={tools}")
|
||||
command = command.replace("/bin/sh /opt/coordinator/install_agent_tools.sh", ":")
|
||||
command = command.replace('HOME=/opt/data/home git config --global user.name "Hermes Agent"', ":")
|
||||
command = command.replace('HOME=/opt/data/home git config --global user.email "hermes@bstein.dev"', ":")
|
||||
result = subprocess.run(
|
||||
["sh", "-c", command],
|
||||
text=True,
|
||||
capture_output=True,
|
||||
env={
|
||||
**os.environ,
|
||||
"PATH": f"{fake_npm.parent}:{os.environ['PATH']}",
|
||||
"HERMES_TEST_TOOLS": str(tools),
|
||||
},
|
||||
)
|
||||
assert result.returncode == 0, result.stderr
|
||||
assert (preserved / "data").read_text(encoding="utf-8") == "preserve"
|
||||
|
||||
|
||||
def test_owner_agent_uses_the_canonical_hostname():
|
||||
paths = [
|
||||
HERMES / "agent-configmap.yaml",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user