- Notifications
You must be signed in to change notification settings - Fork23
feat: add ability to attach to devcontainers#463
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -6,7 +6,7 @@ import { makeCoderSdk, needToken } from "./api" | ||||||||
import{extractAgents}from"./api-helper" | ||||||||
import{CertificateError}from"./error" | ||||||||
import{Storage}from"./storage" | ||||||||
import{toRemoteAuthority,toSafeHost}from"./util" | ||||||||
import{OpenableTreeItem}from"./workspacesProvider" | ||||||||
exportclassCommands{ | ||||||||
@@ -499,6 +499,26 @@ export class Commands { | ||||||||
awaitopenWorkspace(baseUrl,workspaceOwner,workspaceName,workspaceAgent,folderPath,openRecent) | ||||||||
} | ||||||||
/** | ||||||||
* Open a devcontainer from a workspace belonging to the currently logged-in deployment. | ||||||||
* | ||||||||
* Throw if not logged into a deployment. | ||||||||
*/ | ||||||||
publicasyncopenDevContainer(...args:string[]):Promise<void>{ | ||||||||
constbaseUrl=this.restClient.getAxiosInstance().defaults.baseURL | ||||||||
if(!baseUrl){ | ||||||||
thrownewError("You are not logged in") | ||||||||
} | ||||||||
constworkspaceOwner=args[0]asstring | ||||||||
constworkspaceName=args[1]asstring | ||||||||
constworkspaceAgent=undefined// args[2] is reserved, but we do not support multiple agents yet. | ||||||||
constdevContainerName=args[3]asstring | ||||||||
Comment on lines +515 to +516 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. The extension passes a workspaceAgent parameter for the openDevContainer command, but this parameter is being discarded by explicitly setting workspaceAgent to undefined. Consider either using args[2] if provided or updating the extension to no longer supply the parameter. Suggested change
Copilot uses AI. Check for mistakes. 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. We already have precedent for doing this with the | ||||||||
constdevContainerFolder=args[4]asstring | ||||||||
awaitopenDevContainer(baseUrl,workspaceOwner,workspaceName,workspaceAgent,devContainerName,devContainerFolder) | ||||||||
} | ||||||||
/** | ||||||||
* Update the current workspace. If there is no active workspace connection, | ||||||||
* this is a no-op. | ||||||||
@@ -536,10 +556,7 @@ async function openWorkspace( | ||||||||
){ | ||||||||
// A workspace can have multiple agents, but that's handled | ||||||||
// when opening a workspace unless explicitly specified. | ||||||||
constremoteAuthority=toRemoteAuthority(baseUrl,workspaceOwner,workspaceName,workspaceAgent) | ||||||||
letnewWindow=true | ||||||||
// Open in the existing window if no workspaces are open. | ||||||||
@@ -598,3 +615,32 @@ async function openWorkspace( | ||||||||
reuseWindow:!newWindow, | ||||||||
}) | ||||||||
} | ||||||||
asyncfunctionopenDevContainer( | ||||||||
code-asher marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||||||||
baseUrl:string, | ||||||||
workspaceOwner:string, | ||||||||
workspaceName:string, | ||||||||
workspaceAgent:string|undefined, | ||||||||
devContainerName:string, | ||||||||
devContainerFolder:string, | ||||||||
){ | ||||||||
constremoteAuthority=toRemoteAuthority(baseUrl,workspaceOwner,workspaceName,workspaceAgent) | ||||||||
constdevContainer=Buffer.from(JSON.stringify({containerName:devContainerName}),"utf-8").toString("hex") | ||||||||
constdevContainerAuthority=`attached-container+${devContainer}@${remoteAuthority}` | ||||||||
letnewWindow=true | ||||||||
if(!vscode.workspace.workspaceFolders?.length){ | ||||||||
newWindow=false | ||||||||
} | ||||||||
awaitvscode.commands.executeCommand( | ||||||||
"vscode.openFolder", | ||||||||
vscode.Uri.from({ | ||||||||
scheme:"vscode-remote", | ||||||||
authority:devContainerAuthority, | ||||||||
path:devContainerFolder, | ||||||||
}), | ||||||||
newWindow, | ||||||||
) | ||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -111,6 +111,61 @@ export async function activate(ctx: vscode.ExtensionContext): Promise<void> { | ||
await storage.configureCli(toSafeHost(url), url, token) | ||
vscode.commands.executeCommand("coder.open", owner, workspace, agent, folder, openRecent) | ||
} else if (uri.path === "/openDevContainer") { | ||
const workspaceOwner = params.get("owner") | ||
const workspaceName = params.get("workspace") | ||
const workspaceAgent = params.get("agent") | ||
const devContainerName = params.get("devContainerName") | ||
const devContainerFolder = params.get("devContainerFolder") | ||
if (!workspaceOwner) { | ||
throw new Error("workspace owner must be specified as a query parameter") | ||
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. No need to change in this PR since this is a pattern that already existed, but at some point I wonder if we should catch handler errors and show them in an error notification. Currently the only way to see them seems to be to go to the extension's features > runtime status > uncaught errors. | ||
} | ||
if (!workspaceName) { | ||
throw new Error("workspace name must be specified as a query parameter") | ||
} | ||
if (!devContainerName) { | ||
throw new Error("dev container name must be specified as a query parameter") | ||
} | ||
if (!devContainerFolder) { | ||
throw new Error("dev container folder must be specified as a query parameter") | ||
} | ||
// We are not guaranteed that the URL we currently have is for the URL | ||
// this workspace belongs to, or that we even have a URL at all (the | ||
// queries will default to localhost) so ask for it if missing. | ||
// Pre-populate in case we do have the right URL so the user can just | ||
// hit enter and move on. | ||
const url = await commands.maybeAskUrl(params.get("url"), storage.getUrl()) | ||
if (url) { | ||
restClient.setHost(url) | ||
await storage.setUrl(url) | ||
} else { | ||
throw new Error("url must be provided or specified as a query parameter") | ||
} | ||
// If the token is missing we will get a 401 later and the user will be | ||
// prompted to sign in again, so we do not need to ensure it is set now. | ||
// For non-token auth, we write a blank token since the `vscodessh` | ||
// command currently always requires a token file. However, if there is | ||
// a query parameter for non-token auth go ahead and use it anyway; all | ||
// that really matters is the file is created. | ||
const token = needToken() ? params.get("token") : (params.get("token") ?? "") | ||
// Store on disk to be used by the cli. | ||
await storage.configureCli(toSafeHost(url), url, token) | ||
vscode.commands.executeCommand( | ||
"coder.openDevContainer", | ||
workspaceOwner, | ||
workspaceName, | ||
workspaceAgent, | ||
devContainerName, | ||
devContainerFolder, | ||
) | ||
} else { | ||
throw new Error(`Unknown path ${uri.path}`) | ||
} | ||
@@ -123,6 +178,7 @@ export async function activate(ctx: vscode.ExtensionContext): Promise<void> { | ||
vscode.commands.registerCommand("coder.login", commands.login.bind(commands)) | ||
vscode.commands.registerCommand("coder.logout", commands.logout.bind(commands)) | ||
vscode.commands.registerCommand("coder.open", commands.open.bind(commands)) | ||
vscode.commands.registerCommand("coder.openDevContainer", commands.openDevContainer.bind(commands)) | ||
code-asher marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
vscode.commands.registerCommand("coder.openFromSidebar", commands.openFromSidebar.bind(commands)) | ||
vscode.commands.registerCommand("coder.workspace.update", commands.updateWorkspace.bind(commands)) | ||
vscode.commands.registerCommand("coder.createWorkspace", commands.createWorkspace.bind(commands)) | ||