Skip to content

Comments

Auto update IDE settings for serverless ssh mode#4559

Open
ilia-db wants to merge 9 commits intomainfrom
ssh-tunnel-ide-settings
Open

Auto update IDE settings for serverless ssh mode#4559
ilia-db wants to merge 9 commits intomainfrom
ssh-tunnel-ide-settings

Conversation

@ilia-db
Copy link
Contributor

@ilia-db ilia-db commented Feb 20, 2026

Changes

In serverless ssh mode (ssh connect command without cluster flag and with the ide flag set), we need to set up the desired server ports (or socket connection mode) for the connection to go through (as the majority of the localhost ports on the remote side are blocked by iptable rules). Plus the platform (always linux), and extensions (python and jupyter), to make the initial experience smoother.

This is done by checking the IDE settings file and updating it if necessary, prompting the user for confirmation before doing so.

If the settings file is not found (fresh IDE install), we create one with the recommended configuration. If there are any other issues during the update process, we log the error and print the manual instructions for the user, proceeding with the connection anyway.

Tests

New unit tests, plus manual tests on all platforms (WIP)

In serverless ssh mode (ssh connect command without cluster flag and with the ide flag set),
we need to set up the desired server ports (or socket connection mode) for the connection to go through
(as the majority of the localhost ports on the remote side are blocked by iptable rules).
Plus the platform (always linux), and extensions (python and jupyter), to make the initial experience smoother.

This is done by checking the IDE settings file and updating it if necessary, prompting the user for confirmation before doing so.

If the settings file is not found (fresh IDE install), we create one with the recommended configuration.
If there are any other issues during the update process, we log the error and print the manual instructions for the user,
proceeding with the connection anyway.
@eng-dev-ecosystem-bot
Copy link
Collaborator

eng-dev-ecosystem-bot commented Feb 20, 2026

Commit: 66ae021

Run: 22359729939

Env 🟨​KNOWN 💚​RECOVERED 🙈​SKIP ✅​pass 🙈​skip Time
🟨​ aws linux 7 1 7 268 764 8:30
🟨​ aws windows 7 1 7 270 762 7:28
💚​ aws-ucws linux 8 7 364 680 8:22
💚​ aws-ucws windows 8 7 366 678 7:08
💚​ azure linux 2 9 271 762 6:55
💚​ azure windows 2 9 273 760 5:12
💚​ azure-ucws linux 2 9 369 676 8:36
💚​ azure-ucws windows 2 9 371 674 6:05
💚​ gcp linux 2 9 267 765 6:29
💚​ gcp windows 2 9 269 763 5:38
15 interesting tests: 7 KNOWN, 7 SKIP, 1 RECOVERED
Test Name aws linux aws windows aws-ucws linux aws-ucws windows azure linux azure windows azure-ucws linux azure-ucws windows gcp linux gcp windows
🟨​ TestAccept 🟨​K 🟨​K 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
🙈​ TestAccept/bundle/resources/permissions 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions 🟨​K 🟨​K 💚​R 💚​R 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions/DATABRICKS_BUNDLE_ENGINE=direct 🟨​K 🟨​K 💚​R 💚​R
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions/DATABRICKS_BUNDLE_ENGINE=terraform 🟨​K 🟨​K 💚​R 💚​R
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions 🟨​K 🟨​K 💚​R 💚​R 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions/DATABRICKS_BUNDLE_ENGINE=direct 🟨​K 🟨​K 💚​R 💚​R
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions/DATABRICKS_BUNDLE_ENGINE=terraform 🟨​K 🟨​K 💚​R 💚​R
🙈​ TestAccept/bundle/resources/postgres_branches/basic 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/recreate 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/update_protected 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/without_branch_id 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_endpoints/recreate 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/synced_database_tables/basic 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
💚​ TestAccept/ssh/connection 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
Top 26 slowest tests (at least 2 minutes):
duration env testname
3:18 aws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:15 gcp linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:14 gcp windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:08 gcp linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:06 aws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:06 gcp windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:02 aws-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:02 aws-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:55 aws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:51 aws-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:48 aws-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:46 aws-ucws linux TestAccept
2:41 azure-ucws linux TestAccept
2:30 gcp linux TestAccept
2:26 azure linux TestAccept
2:25 aws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:23 azure-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:16 azure-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:13 azure linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:13 azure windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:10 aws-ucws windows TestAccept
2:10 azure-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:08 azure linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:08 azure-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:05 azure windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:05 azure windows TestAccept

}

func saveSettings(path string, settings map[string]any) error {
data, err := json.MarshalIndent(settings, "", " ")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is quite destructive to the user settings file:

  1. all user comments in their settings are stripped
  2. the order of the fields is not preserved

2 suggestions to already existing mitigation of creating a backup file:

  1. be explicit about the settings file might lose comments and current formatting / ordering
  2. show a preview to the user of which settings need to be added - so that they have a chance to paste those settings themselves

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, updated the logic to use hujson lib that preserves formatting and comments

}

if missing.listenOnSocket {
settings[listenOnSocketKey] = true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there any way to limit the scope of this setting to the current connection? if not, we might want to be explicit about that this setting is global and might break other connections the user might be using

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a way - we can copy user setting into a separate folder, modify them there, and launch vscode/cursor with --user-data-dir argument. We'll have to copy all possible user data to it though - settings, tasks, keybindings, etc. And after that they are fully separate, with no easy way to sync with the main user data. We may want to resort to it, but for now I'll add a warning

return fmt.Errorf("failed to prompt user: %w", err)
}
if !shouldUpdate {
log.Infof(ctx, "Skipping IDE settings update")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the settings update is skipped i suggest we should still show to the user what settings we are suggesting. otherwise this could lead to a silently broken workflow.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm now showing what settings we plan to update when we ask for agreement

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would still be good to add a disclaimer in case the user chooses "no", that if their connection does not work they should update their vscode with the settings displayed above

return nil
}

backupPath := path + ".bak"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

two consequent runs of ssh connect might leave user with no good backup of their settings, we can improve here by ensuring that at least one backup is stored on user's disk keeping the settings as they were before user started using this command.

return fmt.Errorf("failed to marshal settings: %w", err)
}

if err := os.WriteFile(path, data, 0o600); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should acquire the file lock before writing here to prevent data loss on concurrent writes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can add file locking with platform specific APIs (or using ready made lib for it), plus add --force-lock option as an escape hatch. It's heavy handed approach and doesn't seem necessary given the use-case, but we can revisit it later on

@ilia-db ilia-db requested a review from anton-107 February 24, 2026 13:42
Copy link
Contributor

@anton-107 anton-107 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, left a few nit comments

return fmt.Errorf("failed to prompt user: %w", err)
}
if !shouldUpdate {
log.Infof(ctx, "Skipping IDE settings update")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would still be good to add a disclaimer in case the user chooses "no", that if their connection does not work they should update their vscode with the settings displayed above


if err := os.WriteFile(path, data, 0o600); err != nil {
func saveSettings(path string, v *hujson.Value) error {
v.Format()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this formats the entire file (so it might be annoying to those user that take extra care their settings.json), ideally we can skip this and only format our own patched segment

lines = append(lines, fmt.Sprintf(" \"%s\": {\"%s\": \"%s\"}", remotePlatformKey, connectionName, remotePlatform))
}
if missing.listenOnSocket {
lines = append(lines, fmt.Sprintf(" \"%s\": true // Global setting that affects all remote ssh connections", listenOnSocketKey))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this is a bit confusing choice of message format - i was expecting this comment to add up in my settings file (since VSCode supports comments there), but the comment is not being saved

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's mainly to get the message across during the approval prompt, I don't think it's necessary in the file itself.

To avoid user-defined formatting of the settings JSON.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants