Skip to content

Commit 6d509d6

Browse files
authored
fix: remote ide no longer reconnects after plugin upgrade (#167)
When the plugin is upgraded while JBClient is connected to a remote dev server via the Coder SSH proxy/tunnel, the upgrade process kills and re-establishes the SSH connection. However, JBClient/Toolbox fails to detect the restored connection and reports "Toolbox: Target environment com.coder.toolbox:bobiverse-bob.dev not found" error. While digging into the Toolbox bytecode—specifically `ClientOverSshTunnelConnector` — I realized the issue likely stems from an incorrect equals implementation in our custom SSH connection info object. In short, when a plugin upgrade terminates the SSH tunnel, the connector’s monitoring logic correctly detects the lost connection and waits. But when the SSH connection is re-established, the monitoring logic fails to recognize it as a valid replacement, because equals is still using the default `Object#equals` rather than a proper value-based implementation. Unfortunately, I wasn’t able to properly test this—specifically, upgrading from a version without the fix to one that includes it—because all Toolbox marketplace feeds are signed, preventing us from using a tool like mitmproxy to serve a locally modified plugin version. Given that, I propose releasing the change first and then performing the upgrade test to confirm the fix. - resolves #61
1 parent 5af07af commit 6d509d6

File tree

2 files changed

+50
-15
lines changed

2 files changed

+50
-15
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
- URL validation is stricter in the connection screen and URI protocol handler
1212
- support for verbose logging a sanitized version of the REST API request and responses
1313

14+
### Fixed
15+
16+
- remote IDE reconnects automatically after plugin upgrade
17+
1418
## 0.6.0 - 2025-07-25
1519

1620
### Changed

src/main/kotlin/com/coder/toolbox/views/EnvironmentView.kt

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,51 @@ class EnvironmentView(
2121
private val workspace: Workspace,
2222
private val agent: WorkspaceAgent,
2323
) : SshEnvironmentContentsView {
24-
override suspend fun getConnectionInfo(): SshConnectionInfo = object : SshConnectionInfo {
25-
/**
26-
* The host name generated by the cli manager for this workspace.
27-
*/
28-
override val host: String = cli.getHostname(url, workspace, agent)
29-
30-
/**
31-
* The port is ignored by the Coder proxy command.
32-
*/
33-
override val port: Int = 22
34-
35-
/**
36-
* The username is ignored by the Coder proxy command.
37-
*/
38-
override val userName: String? = null
24+
override suspend fun getConnectionInfo(): SshConnectionInfo = WorkspaceSshConnectionInfo(url, cli, workspace, agent)
25+
}
26+
27+
private class WorkspaceSshConnectionInfo(
28+
url: URL,
29+
cli: CoderCLIManager,
30+
private val workspace: Workspace,
31+
private val agent: WorkspaceAgent,
32+
) : SshConnectionInfo {
33+
/**
34+
* The host name generated by the cli manager for this workspace.
35+
*/
36+
override val host: String = cli.getHostname(url, workspace, agent)
37+
38+
/**
39+
* The port is ignored by the Coder proxy command.
40+
*/
41+
override val port: Int = 22
42+
43+
/**
44+
* The username is ignored by the Coder proxy command.
45+
*/
46+
override val userName: String? = null
47+
48+
override fun equals(other: Any?): Boolean {
49+
if (this === other) return true
50+
if (javaClass != other?.javaClass) return false
51+
52+
other as WorkspaceSshConnectionInfo
53+
54+
if (port != other.port) return false
55+
if (workspace.name != other.workspace.name) return false
56+
if (agent.name != other.agent.name) return false
57+
if (host != other.host) return false
58+
59+
return true
60+
}
61+
62+
override fun hashCode(): Int {
63+
var result = port
64+
result = 31 * result + workspace.name.hashCode()
65+
result = 31 * result + agent.name.hashCode()
66+
result = 31 * result + host.hashCode()
67+
return result
3968
}
69+
70+
4071
}

0 commit comments

Comments
 (0)