diff --git a/CHANGELOG.md b/CHANGELOG.md index 086ea1d0..4600e7c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ## Unreleased +- Previously, if a workspace stopped or restarted causing the "Start" dialog to + appear in VS Code, the start button would fire a start workspace request regardless + of the workspace status. + Now we perform a check to see if the workspace is still stopped or failed. If its status + has changed out from under the IDE, it will not fire a redundant start request. + ### Changed - Previously, the extension would always log SSH proxy diagnostics to a fixed diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8671c76c..7ec93dc5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -93,6 +93,11 @@ was but for now it means some things are difficult to test as you cannot import ## Development +> [!IMPORTANT] +> Reasoning about networking gets really wonky trying to develop +> this extension from a coder workspace. We currently recommend cloning the +> repo locally + 1. Run `yarn watch` in the background. 2. OPTIONAL: Compile the `coder` binary and place it in the equivalent of `os.tmpdir() + "/coder"`. If this is missing, it will download the binary diff --git a/src/api.ts b/src/api.ts index a237a830..5a2d4c4d 100644 --- a/src/api.ts +++ b/src/api.ts @@ -94,7 +94,7 @@ export async function makeCoderSdk(baseUrl: string, token: string | undefined, s /** * Start or update a workspace and return the updated workspace. */ -export async function startWorkspace(restClient: Api, workspace: Workspace): Promise { +export async function startWorkspaceIfStoppedOrFailed(restClient: Api, workspace: Workspace): Promise { // If the workspace requires the latest active template version, we should attempt // to update that here. // TODO: If param set changes, what do we do?? @@ -103,9 +103,18 @@ export async function startWorkspace(restClient: Api, workspace: Workspace): Pro workspace.template_active_version_id : // Default to not updating the workspace if not required. workspace.latest_build.template_version_id - const latestBuild = await restClient.startWorkspace(workspace.id, versionID) + + // Before we start a workspace, we make an initial request to check it's not already started + const updatedWorkspace = await restClient.getWorkspace(workspace.id) + + if (!["stopped", "failed"].includes(updatedWorkspace.latest_build.status)) { + return updatedWorkspace + } + + const latestBuild = await restClient.startWorkspace(updatedWorkspace.id, versionID) + return { - ...workspace, + ...updatedWorkspace, latest_build: latestBuild, } } diff --git a/src/remote.ts b/src/remote.ts index 07fb94bb..1d10c90d 100644 --- a/src/remote.ts +++ b/src/remote.ts @@ -10,7 +10,7 @@ import * as path from "path" import prettyBytes from "pretty-bytes" import * as semver from "semver" import * as vscode from "vscode" -import { makeCoderSdk, startWorkspace, waitForBuild } from "./api" +import { makeCoderSdk, startWorkspaceIfStoppedOrFailed, waitForBuild } from "./api" import { extractAgents } from "./api-helper" import * as cli from "./cliManager" import { Commands } from "./commands" @@ -105,7 +105,7 @@ export class Remote { return undefined } this.storage.writeToCoderOutputChannel(`Starting ${workspaceName}...`) - workspace = await startWorkspace(restClient, workspace) + workspace = await startWorkspaceIfStoppedOrFailed(restClient, workspace) break case "failed": // On a first attempt, we will try starting a failed workspace @@ -115,7 +115,7 @@ export class Remote { return undefined } this.storage.writeToCoderOutputChannel(`Starting ${workspaceName}...`) - workspace = await startWorkspace(restClient, workspace) + workspace = await startWorkspaceIfStoppedOrFailed(restClient, workspace) break } // Otherwise fall through and error.