-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Start workspaces by shelling out to CLI #400
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
import { spawn, ChildProcessWithoutNullStreams } from "child_process" | ||
import { Api } from "coder/site/src/api/api" | ||
import { ProvisionerJobLog, Workspace } from "coder/site/src/api/typesGenerated" | ||
import fs from "fs/promises" | ||
|
@@ -122,29 +123,56 @@ export async function makeCoderSdk(baseUrl: string, token: string | undefined, s | |
/** | ||
* Start or update a workspace and return the updated workspace. | ||
*/ | ||
export async function startWorkspaceIfStoppedOrFailed(restClient: Api, workspace: Workspace): Promise<Workspace> { | ||
// 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?? | ||
const versionID = workspace.template_require_active_version | ||
? // Use the latest template version | ||
workspace.template_active_version_id | ||
: // Default to not updating the workspace if not required. | ||
workspace.latest_build.template_version_id | ||
|
||
export async function startWorkspaceIfStoppedOrFailed( | ||
restClient: Api, | ||
binPath: string, | ||
workspace: Workspace, | ||
writeEmitter: vscode.EventEmitter<string>, | ||
): Promise<Workspace> { | ||
// 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 new Promise((resolve, reject) => { | ||
const startProcess: ChildProcessWithoutNullStreams = spawn(binPath, [ | ||
"start", | ||
"--yes", | ||
workspace.owner_name + "/" + workspace.name, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will be the slightly tricky part I think. For most folks this will also need
So all that to say, I think we will have to also make sure the |
||
]) | ||
|
||
startProcess.stdout.on("data", (data: Buffer) => { | ||
data | ||
.toString() | ||
.split(/\r*\n/) | ||
.forEach((line: string) => { | ||
if (line !== "") { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are there a lot of blank lines we have to strip? Does the API strip these out for us maybe so this is for parity? Not a big deal, my only thought is that maybe There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did see blank lines here, I believe due to the CLI's use of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Aahhh right, I completely forgot it does that. That makes perfect sense. Since we display this in a (fake) terminal I wonder if we can pass through directly in a way that handles that case so it looks the same as when you run it directly on the command line, but this looks great to me for now. |
||
writeEmitter.fire(line.toString() + "\r\n") | ||
} | ||
}) | ||
}) | ||
|
||
startProcess.stderr.on("data", (data: Buffer) => { | ||
data | ||
.toString() | ||
.split(/\r*\n/) | ||
.forEach((line: string) => { | ||
if (line !== "") { | ||
writeEmitter.fire(line.toString() + "\r\n") | ||
} | ||
}) | ||
}) | ||
|
||
return { | ||
...updatedWorkspace, | ||
latest_build: latestBuild, | ||
} | ||
startProcess.on("close", (code: number) => { | ||
if (code === 0) { | ||
resolve(restClient.getWorkspace(workspace.id)) | ||
} else { | ||
reject(new Error(`"coder start" process exited with code ${code}`)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thinking out loud, I was hitting this (because of the
|
||
} | ||
}) | ||
}) | ||
} | ||
|
||
/** | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was there an issue with the types? I would expect this to have the same effect: