experimental/ssh: keep the IDE remote authority stable across connects - #6550
Merged
Conversation
`ssh connect --ide` launched the IDE with `--remote ssh-remote+<user>@<host>`, where <user> is the remote OS user. On serverless that is a fresh per-instance name (spark-<uuid>), so the authority -- and with it the URI VS Code remembers -- differed on every connect. VS Code keys the "previously opened folders" it lists under a host by URI, so every connect added a duplicate row to the Remote Explorer. The SSH config entry itself was never duplicated; it is overwritten in place. Use the host alias alone as the authority. The host config the CLI writes for the connection already carries a User directive, so ssh still resolves the right remote user. Verified against real serverless compute: the IDE receives `--remote ssh-remote+<name>` and `ssh <name>`, with no user in the destination, connects and lands as the current spark-<uuid>. Co-authored-by: Isaac <no-reply@databricks.com>
Co-authored-by: Isaac <no-reply@databricks.com>
Collaborator
Integration test reportCommit: 6fd07ff
Top 2 slowest tests (at least 2 minutes):
|
rugpanov
approved these changes
Sep 8, 2026
rugpanov
left a comment
Contributor
There was a problem hiding this comment.
Reviewed the change and focused SSH coverage. The stable host-only remote authority preserves SSH user resolution through the generated config and prevents per-instance VS Code/Cursor entries. No blocking findings.
rclarey
approved these changes
Sep 8, 2026
rclarey
left a comment
Contributor
There was a problem hiding this comment.
Code LGTM 👍 It would be good to add a test for the User directive in the generated SSH config since the removal of userName from the remote URI is justified by the User directive being present
…ate getIDE call Pass the already-resolved ideDescriptor into remoteLaunchArgs instead of the ideOption string, removing the redundant getIDE call inside the function. Co-authored-by: Isaac <no-reply@databricks.com>
Collaborator
Integration test reportCommit: cee45b8
1159 interesting tests: 1005 MISS, 153 FAIL, 1 SKIP
Top 50 slowest tests (at least 2 minutes):
|
deco-sdk-tagging Bot
added a commit
that referenced
this pull request
Sep 9, 2026
## Release v1.16.0 ### CLI * `aitools install` now registers the official Claude marketplace if it is missing before installing the Databricks Claude plugin. ([#6485](#6485)) * `databricks aitools install --output json` now reports an `error_category` for a failed or skipped install (per agent, and at the top level for a failure with no per-agent entry), giving coding agents and CI a stable classification of why an install did not complete. ([#6482](#6482)) * `databricks aitools install` honors `--output json`, emitting a structured `{scope, agents[...]}` document that reports each agent's delivery and install status so coding agents and CI can consume the result without scraping the text output. JSON mode requires `--scope` and `--agents` so the command runs without interactive prompts. ([#6481](#6481)) * `databricks bundle sync` now prints sync progress (`Action: PUT`, `Uploaded ...`) by default, matching `databricks sync`. Previously it was silent unless `--output` was passed. Use `--output json` for machine-readable output. ([#6568](#6568)) * Support major-only DBR runtime versions such as `19.x-scala2.13` in the cluster picker used by `databricks auth login --configure-cluster` and `databricks labs`. ([#6574](#6574)) * Deprecated the `databricks environments setup-local --constraints-only` flag in favour of the orthogonal `--no-dbconnect`; the flag still works as a hidden alias but is hidden from `--help` and prints a one-line deprecation notice, and will be removed in a later release. ([#6470](#6470)) * Add orthogonal `--no-constraints` and `--no-dbconnect` flags to `databricks environments setup-local`: `--no-constraints` skips writing the remote Python-version and dependency pins, and `--no-dbconnect` skips the databricks-connect dependency. ([#6464](#6464)) * `databricks environments setup-local` now reports a distinct `E_PROVISION_CONFLICT` error code in `--output json` when the project's dependencies conflict with the pins written for the target environment, making the requirements unsatisfiable (the same conflict surfaced as a `W_USER_CONSTRAINT_CONFLICT` warning); it is reported after the project files are written, without attempting the doomed provisioning, while other provisioning failures continue to report `E_PROVISION`. ([#6479](#6479)) * `databricks ssh connect` and `ssh setup` now verify the tunnel's SSH host key against the key the workspace published for the connection, recorded in `~/.databricks/ssh-tunnel-known-hosts/<name>` instead of `~/.ssh/known_hosts`. Reconnecting with a name used before no longer fails with `Host key verification failed` when the compute behind that name changed, and no longer needs a manual `ssh-keygen -R`; host blocks written by an earlier `databricks ssh setup` pick this up once you re-run it. ([#6557](#6557)) * Stop `databricks ssh connect --ide` from adding a duplicate entry to the IDE's Remote Explorer on every connect: the remote authority is now the SSH host alias alone, instead of embedding the per-instance remote OS user. ([#6550](#6550)) * Add `--max-clients` and `--server-timeout` flags to `databricks ssh setup`, and `--server-timeout` to `databricks ssh connect`. Both are fixed when the SSH tunnel server job is submitted, so `ssh setup` now serializes them into the generated `ProxyCommand` instead of falling back to the built-in defaults. ([#6547](#6547)) * `ssh connect` sessions no longer end when the tunnel's websocket connection is lost. The CLI reattaches to the running session and replays the bytes that were missed, so the shell and everything running in it stay intact, and a transient failure to open a replacement connection for the periodic auth refresh is retried rather than ending the session. Reattaching requires an SSH server started by a CLI that supports it; against an older server the connection behaves as before. ([#6558](#6558)) ### Bundles * Added PyDABs (Python) support for secrets: `Resources.add_secret` and the `secret_mutator` decorator. ([#6553](#6553)) * Fix job and pipeline environment dependencies with a `*` version wildcard (e.g. `numpy==2.5.*`) being treated as local file paths. ([#6555](#6555)) * Add the `postgres_snapshot_schedules` bundle resource for managing a Lakebase Postgres branch's automatic-snapshot schedule (direct deployment engine only). ([#6449](#6449)) ### Dependency Updates * Bump `github.com/databricks/databricks-sdk-go` from v0.175.0 to v0.177.0. ([#6448](#6448)) * Bump Terraform provider from v1.128.0 to v1.131.0. ([#6544](#6544))
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.
Fixes a bug reported by a customer: every
databricks ssh connect --ide=vscodeadded another row to the IDE's Remote Explorer, so the connection list filled up with duplicates of the same workspace folder.Root cause
The SSH config entry is not duplicated —
runIDEwrites one file per connection name and overwrites it in place. What multiplies is the list of previously opened folders VS Code shows under the host.LaunchIDElaunched the IDE with--remote ssh-remote+<remote-OS-user>@<connection-name>. On serverless the remote OS user is a fresh per-instance name. Measured across three consecutive connects:So the authority — and with it the URI VS Code remembers — differed every time. VS Code keys that list by URI, giving one new row per connect.
Fix
Use the host alias alone as the authority (
ssh-remote+<connection-name>). The host config the CLI already writes for the connection carries aUserdirective, so ssh still resolves the right remote user; the value simply stops leaking into the part VS Code persists.The argument construction moves into a small pure
remoteLaunchArgsso it can be asserted directly.Testing
TestRemoteLaunchArgspins the exact arguments for both VS Code and Cursor, including that Cursor keeps--classicfirst.go test ./experimental/ssh/...,go test ./cmd/...andTestAccept/sshpass.--remote ssh-remote+<name>, andssh <name>with no user in the destination connects and lands as the currentspark-<uuid>.Note
Rows already accumulated live in VS Code's own state, so existing users keep theirs (removable from the Remote Explorer context menu). This stops new ones from appearing.
This pull request and its description were written by Isaac.