Repository navigation
Conversation
Reset to Host * before including the source root, preserving typed destination option precedence while allowing jump aliases to read their own configuration. AI assistance: implemented and independently reviewed with OpenAI Codex.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Owner
|
Many thanks for the PR, I've already fixed the issue. Closing. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #1320. An unsaved SSH destination writes a temporary config whose source
Includecurrently remains inside the destination'sHostblock. OpenSSH's implicit ProxyJump child reuses that-Ffile for the jump alias, so its Include is inactive and the child misses the jump's HostName/Port.Insert
Host *immediately before the existing source Include, keeping the typed destination block first. Typed user/port/options retain OpenSSH first-value-wins precedence; jump aliases can read the source config without inheriting destination-only options. The existing ConnectionRepository → daemon launch provider → native OpenSSH path is preserved.Add seven integration-marked native
ssh -Gcases intests/core/test_transient_connections.py. They call actual repository creation and daemon launch preparation, evaluate both the generated config and launch argv, and compare destination/jump settings with a synthetic root. Coverage includes typed user/port precedence, no destination keepalive leakage into the jump, paths with spaces, nested Includes, Match originalhost/Match all boundaries, missing roots, source immutability, mode 0600/0700 permissions and cleanup. Baseline: six failed, one passed. Patched: all seven passed.API and architecture
No public DTO, capability, authentication resolver or alternate connection path is added. No protocol-version or generated API update is needed. Independent Codex review approved the exact patch and final commit; a separate review confirmed the SFTP race attribution below.
Testing
Cloud Linux; Python 3.12.14, OpenSSH 10.0p2 Debian-7+deb13u4 and Ruff 0.15.17. New native cases use temporary configs and
.invalidhosts, no real keys or exec predicates, and onlyssh -Gevaluation. No remote SSH sessions, ProxyCommand execution or authentication were attempted.Passed checks:
PATH=/workspace/sshpilot-1320/.venv/bin:/usr/bin:/bin .venv/bin/pytest -ra tests/core/test_transient_connections.py -m integration -n 0: 7 passed, 14 deselected; independently rerun with the same result. Restricted PATH prevents the generic integration hooks from finding Docker and sweeping containers..venv/bin/pytest -ra tests/core/test_transient_connections.py -m 'not integration and not gui' -n 0: 14 passed, 7 deselected..venv/bin/ruff check src/sshpilot/core/connections/transient.py tests/core/test_transient_connections.py: passed.git diff --check: passed..venv/bin/python scripts/generate_api_artifacts.py --check: passed.Broader checks were run and are not green:
.venv/bin/pytest -ra -m 'not integration and not gui': head 8,312 passed, 13 failed, 95 skipped, 3 warnings; untouched base 8,313 passed, 12 failed, 95 skipped, 3 warnings. The expression also selects property/stress tests and opt-in e2e cases, which skip without their environment..venv/bin/pytest -ra tests/core tests/architecture tests/daemon/test_connection_launch_provider.py tests/daemon/test_ssh_launch.py tests/daemon/test_ssh_launch_parity.py -m 'not integration and not gui' -n 2: 1,311 passed, 3 failed, 1 skipped. All three failures reproduce on the untouched base..venv/bin/ruff check src/ tests/ scripts/generate_api_artifacts.py: three unchanged findings: RUF022 insrc/sshpilot/api/models/__init__.py:373, UP012 insrc/sshpilot/window_tabs.py:85, PIE807 intests/test_connection_dialog_fixes.py:564. These files are independently verified byte-identical to base.The twelve shared broad failures, each observed on both head and untouched base, are:
The thirteenth head failure was
tests/daemon/test_transfer_batch_real_sftp.py::test_losing_the_server_mid_batch_stops_short_with_what_landed. It passed in the uninstrumented full baseline run; that result is preserved. Twenty additional ordinary isolated invocations per checkout all pass, as does the original eight-test module on each checkout.Controlled native scheduling independently reproduces the saved failure on both base and head: when the worker resumes before the reader marks the client closed, real pipe writes produce EPIPE and the unchanged transfer runtime counts all five items handled, failing the original
5 < 5assertion. Three controls per checkout fail identically; the opposite reader-first order passes three times per checkout and stops at one item with no per-item failures. The temporary diagnostic plugin changes only synchronization, fabricating no packets/errors/summary values, and is excluded from this PR. Relevant SFTP code and fixtures are byte-identical to base and bypass transient creation/launch. This establishes a pre-existing disconnect race; it does not turn the historical broad run green or fix that unrelated defect.Limits: Python 3.13, real GTK/desktop, packaged deb/Flatpak/macOS, actual SSH/ProxyJump child sessions, authentication/agents/key use, Match exec/canonicalization, packaging/resource builds and remote CI are untested. Broader headless tests use their existing synthetic local files, sockets, pipes and binaries. Optional MCP/pexpect, GTK/Cairo/gettext and other environment-dependent checks skip where unavailable. No remote CI success is claimed.
AI assistance: implementation, regression-test development and separate independent reviews used OpenAI Codex. No CLA acceptance or DCO sign-off is asserted.