@@ -14,12 +14,12 @@ import { makeCoderSdk, startWorkspace, waitForBuild } from "./api"
14
14
import { extractAgents } from "./api-helper"
15
15
import * as cli from "./cliManager"
16
16
import { Commands } from "./commands"
17
+ import { featureSetForVersion , FeatureSet } from "./featureSet"
17
18
import { getHeaderCommand } from "./headers"
18
19
import { SSHConfig , SSHValues , mergeSSHConfigValues } from "./sshConfig"
19
20
import { computeSSHProperties , sshSupportsSetEnv } from "./sshSupport"
20
21
import { Storage } from "./storage"
21
22
import { AuthorityPrefix , expandPath , parseRemoteAuthority } from "./util"
22
- import { supportsCoderAgentLogDirFlag } from "./version"
23
23
import { WorkspaceAction } from "./workspaceAction"
24
24
25
25
export interface RemoteDetails extends vscode . Disposable {
@@ -34,7 +34,6 @@ export class Remote {
34
34
private readonly storage : Storage ,
35
35
private readonly commands : Commands ,
36
36
private readonly mode : vscode . ExtensionMode ,
37
- private coderVersion : semver . SemVer | null = null ,
38
37
) { }
39
38
40
39
private async confirmStart ( workspaceName : string ) : Promise < boolean > {
@@ -195,16 +194,38 @@ export class Remote {
195
194
// Store for use in commands.
196
195
this . commands . workspaceRestClient = workspaceRestClient
197
196
197
+ let binaryPath : string | undefined
198
+ if ( this . mode === vscode . ExtensionMode . Production ) {
199
+ binaryPath = await this . storage . fetchBinary ( workspaceRestClient , parts . label )
200
+ } else {
201
+ try {
202
+ // In development, try to use `/tmp/coder` as the binary path.
203
+ // This is useful for debugging with a custom bin!
204
+ binaryPath = path . join ( os . tmpdir ( ) , "coder" )
205
+ await fs . stat ( binaryPath )
206
+ } catch ( ex ) {
207
+ binaryPath = await this . storage . fetchBinary ( workspaceRestClient , parts . label )
208
+ }
209
+ }
210
+
198
211
// First thing is to check the version.
199
212
const buildInfo = await workspaceRestClient . getBuildInfo ( )
200
- this . coderVersion = semver . parse ( buildInfo . version )
213
+
214
+ let version : semver . SemVer | null = null
215
+ try {
216
+ let v = await cli . version ( binaryPath )
217
+ if ( ! v ) {
218
+ v = buildInfo . version
219
+ }
220
+ version = semver . parse ( v )
221
+ } catch ( e ) {
222
+ version = semver . parse ( buildInfo . version )
223
+ }
224
+
225
+ const featureSet = featureSetForVersion ( version )
226
+
201
227
// Server versions before v0.14.1 don't support the vscodessh command!
202
- if (
203
- this . coderVersion ?. major === 0 &&
204
- this . coderVersion ?. minor <= 14 &&
205
- this . coderVersion ?. patch < 1 &&
206
- this . coderVersion ?. prerelease . length === 0
207
- ) {
228
+ if ( featureSet . coderExtension ) {
208
229
await this . vscodeProposed . window . showErrorMessage (
209
230
"Incompatible Server" ,
210
231
{
@@ -502,7 +523,7 @@ export class Remote {
502
523
// "Host not found".
503
524
try {
504
525
this . storage . writeToCoderOutputChannel ( "Updating SSH config..." )
505
- await this . updateSSHConfig ( workspaceRestClient , parts . label , parts . host )
526
+ await this . updateSSHConfig ( workspaceRestClient , parts . label , parts . host , binaryPath , featureSet )
506
527
} catch ( error ) {
507
528
this . storage . writeToCoderOutputChannel ( `Failed to configure SSH: ${ error } ` )
508
529
throw error
@@ -542,28 +563,11 @@ export class Remote {
542
563
}
543
564
}
544
565
545
- /**
546
- * Tries to get the install CLI version. If that fails, defaults
547
- * to the remote coder version. For the most part these should be in sync.
548
- */
549
- private async probableCoderVersion ( binaryPath : string ) : Promise < semver . SemVer | null > {
550
- try {
551
- const version = await cli . version ( binaryPath )
552
- const parsedVersion = semver . parse ( version )
553
- if ( ! parsedVersion ) {
554
- return this . coderVersion
555
- }
556
- return parsedVersion
557
- } catch ( e ) {
558
- return this . coderVersion
559
- }
560
- }
561
-
562
566
/**
563
567
* Format's the --log-dir argument for the ProxyCommand
564
568
*/
565
- private async formatLogArg ( binpath : string ) : Promise < string > {
566
- if ( ! supportsCoderAgentLogDirFlag ( await this . probableCoderVersion ( binpath ) ) ) {
569
+ private async formatLogArg ( featureSet : FeatureSet ) : Promise < string > {
570
+ if ( ! featureSet . proxyLogDirectory ) {
567
571
return ""
568
572
}
569
573
@@ -581,7 +585,13 @@ export class Remote {
581
585
582
586
// updateSSHConfig updates the SSH configuration with a wildcard that handles
583
587
// all Coder entries.
584
- private async updateSSHConfig ( restClient : Api , label : string , hostName : string ) {
588
+ private async updateSSHConfig (
589
+ restClient : Api ,
590
+ label : string ,
591
+ hostName : string ,
592
+ binaryPath : string ,
593
+ featureSet : FeatureSet ,
594
+ ) {
585
595
let deploymentSSHConfig = { }
586
596
try {
587
597
const deploymentConfig = await restClient . getDeploymentSSHConfig ( )
@@ -642,20 +652,6 @@ export class Remote {
642
652
const sshConfig = new SSHConfig ( sshConfigFile )
643
653
await sshConfig . load ( )
644
654
645
- let binaryPath : string | undefined
646
- if ( this . mode === vscode . ExtensionMode . Production ) {
647
- binaryPath = await this . storage . fetchBinary ( restClient , label )
648
- } else {
649
- try {
650
- // In development, try to use `/tmp/coder` as the binary path.
651
- // This is useful for debugging with a custom bin!
652
- binaryPath = path . join ( os . tmpdir ( ) , "coder" )
653
- await fs . stat ( binaryPath )
654
- } catch ( ex ) {
655
- binaryPath = await this . storage . fetchBinary ( restClient , label )
656
- }
657
- }
658
-
659
655
const escape = ( str : string ) : string => `"${ str . replace ( / " / g, '\\"' ) } "`
660
656
// Escape a command line to be executed by the Coder binary, so ssh doesn't substitute variables.
661
657
const escapeSubcommand : ( str : string ) => string =
@@ -677,7 +673,7 @@ export class Remote {
677
673
Host : label ? `${ AuthorityPrefix } .${ label } --*` : `${ AuthorityPrefix } --*` ,
678
674
ProxyCommand : `${ escape ( binaryPath ) } ${ headerArg } vscodessh --network-info-dir ${ escape (
679
675
this . storage . getNetworkInfoPath ( ) ,
680
- ) } ${ await this . formatLogArg ( binaryPath ) } --session-token-file ${ escape ( this . storage . getSessionTokenPath ( label ) ) } --url-file ${ escape (
676
+ ) } ${ await this . formatLogArg ( featureSet ) } --session-token-file ${ escape ( this . storage . getSessionTokenPath ( label ) ) } --url-file ${ escape (
681
677
this . storage . getUrlPath ( label ) ,
682
678
) } %h`,
683
679
ConnectTimeout : "0" ,
0 commit comments