From 7da0e3e10e59c01959a52b8ca66fe138cac2bbce Mon Sep 17 00:00:00 2001 From: Benjamin Peinhardt Date: Thu, 5 Sep 2024 23:32:04 +0000 Subject: [PATCH 1/7] push so I can test locally rather than via workspace --- src/api.ts | 19 ++++++++++++++++++- src/remote.ts | 8 +++++--- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/api.ts b/src/api.ts index a237a830..d9cfa451 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,5 +1,5 @@ import { Api } from "coder/site/src/api/api" -import { ProvisionerJobLog, Workspace } from "coder/site/src/api/typesGenerated" +import { ProvisionerJobLog, Workspace, WorkspaceStatus } from "coder/site/src/api/typesGenerated" import fs from "fs/promises" import { ProxyAgent } from "proxy-agent" import * as vscode from "vscode" @@ -103,13 +103,30 @@ 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 + // let latestBuild = (await restClient.getWorkspace(workspace.id)).latest_build + // if (!["starting", "running"].includes(latestBuild.status)) { + + // } + return { ...workspace, latest_build: latestBuild, } } +/** + * Get the status of a workspace + * @param restClient Api + * @param workspaceId string + * @returns WorkspaceStatus + */ +export async function getWorkspaceStatus(restClient: Api, workspaceId: string): Promise { + return (await restClient.getWorkspace(workspaceId)).latest_build.status +} + /** * Wait for the latest build to finish while streaming logs to the emitter. * diff --git a/src/remote.ts b/src/remote.ts index 07fb94bb..b2ce2061 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 { getWorkspaceStatus, makeCoderSdk, startWorkspace, waitForBuild } from "./api" import { extractAgents } from "./api-helper" import * as cli from "./cliManager" import { Commands } from "./commands" @@ -104,8 +104,10 @@ export class Remote { if (!(await this.confirmStart(workspaceName))) { return undefined } - this.storage.writeToCoderOutputChannel(`Starting ${workspaceName}...`) - workspace = await startWorkspace(restClient, workspace) + if (!["running", "starting"].includes(await getWorkspaceStatus(restClient, workspace.id))) { + this.storage.writeToCoderOutputChannel(`Starting ${workspaceName}...`) + workspace = await startWorkspace(restClient, workspace) + } break case "failed": // On a first attempt, we will try starting a failed workspace From 608f116040a54dbf9c6f289815a6ed7f8b99aceb Mon Sep 17 00:00:00 2001 From: Benjamin Peinhardt Date: Fri, 6 Sep 2024 18:25:26 +0000 Subject: [PATCH 2/7] back to normal --- src/api.ts | 12 +----------- src/remote.ts | 8 +++----- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/src/api.ts b/src/api.ts index d9cfa451..bf2b2d01 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,5 +1,5 @@ import { Api } from "coder/site/src/api/api" -import { ProvisionerJobLog, Workspace, WorkspaceStatus } from "coder/site/src/api/typesGenerated" +import { ProvisionerJobLog, Workspace } from "coder/site/src/api/typesGenerated" import fs from "fs/promises" import { ProxyAgent } from "proxy-agent" import * as vscode from "vscode" @@ -117,16 +117,6 @@ export async function startWorkspace(restClient: Api, workspace: Workspace): Pro } } -/** - * Get the status of a workspace - * @param restClient Api - * @param workspaceId string - * @returns WorkspaceStatus - */ -export async function getWorkspaceStatus(restClient: Api, workspaceId: string): Promise { - return (await restClient.getWorkspace(workspaceId)).latest_build.status -} - /** * Wait for the latest build to finish while streaming logs to the emitter. * diff --git a/src/remote.ts b/src/remote.ts index b2ce2061..07fb94bb 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 { getWorkspaceStatus, makeCoderSdk, startWorkspace, waitForBuild } from "./api" +import { makeCoderSdk, startWorkspace, waitForBuild } from "./api" import { extractAgents } from "./api-helper" import * as cli from "./cliManager" import { Commands } from "./commands" @@ -104,10 +104,8 @@ export class Remote { if (!(await this.confirmStart(workspaceName))) { return undefined } - if (!["running", "starting"].includes(await getWorkspaceStatus(restClient, workspace.id))) { - this.storage.writeToCoderOutputChannel(`Starting ${workspaceName}...`) - workspace = await startWorkspace(restClient, workspace) - } + this.storage.writeToCoderOutputChannel(`Starting ${workspaceName}...`) + workspace = await startWorkspace(restClient, workspace) break case "failed": // On a first attempt, we will try starting a failed workspace From c84797bad19fee5542169ac5f67ab1d982a65a92 Mon Sep 17 00:00:00 2001 From: Benjamin Peinhardt Date: Mon, 9 Sep 2024 19:21:14 +0000 Subject: [PATCH 3/7] ashers trying --- src/api.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/api.ts b/src/api.ts index bf2b2d01..8cb9506e 100644 --- a/src/api.ts +++ b/src/api.ts @@ -104,15 +104,17 @@ export async function startWorkspace(restClient: Api, workspace: Workspace): Pro : // 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 - // let latestBuild = (await restClient.getWorkspace(workspace.id)).latest_build - // if (!["starting", "running"].includes(latestBuild.status)) { + const updatedWorkspace = await restClient.getWorkspace(workspace.id) + + if (["starting", "running"].includes(updatedWorkspace.latest_build.status)) { + return updatedWorkspace + } - // } + const latestBuild = await restClient.startWorkspace(updatedWorkspace.id, versionID) return { - ...workspace, + ...updatedWorkspace, latest_build: latestBuild, } } From 9ad58c4a667522dd68ff16bf0e5f2b1da1050d26 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Mon, 9 Sep 2024 14:58:34 -0500 Subject: [PATCH 4/7] update contributing for the next poor soul --- CONTRIBUTING.md | 5 +++++ 1 file changed, 5 insertions(+) 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 From a7ed1ee9bf15c948cce02393b0b1aafc95aa34ff Mon Sep 17 00:00:00 2001 From: Benjamin Date: Mon, 9 Sep 2024 15:12:26 -0500 Subject: [PATCH 5/7] updates baby --- src/api.ts | 4 ++-- src/remote.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/api.ts b/src/api.ts index 8cb9506e..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?? @@ -107,7 +107,7 @@ export async function startWorkspace(restClient: Api, workspace: Workspace): Pro // 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 (["starting", "running"].includes(updatedWorkspace.latest_build.status)) { + if (!["stopped", "failed"].includes(updatedWorkspace.latest_build.status)) { return updatedWorkspace } 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. From 8e63b8dc13266a8cd52e3155d4a14df22848d58f Mon Sep 17 00:00:00 2001 From: Benjamin Date: Mon, 9 Sep 2024 15:18:01 -0500 Subject: [PATCH 6/7] update Changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 086ea1d0..ed13e471 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 From 9b63041ad59aa423ab0d25eae678ea292b0d1a4a Mon Sep 17 00:00:00 2001 From: Benjamin Date: Mon, 9 Sep 2024 15:21:20 -0500 Subject: [PATCH 7/7] lint --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed13e471..4600e7c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,10 @@ ## Unreleased -- Previously, if a workspace stopped or restarted causing the "Start" dialog to +- 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 + 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