Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf8319a8

Browse files
author
Aaron Lehmann
committed
Start workspaces by shelling out to CLI
Replace the REST-API-based start flow with one that shells out to thecoder CLI.
1 parentda1aaed commitf8319a8

File tree

2 files changed

+77
-37
lines changed

2 files changed

+77
-37
lines changed

‎src/api.ts‎

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import{spawn,ChildProcessWithoutNullStreams}from"child_process"
12
import{Api}from"coder/site/src/api/api"
23
import{ProvisionerJobLog,Workspace}from"coder/site/src/api/typesGenerated"
34
importfsfrom"fs/promises"
@@ -122,29 +123,56 @@ export async function makeCoderSdk(baseUrl: string, token: string | undefined, s
122123
/**
123124
* Start or update a workspace and return the updated workspace.
124125
*/
125-
exportasyncfunctionstartWorkspaceIfStoppedOrFailed(restClient:Api,workspace:Workspace):Promise<Workspace>{
126-
// If the workspace requires the latest active template version, we should attempt
127-
// to update that here.
128-
// TODO: If param set changes, what do we do??
129-
constversionID=workspace.template_require_active_version
130-
?// Use the latest template version
131-
workspace.template_active_version_id
132-
:// Default to not updating the workspace if not required.
133-
workspace.latest_build.template_version_id
134-
126+
exportasyncfunctionstartWorkspaceIfStoppedOrFailed(
127+
restClient:Api,
128+
binPath:string,
129+
workspace:Workspace,
130+
writeEmitter:vscode.EventEmitter<string>,
131+
):Promise<Workspace>{
135132
// Before we start a workspace, we make an initial request to check it's not already started
136133
constupdatedWorkspace=awaitrestClient.getWorkspace(workspace.id)
137134

138135
if(!["stopped","failed"].includes(updatedWorkspace.latest_build.status)){
139136
returnupdatedWorkspace
140137
}
141138

142-
constlatestBuild=awaitrestClient.startWorkspace(updatedWorkspace.id,versionID)
139+
returnnewPromise((resolve,reject)=>{
140+
conststartProcess:ChildProcessWithoutNullStreams=spawn(binPath,[
141+
"start",
142+
"--yes",
143+
workspace.owner_name+"/"+workspace.name,
144+
])
145+
146+
startProcess.stdout.on("data",(data:Buffer)=>{
147+
data
148+
.toString()
149+
.split(/\r*\n/)
150+
.forEach((line:string)=>{
151+
if(line!==""){
152+
writeEmitter.fire(line.toString()+"\r\n")
153+
}
154+
})
155+
})
156+
157+
startProcess.stderr.on("data",(data:Buffer)=>{
158+
data
159+
.toString()
160+
.split(/\r*\n/)
161+
.forEach((line:string)=>{
162+
if(line!==""){
163+
writeEmitter.fire(line.toString()+"\r\n")
164+
}
165+
})
166+
})
143167

144-
return{
145-
...updatedWorkspace,
146-
latest_build:latestBuild,
147-
}
168+
startProcess.on("close",(code:number)=>{
169+
if(code===0){
170+
resolve(restClient.getWorkspace(workspace.id))
171+
}else{
172+
reject(newError(`"coder start" process exited with code${code}`))
173+
}
174+
})
175+
})
148176
}
149177

150178
/**

‎src/remote.ts‎

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { computeSSHProperties, sshSupportsSetEnv } from "./sshSupport"
2020
import{Storage}from"./storage"
2121
import{AuthorityPrefix,expandPath,parseRemoteAuthority}from"./util"
2222
import{WorkspaceMonitor}from"./workspaceMonitor"
23+
import{write}from"fs"
2324

2425
exportinterfaceRemoteDetailsextendsvscode.Disposable{
2526
url:string
@@ -50,7 +51,11 @@ export class Remote {
5051
/**
5152
* Try to get the workspace running. Return undefined if the user canceled.
5253
*/
53-
privateasyncmaybeWaitForRunning(restClient:Api,workspace:Workspace):Promise<Workspace|undefined>{
54+
privateasyncmaybeWaitForRunning(
55+
restClient:Api,
56+
workspace:Workspace,
57+
binPath:string,
58+
):Promise<Workspace|undefined>{
5459
// Maybe already running?
5560
if(workspace.latest_build.status==="running"){
5661
returnworkspace
@@ -63,6 +68,28 @@ export class Remote {
6368
letterminal:undefined|vscode.Terminal
6469
letattempts=0
6570

71+
functioninitWriteEmitterAndTerminal():vscode.EventEmitter<string>{
72+
if(!writeEmitter){
73+
writeEmitter=newvscode.EventEmitter<string>()
74+
}
75+
if(!terminal){
76+
terminal=vscode.window.createTerminal({
77+
name:"Build Log",
78+
location:vscode.TerminalLocation.Panel,
79+
// Spin makes this gear icon spin!
80+
iconPath:newvscode.ThemeIcon("gear~spin"),
81+
pty:{
82+
onDidWrite:writeEmitter.event,
83+
close:()=>undefined,
84+
open:()=>undefined,
85+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
86+
}asPartial<vscode.Pseudoterminal>asany,
87+
})
88+
terminal.show(true)
89+
}
90+
returnwriteEmitter
91+
}
92+
6693
try{
6794
// Show a notification while we wait.
6895
returnawaitthis.vscodeProposed.window.withProgress(
@@ -78,33 +105,17 @@ export class Remote {
78105
case"pending":
79106
case"starting":
80107
case"stopping":
81-
if(!writeEmitter){
82-
writeEmitter=newvscode.EventEmitter<string>()
83-
}
84-
if(!terminal){
85-
terminal=vscode.window.createTerminal({
86-
name:"Build Log",
87-
location:vscode.TerminalLocation.Panel,
88-
// Spin makes this gear icon spin!
89-
iconPath:newvscode.ThemeIcon("gear~spin"),
90-
pty:{
91-
onDidWrite:writeEmitter.event,
92-
close:()=>undefined,
93-
open:()=>undefined,
94-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
95-
}asPartial<vscode.Pseudoterminal>asany,
96-
})
97-
terminal.show(true)
98-
}
108+
writeEmitter=initWriteEmitterAndTerminal()
99109
this.storage.writeToCoderOutputChannel(`Waiting for${workspaceName}...`)
100110
workspace=awaitwaitForBuild(restClient,writeEmitter,workspace)
101111
break
102112
case"stopped":
103113
if(!(awaitthis.confirmStart(workspaceName))){
104114
returnundefined
105115
}
116+
writeEmitter=initWriteEmitterAndTerminal()
106117
this.storage.writeToCoderOutputChannel(`Starting${workspaceName}...`)
107-
workspace=awaitstartWorkspaceIfStoppedOrFailed(restClient,workspace)
118+
workspace=awaitstartWorkspaceIfStoppedOrFailed(restClient,binPath,workspace,writeEmitter)
108119
break
109120
case"failed":
110121
// On a first attempt, we will try starting a failed workspace
@@ -113,8 +124,9 @@ export class Remote {
113124
if(!(awaitthis.confirmStart(workspaceName))){
114125
returnundefined
115126
}
127+
writeEmitter=initWriteEmitterAndTerminal()
116128
this.storage.writeToCoderOutputChannel(`Starting${workspaceName}...`)
117-
workspace=awaitstartWorkspaceIfStoppedOrFailed(restClient,workspace)
129+
workspace=awaitstartWorkspaceIfStoppedOrFailed(restClient,binPath,workspace,writeEmitter)
118130
break
119131
}
120132
// Otherwise fall through and error.
@@ -292,7 +304,7 @@ export class Remote {
292304
disposables.push(this.registerLabelFormatter(remoteAuthority,workspace.owner_name,workspace.name))
293305

294306
// If the workspace is not in a running state, try to get it running.
295-
constupdatedWorkspace=awaitthis.maybeWaitForRunning(workspaceRestClient,workspace)
307+
constupdatedWorkspace=awaitthis.maybeWaitForRunning(workspaceRestClient,workspace,binaryPath)
296308
if(!updatedWorkspace){
297309
// User declined to start the workspace.
298310
awaitthis.closeRemote()

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp