From 9bdcd143cf9fe4ee1bd906ad6e4a29cb01f05bb9 Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Wed, 24 Dec 2025 22:34:53 -0800 Subject: [PATCH] Prioritize dedicated SSH key over agent (#133) --- src/compose_farm/executor.py | 14 +++++++++----- tests/test_ssh_keys.py | 5 +++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/compose_farm/executor.py b/src/compose_farm/executor.py index feeffc5..4b38d0f 100644 --- a/src/compose_farm/executor.py +++ b/src/compose_farm/executor.py @@ -159,14 +159,18 @@ def ssh_connect_kwargs(host: Host) -> dict[str, Any]: "username": host.user, "known_hosts": None, } - # Add SSH agent path (auto-detect forwarded agent if needed) - agent_path = get_ssh_auth_sock() - if agent_path: - kwargs["agent_path"] = agent_path - # Add key file fallback for when SSH agent is unavailable + # Add key file fallback (prioritized over agent if present) key_path = get_key_path() + agent_path = get_ssh_auth_sock() + if key_path: + # If dedicated key exists, force use of it and ignore agent + # This avoids issues with stale/broken forwarded agents in Docker kwargs["client_keys"] = [str(key_path)] + elif agent_path: + # Fallback to agent if no dedicated key + kwargs["agent_path"] = agent_path + return kwargs diff --git a/tests/test_ssh_keys.py b/tests/test_ssh_keys.py index 987f410..81b70c7 100644 --- a/tests/test_ssh_keys.py +++ b/tests/test_ssh_keys.py @@ -219,7 +219,7 @@ class TestSshConnectKwargs: assert result["client_keys"] == [str(key_path)] def test_includes_both_agent_and_key(self, tmp_path: Path) -> None: - """Include both agent_path and client_keys when both available.""" + """Prioritize client_keys over agent_path when both available.""" host = Host(address="example.com") key_path = tmp_path / "compose-farm" @@ -229,7 +229,8 @@ class TestSshConnectKwargs: ): result = ssh_connect_kwargs(host) - assert result["agent_path"] == "/tmp/agent.sock" + # Agent should be ignored in favor of the dedicated key + assert "agent_path" not in result assert result["client_keys"] == [str(key_path)] def test_custom_port(self) -> None: