Skip to content

Commit da073b6

Browse files
committed
use featureset object
1 parent 2770ea7 commit da073b6

File tree

2 files changed

+62
-45
lines changed

2 files changed

+62
-45
lines changed

src/featureSet.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import * as semver from "semver"
2+
3+
export type FeatureSet = {
4+
coderExtension: boolean
5+
proxyLogDirectory: boolean
6+
}
7+
8+
/**
9+
* Builds and returns a FeatureSet object for a given coder version.
10+
*/
11+
export function featureSetForVersion(version: semver.SemVer | null): FeatureSet {
12+
return {
13+
coderExtension:
14+
version?.major === 0 && version?.minor <= 14 && version?.patch < 1 && version?.prerelease.length === 0,
15+
16+
// CLI versions before 2.3.3 don't support the --log-dir flag!
17+
// If this check didn't exist, VS Code connections would fail on
18+
// older versions because of an unknown CLI argument.
19+
proxyLogDirectory: (version?.compare("2.3.3") || 0) > 0 || version?.prerelease[0] === "devel",
20+
}
21+
}

src/remote.ts

Lines changed: 41 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ import { makeCoderSdk, startWorkspace, waitForBuild } from "./api"
1414
import { extractAgents } from "./api-helper"
1515
import * as cli from "./cliManager"
1616
import { Commands } from "./commands"
17+
import { featureSetForVersion, FeatureSet } from "./featureSet"
1718
import { getHeaderCommand } from "./headers"
1819
import { SSHConfig, SSHValues, mergeSSHConfigValues } from "./sshConfig"
1920
import { computeSSHProperties, sshSupportsSetEnv } from "./sshSupport"
2021
import { Storage } from "./storage"
2122
import { AuthorityPrefix, expandPath, parseRemoteAuthority } from "./util"
22-
import { supportsCoderAgentLogDirFlag } from "./version"
2323
import { WorkspaceAction } from "./workspaceAction"
2424

2525
export interface RemoteDetails extends vscode.Disposable {
@@ -34,7 +34,6 @@ export class Remote {
3434
private readonly storage: Storage,
3535
private readonly commands: Commands,
3636
private readonly mode: vscode.ExtensionMode,
37-
private coderVersion: semver.SemVer | null = null,
3837
) {}
3938

4039
private async confirmStart(workspaceName: string): Promise<boolean> {
@@ -195,16 +194,38 @@ export class Remote {
195194
// Store for use in commands.
196195
this.commands.workspaceRestClient = workspaceRestClient
197196

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+
198211
// First thing is to check the version.
199212
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+
201227
// 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) {
208229
await this.vscodeProposed.window.showErrorMessage(
209230
"Incompatible Server",
210231
{
@@ -502,7 +523,7 @@ export class Remote {
502523
// "Host not found".
503524
try {
504525
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)
506527
} catch (error) {
507528
this.storage.writeToCoderOutputChannel(`Failed to configure SSH: ${error}`)
508529
throw error
@@ -542,28 +563,11 @@ export class Remote {
542563
}
543564
}
544565

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-
562566
/**
563567
* Format's the --log-dir argument for the ProxyCommand
564568
*/
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) {
567571
return ""
568572
}
569573

@@ -581,7 +585,13 @@ export class Remote {
581585

582586
// updateSSHConfig updates the SSH configuration with a wildcard that handles
583587
// 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+
) {
585595
let deploymentSSHConfig = {}
586596
try {
587597
const deploymentConfig = await restClient.getDeploymentSSHConfig()
@@ -642,20 +652,6 @@ export class Remote {
642652
const sshConfig = new SSHConfig(sshConfigFile)
643653
await sshConfig.load()
644654

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-
659655
const escape = (str: string): string => `"${str.replace(/"/g, '\\"')}"`
660656
// Escape a command line to be executed by the Coder binary, so ssh doesn't substitute variables.
661657
const escapeSubcommand: (str: string) => string =
@@ -677,7 +673,7 @@ export class Remote {
677673
Host: label ? `${AuthorityPrefix}.${label}--*` : `${AuthorityPrefix}--*`,
678674
ProxyCommand: `${escape(binaryPath)}${headerArg} vscodessh --network-info-dir ${escape(
679675
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(
681677
this.storage.getUrlPath(label),
682678
)} %h`,
683679
ConnectTimeout: "0",

0 commit comments

Comments
 (0)