diff --git a/CHANGELOG.md b/CHANGELOG.md index c3af0db4..f07f13fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## Unreleased +- Update `/openDevContainer` to support all dev container features when hostPath + and configFile are provided. + ## [v1.9.2](https://github.com/coder/vscode-coder/releases/tag/v1.9.2) 2025-06-25 ### Fixed diff --git a/src/commands.ts b/src/commands.ts index c1d49f91..d6734376 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -620,18 +620,20 @@ export class Commands { * * Throw if not logged into a deployment. */ - public async openDevContainer(...args: string[]): Promise { + public async openDevContainer( + workspaceOwner: string, + workspaceName: string, + workspaceAgent: string, + devContainerName: string, + devContainerFolder: string, + localWorkspaceFolder: string = "", + localConfigFile: string = "", + ): Promise { const baseUrl = this.restClient.getAxiosInstance().defaults.baseURL; if (!baseUrl) { throw new Error("You are not logged in"); } - const workspaceOwner = args[0] as string; - const workspaceName = args[1] as string; - const workspaceAgent = args[2] as string; - const devContainerName = args[3] as string; - const devContainerFolder = args[4] as string; - await openDevContainer( baseUrl, workspaceOwner, @@ -639,6 +641,8 @@ export class Commands { workspaceAgent, devContainerName, devContainerFolder, + localWorkspaceFolder, + localConfigFile, ); } @@ -751,6 +755,8 @@ async function openDevContainer( workspaceAgent: string, devContainerName: string, devContainerFolder: string, + localWorkspaceFolder: string = "", + localConfigFile: string = "", ) { const remoteAuthority = toRemoteAuthority( baseUrl, @@ -759,11 +765,26 @@ async function openDevContainer( workspaceAgent, ); + const hostPath = localWorkspaceFolder ? localWorkspaceFolder : undefined; + const configFile = + hostPath && localConfigFile + ? { + path: localConfigFile, + scheme: "vscode-fileHost", + } + : undefined; const devContainer = Buffer.from( - JSON.stringify({ containerName: devContainerName }), + JSON.stringify({ + containerName: devContainerName, + hostPath, + configFile, + localDocker: false, + }), "utf-8", ).toString("hex"); - const devContainerAuthority = `attached-container+${devContainer}@${remoteAuthority}`; + + const type = localWorkspaceFolder ? "dev-container" : "attached-container"; + const devContainerAuthority = `${type}+${devContainer}@${remoteAuthority}`; let newWindow = true; if (!vscode.workspace.workspaceFolders?.length) { diff --git a/src/extension.ts b/src/extension.ts index 10fd7783..05eb7319 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -165,6 +165,8 @@ export async function activate(ctx: vscode.ExtensionContext): Promise { const workspaceAgent = params.get("agent"); const devContainerName = params.get("devContainerName"); const devContainerFolder = params.get("devContainerFolder"); + const localWorkspaceFolder = params.get("localWorkspaceFolder"); + const localConfigFile = params.get("localConfigFile"); if (!workspaceOwner) { throw new Error( @@ -190,6 +192,12 @@ export async function activate(ctx: vscode.ExtensionContext): Promise { ); } + if (localConfigFile && !localWorkspaceFolder) { + throw new Error( + "local workspace folder must be specified as a query parameter if local config file is provided", + ); + } + // 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. @@ -228,6 +236,8 @@ export async function activate(ctx: vscode.ExtensionContext): Promise { workspaceAgent, devContainerName, devContainerFolder, + localWorkspaceFolder, + localConfigFile, ); } else { throw new Error(`Unknown path ${uri.path}`);