From 3b319b003f90335bedb3cf073c2b82513c671ea2 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Wed, 10 May 2023 11:16:27 -0400 Subject: [PATCH 01/46] Experimental Base Structure --- .../NetCoreSdkBuildTaskDefinitionBase.ts | 26 +++++++++++++++++++ .../netcore/NetCoreSdkBuildTaskProvider.ts | 16 ++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 src/tasks/netcore/NetCoreSdkBuildTaskDefinitionBase.ts create mode 100644 src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts diff --git a/src/tasks/netcore/NetCoreSdkBuildTaskDefinitionBase.ts b/src/tasks/netcore/NetCoreSdkBuildTaskDefinitionBase.ts new file mode 100644 index 0000000000..f61cf5100d --- /dev/null +++ b/src/tasks/netcore/NetCoreSdkBuildTaskDefinitionBase.ts @@ -0,0 +1,26 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE.md in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { TaskDefinitionBase } from "../TaskDefinitionBase"; + +export interface NetCoreSdkBuildOptions { + /** + * Name of image to build + */ + imageName?: string; + + /** + * Tag of image to build + */ + imageTag?: string; + + platform?: string; // TODO: Change platform to object + + configuration?: string; +} + +export interface NetCoreSdkBuildDefinitionBase extends TaskDefinitionBase { + netcoreSdkBuild?: NetCoreSdkBuildOptions; +} diff --git a/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts b/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts new file mode 100644 index 0000000000..289524e51f --- /dev/null +++ b/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts @@ -0,0 +1,16 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE.md in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Task } from "vscode"; +import { DockerTaskProvider } from "../DockerTaskProvider"; +import { DockerTaskExecutionContext } from "../TaskHelper"; + +export class NetCoreSdkBuildProvider extends DockerTaskProvider { + + protected executeTaskInternal(context: DockerTaskExecutionContext, task: Task): Promise { + throw new Error("Method not implemented."); + } + +} From 794d867be842173955c16e84d66f40d989bf8caf Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Thu, 11 May 2023 12:17:30 -0400 Subject: [PATCH 02/46] register new task provider --- src/tasks/DockerPseudoterminal.ts | 21 +++++--- src/tasks/DockerTaskProvider.ts | 4 +- src/tasks/TaskHelper.ts | 10 ++++ .../NetCoreSdkBuildTaskDefinitionBase.ts | 4 ++ .../netcore/NetCoreSdkBuildTaskProvider.ts | 52 +++++++++++++++++-- 5 files changed, 79 insertions(+), 12 deletions(-) diff --git a/src/tasks/DockerPseudoterminal.ts b/src/tasks/DockerPseudoterminal.ts index 1b4ea47096..31fc59658c 100644 --- a/src/tasks/DockerPseudoterminal.ts +++ b/src/tasks/DockerPseudoterminal.ts @@ -52,9 +52,9 @@ export class DockerPseudoterminal implements Pseudoterminal { this.closeEmitter.fire(code || 0); } - public getCommandRunner(options: Omit): (commandResponse: VoidCommandResponse | PromiseCommandResponse) => Promise { + public getCommandRunner(options: Omit): (commandResponse: VoidCommandResponse | PromiseCommandResponse) => Promise { return async (commandResponse: VoidCommandResponse | PromiseCommandResponse) => { - const output = await this.executeCommandInTerminal({ + const output = await this.executeCommandResponseInTerminal({ ...options, commandResponse: commandResponse, }); @@ -96,16 +96,21 @@ export class DockerPseudoterminal implements Pseudoterminal { this.writeEmitter.fire(`\x1b[${color}${message}\x1b[0m`); } - private async executeCommandInTerminal(options: ExecuteCommandInTerminalOptions): Promise { + private async executeCommandResponseInTerminal(options: ExecuteCommandResponseInTerminalOptions): Promise { const quotedArgs = Shell.getShellOrDefault().quote(options.commandResponse.args); const resolvedQuotedArgs = resolveVariables(quotedArgs, options.folder); const commandLine = [options.commandResponse.command, ...resolvedQuotedArgs].join(' '); + return await this.execAsyncInTerminal(commandLine, options); + } + + public async execAsyncInTerminal(command: string, options?: ExecAsyncInTerminalOptions): Promise { + // Output what we're doing, same style as VSCode does for ShellExecution/ProcessExecution - this.write(`> ${commandLine} <\r\n\r\n`, DEFAULTBOLD); + this.write(`> ${command} <\r\n\r\n`, DEFAULTBOLD); return await execAsync( - commandLine, + command, { cwd: this.resolvedDefinition.options?.cwd || options.folder.uri.fsPath, env: withDockerEnvSettings({ ...process.env, ...this.resolvedDefinition.options?.env }), @@ -120,10 +125,14 @@ export class DockerPseudoterminal implements Pseudoterminal { } ); } + } -type ExecuteCommandInTerminalOptions = { +type ExecuteCommandResponseInTerminalOptions = ExecAsyncInTerminalOptions & { commandResponse: VoidCommandResponse | PromiseCommandResponse; +}; + +type ExecAsyncInTerminalOptions = { folder: WorkspaceFolder; token?: CancellationToken; }; diff --git a/src/tasks/DockerTaskProvider.ts b/src/tasks/DockerTaskProvider.ts index dea5e7b33c..d720ef68c1 100644 --- a/src/tasks/DockerTaskProvider.ts +++ b/src/tasks/DockerTaskProvider.ts @@ -11,11 +11,11 @@ import { ExecError } from '../utils/execAsync'; import { DockerBuildTask } from './DockerBuildTaskProvider'; import { DockerPseudoterminal } from './DockerPseudoterminal'; import { DockerRunTask } from './DockerRunTaskProvider'; -import { DockerTaskExecutionContext, DockerTaskProviderName, TaskHelper } from './TaskHelper'; +import { DockerTaskExecutionContext, DockerTaskProviderName, NetCoreSdkTaskProviderName, TaskHelper } from './TaskHelper'; export abstract class DockerTaskProvider implements TaskProvider { - protected constructor(private readonly telemetryName: DockerTaskProviderName, protected readonly helpers: { [key in DockerPlatform]: TaskHelper }) { } + protected constructor(private readonly telemetryName: DockerTaskProviderName | NetCoreSdkTaskProviderName, protected readonly helpers: { [key in DockerPlatform]: TaskHelper }) { } public provideTasks(token?: CancellationToken): ProviderResult { return []; // Intentionally empty, so that resolveTask gets used diff --git a/src/tasks/TaskHelper.ts b/src/tasks/TaskHelper.ts index 571ccdaf27..a33809ab3d 100644 --- a/src/tasks/TaskHelper.ts +++ b/src/tasks/TaskHelper.ts @@ -20,12 +20,15 @@ import { DockerPseudoterminal } from './DockerPseudoterminal'; import { DockerContainerVolume, DockerRunOptions, DockerRunTaskDefinitionBase } from './DockerRunTaskDefinitionBase'; import { DockerRunTask, DockerRunTaskDefinition, DockerRunTaskProvider } from './DockerRunTaskProvider'; import { TaskDefinitionBase } from './TaskDefinitionBase'; +import { NetCoreSdkBuildProvider } from './netcore/NetCoreSdkBuildTaskProvider'; import { netCoreTaskHelper } from './netcore/NetCoreTaskHelper'; import { nodeTaskHelper } from './node/NodeTaskHelper'; import { pythonTaskHelper } from './python/PythonTaskHelper'; export type DockerTaskProviderName = 'docker-build' | 'docker-run' | 'docker-compose'; +export type NetCoreSdkTaskProviderName = 'dotnet-sdk-build'; + export interface DockerTaskContext { folder: WorkspaceFolder; platform?: DockerPlatform; @@ -100,6 +103,13 @@ export function registerTaskProviders(ctx: ExtensionContext): void { new DockerComposeTaskProvider() ) ); + + ctx.subscriptions.push( + tasks.registerTaskProvider( + 'dotnet-sdk-build', + new NetCoreSdkBuildProvider() + ) + ); } export function hasTask(taskLabel: string, folder: WorkspaceFolder): boolean { diff --git a/src/tasks/netcore/NetCoreSdkBuildTaskDefinitionBase.ts b/src/tasks/netcore/NetCoreSdkBuildTaskDefinitionBase.ts index f61cf5100d..3e604591a7 100644 --- a/src/tasks/netcore/NetCoreSdkBuildTaskDefinitionBase.ts +++ b/src/tasks/netcore/NetCoreSdkBuildTaskDefinitionBase.ts @@ -19,6 +19,10 @@ export interface NetCoreSdkBuildOptions { platform?: string; // TODO: Change platform to object configuration?: string; + + arcitecture?: string; + + os?: string; } export interface NetCoreSdkBuildDefinitionBase extends TaskDefinitionBase { diff --git a/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts b/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts index 289524e51f..a4980a6c03 100644 --- a/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts +++ b/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts @@ -3,14 +3,58 @@ * Licensed under the MIT License. See LICENSE.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Task } from "vscode"; +import { IActionContext } from "@microsoft/vscode-azext-utils"; +import { CancellationToken, Task, WorkspaceFolder } from "vscode"; +import { composeArgs, withArg, withNamedArg } from "../../runtimes/docker"; +import { cloneObject } from "../../utils/cloneObject"; +import { DockerPseudoterminal } from "../DockerPseudoterminal"; import { DockerTaskProvider } from "../DockerTaskProvider"; -import { DockerTaskExecutionContext } from "../TaskHelper"; +import { throwIfCancellationRequested } from "../TaskHelper"; +import { NetCoreSdkBuildDefinitionBase } from "./NetCoreSdkBuildTaskDefinitionBase"; + +export interface NetCoreSdkBuildContext { + folder: WorkspaceFolder; + actionContext?: IActionContext; + cancellationToken?: CancellationToken; + terminal: DockerPseudoterminal; +} + +export interface NetCoreSdkBuildTask extends Task { + definition: NetCoreSdkBuildDefinitionBase; +} export class NetCoreSdkBuildProvider extends DockerTaskProvider { - protected executeTaskInternal(context: DockerTaskExecutionContext, task: Task): Promise { - throw new Error("Method not implemented."); + public constructor() { + super('dotnet-sdk-build',); + } + + protected async executeTaskInternal(context: NetCoreSdkBuildContext, task: NetCoreSdkBuildTask): Promise { + const buildDefinition = cloneObject(task.definition); + buildDefinition.netcoreSdkBuild = buildDefinition.netcoreSdkBuild || {}; + + // TODO: check to see if netcoreSdkBuild is defined, if not apply defaults to netcoreSdkBuild object through `getNetcoreSdkBuildOptions()` + + throwIfCancellationRequested(context); + + const sdkBuildCommand = composeArgs( + withArg('dotnet', 'publish'), + withNamedArg('-os', buildDefinition.netcoreSdkBuild?.os), + withNamedArg('-arch', buildDefinition.netcoreSdkBuild?.arcitecture), + withNamedArg('-c', buildDefinition.netcoreSdkBuild?.configuration), + )(); + + const commandLine = sdkBuildCommand.join(' '); + await context.terminal.execAsyncInTerminal( + commandLine, + { + folder: context.folder, + token: context.cancellationToken, + } + ); + + throwIfCancellationRequested(context); + } } From 127f053d85af52a069b5d22955766155c14c0d61 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Thu, 11 May 2023 17:50:41 -0400 Subject: [PATCH 03/46] added build options for DotnetSdk --- .../netcore/NetCoreSdkBuildTaskProvider.ts | 49 ++++++++++--------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts b/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts index a4980a6c03..193a624559 100644 --- a/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts +++ b/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts @@ -3,21 +3,13 @@ * Licensed under the MIT License. See LICENSE.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext } from "@microsoft/vscode-azext-utils"; -import { CancellationToken, Task, WorkspaceFolder } from "vscode"; -import { composeArgs, withArg, withNamedArg } from "../../runtimes/docker"; +import { Task } from "vscode"; +import { composeArgs, getNativeArchitecture, withArg, withNamedArg } from "../../runtimes/docker"; import { cloneObject } from "../../utils/cloneObject"; -import { DockerPseudoterminal } from "../DockerPseudoterminal"; +import { getDockerOSType } from "../../utils/osUtils"; import { DockerTaskProvider } from "../DockerTaskProvider"; -import { throwIfCancellationRequested } from "../TaskHelper"; -import { NetCoreSdkBuildDefinitionBase } from "./NetCoreSdkBuildTaskDefinitionBase"; - -export interface NetCoreSdkBuildContext { - folder: WorkspaceFolder; - actionContext?: IActionContext; - cancellationToken?: CancellationToken; - terminal: DockerPseudoterminal; -} +import { DockerTaskContext, DockerTaskExecutionContext, getDefaultImageName, throwIfCancellationRequested } from "../TaskHelper"; +import { NetCoreSdkBuildDefinitionBase, NetCoreSdkBuildOptions } from "./NetCoreSdkBuildTaskDefinitionBase"; export interface NetCoreSdkBuildTask extends Task { definition: NetCoreSdkBuildDefinitionBase; @@ -25,23 +17,19 @@ export interface NetCoreSdkBuildTask extends Task { export class NetCoreSdkBuildProvider extends DockerTaskProvider { - public constructor() { - super('dotnet-sdk-build',); - } + public constructor() { super('dotnet-sdk-build', undefined); } - protected async executeTaskInternal(context: NetCoreSdkBuildContext, task: NetCoreSdkBuildTask): Promise { + protected async executeTaskInternal(context: DockerTaskExecutionContext, task: Task): Promise { const buildDefinition = cloneObject(task.definition); - buildDefinition.netcoreSdkBuild = buildDefinition.netcoreSdkBuild || {}; - - // TODO: check to see if netcoreSdkBuild is defined, if not apply defaults to netcoreSdkBuild object through `getNetcoreSdkBuildOptions()` + buildDefinition.netcoreSdkBuild = await this.getDotnetSdkBuildOptions(context, buildDefinition); throwIfCancellationRequested(context); const sdkBuildCommand = composeArgs( withArg('dotnet', 'publish'), - withNamedArg('-os', buildDefinition.netcoreSdkBuild?.os), - withNamedArg('-arch', buildDefinition.netcoreSdkBuild?.arcitecture), - withNamedArg('-c', buildDefinition.netcoreSdkBuild?.configuration), + withNamedArg('-os', buildDefinition.netcoreSdkBuild.platform?.os), + withNamedArg('-arch', buildDefinition.netcoreSdkBuild.platform?.architecture), + withNamedArg('-c', buildDefinition.netcoreSdkBuild.configuration), )(); const commandLine = sdkBuildCommand.join(' '); @@ -54,7 +42,20 @@ export class NetCoreSdkBuildProvider extends DockerTaskProvider { ); throwIfCancellationRequested(context); - } + public async getDotnetSdkBuildOptions(context: DockerTaskContext, buildDefinition: NetCoreSdkBuildDefinitionBase): Promise { + + const buildOptions = buildDefinition.netcoreSdkBuild || {}; + + buildOptions.platform = { + architecture: buildOptions.platform?.architecture || getNativeArchitecture(), + os: buildOptions.platform?.os || await getDockerOSType() + }; + + buildOptions.configuration = 'Debug'; // intentionally default to Debug configuration for now + buildOptions.tag = buildOptions.tag || getDefaultImageName(context.folder.name); + + return buildOptions; + } } From 09236a7c2fb1cba2936072b2c041edc3de9310d4 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Thu, 11 May 2023 17:51:13 -0400 Subject: [PATCH 04/46] removed redundent fields in NetCoreSdkBuildOptions --- .../NetCoreSdkBuildTaskDefinitionBase.ts | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/src/tasks/netcore/NetCoreSdkBuildTaskDefinitionBase.ts b/src/tasks/netcore/NetCoreSdkBuildTaskDefinitionBase.ts index 3e604591a7..90790cbafd 100644 --- a/src/tasks/netcore/NetCoreSdkBuildTaskDefinitionBase.ts +++ b/src/tasks/netcore/NetCoreSdkBuildTaskDefinitionBase.ts @@ -3,26 +3,15 @@ * Licensed under the MIT License. See LICENSE.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { ContainerPlatform } from "../../runtimes/docker"; import { TaskDefinitionBase } from "../TaskDefinitionBase"; export interface NetCoreSdkBuildOptions { - /** - * Name of image to build - */ - imageName?: string; + tag?: string; - /** - * Tag of image to build - */ - imageTag?: string; - - platform?: string; // TODO: Change platform to object + platform?: ContainerPlatform; configuration?: string; - - arcitecture?: string; - - os?: string; } export interface NetCoreSdkBuildDefinitionBase extends TaskDefinitionBase { From dbfc62a09d8f5f3bbd52faf011406783fc2c09b5 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Fri, 12 May 2023 10:28:56 -0400 Subject: [PATCH 05/46] added json schema --- package.json | 74 +++++++++++++++++++ .../netcore/NetCoreSdkBuildTaskProvider.ts | 3 +- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 65e20aa784..b449a4b6cc 100644 --- a/package.json +++ b/package.json @@ -1500,6 +1500,80 @@ "required": [ "dockerCompose" ] + }, + { + "type": "dotnet-sdk-build", + "properties": { + "tag": { + "type": "string", + "description": "%vscode-docker.tasks.docker-build.dockerBuild.tag%" + }, + "platform": { + "anyOf": [ + { + "type": "object", + "properties": { + "os": { + "anyOf": [ + { + "type": "string", + "enum": [ + "linux", + "darwin", + "windows" + ] + }, + { + "type": "string" + } + ], + "description": "%vscode-docker.tasks.docker-build.dockerBuild.platform.os%" + }, + "architecture": { + "anyOf": [ + { + "type": "string", + "enum": [ + "amd64", + "386", + "arm64", + "arm" + ] + }, + { + "type": "string" + } + ], + "description": "%vscode-docker.tasks.docker-build.dockerBuild.platform.architecture%" + } + } + }, + { + "type": "string", + "enum": [ + "linux/amd64", + "linux/386", + "linux/arm64", + "linux/arm", + "darwin/amd64", + "darwin/arm64", + "windows/amd64", + "windows/386", + "windows/arm64", + "windows/arm" + ] + }, + { + "type": "string" + } + ], + "description": "%vscode-docker.tasks.docker-build.dockerBuild.platform%" + }, + "configuration": { + "type": "string", + "description": "%vscode-docker.tasks.docker-build.dockerBuild.configuration%" + } + } } ], "languages": [ diff --git a/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts b/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts index 193a624559..05c89e637d 100644 --- a/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts +++ b/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts @@ -30,6 +30,7 @@ export class NetCoreSdkBuildProvider extends DockerTaskProvider { withNamedArg('-os', buildDefinition.netcoreSdkBuild.platform?.os), withNamedArg('-arch', buildDefinition.netcoreSdkBuild.platform?.architecture), withNamedArg('-c', buildDefinition.netcoreSdkBuild.configuration), + // TODO: add more options )(); const commandLine = sdkBuildCommand.join(' '); @@ -53,7 +54,7 @@ export class NetCoreSdkBuildProvider extends DockerTaskProvider { os: buildOptions.platform?.os || await getDockerOSType() }; - buildOptions.configuration = 'Debug'; // intentionally default to Debug configuration for now + buildOptions.configuration = 'Debug'; // intentionally default to Debug configuration for phase 1 of this feature buildOptions.tag = buildOptions.tag || getDefaultImageName(context.folder.name); return buildOptions; From b9b9607861cb3c770e5889451bebe7a0e1646d55 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Fri, 12 May 2023 15:23:23 -0400 Subject: [PATCH 06/46] basci working implementation of task provider --- package.json | 73 +------------ src/tasks/DockerTaskProvider.ts | 4 +- src/tasks/TaskHelper.ts | 2 - .../netcore/NetCoreSdkBuildTaskProvider.ts | 101 +++++++++++------- ...onBase.ts => NetSdkBuildTaskDefinition.ts} | 11 +- 5 files changed, 65 insertions(+), 126 deletions(-) rename src/tasks/netcore/{NetCoreSdkBuildTaskDefinitionBase.ts => NetSdkBuildTaskDefinition.ts} (57%) diff --git a/package.json b/package.json index b449a4b6cc..3f8ae08737 100644 --- a/package.json +++ b/package.json @@ -1502,78 +1502,7 @@ ] }, { - "type": "dotnet-sdk-build", - "properties": { - "tag": { - "type": "string", - "description": "%vscode-docker.tasks.docker-build.dockerBuild.tag%" - }, - "platform": { - "anyOf": [ - { - "type": "object", - "properties": { - "os": { - "anyOf": [ - { - "type": "string", - "enum": [ - "linux", - "darwin", - "windows" - ] - }, - { - "type": "string" - } - ], - "description": "%vscode-docker.tasks.docker-build.dockerBuild.platform.os%" - }, - "architecture": { - "anyOf": [ - { - "type": "string", - "enum": [ - "amd64", - "386", - "arm64", - "arm" - ] - }, - { - "type": "string" - } - ], - "description": "%vscode-docker.tasks.docker-build.dockerBuild.platform.architecture%" - } - } - }, - { - "type": "string", - "enum": [ - "linux/amd64", - "linux/386", - "linux/arm64", - "linux/arm", - "darwin/amd64", - "darwin/arm64", - "windows/amd64", - "windows/386", - "windows/arm64", - "windows/arm" - ] - }, - { - "type": "string" - } - ], - "description": "%vscode-docker.tasks.docker-build.dockerBuild.platform%" - }, - "configuration": { - "type": "string", - "description": "%vscode-docker.tasks.docker-build.dockerBuild.configuration%" - } - } + "type": "dotnet-sdk-build" } ], "languages": [ diff --git a/src/tasks/DockerTaskProvider.ts b/src/tasks/DockerTaskProvider.ts index d720ef68c1..dea5e7b33c 100644 --- a/src/tasks/DockerTaskProvider.ts +++ b/src/tasks/DockerTaskProvider.ts @@ -11,11 +11,11 @@ import { ExecError } from '../utils/execAsync'; import { DockerBuildTask } from './DockerBuildTaskProvider'; import { DockerPseudoterminal } from './DockerPseudoterminal'; import { DockerRunTask } from './DockerRunTaskProvider'; -import { DockerTaskExecutionContext, DockerTaskProviderName, NetCoreSdkTaskProviderName, TaskHelper } from './TaskHelper'; +import { DockerTaskExecutionContext, DockerTaskProviderName, TaskHelper } from './TaskHelper'; export abstract class DockerTaskProvider implements TaskProvider { - protected constructor(private readonly telemetryName: DockerTaskProviderName | NetCoreSdkTaskProviderName, protected readonly helpers: { [key in DockerPlatform]: TaskHelper }) { } + protected constructor(private readonly telemetryName: DockerTaskProviderName, protected readonly helpers: { [key in DockerPlatform]: TaskHelper }) { } public provideTasks(token?: CancellationToken): ProviderResult { return []; // Intentionally empty, so that resolveTask gets used diff --git a/src/tasks/TaskHelper.ts b/src/tasks/TaskHelper.ts index a33809ab3d..244ab2998b 100644 --- a/src/tasks/TaskHelper.ts +++ b/src/tasks/TaskHelper.ts @@ -27,8 +27,6 @@ import { pythonTaskHelper } from './python/PythonTaskHelper'; export type DockerTaskProviderName = 'docker-build' | 'docker-run' | 'docker-compose'; -export type NetCoreSdkTaskProviderName = 'dotnet-sdk-build'; - export interface DockerTaskContext { folder: WorkspaceFolder; platform?: DockerPlatform; diff --git a/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts b/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts index 05c89e637d..f13ef7dce9 100644 --- a/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts +++ b/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts @@ -3,60 +3,81 @@ * Licensed under the MIT License. See LICENSE.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Task } from "vscode"; -import { composeArgs, getNativeArchitecture, withArg, withNamedArg } from "../../runtimes/docker"; -import { cloneObject } from "../../utils/cloneObject"; +import { IActionContext, callWithTelemetryAndErrorHandling } from '@microsoft/vscode-azext-utils'; +import * as fse from 'fs-extra'; +import { CancellationToken, ProviderResult, ShellExecution, Task, TaskProvider, TaskScope } from "vscode"; +import { ext } from '../../extensionVariables'; +import { Shell, composeArgs, getNativeArchitecture, withArg, withNamedArg } from "../../runtimes/docker"; import { getDockerOSType } from "../../utils/osUtils"; -import { DockerTaskProvider } from "../DockerTaskProvider"; -import { DockerTaskContext, DockerTaskExecutionContext, getDefaultImageName, throwIfCancellationRequested } from "../TaskHelper"; -import { NetCoreSdkBuildDefinitionBase, NetCoreSdkBuildOptions } from "./NetCoreSdkBuildTaskDefinitionBase"; +import { quickPickWorkspaceFolder } from '../../utils/quickPickWorkspaceFolder'; -export interface NetCoreSdkBuildTask extends Task { - definition: NetCoreSdkBuildDefinitionBase; -} +const netSdkTelemetryName = 'dotnet-sdk-build'; -export class NetCoreSdkBuildProvider extends DockerTaskProvider { +export class NetCoreSdkBuildProvider implements TaskProvider { - public constructor() { super('dotnet-sdk-build', undefined); } + provideTasks(token: CancellationToken): ProviderResult { - protected async executeTaskInternal(context: DockerTaskExecutionContext, task: Task): Promise { - const buildDefinition = cloneObject(task.definition); - buildDefinition.netcoreSdkBuild = await this.getDotnetSdkBuildOptions(context, buildDefinition); + return callWithTelemetryAndErrorHandling(`${netSdkTelemetryName}-execute`, async (actionContext: IActionContext) => { + actionContext.errorHandling.suppressDisplay = true; // Suppress display. VSCode already has a modal popup and we don't want focus taken away from Terminal window. + actionContext.errorHandling.rethrow = true; // Rethrow to hit the try/catch outside this block. - throwIfCancellationRequested(context); + // eslint-disable-next-line @typescript-eslint/no-floating-promises + ext.activityMeasurementService.recordActivity('overallnoedit'); - const sdkBuildCommand = composeArgs( - withArg('dotnet', 'publish'), - withNamedArg('-os', buildDefinition.netcoreSdkBuild.platform?.os), - withNamedArg('-arch', buildDefinition.netcoreSdkBuild.platform?.architecture), - withNamedArg('-c', buildDefinition.netcoreSdkBuild.configuration), - // TODO: add more options - )(); + const netSdkBuildCommandPromise = this.getNetSdkBuildCommand(actionContext); + const netSdkBuildCommand = await netSdkBuildCommandPromise; + return netSdkBuildCommandPromise.then(netSdkBuildCommand => { + return [ + new Task( + { type: 'dotnet-sdk-build' }, + TaskScope.Workspace, + 'debug', + 'dotnet-sdk-build', + new ShellExecution(netSdkBuildCommand), + ) + ]; + }); + }); - const commandLine = sdkBuildCommand.join(' '); - await context.terminal.execAsyncInTerminal( - commandLine, - { - folder: context.folder, - token: context.cancellationToken, - } - ); + } - throwIfCancellationRequested(context); + resolveTask(task: Task, token: CancellationToken): ProviderResult { + return task; } - public async getDotnetSdkBuildOptions(context: DockerTaskContext, buildDefinition: NetCoreSdkBuildDefinitionBase): Promise { + async getNetSdkBuildCommand(context: IActionContext) { - const buildOptions = buildDefinition.netcoreSdkBuild || {}; + const configuration = 'Debug'; // intentionally default to Debug configuration for phase 1 of this feature + const imageTag = 'dev'; // intentionally default to dev tag for phase 1 of this feature - buildOptions.platform = { - architecture: buildOptions.platform?.architecture || getNativeArchitecture(), - os: buildOptions.platform?.os || await getDockerOSType() - }; + // {@link https://github.com/dotnet/sdk-container-builds/issues/141} this could change in the future + const publishFlag = this.isWebApp ? '-p:PublishProfile=DefaultContainer' : '/t:PublishContainer'; - buildOptions.configuration = 'Debug'; // intentionally default to Debug configuration for phase 1 of this feature - buildOptions.tag = buildOptions.tag || getDefaultImageName(context.folder.name); + const folderName = await quickPickWorkspaceFolder( + context, + `Unable to determine task scope to execute task ${netSdkTelemetryName}. Please open a workspace folder.` + ); + + const args = composeArgs( + withArg('dotnet', 'publish'), + withNamedArg('-os', await getDockerOSType()), + withNamedArg('-arch', getNativeArchitecture()), // TODO: change this to adhere to .NET Core SDK conventions + withArg(publishFlag), + withNamedArg('-c', configuration), + withNamedArg('-p:ContainerImageName', folderName.name, { assignValue: true }), + withNamedArg('-p:ContainerImageTag', imageTag, { assignValue: true }), + )(); + + // If there is a shell provider, apply its quoting, otherwise just flatten arguments into strings + // const normalizedArgs: string[] = args.map(arg => typeof arg === 'string' ? arg : arg.value); + const quotedArgs = Shell.getShellOrDefault().quote(args); + return quotedArgs.join(' '); - return buildOptions; } + + private async isWebApp(): Promise { + const projectContents = await fse.readFile('${workspaceFolder}/dotnet.csproj'); + return /Sdk\s*=\s*"Microsoft\.NET\.Sdk\.Web"/ig.test(projectContents.toString()); + } + } diff --git a/src/tasks/netcore/NetCoreSdkBuildTaskDefinitionBase.ts b/src/tasks/netcore/NetSdkBuildTaskDefinition.ts similarity index 57% rename from src/tasks/netcore/NetCoreSdkBuildTaskDefinitionBase.ts rename to src/tasks/netcore/NetSdkBuildTaskDefinition.ts index 90790cbafd..fea3a87aa3 100644 --- a/src/tasks/netcore/NetCoreSdkBuildTaskDefinitionBase.ts +++ b/src/tasks/netcore/NetSdkBuildTaskDefinition.ts @@ -3,17 +3,8 @@ * Licensed under the MIT License. See LICENSE.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ContainerPlatform } from "../../runtimes/docker"; import { TaskDefinitionBase } from "../TaskDefinitionBase"; -export interface NetCoreSdkBuildOptions { - tag?: string; +export type NetSdkBuildTaskDefinition = TaskDefinitionBase; - platform?: ContainerPlatform; - configuration?: string; -} - -export interface NetCoreSdkBuildDefinitionBase extends TaskDefinitionBase { - netcoreSdkBuild?: NetCoreSdkBuildOptions; -} From d289b426f042d659c513a7d4b743ae090c585094 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Mon, 15 May 2023 09:50:10 -0400 Subject: [PATCH 07/46] reversed unnecessary commits --- src/tasks/DockerPseudoterminal.ts | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/src/tasks/DockerPseudoterminal.ts b/src/tasks/DockerPseudoterminal.ts index 31fc59658c..1b4ea47096 100644 --- a/src/tasks/DockerPseudoterminal.ts +++ b/src/tasks/DockerPseudoterminal.ts @@ -52,9 +52,9 @@ export class DockerPseudoterminal implements Pseudoterminal { this.closeEmitter.fire(code || 0); } - public getCommandRunner(options: Omit): (commandResponse: VoidCommandResponse | PromiseCommandResponse) => Promise { + public getCommandRunner(options: Omit): (commandResponse: VoidCommandResponse | PromiseCommandResponse) => Promise { return async (commandResponse: VoidCommandResponse | PromiseCommandResponse) => { - const output = await this.executeCommandResponseInTerminal({ + const output = await this.executeCommandInTerminal({ ...options, commandResponse: commandResponse, }); @@ -96,21 +96,16 @@ export class DockerPseudoterminal implements Pseudoterminal { this.writeEmitter.fire(`\x1b[${color}${message}\x1b[0m`); } - private async executeCommandResponseInTerminal(options: ExecuteCommandResponseInTerminalOptions): Promise { + private async executeCommandInTerminal(options: ExecuteCommandInTerminalOptions): Promise { const quotedArgs = Shell.getShellOrDefault().quote(options.commandResponse.args); const resolvedQuotedArgs = resolveVariables(quotedArgs, options.folder); const commandLine = [options.commandResponse.command, ...resolvedQuotedArgs].join(' '); - return await this.execAsyncInTerminal(commandLine, options); - } - - public async execAsyncInTerminal(command: string, options?: ExecAsyncInTerminalOptions): Promise { - // Output what we're doing, same style as VSCode does for ShellExecution/ProcessExecution - this.write(`> ${command} <\r\n\r\n`, DEFAULTBOLD); + this.write(`> ${commandLine} <\r\n\r\n`, DEFAULTBOLD); return await execAsync( - command, + commandLine, { cwd: this.resolvedDefinition.options?.cwd || options.folder.uri.fsPath, env: withDockerEnvSettings({ ...process.env, ...this.resolvedDefinition.options?.env }), @@ -125,14 +120,10 @@ export class DockerPseudoterminal implements Pseudoterminal { } ); } - } -type ExecuteCommandResponseInTerminalOptions = ExecAsyncInTerminalOptions & { +type ExecuteCommandInTerminalOptions = { commandResponse: VoidCommandResponse | PromiseCommandResponse; -}; - -type ExecAsyncInTerminalOptions = { folder: WorkspaceFolder; token?: CancellationToken; }; From 6982df7bc05911366830197816abe4f30e451410 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Mon, 15 May 2023 10:42:02 -0400 Subject: [PATCH 08/46] added dotnet specific util methods --- .../netcore/NetCoreSdkBuildTaskProvider.ts | 56 +++++++++++++++++-- 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts b/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts index f13ef7dce9..a834181e52 100644 --- a/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts +++ b/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts @@ -5,14 +5,29 @@ import { IActionContext, callWithTelemetryAndErrorHandling } from '@microsoft/vscode-azext-utils'; import * as fse from 'fs-extra'; +import * as os from 'os'; import { CancellationToken, ProviderResult, ShellExecution, Task, TaskProvider, TaskScope } from "vscode"; import { ext } from '../../extensionVariables'; -import { Shell, composeArgs, getNativeArchitecture, withArg, withNamedArg } from "../../runtimes/docker"; +import { Shell, composeArgs, withArg, withNamedArg } from "../../runtimes/docker"; import { getDockerOSType } from "../../utils/osUtils"; import { quickPickWorkspaceFolder } from '../../utils/quickPickWorkspaceFolder'; const netSdkTelemetryName = 'dotnet-sdk-build'; +/** + * Native architecture of the current machine in the RID format + * {@link https://github.com/dotnet/runtime/blob/main/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json} + */ +export type RidCpuArchitecture = + | 'x64' + | 'x86' + | 'arm64' + | 'arm' + | 'ppc64le' + | 'mips64' + | 's390x' + | string; + export class NetCoreSdkBuildProvider implements TaskProvider { provideTasks(token: CancellationToken): ProviderResult { @@ -25,8 +40,7 @@ export class NetCoreSdkBuildProvider implements TaskProvider { ext.activityMeasurementService.recordActivity('overallnoedit'); const netSdkBuildCommandPromise = this.getNetSdkBuildCommand(actionContext); - const netSdkBuildCommand = await netSdkBuildCommandPromise; - return netSdkBuildCommandPromise.then(netSdkBuildCommand => { + return await netSdkBuildCommandPromise.then(netSdkBuildCommand => { return [ new Task( { type: 'dotnet-sdk-build' }, @@ -42,7 +56,7 @@ export class NetCoreSdkBuildProvider implements TaskProvider { } resolveTask(task: Task, token: CancellationToken): ProviderResult { - return task; + return task; // we can just return the task as-is } async getNetSdkBuildCommand(context: IActionContext) { @@ -60,8 +74,8 @@ export class NetCoreSdkBuildProvider implements TaskProvider { const args = composeArgs( withArg('dotnet', 'publish'), - withNamedArg('-os', await getDockerOSType()), - withNamedArg('-arch', getNativeArchitecture()), // TODO: change this to adhere to .NET Core SDK conventions + withNamedArg('-os', await this.normalizeOsToRid()), + withNamedArg('-arch', await this.normalizeArchitectureToRid()), // TODO: change this to adhere to .NET Core SDK conventions withArg(publishFlag), withNamedArg('-c', configuration), withNamedArg('-p:ContainerImageName', folderName.name, { assignValue: true }), @@ -80,4 +94,34 @@ export class NetCoreSdkBuildProvider implements TaskProvider { return /Sdk\s*=\s*"Microsoft\.NET\.Sdk\.Web"/ig.test(projectContents.toString()); } + /** + * This method normalizes the Docker OS type to match the .NET Core SDK conventions. + * {@link https://learn.microsoft.com/en-us/dotnet/core/rid-catalog} + */ + private async normalizeOsToRid(): Promise<'linux' | 'win'> { + const osType = await getDockerOSType(); + switch (osType) { + case 'windows': + return 'win'; + default: + return osType; + } + } + + /** + * This method normalizes the native architecture to match the .NET Core SDK conventions. + * {@link https://learn.microsoft.com/en-us/dotnet/core/rid-catalog} + */ + private async normalizeArchitectureToRid(): Promise { + const architecture = os.arch(); + switch (architecture) { + case 'x32': + case 'ia32': + return 'x86'; + default: + return architecture; + } + } + + } From 4cd942ed1e24d09489750a09cda34915f381949c Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Mon, 15 May 2023 10:56:58 -0400 Subject: [PATCH 09/46] fixed dotnet CLI flags --- src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts b/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts index a834181e52..8ec129b6a3 100644 --- a/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts +++ b/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts @@ -74,10 +74,10 @@ export class NetCoreSdkBuildProvider implements TaskProvider { const args = composeArgs( withArg('dotnet', 'publish'), - withNamedArg('-os', await this.normalizeOsToRid()), - withNamedArg('-arch', await this.normalizeArchitectureToRid()), // TODO: change this to adhere to .NET Core SDK conventions + withNamedArg('--os', await this.normalizeOsToRid()), + withNamedArg('--arch', await this.normalizeArchitectureToRid()), withArg(publishFlag), - withNamedArg('-c', configuration), + withNamedArg('--configuration', configuration), withNamedArg('-p:ContainerImageName', folderName.name, { assignValue: true }), withNamedArg('-p:ContainerImageTag', imageTag, { assignValue: true }), )(); From 26058d3da590c353656b0b08fe0b162f6a3fc9ce Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Mon, 15 May 2023 13:07:39 -0400 Subject: [PATCH 10/46] made code more organized --- src/tasks/TaskHelper.ts | 4 +-- ...Provider.ts => NetSdkBuildTaskProvider.ts} | 26 +++++++------------ 2 files changed, 12 insertions(+), 18 deletions(-) rename src/tasks/netcore/{NetCoreSdkBuildTaskProvider.ts => NetSdkBuildTaskProvider.ts} (84%) diff --git a/src/tasks/TaskHelper.ts b/src/tasks/TaskHelper.ts index 244ab2998b..efe4e2503b 100644 --- a/src/tasks/TaskHelper.ts +++ b/src/tasks/TaskHelper.ts @@ -20,8 +20,8 @@ import { DockerPseudoterminal } from './DockerPseudoterminal'; import { DockerContainerVolume, DockerRunOptions, DockerRunTaskDefinitionBase } from './DockerRunTaskDefinitionBase'; import { DockerRunTask, DockerRunTaskDefinition, DockerRunTaskProvider } from './DockerRunTaskProvider'; import { TaskDefinitionBase } from './TaskDefinitionBase'; -import { NetCoreSdkBuildProvider } from './netcore/NetCoreSdkBuildTaskProvider'; import { netCoreTaskHelper } from './netcore/NetCoreTaskHelper'; +import { NetSdkBuildTaskProvider } from './netcore/NetSdkBuildTaskProvider'; import { nodeTaskHelper } from './node/NodeTaskHelper'; import { pythonTaskHelper } from './python/PythonTaskHelper'; @@ -105,7 +105,7 @@ export function registerTaskProviders(ctx: ExtensionContext): void { ctx.subscriptions.push( tasks.registerTaskProvider( 'dotnet-sdk-build', - new NetCoreSdkBuildProvider() + new NetSdkBuildTaskProvider() ) ); } diff --git a/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts b/src/tasks/netcore/NetSdkBuildTaskProvider.ts similarity index 84% rename from src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts rename to src/tasks/netcore/NetSdkBuildTaskProvider.ts index 8ec129b6a3..c45fb10ba0 100644 --- a/src/tasks/netcore/NetCoreSdkBuildTaskProvider.ts +++ b/src/tasks/netcore/NetSdkBuildTaskProvider.ts @@ -12,7 +12,7 @@ import { Shell, composeArgs, withArg, withNamedArg } from "../../runtimes/docker import { getDockerOSType } from "../../utils/osUtils"; import { quickPickWorkspaceFolder } from '../../utils/quickPickWorkspaceFolder'; -const netSdkTelemetryName = 'dotnet-sdk-build'; +const netSdkTaskName = 'dotnet-sdk-build'; /** * Native architecture of the current machine in the RID format @@ -28,11 +28,11 @@ export type RidCpuArchitecture = | 's390x' | string; -export class NetCoreSdkBuildProvider implements TaskProvider { +export class NetSdkBuildTaskProvider implements TaskProvider { provideTasks(token: CancellationToken): ProviderResult { - return callWithTelemetryAndErrorHandling(`${netSdkTelemetryName}-execute`, async (actionContext: IActionContext) => { + return callWithTelemetryAndErrorHandling(`${netSdkTaskName}-execute`, async (actionContext: IActionContext) => { actionContext.errorHandling.suppressDisplay = true; // Suppress display. VSCode already has a modal popup and we don't want focus taken away from Terminal window. actionContext.errorHandling.rethrow = true; // Rethrow to hit the try/catch outside this block. @@ -43,10 +43,10 @@ export class NetCoreSdkBuildProvider implements TaskProvider { return await netSdkBuildCommandPromise.then(netSdkBuildCommand => { return [ new Task( - { type: 'dotnet-sdk-build' }, + { type: netSdkTaskName }, TaskScope.Workspace, 'debug', - 'dotnet-sdk-build', + netSdkTaskName, new ShellExecution(netSdkBuildCommand), ) ]; @@ -59,7 +59,7 @@ export class NetCoreSdkBuildProvider implements TaskProvider { return task; // we can just return the task as-is } - async getNetSdkBuildCommand(context: IActionContext) { + private async getNetSdkBuildCommand(context: IActionContext) { const configuration = 'Debug'; // intentionally default to Debug configuration for phase 1 of this feature const imageTag = 'dev'; // intentionally default to dev tag for phase 1 of this feature @@ -69,7 +69,7 @@ export class NetCoreSdkBuildProvider implements TaskProvider { const folderName = await quickPickWorkspaceFolder( context, - `Unable to determine task scope to execute task ${netSdkTelemetryName}. Please open a workspace folder.` + `Unable to determine task scope to execute task ${netSdkTaskName}. Please open a workspace folder.` ); const args = composeArgs( @@ -82,11 +82,8 @@ export class NetCoreSdkBuildProvider implements TaskProvider { withNamedArg('-p:ContainerImageTag', imageTag, { assignValue: true }), )(); - // If there is a shell provider, apply its quoting, otherwise just flatten arguments into strings - // const normalizedArgs: string[] = args.map(arg => typeof arg === 'string' ? arg : arg.value); const quotedArgs = Shell.getShellOrDefault().quote(args); return quotedArgs.join(' '); - } private async isWebApp(): Promise { @@ -99,13 +96,10 @@ export class NetCoreSdkBuildProvider implements TaskProvider { * {@link https://learn.microsoft.com/en-us/dotnet/core/rid-catalog} */ private async normalizeOsToRid(): Promise<'linux' | 'win'> { - const osType = await getDockerOSType(); - switch (osType) { - case 'windows': - return 'win'; - default: - return osType; + if (await getDockerOSType() === 'windows') { + return 'win'; } + return 'linux'; } /** From 9a148bcc5a79880751d99ac9824aef9db8ed463c Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Mon, 15 May 2023 13:24:31 -0400 Subject: [PATCH 11/46] organiized files into new folder --- src/tasks/TaskHelper.ts | 2 +- src/tasks/{netcore => netSdk}/NetSdkBuildTaskDefinition.ts | 0 src/tasks/{netcore => netSdk}/NetSdkBuildTaskProvider.ts | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename src/tasks/{netcore => netSdk}/NetSdkBuildTaskDefinition.ts (100%) rename src/tasks/{netcore => netSdk}/NetSdkBuildTaskProvider.ts (100%) diff --git a/src/tasks/TaskHelper.ts b/src/tasks/TaskHelper.ts index efe4e2503b..a72fef79d9 100644 --- a/src/tasks/TaskHelper.ts +++ b/src/tasks/TaskHelper.ts @@ -20,8 +20,8 @@ import { DockerPseudoterminal } from './DockerPseudoterminal'; import { DockerContainerVolume, DockerRunOptions, DockerRunTaskDefinitionBase } from './DockerRunTaskDefinitionBase'; import { DockerRunTask, DockerRunTaskDefinition, DockerRunTaskProvider } from './DockerRunTaskProvider'; import { TaskDefinitionBase } from './TaskDefinitionBase'; +import { NetSdkBuildTaskProvider } from './netSdk/NetSdkBuildTaskProvider'; import { netCoreTaskHelper } from './netcore/NetCoreTaskHelper'; -import { NetSdkBuildTaskProvider } from './netcore/NetSdkBuildTaskProvider'; import { nodeTaskHelper } from './node/NodeTaskHelper'; import { pythonTaskHelper } from './python/PythonTaskHelper'; diff --git a/src/tasks/netcore/NetSdkBuildTaskDefinition.ts b/src/tasks/netSdk/NetSdkBuildTaskDefinition.ts similarity index 100% rename from src/tasks/netcore/NetSdkBuildTaskDefinition.ts rename to src/tasks/netSdk/NetSdkBuildTaskDefinition.ts diff --git a/src/tasks/netcore/NetSdkBuildTaskProvider.ts b/src/tasks/netSdk/NetSdkBuildTaskProvider.ts similarity index 100% rename from src/tasks/netcore/NetSdkBuildTaskProvider.ts rename to src/tasks/netSdk/NetSdkBuildTaskProvider.ts From 440cb490daab1166711700aa1f5f91003b2cd71a Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Wed, 17 May 2023 07:37:28 -0400 Subject: [PATCH 12/46] added helper class --- package.json | 2 +- .../DockerDebugConfigurationProvider.ts | 21 ++++- src/tasks/TaskHelper.ts | 5 +- src/tasks/netSdk/NetSdkBuildTaskProvider.ts | 86 +----------------- src/tasks/netSdk/NetSdkTaskHelper.ts | 91 +++++++++++++++++++ 5 files changed, 117 insertions(+), 88 deletions(-) create mode 100644 src/tasks/netSdk/NetSdkTaskHelper.ts diff --git a/package.json b/package.json index 3f8ae08737..5db35f6b80 100644 --- a/package.json +++ b/package.json @@ -1502,7 +1502,7 @@ ] }, { - "type": "dotnet-sdk-build" + "type": "dotnet-image-build" } ], "languages": [ diff --git a/src/debugging/DockerDebugConfigurationProvider.ts b/src/debugging/DockerDebugConfigurationProvider.ts index 83e8a7f531..078b31071b 100644 --- a/src/debugging/DockerDebugConfigurationProvider.ts +++ b/src/debugging/DockerDebugConfigurationProvider.ts @@ -42,6 +42,8 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi } public provideDebugConfigurations(folder: WorkspaceFolder | undefined, token?: CancellationToken): ProviderResult { + + // eslint-disable-next-line @typescript-eslint/no-floating-promises const add: MessageItem = { title: l10n.t('Add Docker Files') }; // Prompt them to add Docker files since they probably haven't @@ -59,8 +61,21 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi return []; } + private async showWizardContext(): Promise { + // 1) Getting the value + await window.showQuickPick(['explorer', 'search', 'scm', 'debug', 'extensions'], { placeHolder: 'Select the view to show when opening a window.' }); + } + public resolveDebugConfiguration(folder: WorkspaceFolder | undefined, debugConfiguration: DockerDebugConfiguration, token?: CancellationToken): ProviderResult { - return callWithTelemetryAndErrorHandling( + + let wizardContextPromise: Promise | null = null; + + // Start executing showWizardContext and store the promise + if (!wizardContextPromise) { + wizardContextPromise = this.showWizardContext(); + } + + return wizardContextPromise.then(() => callWithTelemetryAndErrorHandling( debugConfiguration.request === 'attach' ? 'docker-attach' : 'docker-launch', async (actionContext: IActionContext) => { // eslint-disable-next-line @typescript-eslint/no-floating-promises @@ -78,7 +93,7 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi if (debugConfiguration.type === undefined) { // If type is undefined, they may be doing F5 without creating any real launch.json, which won't work // VSCode subsequently will call provideDebugConfigurations which will show an error message - return null; + return undefined; } if (!debugConfiguration.request) { @@ -99,7 +114,7 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi debugConfiguration ); } - ); + )); } private async resolveDebugConfigurationInternal(context: DockerDebugContext, originalConfiguration: DockerDebugConfiguration): Promise { diff --git a/src/tasks/TaskHelper.ts b/src/tasks/TaskHelper.ts index a72fef79d9..9103e5f3a1 100644 --- a/src/tasks/TaskHelper.ts +++ b/src/tasks/TaskHelper.ts @@ -21,6 +21,7 @@ import { DockerContainerVolume, DockerRunOptions, DockerRunTaskDefinitionBase } import { DockerRunTask, DockerRunTaskDefinition, DockerRunTaskProvider } from './DockerRunTaskProvider'; import { TaskDefinitionBase } from './TaskDefinitionBase'; import { NetSdkBuildTaskProvider } from './netSdk/NetSdkBuildTaskProvider'; +import { netTaskHelper } from './netSdk/NetSdkTaskHelper'; import { netCoreTaskHelper } from './netcore/NetCoreTaskHelper'; import { nodeTaskHelper } from './node/NodeTaskHelper'; import { pythonTaskHelper } from './python/PythonTaskHelper'; @@ -104,8 +105,8 @@ export function registerTaskProviders(ctx: ExtensionContext): void { ctx.subscriptions.push( tasks.registerTaskProvider( - 'dotnet-sdk-build', - new NetSdkBuildTaskProvider() + 'dotnet-image-build', + new NetSdkBuildTaskProvider(netTaskHelper) ) ); } diff --git a/src/tasks/netSdk/NetSdkBuildTaskProvider.ts b/src/tasks/netSdk/NetSdkBuildTaskProvider.ts index c45fb10ba0..b0431c0de9 100644 --- a/src/tasks/netSdk/NetSdkBuildTaskProvider.ts +++ b/src/tasks/netSdk/NetSdkBuildTaskProvider.ts @@ -4,32 +4,14 @@ *--------------------------------------------------------------------------------------------*/ import { IActionContext, callWithTelemetryAndErrorHandling } from '@microsoft/vscode-azext-utils'; -import * as fse from 'fs-extra'; -import * as os from 'os'; import { CancellationToken, ProviderResult, ShellExecution, Task, TaskProvider, TaskScope } from "vscode"; import { ext } from '../../extensionVariables'; -import { Shell, composeArgs, withArg, withNamedArg } from "../../runtimes/docker"; -import { getDockerOSType } from "../../utils/osUtils"; -import { quickPickWorkspaceFolder } from '../../utils/quickPickWorkspaceFolder'; - -const netSdkTaskName = 'dotnet-sdk-build'; - -/** - * Native architecture of the current machine in the RID format - * {@link https://github.com/dotnet/runtime/blob/main/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json} - */ -export type RidCpuArchitecture = - | 'x64' - | 'x86' - | 'arm64' - | 'arm' - | 'ppc64le' - | 'mips64' - | 's390x' - | string; +import { NetSdkTaskHelper, netSdkTaskName } from './NetSdkTaskHelper'; export class NetSdkBuildTaskProvider implements TaskProvider { + public constructor(protected readonly helper: NetSdkTaskHelper) { } + provideTasks(token: CancellationToken): ProviderResult { return callWithTelemetryAndErrorHandling(`${netSdkTaskName}-execute`, async (actionContext: IActionContext) => { @@ -39,7 +21,7 @@ export class NetSdkBuildTaskProvider implements TaskProvider { // eslint-disable-next-line @typescript-eslint/no-floating-promises ext.activityMeasurementService.recordActivity('overallnoedit'); - const netSdkBuildCommandPromise = this.getNetSdkBuildCommand(actionContext); + const netSdkBuildCommandPromise = this.helper.getNetSdkBuildCommand(actionContext); return await netSdkBuildCommandPromise.then(netSdkBuildCommand => { return [ new Task( @@ -58,64 +40,4 @@ export class NetSdkBuildTaskProvider implements TaskProvider { resolveTask(task: Task, token: CancellationToken): ProviderResult { return task; // we can just return the task as-is } - - private async getNetSdkBuildCommand(context: IActionContext) { - - const configuration = 'Debug'; // intentionally default to Debug configuration for phase 1 of this feature - const imageTag = 'dev'; // intentionally default to dev tag for phase 1 of this feature - - // {@link https://github.com/dotnet/sdk-container-builds/issues/141} this could change in the future - const publishFlag = this.isWebApp ? '-p:PublishProfile=DefaultContainer' : '/t:PublishContainer'; - - const folderName = await quickPickWorkspaceFolder( - context, - `Unable to determine task scope to execute task ${netSdkTaskName}. Please open a workspace folder.` - ); - - const args = composeArgs( - withArg('dotnet', 'publish'), - withNamedArg('--os', await this.normalizeOsToRid()), - withNamedArg('--arch', await this.normalizeArchitectureToRid()), - withArg(publishFlag), - withNamedArg('--configuration', configuration), - withNamedArg('-p:ContainerImageName', folderName.name, { assignValue: true }), - withNamedArg('-p:ContainerImageTag', imageTag, { assignValue: true }), - )(); - - const quotedArgs = Shell.getShellOrDefault().quote(args); - return quotedArgs.join(' '); - } - - private async isWebApp(): Promise { - const projectContents = await fse.readFile('${workspaceFolder}/dotnet.csproj'); - return /Sdk\s*=\s*"Microsoft\.NET\.Sdk\.Web"/ig.test(projectContents.toString()); - } - - /** - * This method normalizes the Docker OS type to match the .NET Core SDK conventions. - * {@link https://learn.microsoft.com/en-us/dotnet/core/rid-catalog} - */ - private async normalizeOsToRid(): Promise<'linux' | 'win'> { - if (await getDockerOSType() === 'windows') { - return 'win'; - } - return 'linux'; - } - - /** - * This method normalizes the native architecture to match the .NET Core SDK conventions. - * {@link https://learn.microsoft.com/en-us/dotnet/core/rid-catalog} - */ - private async normalizeArchitectureToRid(): Promise { - const architecture = os.arch(); - switch (architecture) { - case 'x32': - case 'ia32': - return 'x86'; - default: - return architecture; - } - } - - } diff --git a/src/tasks/netSdk/NetSdkTaskHelper.ts b/src/tasks/netSdk/NetSdkTaskHelper.ts new file mode 100644 index 0000000000..8db2b56f8f --- /dev/null +++ b/src/tasks/netSdk/NetSdkTaskHelper.ts @@ -0,0 +1,91 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE.md in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IActionContext } from "@microsoft/vscode-azext-utils"; +import * as fse from 'fs-extra'; +import * as os from 'os'; +import { Shell, composeArgs, withArg, withNamedArg } from "../../runtimes/docker"; +import { getDockerOSType } from "../../utils/osUtils"; +import { quickPickWorkspaceFolder } from "../../utils/quickPickWorkspaceFolder"; + +/** + * Native architecture of the current machine in the RID format + * {@link https://github.com/dotnet/runtime/blob/main/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json} + */ +export type RidCpuArchitecture = + | 'x64' + | 'x86' + | 'arm64' + | 'arm' + | 'ppc64le' + | 'mips64' + | 's390x' + | string; + +export const netSdkTaskName = 'dotnet-image-build'; + +export class NetSdkTaskHelper { + + public async getNetSdkBuildCommand(context: IActionContext) { + + const configuration = 'Debug'; // intentionally default to Debug configuration for phase 1 of this feature + const imageTag = 'dev'; // intentionally default to dev tag for phase 1 of this feature + + // {@link https://github.com/dotnet/sdk-container-builds/issues/141} this could change in the future + const publishFlag = this.isWebApp ? '-p:PublishProfile=DefaultContainer' : '/t:PublishContainer'; + + const folderName = await quickPickWorkspaceFolder( + context, + `Unable to determine task scope to execute task ${netSdkTaskName}. Please open a workspace folder.` + ); + + const args = composeArgs( + withArg('dotnet', 'publish'), + withNamedArg('--os', await this.normalizeOsToRid()), + withNamedArg('--arch', await this.normalizeArchitectureToRid()), + withArg(publishFlag), + withNamedArg('--configuration', configuration), + withNamedArg('-p:ContainerImageName', folderName.name, { assignValue: true }), + withNamedArg('-p:ContainerImageTag', imageTag, { assignValue: true }), + )(); + + const quotedArgs = Shell.getShellOrDefault().quote(args); + return quotedArgs.join(' '); + } + + public async isWebApp(): Promise { + const projectContents = await fse.readFile('${workspaceFolder}/dotnet.csproj'); + return /Sdk\s*=\s*"Microsoft\.NET\.Sdk\.Web"/ig.test(projectContents.toString()); + } + + /** + * This method normalizes the Docker OS type to match the .NET Core SDK conventions. + * {@link https://learn.microsoft.com/en-us/dotnet/core/rid-catalog} + */ + public async normalizeOsToRid(): Promise<'linux' | 'win'> { + if (await getDockerOSType() === 'windows') { + return 'win'; + } + return 'linux'; + } + + /** + * This method normalizes the native architecture to match the .NET Core SDK conventions. + * {@link https://learn.microsoft.com/en-us/dotnet/core/rid-catalog} + */ + public async normalizeArchitectureToRid(): Promise { + const architecture = os.arch(); + switch (architecture) { + case 'x32': + case 'ia32': + return 'x86'; + default: + return architecture; + } + } +} + +export const netTaskHelper = new NetSdkTaskHelper(); + From ee21b06981904e8b499e1b6b164e786b03da4e6b Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Wed, 17 May 2023 11:11:26 -0500 Subject: [PATCH 13/46] combined build & run into one task --- package.json | 2 +- src/tasks/DockerPseudoterminal.ts | 21 ++++++--- src/tasks/DockerTaskProvider.ts | 2 +- src/tasks/TaskHelper.ts | 8 ++-- src/tasks/netSdk/NetSdkBuildTaskProvider.ts | 43 ----------------- src/tasks/netSdk/NetSdkRunTaskProvider.ts | 51 +++++++++++++++++++++ src/tasks/netSdk/NetSdkTaskHelper.ts | 34 ++++++++++++-- 7 files changed, 101 insertions(+), 60 deletions(-) delete mode 100644 src/tasks/netSdk/NetSdkBuildTaskProvider.ts create mode 100644 src/tasks/netSdk/NetSdkRunTaskProvider.ts diff --git a/package.json b/package.json index 5db35f6b80..994bf04f2b 100644 --- a/package.json +++ b/package.json @@ -1502,7 +1502,7 @@ ] }, { - "type": "dotnet-image-build" + "type": "dotnet-sdk-run" } ], "languages": [ diff --git a/src/tasks/DockerPseudoterminal.ts b/src/tasks/DockerPseudoterminal.ts index 1b4ea47096..31fc59658c 100644 --- a/src/tasks/DockerPseudoterminal.ts +++ b/src/tasks/DockerPseudoterminal.ts @@ -52,9 +52,9 @@ export class DockerPseudoterminal implements Pseudoterminal { this.closeEmitter.fire(code || 0); } - public getCommandRunner(options: Omit): (commandResponse: VoidCommandResponse | PromiseCommandResponse) => Promise { + public getCommandRunner(options: Omit): (commandResponse: VoidCommandResponse | PromiseCommandResponse) => Promise { return async (commandResponse: VoidCommandResponse | PromiseCommandResponse) => { - const output = await this.executeCommandInTerminal({ + const output = await this.executeCommandResponseInTerminal({ ...options, commandResponse: commandResponse, }); @@ -96,16 +96,21 @@ export class DockerPseudoterminal implements Pseudoterminal { this.writeEmitter.fire(`\x1b[${color}${message}\x1b[0m`); } - private async executeCommandInTerminal(options: ExecuteCommandInTerminalOptions): Promise { + private async executeCommandResponseInTerminal(options: ExecuteCommandResponseInTerminalOptions): Promise { const quotedArgs = Shell.getShellOrDefault().quote(options.commandResponse.args); const resolvedQuotedArgs = resolveVariables(quotedArgs, options.folder); const commandLine = [options.commandResponse.command, ...resolvedQuotedArgs].join(' '); + return await this.execAsyncInTerminal(commandLine, options); + } + + public async execAsyncInTerminal(command: string, options?: ExecAsyncInTerminalOptions): Promise { + // Output what we're doing, same style as VSCode does for ShellExecution/ProcessExecution - this.write(`> ${commandLine} <\r\n\r\n`, DEFAULTBOLD); + this.write(`> ${command} <\r\n\r\n`, DEFAULTBOLD); return await execAsync( - commandLine, + command, { cwd: this.resolvedDefinition.options?.cwd || options.folder.uri.fsPath, env: withDockerEnvSettings({ ...process.env, ...this.resolvedDefinition.options?.env }), @@ -120,10 +125,14 @@ export class DockerPseudoterminal implements Pseudoterminal { } ); } + } -type ExecuteCommandInTerminalOptions = { +type ExecuteCommandResponseInTerminalOptions = ExecAsyncInTerminalOptions & { commandResponse: VoidCommandResponse | PromiseCommandResponse; +}; + +type ExecAsyncInTerminalOptions = { folder: WorkspaceFolder; token?: CancellationToken; }; diff --git a/src/tasks/DockerTaskProvider.ts b/src/tasks/DockerTaskProvider.ts index dea5e7b33c..a3929709a0 100644 --- a/src/tasks/DockerTaskProvider.ts +++ b/src/tasks/DockerTaskProvider.ts @@ -15,7 +15,7 @@ import { DockerTaskExecutionContext, DockerTaskProviderName, TaskHelper } from ' export abstract class DockerTaskProvider implements TaskProvider { - protected constructor(private readonly telemetryName: DockerTaskProviderName, protected readonly helpers: { [key in DockerPlatform]: TaskHelper }) { } + protected constructor(private readonly telemetryName: DockerTaskProviderName, protected readonly helpers?: { [key in DockerPlatform]: TaskHelper }) { } public provideTasks(token?: CancellationToken): ProviderResult { return []; // Intentionally empty, so that resolveTask gets used diff --git a/src/tasks/TaskHelper.ts b/src/tasks/TaskHelper.ts index 9103e5f3a1..d03a079ed6 100644 --- a/src/tasks/TaskHelper.ts +++ b/src/tasks/TaskHelper.ts @@ -20,13 +20,13 @@ import { DockerPseudoterminal } from './DockerPseudoterminal'; import { DockerContainerVolume, DockerRunOptions, DockerRunTaskDefinitionBase } from './DockerRunTaskDefinitionBase'; import { DockerRunTask, DockerRunTaskDefinition, DockerRunTaskProvider } from './DockerRunTaskProvider'; import { TaskDefinitionBase } from './TaskDefinitionBase'; -import { NetSdkBuildTaskProvider } from './netSdk/NetSdkBuildTaskProvider'; +import { NetSdkRunTaskProvider } from './netSdk/NetSdkRunTaskProvider'; import { netTaskHelper } from './netSdk/NetSdkTaskHelper'; import { netCoreTaskHelper } from './netcore/NetCoreTaskHelper'; import { nodeTaskHelper } from './node/NodeTaskHelper'; import { pythonTaskHelper } from './python/PythonTaskHelper'; -export type DockerTaskProviderName = 'docker-build' | 'docker-run' | 'docker-compose'; +export type DockerTaskProviderName = 'docker-build' | 'docker-run' | 'docker-compose' | 'dotnet-sdk-run'; export interface DockerTaskContext { folder: WorkspaceFolder; @@ -105,8 +105,8 @@ export function registerTaskProviders(ctx: ExtensionContext): void { ctx.subscriptions.push( tasks.registerTaskProvider( - 'dotnet-image-build', - new NetSdkBuildTaskProvider(netTaskHelper) + 'dotnet-sdk-run', + new NetSdkRunTaskProvider(netTaskHelper) ) ); } diff --git a/src/tasks/netSdk/NetSdkBuildTaskProvider.ts b/src/tasks/netSdk/NetSdkBuildTaskProvider.ts deleted file mode 100644 index b0431c0de9..0000000000 --- a/src/tasks/netSdk/NetSdkBuildTaskProvider.ts +++ /dev/null @@ -1,43 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See LICENSE.md in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext, callWithTelemetryAndErrorHandling } from '@microsoft/vscode-azext-utils'; -import { CancellationToken, ProviderResult, ShellExecution, Task, TaskProvider, TaskScope } from "vscode"; -import { ext } from '../../extensionVariables'; -import { NetSdkTaskHelper, netSdkTaskName } from './NetSdkTaskHelper'; - -export class NetSdkBuildTaskProvider implements TaskProvider { - - public constructor(protected readonly helper: NetSdkTaskHelper) { } - - provideTasks(token: CancellationToken): ProviderResult { - - return callWithTelemetryAndErrorHandling(`${netSdkTaskName}-execute`, async (actionContext: IActionContext) => { - actionContext.errorHandling.suppressDisplay = true; // Suppress display. VSCode already has a modal popup and we don't want focus taken away from Terminal window. - actionContext.errorHandling.rethrow = true; // Rethrow to hit the try/catch outside this block. - - // eslint-disable-next-line @typescript-eslint/no-floating-promises - ext.activityMeasurementService.recordActivity('overallnoedit'); - - const netSdkBuildCommandPromise = this.helper.getNetSdkBuildCommand(actionContext); - return await netSdkBuildCommandPromise.then(netSdkBuildCommand => { - return [ - new Task( - { type: netSdkTaskName }, - TaskScope.Workspace, - 'debug', - netSdkTaskName, - new ShellExecution(netSdkBuildCommand), - ) - ]; - }); - }); - - } - - resolveTask(task: Task, token: CancellationToken): ProviderResult { - return task; // we can just return the task as-is - } -} diff --git a/src/tasks/netSdk/NetSdkRunTaskProvider.ts b/src/tasks/netSdk/NetSdkRunTaskProvider.ts new file mode 100644 index 0000000000..d8d8673c36 --- /dev/null +++ b/src/tasks/netSdk/NetSdkRunTaskProvider.ts @@ -0,0 +1,51 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE.md in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { CancellationToken, ProviderResult, Task, TaskScope } from "vscode"; +import { DockerTaskProvider } from '../DockerTaskProvider'; +import { DockerTaskExecutionContext } from '../TaskHelper'; +import { NetSdkTaskHelper, netSdkRunTaskSymbol } from './NetSdkTaskHelper'; + +export class NetSdkRunTaskProvider extends DockerTaskProvider { + + public constructor(protected readonly helper: NetSdkTaskHelper) { super(netSdkRunTaskSymbol, undefined); } + + provideTasks(token: CancellationToken): ProviderResult { + // provide the bare minimum: a task that will show up in the command palette + return [ + new Task( + { type: netSdkRunTaskSymbol }, + TaskScope.Workspace, + 'debug', + netSdkRunTaskSymbol + ) + ]; + } + + protected async executeTaskInternal(context: DockerTaskExecutionContext, task: Task): Promise { + + const buildCommand = await this.helper.getNetSdkBuildCommand(context.actionContext); + await context.terminal.execAsyncInTerminal( + buildCommand, + { + folder: context.folder, + token: context.cancellationToken, + } + ); + + const runCommand = await this.helper.getNetSdkRunCommand(context.actionContext); + await context.terminal.execAsyncInTerminal( + runCommand, + { + folder: context.folder, + token: context.cancellationToken, + } + ); + + return Promise.resolve(); + } +} + + diff --git a/src/tasks/netSdk/NetSdkTaskHelper.ts b/src/tasks/netSdk/NetSdkTaskHelper.ts index 8db2b56f8f..b4c8ffaa7e 100644 --- a/src/tasks/netSdk/NetSdkTaskHelper.ts +++ b/src/tasks/netSdk/NetSdkTaskHelper.ts @@ -6,6 +6,7 @@ import { IActionContext } from "@microsoft/vscode-azext-utils"; import * as fse from 'fs-extra'; import * as os from 'os'; +import { ext } from "../../extensionVariables"; import { Shell, composeArgs, withArg, withNamedArg } from "../../runtimes/docker"; import { getDockerOSType } from "../../utils/osUtils"; import { quickPickWorkspaceFolder } from "../../utils/quickPickWorkspaceFolder"; @@ -24,7 +25,8 @@ export type RidCpuArchitecture = | 's390x' | string; -export const netSdkTaskName = 'dotnet-image-build'; +export const netSdkBuildTaskSymbol = 'dotnet-sdk-build'; +export const netSdkRunTaskSymbol = 'dotnet-sdk-run'; export class NetSdkTaskHelper { @@ -36,10 +38,7 @@ export class NetSdkTaskHelper { // {@link https://github.com/dotnet/sdk-container-builds/issues/141} this could change in the future const publishFlag = this.isWebApp ? '-p:PublishProfile=DefaultContainer' : '/t:PublishContainer'; - const folderName = await quickPickWorkspaceFolder( - context, - `Unable to determine task scope to execute task ${netSdkTaskName}. Please open a workspace folder.` - ); + const folderName = await this.getFolderName(context); const args = composeArgs( withArg('dotnet', 'publish'), @@ -55,6 +54,24 @@ export class NetSdkTaskHelper { return quotedArgs.join(' '); } + public async getNetSdkRunCommand(context: IActionContext): Promise { + const client = await ext.runtimeManager.getClient(); + const folderName = await this.getFolderName(context); + + const command = await client.runContainer({ + detached: true, + publishAllPorts: true, + name: folderName.name, + environmentVariables: {}, + removeOnExit: false, // TODO: confirm with team + imageRef: `${folderName.name}:dev`, + }); + + const quotedArgs = Shell.getShellOrDefault().quote(command.args); + + return quotedArgs.join(' '); + } + public async isWebApp(): Promise { const projectContents = await fse.readFile('${workspaceFolder}/dotnet.csproj'); return /Sdk\s*=\s*"Microsoft\.NET\.Sdk\.Web"/ig.test(projectContents.toString()); @@ -85,6 +102,13 @@ export class NetSdkTaskHelper { return architecture; } } + + public async getFolderName(context: IActionContext) { + return await quickPickWorkspaceFolder( + context, + `Unable to determine task scope to execute task ${netSdkBuildTaskSymbol}. Please open a workspace folder.` + ); + } } export const netTaskHelper = new NetSdkTaskHelper(); From 7d6277735d82434ceeff840080a9276a2f85de4e Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Wed, 17 May 2023 15:36:15 -0500 Subject: [PATCH 14/46] adddded working version of run command --- src/tasks/netSdk/NetSdkRunTaskProvider.ts | 2 -- src/tasks/netSdk/NetSdkTaskHelper.ts | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/tasks/netSdk/NetSdkRunTaskProvider.ts b/src/tasks/netSdk/NetSdkRunTaskProvider.ts index d8d8673c36..098e91f489 100644 --- a/src/tasks/netSdk/NetSdkRunTaskProvider.ts +++ b/src/tasks/netSdk/NetSdkRunTaskProvider.ts @@ -47,5 +47,3 @@ export class NetSdkRunTaskProvider extends DockerTaskProvider { return Promise.resolve(); } } - - diff --git a/src/tasks/netSdk/NetSdkTaskHelper.ts b/src/tasks/netSdk/NetSdkTaskHelper.ts index b4c8ffaa7e..0de8172d78 100644 --- a/src/tasks/netSdk/NetSdkTaskHelper.ts +++ b/src/tasks/netSdk/NetSdkTaskHelper.ts @@ -68,8 +68,9 @@ export class NetSdkTaskHelper { }); const quotedArgs = Shell.getShellOrDefault().quote(command.args); + const commandLine = [client.commandName, ...quotedArgs].join(' '); - return quotedArgs.join(' '); + return commandLine; } public async isWebApp(): Promise { From 78f137446252170998f245bd878f5283f2f5d98d Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Thu, 18 May 2023 09:25:22 -0500 Subject: [PATCH 15/46] added mounts to run arg --- src/tasks/DockerRunTaskProvider.ts | 22 +++++++++--------- src/tasks/netSdk/NetSdkTaskHelper.ts | 34 +++++++++++++++++++++++----- 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/src/tasks/DockerRunTaskProvider.ts b/src/tasks/DockerRunTaskProvider.ts index ded5b83ca8..0cfd4d7cd0 100644 --- a/src/tasks/DockerRunTaskProvider.ts +++ b/src/tasks/DockerRunTaskProvider.ts @@ -64,7 +64,7 @@ export class DockerRunTaskProvider extends DockerTaskProvider { environmentVariables: options.env, environmentFiles: options.envFiles, labels: getAggregateLabels(options.labels, defaultVsCodeLabels), - mounts: this.getMounts(options.volumes), + mounts: getMounts(options.volumes), ports: options.ports, addHost: options.extraHosts, entrypoint: options.entrypoint, @@ -92,15 +92,15 @@ export class DockerRunTaskProvider extends DockerTaskProvider { throw new Error(l10n.t('No Docker image name was provided or resolved.')); } } +} - private getMounts(volumes?: DockerContainerVolume[]): RunContainerBindMount[] | undefined { - return volumes?.map(v => { - return { - source: v.localPath, - destination: v.containerPath, - readOnly: v.permissions === 'ro' || (v.permissions as unknown === 'ro,z'), // Maintain compatibility with old `ro,z` option as much as possible - type: 'bind', - }; - }); - } +export function getMounts(volumes?: DockerContainerVolume[]): RunContainerBindMount[] | undefined { + return volumes?.map(v => { + return { + source: v.localPath, + destination: v.containerPath, + readOnly: v.permissions === 'ro' || (v.permissions as unknown === 'ro,z'), // Maintain compatibility with old `ro,z` option as much as possible + type: 'bind', + }; + }); } diff --git a/src/tasks/netSdk/NetSdkTaskHelper.ts b/src/tasks/netSdk/NetSdkTaskHelper.ts index 0de8172d78..d5c6baf5d7 100644 --- a/src/tasks/netSdk/NetSdkTaskHelper.ts +++ b/src/tasks/netSdk/NetSdkTaskHelper.ts @@ -6,10 +6,16 @@ import { IActionContext } from "@microsoft/vscode-azext-utils"; import * as fse from 'fs-extra'; import * as os from 'os'; +import { WorkspaceFolder } from "vscode"; +import { vsDbgInstallBasePath } from "../../debugging/netcore/VsDbgHelper"; import { ext } from "../../extensionVariables"; -import { Shell, composeArgs, withArg, withNamedArg } from "../../runtimes/docker"; +import { RunContainerBindMount, Shell, composeArgs, withArg, withNamedArg } from "../../runtimes/docker"; import { getDockerOSType } from "../../utils/osUtils"; import { quickPickWorkspaceFolder } from "../../utils/quickPickWorkspaceFolder"; +import { DockerContainerVolume } from "../DockerRunTaskDefinitionBase"; +import { getMounts } from "../DockerRunTaskProvider"; +import { defaultVsCodeLabels } from "../TaskDefinitionBase"; +import { addVolumeWithoutConflicts } from "../TaskHelper"; /** * Native architecture of the current machine in the RID format @@ -63,8 +69,10 @@ export class NetSdkTaskHelper { publishAllPorts: true, name: folderName.name, environmentVariables: {}, - removeOnExit: false, // TODO: confirm with team + removeOnExit: true, imageRef: `${folderName.name}:dev`, + labels: defaultVsCodeLabels, + mounts: await this.getMounts(), }); const quotedArgs = Shell.getShellOrDefault().quote(command.args); @@ -73,7 +81,7 @@ export class NetSdkTaskHelper { return commandLine; } - public async isWebApp(): Promise { + private async isWebApp(): Promise { const projectContents = await fse.readFile('${workspaceFolder}/dotnet.csproj'); return /Sdk\s*=\s*"Microsoft\.NET\.Sdk\.Web"/ig.test(projectContents.toString()); } @@ -82,7 +90,7 @@ export class NetSdkTaskHelper { * This method normalizes the Docker OS type to match the .NET Core SDK conventions. * {@link https://learn.microsoft.com/en-us/dotnet/core/rid-catalog} */ - public async normalizeOsToRid(): Promise<'linux' | 'win'> { + private async normalizeOsToRid(): Promise<'linux' | 'win'> { if (await getDockerOSType() === 'windows') { return 'win'; } @@ -93,7 +101,7 @@ export class NetSdkTaskHelper { * This method normalizes the native architecture to match the .NET Core SDK conventions. * {@link https://learn.microsoft.com/en-us/dotnet/core/rid-catalog} */ - public async normalizeArchitectureToRid(): Promise { + private async normalizeArchitectureToRid(): Promise { const architecture = os.arch(); switch (architecture) { case 'x32': @@ -104,12 +112,26 @@ export class NetSdkTaskHelper { } } - public async getFolderName(context: IActionContext) { + private async getFolderName(context: IActionContext): Promise { return await quickPickWorkspaceFolder( context, `Unable to determine task scope to execute task ${netSdkBuildTaskSymbol}. Please open a workspace folder.` ); } + + private async getMounts(): Promise { + const volumes: DockerContainerVolume[] = []; + const isLinux = await getDockerOSType() === 'linux'; + + const debuggerVolume: DockerContainerVolume = { + localPath: vsDbgInstallBasePath, + containerPath: isLinux ? 'C:\\remote_debugger' : '/remote_debugger', + permissions: 'ro' + }; + + addVolumeWithoutConflicts(volumes, debuggerVolume); + return getMounts(volumes); + } } export const netTaskHelper = new NetSdkTaskHelper(); From 9832b7bce5bfbc542c210d98c8295b9417c904dd Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Wed, 24 May 2023 15:42:22 -0400 Subject: [PATCH 16/46] added ambient launch task --- .../DockerDebugConfigurationProvider.ts | 23 ++++++++++++++----- src/tasks/netSdk/NetSdkRunTaskProvider.ts | 19 ++++++++++++--- src/tasks/netSdk/NetSdkTaskHelper.ts | 10 ++++---- 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/debugging/DockerDebugConfigurationProvider.ts b/src/debugging/DockerDebugConfigurationProvider.ts index 078b31071b..f04ce05090 100644 --- a/src/debugging/DockerDebugConfigurationProvider.ts +++ b/src/debugging/DockerDebugConfigurationProvider.ts @@ -61,21 +61,21 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi return []; } - private async showWizardContext(): Promise { + private async showWizardContext(): Promise { // 1) Getting the value - await window.showQuickPick(['explorer', 'search', 'scm', 'debug', 'extensions'], { placeHolder: 'Select the view to show when opening a window.' }); + return await window.showQuickPick(['Dockerfile', '.NET Container (Debug only)'], { placeHolder: 'Select how you want to debug your .NET project' }); } public resolveDebugConfiguration(folder: WorkspaceFolder | undefined, debugConfiguration: DockerDebugConfiguration, token?: CancellationToken): ProviderResult { - let wizardContextPromise: Promise | null = null; + let wizardContextPromise: Promise | null = null; // Start executing showWizardContext and store the promise if (!wizardContextPromise) { wizardContextPromise = this.showWizardContext(); } - return wizardContextPromise.then(() => callWithTelemetryAndErrorHandling( + return wizardContextPromise.then((wizardContext) => callWithTelemetryAndErrorHandling( debugConfiguration.request === 'attach' ? 'docker-attach' : 'docker-launch', async (actionContext: IActionContext) => { // eslint-disable-next-line @typescript-eslint/no-floating-promises @@ -90,10 +90,21 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi } } - if (debugConfiguration.type === undefined) { + // eslint-disable-next-line no-constant-condition + if (debugConfiguration.type === undefined + && wizardContext === 'Dockerfile', '.NET Container (Debug only)') { + + debugConfiguration.type = 'docker'; + debugConfiguration.request = 'launch'; + debugConfiguration.name = 'Docker .NET Launch'; + debugConfiguration.platform = 'netCore'; + debugConfiguration.netCore = { + appProject: "${workspaceFolder}/dotnet.csproj" + }; + debugConfiguration.preLaunchTask = 'dotnet-sdk-run: sdk-debug'; + // If type is undefined, they may be doing F5 without creating any real launch.json, which won't work // VSCode subsequently will call provideDebugConfigurations which will show an error message - return undefined; } if (!debugConfiguration.request) { diff --git a/src/tasks/netSdk/NetSdkRunTaskProvider.ts b/src/tasks/netSdk/NetSdkRunTaskProvider.ts index 098e91f489..9931feecee 100644 --- a/src/tasks/netSdk/NetSdkRunTaskProvider.ts +++ b/src/tasks/netSdk/NetSdkRunTaskProvider.ts @@ -3,7 +3,8 @@ * Licensed under the MIT License. See LICENSE.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CancellationToken, ProviderResult, Task, TaskScope } from "vscode"; +import { CancellationToken, CustomExecution, ProviderResult, Task, TaskDefinition, TaskScope } from "vscode"; +import { DockerPseudoterminal } from "../DockerPseudoterminal"; import { DockerTaskProvider } from '../DockerTaskProvider'; import { DockerTaskExecutionContext } from '../TaskHelper'; import { NetSdkTaskHelper, netSdkRunTaskSymbol } from './NetSdkTaskHelper'; @@ -14,12 +15,24 @@ export class NetSdkRunTaskProvider extends DockerTaskProvider { provideTasks(token: CancellationToken): ProviderResult { // provide the bare minimum: a task that will show up in the command palette + const problemMatchers = ["$myProblemMatcher"]; + + const task = new Task( + { type: netSdkRunTaskSymbol }, + TaskScope.Workspace, + 'sdk-debug', + netSdkRunTaskSymbol, + problemMatchers + ); + return [ new Task( { type: netSdkRunTaskSymbol }, TaskScope.Workspace, - 'debug', - netSdkRunTaskSymbol + 'sdk-debug', + netSdkRunTaskSymbol, + new CustomExecution(async (resolvedDefinition: TaskDefinition) => Promise.resolve(new DockerPseudoterminal(this, task, resolvedDefinition))), + problemMatchers ) ]; } diff --git a/src/tasks/netSdk/NetSdkTaskHelper.ts b/src/tasks/netSdk/NetSdkTaskHelper.ts index d5c6baf5d7..65522987d6 100644 --- a/src/tasks/netSdk/NetSdkTaskHelper.ts +++ b/src/tasks/netSdk/NetSdkTaskHelper.ts @@ -31,7 +31,6 @@ export type RidCpuArchitecture = | 's390x' | string; -export const netSdkBuildTaskSymbol = 'dotnet-sdk-build'; export const netSdkRunTaskSymbol = 'dotnet-sdk-run'; export class NetSdkTaskHelper { @@ -53,7 +52,7 @@ export class NetSdkTaskHelper { withArg(publishFlag), withNamedArg('--configuration', configuration), withNamedArg('-p:ContainerImageName', folderName.name, { assignValue: true }), - withNamedArg('-p:ContainerImageTag', imageTag, { assignValue: true }), + withNamedArg('-p:ContainerImageTag', imageTag, { assignValue: true }) )(); const quotedArgs = Shell.getShellOrDefault().quote(args); @@ -67,12 +66,13 @@ export class NetSdkTaskHelper { const command = await client.runContainer({ detached: true, publishAllPorts: true, - name: folderName.name, + name: `${folderName.name}-dev`, environmentVariables: {}, removeOnExit: true, imageRef: `${folderName.name}:dev`, labels: defaultVsCodeLabels, mounts: await this.getMounts(), + customOptions: '--expose 8080', }); const quotedArgs = Shell.getShellOrDefault().quote(command.args); @@ -115,7 +115,7 @@ export class NetSdkTaskHelper { private async getFolderName(context: IActionContext): Promise { return await quickPickWorkspaceFolder( context, - `Unable to determine task scope to execute task ${netSdkBuildTaskSymbol}. Please open a workspace folder.` + `Unable to determine task scope to execute task ${netSdkRunTaskSymbol}. Please open a workspace folder.` ); } @@ -125,7 +125,7 @@ export class NetSdkTaskHelper { const debuggerVolume: DockerContainerVolume = { localPath: vsDbgInstallBasePath, - containerPath: isLinux ? 'C:\\remote_debugger' : '/remote_debugger', + containerPath: isLinux ? '/remote_debugger' : 'C:\\remote_debugger', permissions: 'ro' }; From b2712c8f238c1cb5c8b8b2b676976ec1a1831205 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Wed, 24 May 2023 16:37:42 -0400 Subject: [PATCH 17/46] working version of ambient launch task --- src/debugging/DockerDebugConfigurationProvider.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/debugging/DockerDebugConfigurationProvider.ts b/src/debugging/DockerDebugConfigurationProvider.ts index f04ce05090..a365882617 100644 --- a/src/debugging/DockerDebugConfigurationProvider.ts +++ b/src/debugging/DockerDebugConfigurationProvider.ts @@ -92,7 +92,7 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi // eslint-disable-next-line no-constant-condition if (debugConfiguration.type === undefined - && wizardContext === 'Dockerfile', '.NET Container (Debug only)') { + && wizardContext === '.NET Container (Debug only)') { debugConfiguration.type = 'docker'; debugConfiguration.request = 'launch'; From 86cc95f5ae039e65497f9498513e1c24c1dcaa9d Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Thu, 25 May 2023 14:13:00 -0400 Subject: [PATCH 18/46] added prompt for docker debugger on csharp languag --- package.json | 6 ++++++ src/debugging/DockerDebugConfigurationProvider.ts | 7 ++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 994bf04f2b..f49d67561f 100644 --- a/package.json +++ b/package.json @@ -636,6 +636,12 @@ { "type": "docker", "label": "Docker: Debug in Container", + "languages": [ + "csharp", + "razor", + "qsharp", + "aspnetcorerazor" + ], "configurationAttributes": { "launch": { "properties": { diff --git a/src/debugging/DockerDebugConfigurationProvider.ts b/src/debugging/DockerDebugConfigurationProvider.ts index a365882617..066bde41ca 100644 --- a/src/debugging/DockerDebugConfigurationProvider.ts +++ b/src/debugging/DockerDebugConfigurationProvider.ts @@ -92,7 +92,7 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi // eslint-disable-next-line no-constant-condition if (debugConfiguration.type === undefined - && wizardContext === '.NET Container (Debug only)') { + && wizardContext === '.NET Container (Debug only)') { // TODO: Add check for .NET project debugConfiguration.type = 'docker'; debugConfiguration.request = 'launch'; @@ -106,6 +106,11 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi // If type is undefined, they may be doing F5 without creating any real launch.json, which won't work // VSCode subsequently will call provideDebugConfigurations which will show an error message } + else if (debugConfiguration.type === undefined + && wizardContext === 'Dockerfile') { + await commands.executeCommand('vscode-docker.configure'); + } + if (!debugConfiguration.request) { throw new Error(l10n.t('The property "request" must be specified in the debug config.')); From 796c1adefb52acdc7154062a34770f7e40d6da75 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Fri, 26 May 2023 15:06:38 -0400 Subject: [PATCH 19/46] stored user image build choices --- .../DockerDebugConfigurationProvider.ts | 82 ++++++++----------- .../wizard/net/NetSdkChooseBuildStep.ts | 58 +++++++++++++ .../wizard/net/netContainerBuild.ts | 27 ++++++ src/tasks/netSdk/NetSdkTaskHelper.ts | 1 + src/utils/StateUtils.ts | 16 ++++ 5 files changed, 135 insertions(+), 49 deletions(-) create mode 100644 src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts create mode 100644 src/scaffolding/wizard/net/netContainerBuild.ts create mode 100644 src/utils/StateUtils.ts diff --git a/src/debugging/DockerDebugConfigurationProvider.ts b/src/debugging/DockerDebugConfigurationProvider.ts index 066bde41ca..fb4e064fc6 100644 --- a/src/debugging/DockerDebugConfigurationProvider.ts +++ b/src/debugging/DockerDebugConfigurationProvider.ts @@ -4,9 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import { callWithTelemetryAndErrorHandling, IActionContext, registerEvent } from '@microsoft/vscode-azext-utils'; -import { CancellationToken, commands, debug, DebugConfiguration, DebugConfigurationProvider, DebugSession, l10n, MessageItem, ProviderResult, window, workspace, WorkspaceFolder } from 'vscode'; +import { CancellationToken, commands, debug, DebugConfiguration, DebugConfigurationProvider, DebugSession, l10n, ProviderResult, workspace, WorkspaceFolder } from 'vscode'; import { DockerOrchestration } from '../constants'; import { ext } from '../extensionVariables'; +import { netContainerBuild } from '../scaffolding/wizard/net/netContainerBuild'; +import { NetChooseBuildTypeContext } from '../scaffolding/wizard/net/NetSdkChooseBuildStep'; import { getAssociatedDockerRunTask } from '../tasks/TaskHelper'; import { DebugHelper, DockerDebugContext, ResolvedDebugConfiguration } from './DebugHelper'; import { DockerPlatform, getPlatform } from './DockerPlatformHelper'; @@ -42,40 +44,12 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi } public provideDebugConfigurations(folder: WorkspaceFolder | undefined, token?: CancellationToken): ProviderResult { - - // eslint-disable-next-line @typescript-eslint/no-floating-promises - const add: MessageItem = { title: l10n.t('Add Docker Files') }; - - // Prompt them to add Docker files since they probably haven't - /* eslint-disable-next-line @typescript-eslint/no-floating-promises */ - window.showErrorMessage( - l10n.t('To debug in a Docker container on supported platforms, use the command "Docker: Add Docker Files to Workspace", or click "Add Docker Files".'), - ...[add]) - .then((result) => { - if (result === add) { - /* eslint-disable-next-line @typescript-eslint/no-floating-promises */ - commands.executeCommand('vscode-docker.configure'); - } - }); - return []; } - private async showWizardContext(): Promise { - // 1) Getting the value - return await window.showQuickPick(['Dockerfile', '.NET Container (Debug only)'], { placeHolder: 'Select how you want to debug your .NET project' }); - } - public resolveDebugConfiguration(folder: WorkspaceFolder | undefined, debugConfiguration: DockerDebugConfiguration, token?: CancellationToken): ProviderResult { - let wizardContextPromise: Promise | null = null; - - // Start executing showWizardContext and store the promise - if (!wizardContextPromise) { - wizardContextPromise = this.showWizardContext(); - } - - return wizardContextPromise.then((wizardContext) => callWithTelemetryAndErrorHandling( + return callWithTelemetryAndErrorHandling( debugConfiguration.request === 'attach' ? 'docker-attach' : 'docker-launch', async (actionContext: IActionContext) => { // eslint-disable-next-line @typescript-eslint/no-floating-promises @@ -90,25 +64,24 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi } } + // eslint-disable-next-line no-constant-condition - if (debugConfiguration.type === undefined - && wizardContext === '.NET Container (Debug only)') { // TODO: Add check for .NET project - - debugConfiguration.type = 'docker'; - debugConfiguration.request = 'launch'; - debugConfiguration.name = 'Docker .NET Launch'; - debugConfiguration.platform = 'netCore'; - debugConfiguration.netCore = { - appProject: "${workspaceFolder}/dotnet.csproj" - }; - debugConfiguration.preLaunchTask = 'dotnet-sdk-run: sdk-debug'; - - // If type is undefined, they may be doing F5 without creating any real launch.json, which won't work - // VSCode subsequently will call provideDebugConfigurations which will show an error message - } - else if (debugConfiguration.type === undefined - && wizardContext === 'Dockerfile') { - await commands.executeCommand('vscode-docker.configure'); + // if the user has not created a launch.json yet, we will help them do that + if (debugConfiguration.type === undefined) { // TODO: Add check for .NET project + const netCoreBuildContext: NetChooseBuildTypeContext = { ...actionContext }; + await netContainerBuild(netCoreBuildContext); + + if (netCoreBuildContext.containerBuildOptions && + netCoreBuildContext.containerBuildOptions === 'Use .NET SDK') { + // set up for .NET SDK build + this.configureNetSdkBuild(debugConfiguration); + } + else { + // set up for Dockerfile scaffolding + // TODO: Automatically launch after scaffolding is complete + await commands.executeCommand('vscode-docker.configure'); + return undefined; + } } @@ -130,7 +103,7 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi debugConfiguration ); } - )); + ); } private async resolveDebugConfigurationInternal(context: DockerDebugContext, originalConfiguration: DockerDebugConfiguration): Promise { @@ -201,4 +174,15 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi } } } + + private configureNetSdkBuild(debugConfiguration: DockerDebugConfiguration): void { + debugConfiguration.type = 'docker'; + debugConfiguration.request = 'launch'; + debugConfiguration.name = 'Docker .NET Launch'; + debugConfiguration.platform = 'netCore'; + debugConfiguration.netCore = { + appProject: "${workspaceFolder}/dotnet.csproj" + }; + debugConfiguration.preLaunchTask = 'dotnet-sdk-run: sdk-debug'; + } } diff --git a/src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts b/src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts new file mode 100644 index 0000000000..3418d05ab3 --- /dev/null +++ b/src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts @@ -0,0 +1,58 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE.md in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IActionContext, IAzureQuickPickItem } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { getFromWorkspaceState, updateWorkspaceState } from '../../../utils/StateUtils'; +import { TelemetryPromptStep } from '../TelemetryPromptStep'; + +export const NetContainerBuildOptions = [ + 'Use a Dockerfile', + 'Use .NET SDK' +] as const; + +type NetContainerBuildOptionsTuple = typeof NetContainerBuildOptions; +export type NetContainerBuildOptions = NetContainerBuildOptionsTuple[number]; + +export interface NetChooseBuildTypeContext extends IActionContext { + containerBuildOptions?: NetContainerBuildOptions; +} + +export class NetSdkChooseBuildStep extends TelemetryPromptStep { + public async prompt(wizardContext: NetChooseBuildTypeContext): Promise { + + // get workspace momento storage + const containerBuildOptions = await getFromWorkspaceState('containerBuildOptions'); + + // only remember if it was .NET SDK, otherwise prompt again + if (containerBuildOptions === 'Use .NET SDK') { // only remember if it was .NET SDK, otherwise prompt again + wizardContext.containerBuildOptions = containerBuildOptions; + return; + } + + const opt: vscode.QuickPickOptions = { + matchOnDescription: true, + matchOnDetail: true, + placeHolder: vscode.l10n.t('How would you like to build your container image?'), + }; + + const buildOptions = NetContainerBuildOptions as readonly NetContainerBuildOptions[]; + const items = buildOptions.map(p => >{ label: p, data: p }); + + const response = await wizardContext.ui.showQuickPick(items, opt); + wizardContext.containerBuildOptions = response.data; + + // update workspace momento storage + await updateWorkspaceState('containerBuildOptions', wizardContext.containerBuildOptions); + } + + public shouldPrompt(wizardContext: NetChooseBuildTypeContext): boolean { + return !wizardContext.containerBuildOptions; + } + + protected setTelemetry(wizardContext: NetChooseBuildTypeContext): void { + wizardContext.telemetry.properties.netSdkBuildStep = wizardContext.containerBuildOptions; + } +} diff --git a/src/scaffolding/wizard/net/netContainerBuild.ts b/src/scaffolding/wizard/net/netContainerBuild.ts new file mode 100644 index 0000000000..101727bc78 --- /dev/null +++ b/src/scaffolding/wizard/net/netContainerBuild.ts @@ -0,0 +1,27 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE.md in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { AzureWizard, AzureWizardPromptStep, UserCancelledError } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { NetChooseBuildTypeContext, NetSdkChooseBuildStep } from './NetSdkChooseBuildStep'; + +export async function netContainerBuild(wizardContext: Partial, apiInput?: NetChooseBuildTypeContext): Promise { + if (!vscode.workspace.isTrusted) { + throw new UserCancelledError('enforceTrust'); + } + + const promptSteps: AzureWizardPromptStep[] = [ + new NetSdkChooseBuildStep(), + ]; + + const wizard = new AzureWizard(wizardContext as NetChooseBuildTypeContext, { + promptSteps: promptSteps, + title: vscode.l10n.t('Initialize for Debugging'), + }); + + await wizard.prompt(); + await wizard.execute(); + +} diff --git a/src/tasks/netSdk/NetSdkTaskHelper.ts b/src/tasks/netSdk/NetSdkTaskHelper.ts index 65522987d6..286679ddec 100644 --- a/src/tasks/netSdk/NetSdkTaskHelper.ts +++ b/src/tasks/netSdk/NetSdkTaskHelper.ts @@ -73,6 +73,7 @@ export class NetSdkTaskHelper { labels: defaultVsCodeLabels, mounts: await this.getMounts(), customOptions: '--expose 8080', + entrypoint: '/bin/sh' }); const quotedArgs = Shell.getShellOrDefault().quote(command.args); diff --git a/src/utils/StateUtils.ts b/src/utils/StateUtils.ts new file mode 100644 index 0000000000..e7e38aadcf --- /dev/null +++ b/src/utils/StateUtils.ts @@ -0,0 +1,16 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE.md in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ext } from '../extensionVariables'; + +export async function getFromWorkspaceState(key: string): Promise { + return ext.context.workspaceState.get(key); +} + +export async function updateWorkspaceState(key: string, value: T): Promise { + return ext.context.workspaceState.update(key, value); +} + + From 068fcc176917a2abf9c49b1eb6318cfe33cf29dd Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Tue, 30 May 2023 16:19:40 -0400 Subject: [PATCH 20/46] added auto .csproj selection & refactored code --- .../DockerDebugConfigurationProvider.ts | 71 +++++++++++++------ .../wizard/net/NetSdkChooseBuildStep.ts | 7 +- .../wizard/net/netContainerBuild.ts | 9 ++- src/tasks/netSdk/NetSdkRunTaskProvider.ts | 4 +- src/tasks/netSdk/NetSdkTaskHelper.ts | 29 ++++---- 5 files changed, 75 insertions(+), 45 deletions(-) diff --git a/src/debugging/DockerDebugConfigurationProvider.ts b/src/debugging/DockerDebugConfigurationProvider.ts index fb4e064fc6..122f9b1aa7 100644 --- a/src/debugging/DockerDebugConfigurationProvider.ts +++ b/src/debugging/DockerDebugConfigurationProvider.ts @@ -5,11 +5,11 @@ import { callWithTelemetryAndErrorHandling, IActionContext, registerEvent } from '@microsoft/vscode-azext-utils'; import { CancellationToken, commands, debug, DebugConfiguration, DebugConfigurationProvider, DebugSession, l10n, ProviderResult, workspace, WorkspaceFolder } from 'vscode'; -import { DockerOrchestration } from '../constants'; +import { CSPROJ_GLOB_PATTERN, DockerOrchestration } from '../constants'; import { ext } from '../extensionVariables'; -import { netContainerBuild } from '../scaffolding/wizard/net/netContainerBuild'; -import { NetChooseBuildTypeContext } from '../scaffolding/wizard/net/NetSdkChooseBuildStep'; +import { NetChooseBuildTypeContext, netContainerBuild } from '../scaffolding/wizard/net/netContainerBuild'; import { getAssociatedDockerRunTask } from '../tasks/TaskHelper'; +import { resolveFilesOfPattern } from '../utils/quickPickFile'; import { DebugHelper, DockerDebugContext, ResolvedDebugConfiguration } from './DebugHelper'; import { DockerPlatform, getPlatform } from './DockerPlatformHelper'; import { NetCoreDockerDebugConfiguration } from './netcore/NetCoreDebugHelper'; @@ -64,27 +64,18 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi } } - - // eslint-disable-next-line no-constant-condition // if the user has not created a launch.json yet, we will help them do that - if (debugConfiguration.type === undefined) { // TODO: Add check for .NET project - const netCoreBuildContext: NetChooseBuildTypeContext = { ...actionContext }; - await netContainerBuild(netCoreBuildContext); - - if (netCoreBuildContext.containerBuildOptions && - netCoreBuildContext.containerBuildOptions === 'Use .NET SDK') { - // set up for .NET SDK build - this.configureNetSdkBuild(debugConfiguration); - } - else { - // set up for Dockerfile scaffolding - // TODO: Automatically launch after scaffolding is complete - await commands.executeCommand('vscode-docker.configure'); + if (debugConfiguration.type === undefined && + debugConfiguration.request === undefined && + debugConfiguration.name === undefined) { + + const useSDKBuild = await this.handleEmptyDebugConfig(debugConfiguration, folder, actionContext); + + if (!useSDKBuild) { // TODO: automatically launch right after scaffolding return undefined; } } - if (!debugConfiguration.request) { throw new Error(l10n.t('The property "request" must be specified in the debug config.')); } @@ -175,14 +166,48 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi } } - private configureNetSdkBuild(debugConfiguration: DockerDebugConfiguration): void { + /** + * If the user has an empty debug launch.json, then we will help them either scaffold docker files or configure for .NET Core + * @returns true if the user should use .NET SDK build + * false if the user should scaffold docker files + */ + private async handleEmptyDebugConfig(debugConfiguration: DockerDebugConfiguration, folder: WorkspaceFolder, actionContext: IActionContext): Promise { + + // Get a list of all the csproj files in the workspace + const csProjUris = await resolveFilesOfPattern(folder, [CSPROJ_GLOB_PATTERN]); + + // If there are no csproj files, then we assume it's not a .NET Core project -> scaffold docker files + if (!csProjUris || csProjUris.length === 0) { + await commands.executeCommand('vscode-docker.configure'); + return false; + } + // If there are one or more .csproj file, then we assume it's a .NET Core project -> configure for .NET Core + else { + const netCoreBuildContext: NetChooseBuildTypeContext = { + ...actionContext, + scaffoldType: 'debugging', + workspaceFolder: folder, + }; + + await netContainerBuild(netCoreBuildContext); + + if (netCoreBuildContext?.containerBuildOptions === 'Use .NET SDK') { + // set up for .NET SDK build + this.configureNetSdkBuild(debugConfiguration, netCoreBuildContext); + return true; + } + else { + await commands.executeCommand('vscode-docker.configure'); + return false; + } + } + } + + private configureNetSdkBuild(debugConfiguration: DockerDebugConfiguration, context: NetChooseBuildTypeContext): void { debugConfiguration.type = 'docker'; debugConfiguration.request = 'launch'; debugConfiguration.name = 'Docker .NET Launch'; debugConfiguration.platform = 'netCore'; - debugConfiguration.netCore = { - appProject: "${workspaceFolder}/dotnet.csproj" - }; debugConfiguration.preLaunchTask = 'dotnet-sdk-run: sdk-debug'; } } diff --git a/src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts b/src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts index 3418d05ab3..a8559bec05 100644 --- a/src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts +++ b/src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts @@ -3,10 +3,11 @@ * Licensed under the MIT License. See LICENSE.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IActionContext, IAzureQuickPickItem } from '@microsoft/vscode-azext-utils'; +import { IAzureQuickPickItem } from '@microsoft/vscode-azext-utils'; import * as vscode from 'vscode'; import { getFromWorkspaceState, updateWorkspaceState } from '../../../utils/StateUtils'; import { TelemetryPromptStep } from '../TelemetryPromptStep'; +import { NetChooseBuildTypeContext } from './netContainerBuild'; export const NetContainerBuildOptions = [ 'Use a Dockerfile', @@ -16,10 +17,6 @@ export const NetContainerBuildOptions = [ type NetContainerBuildOptionsTuple = typeof NetContainerBuildOptions; export type NetContainerBuildOptions = NetContainerBuildOptionsTuple[number]; -export interface NetChooseBuildTypeContext extends IActionContext { - containerBuildOptions?: NetContainerBuildOptions; -} - export class NetSdkChooseBuildStep extends TelemetryPromptStep { public async prompt(wizardContext: NetChooseBuildTypeContext): Promise { diff --git a/src/scaffolding/wizard/net/netContainerBuild.ts b/src/scaffolding/wizard/net/netContainerBuild.ts index 101727bc78..b95afa481d 100644 --- a/src/scaffolding/wizard/net/netContainerBuild.ts +++ b/src/scaffolding/wizard/net/netContainerBuild.ts @@ -5,7 +5,12 @@ import { AzureWizard, AzureWizardPromptStep, UserCancelledError } from '@microsoft/vscode-azext-utils'; import * as vscode from 'vscode'; -import { NetChooseBuildTypeContext, NetSdkChooseBuildStep } from './NetSdkChooseBuildStep'; +import { ScaffoldingWizardContext } from '../ScaffoldingWizardContext'; +import { NetContainerBuildOptions, NetSdkChooseBuildStep } from './NetSdkChooseBuildStep'; + +export interface NetChooseBuildTypeContext extends ScaffoldingWizardContext { + containerBuildOptions?: NetContainerBuildOptions; +} export async function netContainerBuild(wizardContext: Partial, apiInput?: NetChooseBuildTypeContext): Promise { if (!vscode.workspace.isTrusted) { @@ -13,7 +18,7 @@ export async function netContainerBuild(wizardContext: Partial[] = [ - new NetSdkChooseBuildStep(), + new NetSdkChooseBuildStep() ]; const wizard = new AzureWizard(wizardContext as NetChooseBuildTypeContext, { diff --git a/src/tasks/netSdk/NetSdkRunTaskProvider.ts b/src/tasks/netSdk/NetSdkRunTaskProvider.ts index 9931feecee..f5882d784d 100644 --- a/src/tasks/netSdk/NetSdkRunTaskProvider.ts +++ b/src/tasks/netSdk/NetSdkRunTaskProvider.ts @@ -39,7 +39,7 @@ export class NetSdkRunTaskProvider extends DockerTaskProvider { protected async executeTaskInternal(context: DockerTaskExecutionContext, task: Task): Promise { - const buildCommand = await this.helper.getNetSdkBuildCommand(context.actionContext); + const buildCommand = await this.helper.getNetSdkBuildCommand(context); await context.terminal.execAsyncInTerminal( buildCommand, { @@ -48,7 +48,7 @@ export class NetSdkRunTaskProvider extends DockerTaskProvider { } ); - const runCommand = await this.helper.getNetSdkRunCommand(context.actionContext); + const runCommand = await this.helper.getNetSdkRunCommand(context); await context.terminal.execAsyncInTerminal( runCommand, { diff --git a/src/tasks/netSdk/NetSdkTaskHelper.ts b/src/tasks/netSdk/NetSdkTaskHelper.ts index 286679ddec..d6be1708c7 100644 --- a/src/tasks/netSdk/NetSdkTaskHelper.ts +++ b/src/tasks/netSdk/NetSdkTaskHelper.ts @@ -4,18 +4,19 @@ *--------------------------------------------------------------------------------------------*/ import { IActionContext } from "@microsoft/vscode-azext-utils"; -import * as fse from 'fs-extra'; import * as os from 'os'; -import { WorkspaceFolder } from "vscode"; +import { WorkspaceFolder, l10n } from "vscode"; import { vsDbgInstallBasePath } from "../../debugging/netcore/VsDbgHelper"; import { ext } from "../../extensionVariables"; import { RunContainerBindMount, Shell, composeArgs, withArg, withNamedArg } from "../../runtimes/docker"; import { getDockerOSType } from "../../utils/osUtils"; +import { quickPickProjectFileItem } from "../../utils/quickPickFile"; import { quickPickWorkspaceFolder } from "../../utils/quickPickWorkspaceFolder"; import { DockerContainerVolume } from "../DockerRunTaskDefinitionBase"; import { getMounts } from "../DockerRunTaskProvider"; import { defaultVsCodeLabels } from "../TaskDefinitionBase"; -import { addVolumeWithoutConflicts } from "../TaskHelper"; +import { DockerTaskContext, DockerTaskExecutionContext, addVolumeWithoutConflicts } from "../TaskHelper"; +import { NetCoreTaskHelper } from "../netcore/NetCoreTaskHelper"; /** * Native architecture of the current machine in the RID format @@ -35,15 +36,17 @@ export const netSdkRunTaskSymbol = 'dotnet-sdk-run'; export class NetSdkTaskHelper { - public async getNetSdkBuildCommand(context: IActionContext) { + public async getNetSdkBuildCommand(context: DockerTaskExecutionContext) { const configuration = 'Debug'; // intentionally default to Debug configuration for phase 1 of this feature const imageTag = 'dev'; // intentionally default to dev tag for phase 1 of this feature // {@link https://github.com/dotnet/sdk-container-builds/issues/141} this could change in the future - const publishFlag = this.isWebApp ? '-p:PublishProfile=DefaultContainer' : '/t:PublishContainer'; - const folderName = await this.getFolderName(context); + const projPath = await this.inferProjPath(context); + const publishFlag = NetCoreTaskHelper.isWebApp(projPath) ? '-p:PublishProfile=DefaultContainer' : '/t:PublishContainer'; + + const folderName = await this.getFolderName(context.actionContext); const args = composeArgs( withArg('dotnet', 'publish'), @@ -59,9 +62,9 @@ export class NetSdkTaskHelper { return quotedArgs.join(' '); } - public async getNetSdkRunCommand(context: IActionContext): Promise { + public async getNetSdkRunCommand(context: DockerTaskExecutionContext): Promise { const client = await ext.runtimeManager.getClient(); - const folderName = await this.getFolderName(context); + const folderName = await this.getFolderName(context.actionContext); const command = await client.runContainer({ detached: true, @@ -82,11 +85,6 @@ export class NetSdkTaskHelper { return commandLine; } - private async isWebApp(): Promise { - const projectContents = await fse.readFile('${workspaceFolder}/dotnet.csproj'); - return /Sdk\s*=\s*"Microsoft\.NET\.Sdk\.Web"/ig.test(projectContents.toString()); - } - /** * This method normalizes the Docker OS type to match the .NET Core SDK conventions. * {@link https://learn.microsoft.com/en-us/dotnet/core/rid-catalog} @@ -133,6 +131,11 @@ export class NetSdkTaskHelper { addVolumeWithoutConflicts(volumes, debuggerVolume); return getMounts(volumes); } + + private async inferProjPath(context: DockerTaskContext): Promise { + const item = await quickPickProjectFileItem(context.actionContext, undefined, context.folder, l10n.t('No .NET project file (.csproj or .fsproj) could be found.')); + return item.absoluteFilePath; + } } export const netTaskHelper = new NetSdkTaskHelper(); From a054ac9840ca75df21731b5d3cefe36fde369461 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Thu, 1 Jun 2023 16:43:58 -0400 Subject: [PATCH 21/46] added debug helper --- src/debugging/DebugHelper.ts | 2 + .../DockerDebugConfigurationProvider.ts | 87 +++++++++---------- src/debugging/DockerPlatformHelper.ts | 6 +- src/debugging/netSdk/NetSdkDebugHelper.ts | 43 +++++++++ src/tasks/TaskHelper.ts | 3 +- src/tasks/netSdk/NetSdkTaskHelper.ts | 16 ++-- 6 files changed, 102 insertions(+), 55 deletions(-) create mode 100644 src/debugging/netSdk/NetSdkDebugHelper.ts diff --git a/src/debugging/DebugHelper.ts b/src/debugging/DebugHelper.ts index 024cf5cde6..df544874a4 100644 --- a/src/debugging/DebugHelper.ts +++ b/src/debugging/DebugHelper.ts @@ -12,6 +12,7 @@ import { DockerDebugConfiguration, DockerDebugConfigurationProvider } from './Do import { DockerPlatform } from './DockerPlatformHelper'; import { registerServerReadyAction } from './DockerServerReadyAction'; import { netCoreDebugHelper } from './netcore/NetCoreDebugHelper'; +import { netSdkDebugHelper } from './netSdk/NetSdkDebugHelper'; import { nodeDebugHelper } from './node/NodeDebugHelper'; import { pythonDebugHelper } from './python/PythonDebugHelper'; @@ -51,6 +52,7 @@ export function registerDebugProvider(ctx: ExtensionContext): void { netCore: netCoreDebugHelper, node: nodeDebugHelper, python: pythonDebugHelper, + netSdk: netSdkDebugHelper } ) ) diff --git a/src/debugging/DockerDebugConfigurationProvider.ts b/src/debugging/DockerDebugConfigurationProvider.ts index 122f9b1aa7..c9804d71d4 100644 --- a/src/debugging/DockerDebugConfigurationProvider.ts +++ b/src/debugging/DockerDebugConfigurationProvider.ts @@ -7,12 +7,12 @@ import { callWithTelemetryAndErrorHandling, IActionContext, registerEvent } from import { CancellationToken, commands, debug, DebugConfiguration, DebugConfigurationProvider, DebugSession, l10n, ProviderResult, workspace, WorkspaceFolder } from 'vscode'; import { CSPROJ_GLOB_PATTERN, DockerOrchestration } from '../constants'; import { ext } from '../extensionVariables'; -import { NetChooseBuildTypeContext, netContainerBuild } from '../scaffolding/wizard/net/netContainerBuild'; import { getAssociatedDockerRunTask } from '../tasks/TaskHelper'; import { resolveFilesOfPattern } from '../utils/quickPickFile'; import { DebugHelper, DockerDebugContext, ResolvedDebugConfiguration } from './DebugHelper'; import { DockerPlatform, getPlatform } from './DockerPlatformHelper'; import { NetCoreDockerDebugConfiguration } from './netcore/NetCoreDebugHelper'; +import { netSdkDebugHelper } from './netSdk/NetSdkDebugHelper'; import { NodeDockerDebugConfiguration } from './node/NodeDebugHelper'; export interface DockerDebugConfiguration extends NetCoreDockerDebugConfiguration, NodeDockerDebugConfiguration { @@ -44,7 +44,17 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi } public provideDebugConfigurations(folder: WorkspaceFolder | undefined, token?: CancellationToken): ProviderResult { + + // let's only do NET SDK for now + // return callWithTelemetryAndErrorHandling( + // 'docker-provideDebugConfigurations', //TODO: change this later + // async (actionContext: IActionContext) => { + // return this.handleEmptyDebugConfig(folder, actionContext); + // } + // ); + return []; + } public resolveDebugConfiguration(folder: WorkspaceFolder | undefined, debugConfiguration: DockerDebugConfiguration, token?: CancellationToken): ProviderResult { @@ -64,16 +74,11 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi } } - // if the user has not created a launch.json yet, we will help them do that if (debugConfiguration.type === undefined && debugConfiguration.request === undefined && debugConfiguration.name === undefined) { - - const useSDKBuild = await this.handleEmptyDebugConfig(debugConfiguration, folder, actionContext); - - if (!useSDKBuild) { // TODO: automatically launch right after scaffolding - return undefined; - } + const netConfig = await this.handleEmptyDebugConfig(folder, actionContext); + this.copyDebugConfiguration(netConfig[0], debugConfiguration); } if (!debugConfiguration.request) { @@ -166,48 +171,42 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi } } + // write a method that takes in two DockerDebugConfiguration and copy the properties from the second one to the first one + private copyDebugConfiguration(from: DockerDebugConfiguration, to: DockerDebugConfiguration): void { + for (const key of Object.keys(from)) { + if (from[key] !== undefined) { + to[key] = from[key]; + } + } + } + /** - * If the user has an empty debug launch.json, then we will help them either scaffold docker files or configure for .NET Core - * @returns true if the user should use .NET SDK build - * false if the user should scaffold docker files + * If the user has an empty debug launch.json, then we will: + * 1. check if it's a .NET Core project, if so, we will provide .NET Core debug configurations + * 2. otherwise, we will scaffold docker files */ - private async handleEmptyDebugConfig(debugConfiguration: DockerDebugConfiguration, folder: WorkspaceFolder, actionContext: IActionContext): Promise { + public async handleEmptyDebugConfig(folder: WorkspaceFolder, actionContext: IActionContext): Promise { - // Get a list of all the csproj files in the workspace - const csProjUris = await resolveFilesOfPattern(folder, [CSPROJ_GLOB_PATTERN]); + // NOTE: we can not determine which helper it is by DockerDebugContext, so we need to basically check the + // type of files inside the folder here. let's only do it for .NET Core for now, we can add more later - // If there are no csproj files, then we assume it's not a .NET Core project -> scaffold docker files - if (!csProjUris || csProjUris.length === 0) { - await commands.executeCommand('vscode-docker.configure'); - return false; + // check if it's a .NET Core project + const csProjUris = await resolveFilesOfPattern(folder, [CSPROJ_GLOB_PATTERN]); + if (csProjUris) { + return await netSdkDebugHelper.provideDebugConfigurations( + { + actionContext, + dockerfile: undefined, + folder: folder + }, + { + appProject: csProjUris[0].absoluteFilePath, + }); } - // If there are one or more .csproj file, then we assume it's a .NET Core project -> configure for .NET Core else { - const netCoreBuildContext: NetChooseBuildTypeContext = { - ...actionContext, - scaffoldType: 'debugging', - workspaceFolder: folder, - }; - - await netContainerBuild(netCoreBuildContext); - - if (netCoreBuildContext?.containerBuildOptions === 'Use .NET SDK') { - // set up for .NET SDK build - this.configureNetSdkBuild(debugConfiguration, netCoreBuildContext); - return true; - } - else { - await commands.executeCommand('vscode-docker.configure'); - return false; - } + // scaffold docker files + await commands.executeCommand('vscode-docker.configure'); + return []; } } - - private configureNetSdkBuild(debugConfiguration: DockerDebugConfiguration, context: NetChooseBuildTypeContext): void { - debugConfiguration.type = 'docker'; - debugConfiguration.request = 'launch'; - debugConfiguration.name = 'Docker .NET Launch'; - debugConfiguration.platform = 'netCore'; - debugConfiguration.preLaunchTask = 'dotnet-sdk-run: sdk-debug'; - } } diff --git a/src/debugging/DockerPlatformHelper.ts b/src/debugging/DockerPlatformHelper.ts index b204d2914b..542ce824fe 100644 --- a/src/debugging/DockerPlatformHelper.ts +++ b/src/debugging/DockerPlatformHelper.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See LICENSE.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -export type DockerPlatform = 'netCore' | 'node' | 'python'; +export type DockerPlatform = 'netCore' | 'node' | 'python' | 'netSdk'; interface DockerPlatformConfiguration { platform?: DockerPlatform; @@ -13,7 +13,9 @@ interface DockerPlatformConfiguration { } export function getPlatform(configuration: T): DockerPlatform | undefined { - if (configuration.platform === 'netCore' || configuration.netCore !== undefined) { + if (configuration.platform === 'netSdk') { + return 'netSdk'; + } else if (configuration.platform === 'netCore' || configuration.netCore !== undefined) { return 'netCore'; } else if (configuration.platform === 'node' || configuration.node !== undefined) { return 'node'; diff --git a/src/debugging/netSdk/NetSdkDebugHelper.ts b/src/debugging/netSdk/NetSdkDebugHelper.ts new file mode 100644 index 0000000000..70b33c6d49 --- /dev/null +++ b/src/debugging/netSdk/NetSdkDebugHelper.ts @@ -0,0 +1,43 @@ +import { commands } from "vscode"; +import { NetChooseBuildTypeContext, netContainerBuild } from "../../scaffolding/wizard/net/netContainerBuild"; +import { unresolveWorkspaceFolder } from "../../utils/resolveVariables"; +import { DockerDebugScaffoldContext } from "../DebugHelper"; +import { DockerDebugConfiguration } from "../DockerDebugConfigurationProvider"; +import { NetCoreDebugHelper, NetCoreDebugScaffoldingOptions } from "../netcore/NetCoreDebugHelper"; + +export class NetSdkDebugHelper extends NetCoreDebugHelper { + + public async provideDebugConfigurations(context: DockerDebugScaffoldContext, options?: NetCoreDebugScaffoldingOptions): Promise { + + const providers: DockerDebugConfiguration[] = []; + + const netCoreBuildContext: NetChooseBuildTypeContext = { + ...context.actionContext, + scaffoldType: 'debugging', + workspaceFolder: context.folder, + }; + + await netContainerBuild(netCoreBuildContext); + + if (netCoreBuildContext?.containerBuildOptions === 'Use .NET SDK') { + providers.push({ + platform: 'netCore', + name: 'Docker .NET Launch', + type: 'docker', + request: 'launch', + netCore: { + appProject: unresolveWorkspaceFolder(options.appProject, context.folder), + enableDebugging: true, + }, + preLaunchTask: 'dotnet-sdk-run: sdk-debug', + }); + } else { + await commands.executeCommand('vscode-docker.configure'); + } + + return providers; + } + +} + +export const netSdkDebugHelper = new NetSdkDebugHelper(); diff --git a/src/tasks/TaskHelper.ts b/src/tasks/TaskHelper.ts index d03a079ed6..53732b3c55 100644 --- a/src/tasks/TaskHelper.ts +++ b/src/tasks/TaskHelper.ts @@ -79,7 +79,8 @@ export function registerTaskProviders(ctx: ExtensionContext): void { const helpers = { netCore: netCoreTaskHelper, node: nodeTaskHelper, - python: pythonTaskHelper + python: pythonTaskHelper, + netSdk: undefined }; ctx.subscriptions.push( diff --git a/src/tasks/netSdk/NetSdkTaskHelper.ts b/src/tasks/netSdk/NetSdkTaskHelper.ts index d6be1708c7..b641dbed67 100644 --- a/src/tasks/netSdk/NetSdkTaskHelper.ts +++ b/src/tasks/netSdk/NetSdkTaskHelper.ts @@ -15,7 +15,7 @@ import { quickPickWorkspaceFolder } from "../../utils/quickPickWorkspaceFolder"; import { DockerContainerVolume } from "../DockerRunTaskDefinitionBase"; import { getMounts } from "../DockerRunTaskProvider"; import { defaultVsCodeLabels } from "../TaskDefinitionBase"; -import { DockerTaskContext, DockerTaskExecutionContext, addVolumeWithoutConflicts } from "../TaskHelper"; +import { DockerTaskExecutionContext, addVolumeWithoutConflicts } from "../TaskHelper"; import { NetCoreTaskHelper } from "../netcore/NetCoreTaskHelper"; /** @@ -43,7 +43,7 @@ export class NetSdkTaskHelper { // {@link https://github.com/dotnet/sdk-container-builds/issues/141} this could change in the future - const projPath = await this.inferProjPath(context); + const projPath = await this.inferProjPath(context.actionContext, context.folder); const publishFlag = NetCoreTaskHelper.isWebApp(projPath) ? '-p:PublishProfile=DefaultContainer' : '/t:PublishContainer'; const folderName = await this.getFolderName(context.actionContext); @@ -85,6 +85,11 @@ export class NetSdkTaskHelper { return commandLine; } + public async inferProjPath(context: IActionContext, folder: WorkspaceFolder): Promise { + const item = await quickPickProjectFileItem(context, undefined, folder, l10n.t('No .NET project file (.csproj or .fsproj) could be found.')); + return item.absoluteFilePath; + } + /** * This method normalizes the Docker OS type to match the .NET Core SDK conventions. * {@link https://learn.microsoft.com/en-us/dotnet/core/rid-catalog} @@ -111,7 +116,7 @@ export class NetSdkTaskHelper { } } - private async getFolderName(context: IActionContext): Promise { + public async getFolderName(context: IActionContext): Promise { return await quickPickWorkspaceFolder( context, `Unable to determine task scope to execute task ${netSdkRunTaskSymbol}. Please open a workspace folder.` @@ -131,11 +136,6 @@ export class NetSdkTaskHelper { addVolumeWithoutConflicts(volumes, debuggerVolume); return getMounts(volumes); } - - private async inferProjPath(context: DockerTaskContext): Promise { - const item = await quickPickProjectFileItem(context.actionContext, undefined, context.folder, l10n.t('No .NET project file (.csproj or .fsproj) could be found.')); - return item.absoluteFilePath; - } } export const netTaskHelper = new NetSdkTaskHelper(); From b113ce7886ed2961fd91f939a556259bf3ce0b73 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Fri, 2 Jun 2023 11:33:17 -0400 Subject: [PATCH 22/46] small tweaks to handle null cases --- .../DockerDebugConfigurationProvider.ts | 36 +++++++++++-------- src/debugging/netSdk/NetSdkDebugHelper.ts | 2 +- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/debugging/DockerDebugConfigurationProvider.ts b/src/debugging/DockerDebugConfigurationProvider.ts index c9804d71d4..c49d579f51 100644 --- a/src/debugging/DockerDebugConfigurationProvider.ts +++ b/src/debugging/DockerDebugConfigurationProvider.ts @@ -46,14 +46,12 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi public provideDebugConfigurations(folder: WorkspaceFolder | undefined, token?: CancellationToken): ProviderResult { // let's only do NET SDK for now - // return callWithTelemetryAndErrorHandling( - // 'docker-provideDebugConfigurations', //TODO: change this later - // async (actionContext: IActionContext) => { - // return this.handleEmptyDebugConfig(folder, actionContext); - // } - // ); - - return []; + return callWithTelemetryAndErrorHandling( + 'docker-provideDebugConfigurations', //TODO: change this later + async (actionContext: IActionContext) => { + return this.handleEmptyDebugConfig(folder, actionContext); + } + ); } @@ -77,8 +75,12 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi if (debugConfiguration.type === undefined && debugConfiguration.request === undefined && debugConfiguration.name === undefined) { - const netConfig = await this.handleEmptyDebugConfig(folder, actionContext); - this.copyDebugConfiguration(netConfig[0], debugConfiguration); + const newlyCreatedDebugConfig = await this.handleEmptyDebugConfig(folder, actionContext); + this.copyDebugConfiguration(newlyCreatedDebugConfig, debugConfiguration); + // if there is no debugConfiguration, we should return undefined to exit the debug session + if (newlyCreatedDebugConfig.length === 0) { + return undefined; + } } if (!debugConfiguration.request) { @@ -172,7 +174,12 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi } // write a method that takes in two DockerDebugConfiguration and copy the properties from the second one to the first one - private copyDebugConfiguration(from: DockerDebugConfiguration, to: DockerDebugConfiguration): void { + private copyDebugConfiguration(fromArray: DockerDebugConfiguration[], to: DockerDebugConfiguration): void { + if (!fromArray || !fromArray[0]) { + return; + } + + const from = fromArray[0]; for (const key of Object.keys(from)) { if (from[key] !== undefined) { to[key] = from[key]; @@ -185,7 +192,7 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi * 1. check if it's a .NET Core project, if so, we will provide .NET Core debug configurations * 2. otherwise, we will scaffold docker files */ - public async handleEmptyDebugConfig(folder: WorkspaceFolder, actionContext: IActionContext): Promise { + private async handleEmptyDebugConfig(folder: WorkspaceFolder, actionContext: IActionContext): Promise { // NOTE: we can not determine which helper it is by DockerDebugContext, so we need to basically check the // type of files inside the folder here. let's only do it for .NET Core for now, we can add more later @@ -200,11 +207,12 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi folder: folder }, { - appProject: csProjUris[0].absoluteFilePath, + appProject: csProjUris[0]?.absoluteFilePath || '', }); } + // TODO: {potentially} in the future, we can add more support for ambient tasks for other types of projects else { - // scaffold docker files + // for now, we scaffold docker files await commands.executeCommand('vscode-docker.configure'); return []; } diff --git a/src/debugging/netSdk/NetSdkDebugHelper.ts b/src/debugging/netSdk/NetSdkDebugHelper.ts index 70b33c6d49..4c7d0e1d15 100644 --- a/src/debugging/netSdk/NetSdkDebugHelper.ts +++ b/src/debugging/netSdk/NetSdkDebugHelper.ts @@ -21,10 +21,10 @@ export class NetSdkDebugHelper extends NetCoreDebugHelper { if (netCoreBuildContext?.containerBuildOptions === 'Use .NET SDK') { providers.push({ - platform: 'netCore', name: 'Docker .NET Launch', type: 'docker', request: 'launch', + platform: 'netSdk', netCore: { appProject: unresolveWorkspaceFolder(options.appProject, context.folder), enableDebugging: true, From edf133850062459abde5733e89c15b9a8c5d4019 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Fri, 2 Jun 2023 12:04:23 -0400 Subject: [PATCH 23/46] add appOutput override to fix dotnet project name bug --- src/debugging/netSdk/NetSdkDebugHelper.ts | 5 +++++ src/debugging/netcore/NetCoreDebugHelper.ts | 10 +++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/debugging/netSdk/NetSdkDebugHelper.ts b/src/debugging/netSdk/NetSdkDebugHelper.ts index 4c7d0e1d15..fd497e3631 100644 --- a/src/debugging/netSdk/NetSdkDebugHelper.ts +++ b/src/debugging/netSdk/NetSdkDebugHelper.ts @@ -28,6 +28,7 @@ export class NetSdkDebugHelper extends NetCoreDebugHelper { netCore: { appProject: unresolveWorkspaceFolder(options.appProject, context.folder), enableDebugging: true, + appOutput: this.getAppOutput(context), }, preLaunchTask: 'dotnet-sdk-run: sdk-debug', }); @@ -38,6 +39,10 @@ export class NetSdkDebugHelper extends NetCoreDebugHelper { return providers; } + private getAppOutput(context: DockerDebugScaffoldContext): string { + const folderName = context.folder.name || 'dotnet'; + return `${folderName}.dll`; + } } export const netSdkDebugHelper = new NetSdkDebugHelper(); diff --git a/src/debugging/netcore/NetCoreDebugHelper.ts b/src/debugging/netcore/NetCoreDebugHelper.ts index c992b9f834..804d631844 100644 --- a/src/debugging/netcore/NetCoreDebugHelper.ts +++ b/src/debugging/netcore/NetCoreDebugHelper.ts @@ -6,9 +6,9 @@ import { DialogResponses, IActionContext, UserCancelledError } from '@microsoft/vscode-azext-utils'; import * as fse from 'fs-extra'; import * as path from 'path'; -import { DebugConfiguration, l10n, MessageItem, ProgressLocation, window } from 'vscode'; +import { DebugConfiguration, MessageItem, ProgressLocation, l10n, window } from 'vscode'; import { ext } from '../../extensionVariables'; -import { CommandLineArgs, composeArgs, ContainerOS, VoidCommandResponse, withArg, withQuotedArg } from '../../runtimes/docker'; +import { CommandLineArgs, ContainerOS, VoidCommandResponse, composeArgs, withArg, withQuotedArg } from '../../runtimes/docker'; import { NetCoreTaskHelper, NetCoreTaskOptions } from '../../tasks/netcore/NetCoreTaskHelper'; import { ContainerTreeItem } from '../../tree/containers/ContainerTreeItem'; import { getNetCoreProjectInfo } from '../../utils/netCoreUtils'; @@ -16,10 +16,10 @@ import { getDockerOSType, isArm64Mac } from '../../utils/osUtils'; import { pathNormalize } from '../../utils/pathNormalize'; import { PlatformOS } from '../../utils/platform'; import { unresolveWorkspaceFolder } from '../../utils/resolveVariables'; -import { DebugHelper, DockerDebugContext, DockerDebugScaffoldContext, inferContainerName, ResolvedDebugConfiguration, resolveDockerServerReadyAction } from '../DebugHelper'; +import { DebugHelper, DockerDebugContext, DockerDebugScaffoldContext, ResolvedDebugConfiguration, inferContainerName, resolveDockerServerReadyAction } from '../DebugHelper'; import { DockerAttachConfiguration, DockerDebugConfiguration } from '../DockerDebugConfigurationProvider'; import { exportCertificateIfNecessary, getHostSecretsFolders, trustCertificateIfNecessary } from './AspNetSslHelper'; -import { installDebuggersIfNecessary, vsDbgInstallBasePath, VsDbgType } from './VsDbgHelper'; +import { VsDbgType, installDebuggersIfNecessary, vsDbgInstallBasePath } from './VsDbgHelper'; export interface NetCoreDebugOptions extends NetCoreTaskOptions { appOutput?: string; @@ -68,7 +68,7 @@ export class NetCoreDebugHelper implements DebugHelper { debugConfiguration.netCore.appProject = await NetCoreTaskHelper.inferAppProject(context, debugConfiguration.netCore); // This method internally checks the user-defined input first const { configureSsl, containerName, platformOS } = await this.loadExternalInfo(context, debugConfiguration); - const appOutput = await this.inferAppOutput(debugConfiguration.netCore); + const appOutput = debugConfiguration.netCore?.appOutput || await this.inferAppOutput(debugConfiguration.netCore); if (context.cancellationToken && context.cancellationToken.isCancellationRequested) { // inferAppOutput is slow, give a chance to cancel return undefined; From 8920a8fe50269383944dc19e0c31c13778e60919 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Mon, 5 Jun 2023 09:37:07 -0400 Subject: [PATCH 24/46] fixed image not running if foldername has special chars --- src/tasks/netSdk/NetSdkTaskHelper.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/tasks/netSdk/NetSdkTaskHelper.ts b/src/tasks/netSdk/NetSdkTaskHelper.ts index b641dbed67..c16711394b 100644 --- a/src/tasks/netSdk/NetSdkTaskHelper.ts +++ b/src/tasks/netSdk/NetSdkTaskHelper.ts @@ -9,13 +9,14 @@ import { WorkspaceFolder, l10n } from "vscode"; import { vsDbgInstallBasePath } from "../../debugging/netcore/VsDbgHelper"; import { ext } from "../../extensionVariables"; import { RunContainerBindMount, Shell, composeArgs, withArg, withNamedArg } from "../../runtimes/docker"; +import { getValidImageName } from "../../utils/getValidImageName"; import { getDockerOSType } from "../../utils/osUtils"; import { quickPickProjectFileItem } from "../../utils/quickPickFile"; import { quickPickWorkspaceFolder } from "../../utils/quickPickWorkspaceFolder"; import { DockerContainerVolume } from "../DockerRunTaskDefinitionBase"; import { getMounts } from "../DockerRunTaskProvider"; import { defaultVsCodeLabels } from "../TaskDefinitionBase"; -import { DockerTaskExecutionContext, addVolumeWithoutConflicts } from "../TaskHelper"; +import { DockerTaskExecutionContext, addVolumeWithoutConflicts, getDefaultContainerName, getDefaultImageName } from "../TaskHelper"; import { NetCoreTaskHelper } from "../netcore/NetCoreTaskHelper"; /** @@ -33,17 +34,16 @@ export type RidCpuArchitecture = | string; export const netSdkRunTaskSymbol = 'dotnet-sdk-run'; +const imageTag = 'dev'; // intentionally default to dev tag for phase 1 of this feature export class NetSdkTaskHelper { public async getNetSdkBuildCommand(context: DockerTaskExecutionContext) { const configuration = 'Debug'; // intentionally default to Debug configuration for phase 1 of this feature - const imageTag = 'dev'; // intentionally default to dev tag for phase 1 of this feature - - // {@link https://github.com/dotnet/sdk-container-builds/issues/141} this could change in the future const projPath = await this.inferProjPath(context.actionContext, context.folder); + // {@link https://github.com/dotnet/sdk-container-builds/issues/141} this could change in the future const publishFlag = NetCoreTaskHelper.isWebApp(projPath) ? '-p:PublishProfile=DefaultContainer' : '/t:PublishContainer'; const folderName = await this.getFolderName(context.actionContext); @@ -54,7 +54,7 @@ export class NetSdkTaskHelper { withNamedArg('--arch', await this.normalizeArchitectureToRid()), withArg(publishFlag), withNamedArg('--configuration', configuration), - withNamedArg('-p:ContainerImageName', folderName.name, { assignValue: true }), + withNamedArg('-p:ContainerImageName', getValidImageName(folderName.name), { assignValue: true }), withNamedArg('-p:ContainerImageTag', imageTag, { assignValue: true }) )(); @@ -69,10 +69,10 @@ export class NetSdkTaskHelper { const command = await client.runContainer({ detached: true, publishAllPorts: true, - name: `${folderName.name}-dev`, + name: getDefaultContainerName(folderName.name, imageTag), environmentVariables: {}, removeOnExit: true, - imageRef: `${folderName.name}:dev`, + imageRef: getDefaultImageName(folderName.name, imageTag), labels: defaultVsCodeLabels, mounts: await this.getMounts(), customOptions: '--expose 8080', @@ -86,8 +86,8 @@ export class NetSdkTaskHelper { } public async inferProjPath(context: IActionContext, folder: WorkspaceFolder): Promise { - const item = await quickPickProjectFileItem(context, undefined, folder, l10n.t('No .NET project file (.csproj or .fsproj) could be found.')); - return item.absoluteFilePath; + const item = await quickPickProjectFileItem(context, undefined, folder, l10n.t('No .csproj file could be found.')); + return item.absoluteFilePath || ''; } /** From def78b988c68ba8600889c76038df8cd12a9db45 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Mon, 5 Jun 2023 10:23:35 -0400 Subject: [PATCH 25/46] changed task name and altered schema --- package.json | 2 +- src/debugging/netSdk/NetSdkDebugHelper.ts | 7 ++----- src/tasks/TaskHelper.ts | 4 ++-- src/tasks/netSdk/NetSdkRunTaskProvider.ts | 18 ++++++++++-------- src/tasks/netSdk/NetSdkTaskHelper.ts | 4 ++-- 5 files changed, 17 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index f49d67561f..09d2b0d0db 100644 --- a/package.json +++ b/package.json @@ -1508,7 +1508,7 @@ ] }, { - "type": "dotnet-sdk-run" + "type": "dotnet-container-sdk" } ], "languages": [ diff --git a/src/debugging/netSdk/NetSdkDebugHelper.ts b/src/debugging/netSdk/NetSdkDebugHelper.ts index fd497e3631..c6c0f42ffc 100644 --- a/src/debugging/netSdk/NetSdkDebugHelper.ts +++ b/src/debugging/netSdk/NetSdkDebugHelper.ts @@ -21,16 +21,13 @@ export class NetSdkDebugHelper extends NetCoreDebugHelper { if (netCoreBuildContext?.containerBuildOptions === 'Use .NET SDK') { providers.push({ - name: 'Docker .NET Launch', + name: 'Docker .NET Container SDK Launch', type: 'docker', request: 'launch', - platform: 'netSdk', + preLaunchTask: 'dotnet-container-sdk: debug', netCore: { appProject: unresolveWorkspaceFolder(options.appProject, context.folder), - enableDebugging: true, - appOutput: this.getAppOutput(context), }, - preLaunchTask: 'dotnet-sdk-run: sdk-debug', }); } else { await commands.executeCommand('vscode-docker.configure'); diff --git a/src/tasks/TaskHelper.ts b/src/tasks/TaskHelper.ts index 53732b3c55..241d767a59 100644 --- a/src/tasks/TaskHelper.ts +++ b/src/tasks/TaskHelper.ts @@ -26,7 +26,7 @@ import { netCoreTaskHelper } from './netcore/NetCoreTaskHelper'; import { nodeTaskHelper } from './node/NodeTaskHelper'; import { pythonTaskHelper } from './python/PythonTaskHelper'; -export type DockerTaskProviderName = 'docker-build' | 'docker-run' | 'docker-compose' | 'dotnet-sdk-run'; +export type DockerTaskProviderName = 'docker-build' | 'docker-run' | 'docker-compose' | 'dotnet-container-sdk'; export interface DockerTaskContext { folder: WorkspaceFolder; @@ -106,7 +106,7 @@ export function registerTaskProviders(ctx: ExtensionContext): void { ctx.subscriptions.push( tasks.registerTaskProvider( - 'dotnet-sdk-run', + 'dotnet-container-sdk', new NetSdkRunTaskProvider(netTaskHelper) ) ); diff --git a/src/tasks/netSdk/NetSdkRunTaskProvider.ts b/src/tasks/netSdk/NetSdkRunTaskProvider.ts index f5882d784d..439e8588de 100644 --- a/src/tasks/netSdk/NetSdkRunTaskProvider.ts +++ b/src/tasks/netSdk/NetSdkRunTaskProvider.ts @@ -9,36 +9,37 @@ import { DockerTaskProvider } from '../DockerTaskProvider'; import { DockerTaskExecutionContext } from '../TaskHelper'; import { NetSdkTaskHelper, netSdkRunTaskSymbol } from './NetSdkTaskHelper'; +const netSdkDebugTaskName = 'debug'; export class NetSdkRunTaskProvider extends DockerTaskProvider { public constructor(protected readonly helper: NetSdkTaskHelper) { super(netSdkRunTaskSymbol, undefined); } provideTasks(token: CancellationToken): ProviderResult { - // provide the bare minimum: a task that will show up in the command palette - const problemMatchers = ["$myProblemMatcher"]; + // we need to initialize a task first so we can pass it into `DockerPseudoterminal` const task = new Task( { type: netSdkRunTaskSymbol }, TaskScope.Workspace, - 'sdk-debug', - netSdkRunTaskSymbol, - problemMatchers + netSdkDebugTaskName, + netSdkRunTaskSymbol ); return [ new Task( { type: netSdkRunTaskSymbol }, TaskScope.Workspace, - 'sdk-debug', + netSdkDebugTaskName, netSdkRunTaskSymbol, - new CustomExecution(async (resolvedDefinition: TaskDefinition) => Promise.resolve(new DockerPseudoterminal(this, task, resolvedDefinition))), - problemMatchers + new CustomExecution( + async (resolvedDefinition: TaskDefinition) => Promise.resolve(new DockerPseudoterminal(this, task, resolvedDefinition)) + ), ) ]; } protected async executeTaskInternal(context: DockerTaskExecutionContext, task: Task): Promise { + // use dotnet to build the image const buildCommand = await this.helper.getNetSdkBuildCommand(context); await context.terminal.execAsyncInTerminal( buildCommand, @@ -48,6 +49,7 @@ export class NetSdkRunTaskProvider extends DockerTaskProvider { } ); + // use docker run to run the image const runCommand = await this.helper.getNetSdkRunCommand(context); await context.terminal.execAsyncInTerminal( runCommand, diff --git a/src/tasks/netSdk/NetSdkTaskHelper.ts b/src/tasks/netSdk/NetSdkTaskHelper.ts index c16711394b..ba306c3eb6 100644 --- a/src/tasks/netSdk/NetSdkTaskHelper.ts +++ b/src/tasks/netSdk/NetSdkTaskHelper.ts @@ -33,7 +33,7 @@ export type RidCpuArchitecture = | 's390x' | string; -export const netSdkRunTaskSymbol = 'dotnet-sdk-run'; +export const netSdkRunTaskSymbol = 'dotnet-container-sdk'; const imageTag = 'dev'; // intentionally default to dev tag for phase 1 of this feature export class NetSdkTaskHelper { @@ -41,8 +41,8 @@ export class NetSdkTaskHelper { public async getNetSdkBuildCommand(context: DockerTaskExecutionContext) { const configuration = 'Debug'; // intentionally default to Debug configuration for phase 1 of this feature - const projPath = await this.inferProjPath(context.actionContext, context.folder); + // {@link https://github.com/dotnet/sdk-container-builds/issues/141} this could change in the future const publishFlag = NetCoreTaskHelper.isWebApp(projPath) ? '-p:PublishProfile=DefaultContainer' : '/t:PublishContainer'; From 8b5fedddcb7e7444ecb78be0bb3b5447cbc01b12 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Mon, 5 Jun 2023 10:46:40 -0400 Subject: [PATCH 26/46] determine helper from prelaunchtask instead of `platform` --- src/debugging/DockerDebugConfigurationProvider.ts | 12 ++++++------ src/debugging/DockerPlatformHelper.ts | 3 ++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/debugging/DockerDebugConfigurationProvider.ts b/src/debugging/DockerDebugConfigurationProvider.ts index c49d579f51..71995e260c 100644 --- a/src/debugging/DockerDebugConfigurationProvider.ts +++ b/src/debugging/DockerDebugConfigurationProvider.ts @@ -45,7 +45,6 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi public provideDebugConfigurations(folder: WorkspaceFolder | undefined, token?: CancellationToken): ProviderResult { - // let's only do NET SDK for now return callWithTelemetryAndErrorHandling( 'docker-provideDebugConfigurations', //TODO: change this later async (actionContext: IActionContext) => { @@ -56,7 +55,6 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi } public resolveDebugConfiguration(folder: WorkspaceFolder | undefined, debugConfiguration: DockerDebugConfiguration, token?: CancellationToken): ProviderResult { - return callWithTelemetryAndErrorHandling( debugConfiguration.request === 'attach' ? 'docker-attach' : 'docker-launch', async (actionContext: IActionContext) => { @@ -173,7 +171,9 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi } } - // write a method that takes in two DockerDebugConfiguration and copy the properties from the second one to the first one + /** + * Copies the first debug configuration from the array to the second one. + */ private copyDebugConfiguration(fromArray: DockerDebugConfiguration[], to: DockerDebugConfiguration): void { if (!fromArray || !fromArray[0]) { return; @@ -194,8 +194,8 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi */ private async handleEmptyDebugConfig(folder: WorkspaceFolder, actionContext: IActionContext): Promise { - // NOTE: we can not determine which helper it is by DockerDebugContext, so we need to basically check the - // type of files inside the folder here. let's only do it for .NET Core for now, we can add more later + // NOTE: We can not determine the language from `DockerDebugContext`, so we need to check the + // type of files inside the folder here to determine the language. // check if it's a .NET Core project const csProjUris = await resolveFilesOfPattern(folder, [CSPROJ_GLOB_PATTERN]); @@ -210,11 +210,11 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi appProject: csProjUris[0]?.absoluteFilePath || '', }); } - // TODO: {potentially} in the future, we can add more support for ambient tasks for other types of projects else { // for now, we scaffold docker files await commands.executeCommand('vscode-docker.configure'); return []; } + // TODO: (potentially) in the future, we can add more support for ambient tasks for other types of projects } } diff --git a/src/debugging/DockerPlatformHelper.ts b/src/debugging/DockerPlatformHelper.ts index 542ce824fe..9513e9c6d0 100644 --- a/src/debugging/DockerPlatformHelper.ts +++ b/src/debugging/DockerPlatformHelper.ts @@ -10,10 +10,11 @@ interface DockerPlatformConfiguration { netCore?: unknown; node?: unknown; python?: unknown; + preLaunchTask?: string; } export function getPlatform(configuration: T): DockerPlatform | undefined { - if (configuration.platform === 'netSdk') { + if (configuration.preLaunchTask === 'dotnet-container-sdk: debug' && configuration.netCore !== undefined) { return 'netSdk'; } else if (configuration.platform === 'netCore' || configuration.netCore !== undefined) { return 'netCore'; From 132f252bd8e845634f72d6ef8d3147728ab3ff21 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Mon, 5 Jun 2023 12:05:08 -0400 Subject: [PATCH 27/46] move helper methods to taskhelper --- src/tasks/DockerRunTaskProvider.ts | 16 ++-------------- src/tasks/DockerTaskProvider.ts | 2 +- src/tasks/TaskHelper.ts | 13 ++++++++++++- src/tasks/netSdk/NetSdkTaskHelper.ts | 7 +++---- 4 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/tasks/DockerRunTaskProvider.ts b/src/tasks/DockerRunTaskProvider.ts index 0cfd4d7cd0..b4924dcdff 100644 --- a/src/tasks/DockerRunTaskProvider.ts +++ b/src/tasks/DockerRunTaskProvider.ts @@ -6,14 +6,13 @@ import { l10n, Task } from 'vscode'; import { DockerPlatform } from '../debugging/DockerPlatformHelper'; import { ext } from '../extensionVariables'; -import { RunContainerBindMount } from '../runtimes/docker'; import { cloneObject } from '../utils/cloneObject'; -import { DockerContainerVolume, DockerRunOptions } from './DockerRunTaskDefinitionBase'; +import { DockerRunOptions } from './DockerRunTaskDefinitionBase'; import { DockerTaskProvider } from './DockerTaskProvider'; import { NetCoreRunTaskDefinition } from './netcore/NetCoreTaskHelper'; import { NodeRunTaskDefinition } from './node/NodeTaskHelper'; import { defaultVsCodeLabels, getAggregateLabels } from './TaskDefinitionBase'; -import { DockerRunTaskContext, getAssociatedDockerBuildTask, TaskHelper, throwIfCancellationRequested } from './TaskHelper'; +import { DockerRunTaskContext, getAssociatedDockerBuildTask, getMounts, TaskHelper, throwIfCancellationRequested } from './TaskHelper'; export interface DockerRunTaskDefinition extends NetCoreRunTaskDefinition, NodeRunTaskDefinition { label?: string; @@ -93,14 +92,3 @@ export class DockerRunTaskProvider extends DockerTaskProvider { } } } - -export function getMounts(volumes?: DockerContainerVolume[]): RunContainerBindMount[] | undefined { - return volumes?.map(v => { - return { - source: v.localPath, - destination: v.containerPath, - readOnly: v.permissions === 'ro' || (v.permissions as unknown === 'ro,z'), // Maintain compatibility with old `ro,z` option as much as possible - type: 'bind', - }; - }); -} diff --git a/src/tasks/DockerTaskProvider.ts b/src/tasks/DockerTaskProvider.ts index a3929709a0..dea5e7b33c 100644 --- a/src/tasks/DockerTaskProvider.ts +++ b/src/tasks/DockerTaskProvider.ts @@ -15,7 +15,7 @@ import { DockerTaskExecutionContext, DockerTaskProviderName, TaskHelper } from ' export abstract class DockerTaskProvider implements TaskProvider { - protected constructor(private readonly telemetryName: DockerTaskProviderName, protected readonly helpers?: { [key in DockerPlatform]: TaskHelper }) { } + protected constructor(private readonly telemetryName: DockerTaskProviderName, protected readonly helpers: { [key in DockerPlatform]: TaskHelper }) { } public provideTasks(token?: CancellationToken): ProviderResult { return []; // Intentionally empty, so that resolveTask gets used diff --git a/src/tasks/TaskHelper.ts b/src/tasks/TaskHelper.ts index 241d767a59..2cd98dd169 100644 --- a/src/tasks/TaskHelper.ts +++ b/src/tasks/TaskHelper.ts @@ -9,7 +9,7 @@ import { CancellationToken, ConfigurationTarget, ExtensionContext, QuickPickItem import { DebugConfigurationBase } from '../debugging/DockerDebugConfigurationBase'; import { DockerDebugConfiguration } from '../debugging/DockerDebugConfigurationProvider'; import { DockerPlatform } from '../debugging/DockerPlatformHelper'; -import { ContainerPlatform } from '../runtimes/docker'; +import { ContainerPlatform, RunContainerBindMount } from '../runtimes/docker'; import { getValidImageName, getValidImageNameWithTag } from '../utils/getValidImageName'; import { pathNormalize } from '../utils/pathNormalize'; import { resolveVariables } from '../utils/resolveVariables'; @@ -287,3 +287,14 @@ export function normalizePlatform(platform: string | ContainerPlatform): Contain return platform as ContainerPlatform || undefined; } + +export function getMounts(volumes?: DockerContainerVolume[]): RunContainerBindMount[] | undefined { + return volumes?.map(v => { + return { + source: v.localPath, + destination: v.containerPath, + readOnly: v.permissions === 'ro' || (v.permissions as unknown === 'ro,z'), // Maintain compatibility with old `ro,z` option as much as possible + type: 'bind', + }; + }); +} diff --git a/src/tasks/netSdk/NetSdkTaskHelper.ts b/src/tasks/netSdk/NetSdkTaskHelper.ts index ba306c3eb6..b899ce1f4d 100644 --- a/src/tasks/netSdk/NetSdkTaskHelper.ts +++ b/src/tasks/netSdk/NetSdkTaskHelper.ts @@ -14,9 +14,8 @@ import { getDockerOSType } from "../../utils/osUtils"; import { quickPickProjectFileItem } from "../../utils/quickPickFile"; import { quickPickWorkspaceFolder } from "../../utils/quickPickWorkspaceFolder"; import { DockerContainerVolume } from "../DockerRunTaskDefinitionBase"; -import { getMounts } from "../DockerRunTaskProvider"; import { defaultVsCodeLabels } from "../TaskDefinitionBase"; -import { DockerTaskExecutionContext, addVolumeWithoutConflicts, getDefaultContainerName, getDefaultImageName } from "../TaskHelper"; +import { DockerTaskExecutionContext, addVolumeWithoutConflicts, getDefaultContainerName, getDefaultImageName, getMounts } from "../TaskHelper"; import { NetCoreTaskHelper } from "../netcore/NetCoreTaskHelper"; /** @@ -74,7 +73,7 @@ export class NetSdkTaskHelper { removeOnExit: true, imageRef: getDefaultImageName(folderName.name, imageTag), labels: defaultVsCodeLabels, - mounts: await this.getMounts(), + mounts: await this.getRemoteDebuggerMount(), customOptions: '--expose 8080', entrypoint: '/bin/sh' }); @@ -123,7 +122,7 @@ export class NetSdkTaskHelper { ); } - private async getMounts(): Promise { + private async getRemoteDebuggerMount(): Promise { const volumes: DockerContainerVolume[] = []; const isLinux = await getDockerOSType() === 'linux'; From bcb9d9dad1a1e18f0bdf073dd635e462fee46e78 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Mon, 5 Jun 2023 12:46:22 -0400 Subject: [PATCH 28/46] cleaned up unused comments & method --- package.json | 1 - src/debugging/netSdk/NetSdkDebugHelper.ts | 7 +------ src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts | 4 ++-- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 09d2b0d0db..f29f5367bf 100644 --- a/package.json +++ b/package.json @@ -639,7 +639,6 @@ "languages": [ "csharp", "razor", - "qsharp", "aspnetcorerazor" ], "configurationAttributes": { diff --git a/src/debugging/netSdk/NetSdkDebugHelper.ts b/src/debugging/netSdk/NetSdkDebugHelper.ts index c6c0f42ffc..2c310518ae 100644 --- a/src/debugging/netSdk/NetSdkDebugHelper.ts +++ b/src/debugging/netSdk/NetSdkDebugHelper.ts @@ -1,5 +1,5 @@ import { commands } from "vscode"; -import { NetChooseBuildTypeContext, netContainerBuild } from "../../scaffolding/wizard/net/netContainerBuild"; +import { NetChooseBuildTypeContext, netContainerBuild } from "../../scaffolding/wizard/net/NetContainerBuild"; import { unresolveWorkspaceFolder } from "../../utils/resolveVariables"; import { DockerDebugScaffoldContext } from "../DebugHelper"; import { DockerDebugConfiguration } from "../DockerDebugConfigurationProvider"; @@ -35,11 +35,6 @@ export class NetSdkDebugHelper extends NetCoreDebugHelper { return providers; } - - private getAppOutput(context: DockerDebugScaffoldContext): string { - const folderName = context.folder.name || 'dotnet'; - return `${folderName}.dll`; - } } export const netSdkDebugHelper = new NetSdkDebugHelper(); diff --git a/src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts b/src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts index a8559bec05..b93a3be1eb 100644 --- a/src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts +++ b/src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts @@ -7,7 +7,7 @@ import { IAzureQuickPickItem } from '@microsoft/vscode-azext-utils'; import * as vscode from 'vscode'; import { getFromWorkspaceState, updateWorkspaceState } from '../../../utils/StateUtils'; import { TelemetryPromptStep } from '../TelemetryPromptStep'; -import { NetChooseBuildTypeContext } from './netContainerBuild'; +import { NetChooseBuildTypeContext } from './NetContainerBuild'; export const NetContainerBuildOptions = [ 'Use a Dockerfile', @@ -24,7 +24,7 @@ export class NetSdkChooseBuildStep extends TelemetryPromptStep('containerBuildOptions'); // only remember if it was .NET SDK, otherwise prompt again - if (containerBuildOptions === 'Use .NET SDK') { // only remember if it was .NET SDK, otherwise prompt again + if (containerBuildOptions === 'Use .NET SDK') { wizardContext.containerBuildOptions = containerBuildOptions; return; } From 46df75454cd52c790bccd401d35ce3fe3a5ae461 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Mon, 5 Jun 2023 13:06:00 -0400 Subject: [PATCH 29/46] made NetTaskHelper more readable --- src/tasks/netSdk/NetSdkRunTaskProvider.ts | 12 ++++---- src/tasks/netSdk/NetSdkTaskHelper.ts | 37 +++++++++++------------ 2 files changed, 23 insertions(+), 26 deletions(-) diff --git a/src/tasks/netSdk/NetSdkRunTaskProvider.ts b/src/tasks/netSdk/NetSdkRunTaskProvider.ts index 439e8588de..5753b97e85 100644 --- a/src/tasks/netSdk/NetSdkRunTaskProvider.ts +++ b/src/tasks/netSdk/NetSdkRunTaskProvider.ts @@ -7,29 +7,29 @@ import { CancellationToken, CustomExecution, ProviderResult, Task, TaskDefinitio import { DockerPseudoterminal } from "../DockerPseudoterminal"; import { DockerTaskProvider } from '../DockerTaskProvider'; import { DockerTaskExecutionContext } from '../TaskHelper'; -import { NetSdkTaskHelper, netSdkRunTaskSymbol } from './NetSdkTaskHelper'; +import { NET_SDK_RUN_TASK_SYMBOL, NetSdkTaskHelper } from './NetSdkTaskHelper'; const netSdkDebugTaskName = 'debug'; export class NetSdkRunTaskProvider extends DockerTaskProvider { - public constructor(protected readonly helper: NetSdkTaskHelper) { super(netSdkRunTaskSymbol, undefined); } + public constructor(protected readonly helper: NetSdkTaskHelper) { super(NET_SDK_RUN_TASK_SYMBOL, undefined); } provideTasks(token: CancellationToken): ProviderResult { // we need to initialize a task first so we can pass it into `DockerPseudoterminal` const task = new Task( - { type: netSdkRunTaskSymbol }, + { type: NET_SDK_RUN_TASK_SYMBOL }, TaskScope.Workspace, netSdkDebugTaskName, - netSdkRunTaskSymbol + NET_SDK_RUN_TASK_SYMBOL ); return [ new Task( - { type: netSdkRunTaskSymbol }, + { type: NET_SDK_RUN_TASK_SYMBOL }, TaskScope.Workspace, netSdkDebugTaskName, - netSdkRunTaskSymbol, + NET_SDK_RUN_TASK_SYMBOL, new CustomExecution( async (resolvedDefinition: TaskDefinition) => Promise.resolve(new DockerPseudoterminal(this, task, resolvedDefinition)) ), diff --git a/src/tasks/netSdk/NetSdkTaskHelper.ts b/src/tasks/netSdk/NetSdkTaskHelper.ts index b899ce1f4d..105678cd69 100644 --- a/src/tasks/netSdk/NetSdkTaskHelper.ts +++ b/src/tasks/netSdk/NetSdkTaskHelper.ts @@ -32,12 +32,13 @@ export type RidCpuArchitecture = | 's390x' | string; -export const netSdkRunTaskSymbol = 'dotnet-container-sdk'; -const imageTag = 'dev'; // intentionally default to dev tag for phase 1 of this feature +export const NET_SDK_RUN_TASK_SYMBOL = 'dotnet-container-sdk'; +const IMAGE_TAG = 'dev'; // intentionally default to dev tag for phase 1 of this feature +const ERR_MSG_NO_WORKSPACE_FOLDER = l10n.t(`Unable to determine task scope to execute task ${NET_SDK_RUN_TASK_SYMBOL}. Please open a workspace folder.`); export class NetSdkTaskHelper { - public async getNetSdkBuildCommand(context: DockerTaskExecutionContext) { + public async getNetSdkBuildCommand(context: DockerTaskExecutionContext): Promise { const configuration = 'Debug'; // intentionally default to Debug configuration for phase 1 of this feature const projPath = await this.inferProjPath(context.actionContext, context.folder); @@ -45,7 +46,7 @@ export class NetSdkTaskHelper { // {@link https://github.com/dotnet/sdk-container-builds/issues/141} this could change in the future const publishFlag = NetCoreTaskHelper.isWebApp(projPath) ? '-p:PublishProfile=DefaultContainer' : '/t:PublishContainer'; - const folderName = await this.getFolderName(context.actionContext); + const folderName = await quickPickWorkspaceFolder(context.actionContext, ERR_MSG_NO_WORKSPACE_FOLDER); const args = composeArgs( withArg('dotnet', 'publish'), @@ -54,7 +55,7 @@ export class NetSdkTaskHelper { withArg(publishFlag), withNamedArg('--configuration', configuration), withNamedArg('-p:ContainerImageName', getValidImageName(folderName.name), { assignValue: true }), - withNamedArg('-p:ContainerImageTag', imageTag, { assignValue: true }) + withNamedArg('-p:ContainerImageTag', IMAGE_TAG, { assignValue: true }) )(); const quotedArgs = Shell.getShellOrDefault().quote(args); @@ -63,15 +64,15 @@ export class NetSdkTaskHelper { public async getNetSdkRunCommand(context: DockerTaskExecutionContext): Promise { const client = await ext.runtimeManager.getClient(); - const folderName = await this.getFolderName(context.actionContext); + const folderName = await quickPickWorkspaceFolder(context.actionContext, ERR_MSG_NO_WORKSPACE_FOLDER); const command = await client.runContainer({ detached: true, publishAllPorts: true, - name: getDefaultContainerName(folderName.name, imageTag), + name: getDefaultContainerName(folderName.name, IMAGE_TAG), environmentVariables: {}, removeOnExit: true, - imageRef: getDefaultImageName(folderName.name, imageTag), + imageRef: getDefaultImageName(folderName.name, IMAGE_TAG), labels: defaultVsCodeLabels, mounts: await this.getRemoteDebuggerMount(), customOptions: '--expose 8080', @@ -85,7 +86,8 @@ export class NetSdkTaskHelper { } public async inferProjPath(context: IActionContext, folder: WorkspaceFolder): Promise { - const item = await quickPickProjectFileItem(context, undefined, folder, l10n.t('No .csproj file could be found.')); + const noProjectFileErrMessage = l10n.t('No .csproj file could be found.'); + const item = await quickPickProjectFileItem(context, undefined, folder, noProjectFileErrMessage); return item.absoluteFilePath || ''; } @@ -94,10 +96,8 @@ export class NetSdkTaskHelper { * {@link https://learn.microsoft.com/en-us/dotnet/core/rid-catalog} */ private async normalizeOsToRid(): Promise<'linux' | 'win'> { - if (await getDockerOSType() === 'windows') { - return 'win'; - } - return 'linux'; + const dockerOsType = await getDockerOSType(); + return dockerOsType === 'windows' ? 'win' : 'linux'; } /** @@ -115,13 +115,10 @@ export class NetSdkTaskHelper { } } - public async getFolderName(context: IActionContext): Promise { - return await quickPickWorkspaceFolder( - context, - `Unable to determine task scope to execute task ${netSdkRunTaskSymbol}. Please open a workspace folder.` - ); - } - + /** + * This methods returns the mount for the remote debugger ONLY as the SDK built container will have + * everything it needs to run the app already inside. + */ private async getRemoteDebuggerMount(): Promise { const volumes: DockerContainerVolume[] = []; const isLinux = await getDockerOSType() === 'linux'; From 0afe70874b5af3478b240c2e494641c78976a55d Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Mon, 5 Jun 2023 13:30:12 -0400 Subject: [PATCH 30/46] changed momento name to more detailed --- src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts b/src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts index b93a3be1eb..2d1a5b1e91 100644 --- a/src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts +++ b/src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts @@ -21,7 +21,7 @@ export class NetSdkChooseBuildStep extends TelemetryPromptStep { // get workspace momento storage - const containerBuildOptions = await getFromWorkspaceState('containerBuildOptions'); + const containerBuildOptions = await getFromWorkspaceState('netContainerBuildOptions'); // only remember if it was .NET SDK, otherwise prompt again if (containerBuildOptions === 'Use .NET SDK') { @@ -42,7 +42,7 @@ export class NetSdkChooseBuildStep extends TelemetryPromptStep('containerBuildOptions', wizardContext.containerBuildOptions); + await updateWorkspaceState('netContainerBuildOptions', wizardContext.containerBuildOptions); } public shouldPrompt(wizardContext: NetChooseBuildTypeContext): boolean { From e29212cc26b5d2505580b0a66e049bfacc33970e Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Tue, 6 Jun 2023 10:57:42 -0400 Subject: [PATCH 31/46] changed targets to find SDK Container path --- resources/netCore/GetProjectProperties.targets | 11 ++++++++--- src/debugging/netcore/NetCoreDebugHelper.ts | 18 +++++++++++++----- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/resources/netCore/GetProjectProperties.targets b/resources/netCore/GetProjectProperties.targets index b2506173b4..929dd3ae4e 100644 --- a/resources/netCore/GetProjectProperties.targets +++ b/resources/netCore/GetProjectProperties.targets @@ -1,11 +1,16 @@ - - + + $(GetProjectPropertiesDependsOn);ComputeContainerConfig; + + + diff --git a/src/debugging/netcore/NetCoreDebugHelper.ts b/src/debugging/netcore/NetCoreDebugHelper.ts index 804d631844..184c42598a 100644 --- a/src/debugging/netcore/NetCoreDebugHelper.ts +++ b/src/debugging/netcore/NetCoreDebugHelper.ts @@ -68,7 +68,7 @@ export class NetCoreDebugHelper implements DebugHelper { debugConfiguration.netCore.appProject = await NetCoreTaskHelper.inferAppProject(context, debugConfiguration.netCore); // This method internally checks the user-defined input first const { configureSsl, containerName, platformOS } = await this.loadExternalInfo(context, debugConfiguration); - const appOutput = debugConfiguration.netCore?.appOutput || await this.inferAppOutput(debugConfiguration.netCore); + const appOutput = debugConfiguration.netCore?.appOutput || await this.inferAppOutput(debugConfiguration); if (context.cancellationToken && context.cancellationToken.isCancellationRequested) { // inferAppOutput is slow, give a chance to cancel return undefined; @@ -176,13 +176,21 @@ export class NetCoreDebugHelper implements DebugHelper { }; } - private async inferAppOutput(helperOptions: NetCoreDebugOptions): Promise { - const projectInfo = await getNetCoreProjectInfo('GetProjectProperties', helperOptions.appProject); + private async inferAppOutput(debugConfiguration: DockerDebugConfiguration): Promise { + const projectInfo = await getNetCoreProjectInfo('GetProjectProperties', debugConfiguration.netCore?.appProject); + if (projectInfo.length < 3) { throw new Error(l10n.t('Unable to determine assembly output path.')); } - - return projectInfo[2]; // First line is assembly name, second is target framework, third+ are output path(s) + else if (debugConfiguration.preLaunchTask === 'dotnet-container-sdk: debug' + && projectInfo.length === 5 + && projectInfo[4] === 'true') { // if .NET has support for SDK Build + // fourth is output path and fifth is whether .NET supports SDK Containers + return projectInfo[3]; + } + else { + return projectInfo[2]; // First line is assembly name, second is target framework, third+ are output path(s) + } } private async loadExternalInfo(context: DockerDebugContext, debugConfiguration: DockerDebugConfiguration): Promise<{ configureSsl: boolean, containerName: string, platformOS: PlatformOS }> { From 75f491d711398bc065a453921cad4bc5ac6f354b Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Tue, 6 Jun 2023 12:09:13 -0400 Subject: [PATCH 32/46] added method to check for sdk container builds --- src/debugging/DockerPlatformHelper.ts | 4 +++- src/debugging/netSdk/NetSdkDebugHelper.ts | 13 ++++++++++++- src/debugging/netcore/NetCoreDebugHelper.ts | 9 ++++++--- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/debugging/DockerPlatformHelper.ts b/src/debugging/DockerPlatformHelper.ts index 9513e9c6d0..de09528e35 100644 --- a/src/debugging/DockerPlatformHelper.ts +++ b/src/debugging/DockerPlatformHelper.ts @@ -3,6 +3,8 @@ * Licensed under the MIT License. See LICENSE.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { netSdkDebugHelper } from "./netSdk/NetSdkDebugHelper"; + export type DockerPlatform = 'netCore' | 'node' | 'python' | 'netSdk'; interface DockerPlatformConfiguration { @@ -14,7 +16,7 @@ interface DockerPlatformConfiguration { } export function getPlatform(configuration: T): DockerPlatform | undefined { - if (configuration.preLaunchTask === 'dotnet-container-sdk: debug' && configuration.netCore !== undefined) { + if (netSdkDebugHelper.isDotnetSdkBuild(configuration?.preLaunchTask) && configuration.netCore !== undefined) { return 'netSdk'; } else if (configuration.platform === 'netCore' || configuration.netCore !== undefined) { return 'netCore'; diff --git a/src/debugging/netSdk/NetSdkDebugHelper.ts b/src/debugging/netSdk/NetSdkDebugHelper.ts index 2c310518ae..a5ae3f3a86 100644 --- a/src/debugging/netSdk/NetSdkDebugHelper.ts +++ b/src/debugging/netSdk/NetSdkDebugHelper.ts @@ -5,6 +5,7 @@ import { DockerDebugScaffoldContext } from "../DebugHelper"; import { DockerDebugConfiguration } from "../DockerDebugConfigurationProvider"; import { NetCoreDebugHelper, NetCoreDebugScaffoldingOptions } from "../netcore/NetCoreDebugHelper"; +const netContainerSdkBuildSymbol = 'dotnet-container-sdk: debug'; export class NetSdkDebugHelper extends NetCoreDebugHelper { public async provideDebugConfigurations(context: DockerDebugScaffoldContext, options?: NetCoreDebugScaffoldingOptions): Promise { @@ -24,7 +25,7 @@ export class NetSdkDebugHelper extends NetCoreDebugHelper { name: 'Docker .NET Container SDK Launch', type: 'docker', request: 'launch', - preLaunchTask: 'dotnet-container-sdk: debug', + preLaunchTask: netContainerSdkBuildSymbol, netCore: { appProject: unresolveWorkspaceFolder(options.appProject, context.folder), }, @@ -35,6 +36,16 @@ export class NetSdkDebugHelper extends NetCoreDebugHelper { return providers; } + + /** + * Checks if the launch task is using the .NET SDK Container build + * @param preLaunchTask + * @returns true if the launch task is using the .NET SDK Container build + * false otherwise + */ + public isDotnetSdkBuild(preLaunchTask: string): boolean { + return preLaunchTask && preLaunchTask === netContainerSdkBuildSymbol; + } } export const netSdkDebugHelper = new NetSdkDebugHelper(); diff --git a/src/debugging/netcore/NetCoreDebugHelper.ts b/src/debugging/netcore/NetCoreDebugHelper.ts index 184c42598a..99587ad6b9 100644 --- a/src/debugging/netcore/NetCoreDebugHelper.ts +++ b/src/debugging/netcore/NetCoreDebugHelper.ts @@ -18,6 +18,7 @@ import { PlatformOS } from '../../utils/platform'; import { unresolveWorkspaceFolder } from '../../utils/resolveVariables'; import { DebugHelper, DockerDebugContext, DockerDebugScaffoldContext, ResolvedDebugConfiguration, inferContainerName, resolveDockerServerReadyAction } from '../DebugHelper'; import { DockerAttachConfiguration, DockerDebugConfiguration } from '../DockerDebugConfigurationProvider'; +import { netSdkDebugHelper } from '../netSdk/NetSdkDebugHelper'; import { exportCertificateIfNecessary, getHostSecretsFolders, trustCertificateIfNecessary } from './AspNetSslHelper'; import { VsDbgType, installDebuggersIfNecessary, vsDbgInstallBasePath } from './VsDbgHelper'; @@ -90,7 +91,9 @@ export class NetCoreDebugHelper implements DebugHelper { const additionalProbingPathsArgs = NetCoreDebugHelper.getAdditionalProbingPathsArgs(platformOS); - const containerAppOutput = NetCoreDebugHelper.getContainerAppOutput(debugConfiguration, appOutput, platformOS); + const containerAppOutput = netSdkDebugHelper.isDotnetSdkBuild(debugConfiguration?.preLaunchTask) + ? appOutput + : NetCoreDebugHelper.getContainerAppOutput(debugConfiguration, appOutput, platformOS); const dockerServerReadyAction = resolveDockerServerReadyAction( debugConfiguration, @@ -182,8 +185,8 @@ export class NetCoreDebugHelper implements DebugHelper { if (projectInfo.length < 3) { throw new Error(l10n.t('Unable to determine assembly output path.')); } - else if (debugConfiguration.preLaunchTask === 'dotnet-container-sdk: debug' - && projectInfo.length === 5 + else if (netSdkDebugHelper.isDotnetSdkBuild(debugConfiguration.preLaunchTask) + && projectInfo.length >= 5 && projectInfo[4] === 'true') { // if .NET has support for SDK Build // fourth is output path and fifth is whether .NET supports SDK Containers return projectInfo[3]; From 00af811584b28cd9097af534c824af9dfb8f2a10 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Tue, 6 Jun 2023 13:15:32 -0400 Subject: [PATCH 33/46] set git ignore case to false --- .../wizard/net/NetContainerBuild.ts | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/scaffolding/wizard/net/NetContainerBuild.ts diff --git a/src/scaffolding/wizard/net/NetContainerBuild.ts b/src/scaffolding/wizard/net/NetContainerBuild.ts new file mode 100644 index 0000000000..b95afa481d --- /dev/null +++ b/src/scaffolding/wizard/net/NetContainerBuild.ts @@ -0,0 +1,32 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE.md in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { AzureWizard, AzureWizardPromptStep, UserCancelledError } from '@microsoft/vscode-azext-utils'; +import * as vscode from 'vscode'; +import { ScaffoldingWizardContext } from '../ScaffoldingWizardContext'; +import { NetContainerBuildOptions, NetSdkChooseBuildStep } from './NetSdkChooseBuildStep'; + +export interface NetChooseBuildTypeContext extends ScaffoldingWizardContext { + containerBuildOptions?: NetContainerBuildOptions; +} + +export async function netContainerBuild(wizardContext: Partial, apiInput?: NetChooseBuildTypeContext): Promise { + if (!vscode.workspace.isTrusted) { + throw new UserCancelledError('enforceTrust'); + } + + const promptSteps: AzureWizardPromptStep[] = [ + new NetSdkChooseBuildStep() + ]; + + const wizard = new AzureWizard(wizardContext as NetChooseBuildTypeContext, { + promptSteps: promptSteps, + title: vscode.l10n.t('Initialize for Debugging'), + }); + + await wizard.prompt(); + await wizard.execute(); + +} From d69f933121703d163289f1a0b136688df35b1993 Mon Sep 17 00:00:00 2001 From: "Alex Yang [MSFT]" <59073590+alexyaang@users.noreply.github.com> Date: Tue, 6 Jun 2023 13:23:08 -0400 Subject: [PATCH 34/46] Delete netContainerBuild.ts --- .../wizard/net/netContainerBuild.ts | 32 ------------------- 1 file changed, 32 deletions(-) delete mode 100644 src/scaffolding/wizard/net/netContainerBuild.ts diff --git a/src/scaffolding/wizard/net/netContainerBuild.ts b/src/scaffolding/wizard/net/netContainerBuild.ts deleted file mode 100644 index b95afa481d..0000000000 --- a/src/scaffolding/wizard/net/netContainerBuild.ts +++ /dev/null @@ -1,32 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See LICENSE.md in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizard, AzureWizardPromptStep, UserCancelledError } from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { ScaffoldingWizardContext } from '../ScaffoldingWizardContext'; -import { NetContainerBuildOptions, NetSdkChooseBuildStep } from './NetSdkChooseBuildStep'; - -export interface NetChooseBuildTypeContext extends ScaffoldingWizardContext { - containerBuildOptions?: NetContainerBuildOptions; -} - -export async function netContainerBuild(wizardContext: Partial, apiInput?: NetChooseBuildTypeContext): Promise { - if (!vscode.workspace.isTrusted) { - throw new UserCancelledError('enforceTrust'); - } - - const promptSteps: AzureWizardPromptStep[] = [ - new NetSdkChooseBuildStep() - ]; - - const wizard = new AzureWizard(wizardContext as NetChooseBuildTypeContext, { - promptSteps: promptSteps, - title: vscode.l10n.t('Initialize for Debugging'), - }); - - await wizard.prompt(); - await wizard.execute(); - -} From aff5e9e848fc99fcc29696a1d2f75b4dd317ac5d Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Tue, 6 Jun 2023 15:27:30 -0400 Subject: [PATCH 35/46] added error checking --- src/debugging/netcore/NetCoreDebugHelper.ts | 16 ++++++++-------- src/tasks/netSdk/NetSdkBuildTaskDefinition.ts | 10 ---------- 2 files changed, 8 insertions(+), 18 deletions(-) delete mode 100644 src/tasks/netSdk/NetSdkBuildTaskDefinition.ts diff --git a/src/debugging/netcore/NetCoreDebugHelper.ts b/src/debugging/netcore/NetCoreDebugHelper.ts index 99587ad6b9..a4fc6689e2 100644 --- a/src/debugging/netcore/NetCoreDebugHelper.ts +++ b/src/debugging/netcore/NetCoreDebugHelper.ts @@ -185,15 +185,15 @@ export class NetCoreDebugHelper implements DebugHelper { if (projectInfo.length < 3) { throw new Error(l10n.t('Unable to determine assembly output path.')); } - else if (netSdkDebugHelper.isDotnetSdkBuild(debugConfiguration.preLaunchTask) - && projectInfo.length >= 5 - && projectInfo[4] === 'true') { // if .NET has support for SDK Build - // fourth is output path and fifth is whether .NET supports SDK Containers - return projectInfo[3]; - } - else { - return projectInfo[2]; // First line is assembly name, second is target framework, third+ are output path(s) + + if (netSdkDebugHelper.isDotnetSdkBuild(debugConfiguration.preLaunchTask) && projectInfo.length >= 5) { // if .NET has support for SDK Build + if (projectInfo[4] === 'true') { // fifth is whether .NET supports SDK Containers + return projectInfo[3]; // fourth is output path and + } + throw new Error(l10n.t('Your current version of .NET SDK does not support Container build. Please update a newer version of .NET SDK.')); } + + return projectInfo[2]; // First line is assembly name, second is target framework, third+ are output path(s) } private async loadExternalInfo(context: DockerDebugContext, debugConfiguration: DockerDebugConfiguration): Promise<{ configureSsl: boolean, containerName: string, platformOS: PlatformOS }> { diff --git a/src/tasks/netSdk/NetSdkBuildTaskDefinition.ts b/src/tasks/netSdk/NetSdkBuildTaskDefinition.ts deleted file mode 100644 index fea3a87aa3..0000000000 --- a/src/tasks/netSdk/NetSdkBuildTaskDefinition.ts +++ /dev/null @@ -1,10 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See LICENSE.md in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { TaskDefinitionBase } from "../TaskDefinitionBase"; - -export type NetSdkBuildTaskDefinition = TaskDefinitionBase; - - From 17142bead09dbf3c15ac19307dffcaeae3fa799c Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Tue, 6 Jun 2023 14:58:43 -0400 Subject: [PATCH 36/46] added error checking --- src/debugging/netcore/NetCoreDebugHelper.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/debugging/netcore/NetCoreDebugHelper.ts b/src/debugging/netcore/NetCoreDebugHelper.ts index a4fc6689e2..51ac7d7c5f 100644 --- a/src/debugging/netcore/NetCoreDebugHelper.ts +++ b/src/debugging/netcore/NetCoreDebugHelper.ts @@ -188,9 +188,10 @@ export class NetCoreDebugHelper implements DebugHelper { if (netSdkDebugHelper.isDotnetSdkBuild(debugConfiguration.preLaunchTask) && projectInfo.length >= 5) { // if .NET has support for SDK Build if (projectInfo[4] === 'true') { // fifth is whether .NET supports SDK Containers - return projectInfo[3]; // fourth is output path and + return projectInfo[3]; // fourth is output path } - throw new Error(l10n.t('Your current version of .NET SDK does not support Container build. Please update a newer version of .NET SDK.')); + + throw new Error(l10n.t('Your current version of .NET SDK does not support SDK Container build. Please update to a later version of .NET SDK to use this feature.')); } return projectInfo[2]; // First line is assembly name, second is target framework, third+ are output path(s) From 583a4d5f28d6f1bec937a7d8c8e0c6466d07efac Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Wed, 7 Jun 2023 16:33:00 -0400 Subject: [PATCH 37/46] Changed const to pascal case & use pre-defined options --- .../DockerDebugConfigurationProvider.ts | 10 +++--- src/debugging/netSdk/NetSdkDebugHelper.ts | 15 +++++---- .../wizard/net/NetContainerBuild.ts | 1 - .../wizard/net/NetSdkChooseBuildStep.ts | 8 ++--- src/tasks/netSdk/NetSdkRunTaskProvider.ts | 32 ++++++++----------- src/tasks/netSdk/NetSdkTaskHelper.ts | 18 +++++------ 6 files changed, 39 insertions(+), 45 deletions(-) diff --git a/src/debugging/DockerDebugConfigurationProvider.ts b/src/debugging/DockerDebugConfigurationProvider.ts index 71995e260c..3832203dbd 100644 --- a/src/debugging/DockerDebugConfigurationProvider.ts +++ b/src/debugging/DockerDebugConfigurationProvider.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See LICENSE.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { callWithTelemetryAndErrorHandling, IActionContext, registerEvent } from '@microsoft/vscode-azext-utils'; +import { callWithTelemetryAndErrorHandling, IActionContext, registerEvent, UserCancelledError } from '@microsoft/vscode-azext-utils'; import { CancellationToken, commands, debug, DebugConfiguration, DebugConfigurationProvider, DebugSession, l10n, ProviderResult, workspace, WorkspaceFolder } from 'vscode'; import { CSPROJ_GLOB_PATTERN, DockerOrchestration } from '../constants'; import { ext } from '../extensionVariables'; @@ -208,12 +208,12 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi }, { appProject: csProjUris[0]?.absoluteFilePath || '', - }); - } - else { + } + ); + } else { // for now, we scaffold docker files await commands.executeCommand('vscode-docker.configure'); - return []; + throw new UserCancelledError(); } // TODO: (potentially) in the future, we can add more support for ambient tasks for other types of projects } diff --git a/src/debugging/netSdk/NetSdkDebugHelper.ts b/src/debugging/netSdk/NetSdkDebugHelper.ts index a5ae3f3a86..bee0a7bd23 100644 --- a/src/debugging/netSdk/NetSdkDebugHelper.ts +++ b/src/debugging/netSdk/NetSdkDebugHelper.ts @@ -1,16 +1,17 @@ import { commands } from "vscode"; import { NetChooseBuildTypeContext, netContainerBuild } from "../../scaffolding/wizard/net/NetContainerBuild"; +import { NetContainerBuildOptions } from "../../scaffolding/wizard/net/NetSdkChooseBuildStep"; import { unresolveWorkspaceFolder } from "../../utils/resolveVariables"; import { DockerDebugScaffoldContext } from "../DebugHelper"; import { DockerDebugConfiguration } from "../DockerDebugConfigurationProvider"; import { NetCoreDebugHelper, NetCoreDebugScaffoldingOptions } from "../netcore/NetCoreDebugHelper"; -const netContainerSdkBuildSymbol = 'dotnet-container-sdk: debug'; +const NetSdkTaskFullSymbol = 'dotnet-container-sdk: debug'; export class NetSdkDebugHelper extends NetCoreDebugHelper { public async provideDebugConfigurations(context: DockerDebugScaffoldContext, options?: NetCoreDebugScaffoldingOptions): Promise { - const providers: DockerDebugConfiguration[] = []; + const configurations: DockerDebugConfiguration[] = []; const netCoreBuildContext: NetChooseBuildTypeContext = { ...context.actionContext, @@ -20,12 +21,12 @@ export class NetSdkDebugHelper extends NetCoreDebugHelper { await netContainerBuild(netCoreBuildContext); - if (netCoreBuildContext?.containerBuildOptions === 'Use .NET SDK') { - providers.push({ + if (netCoreBuildContext?.containerBuildOptions === NetContainerBuildOptions[1]) { + configurations.push({ name: 'Docker .NET Container SDK Launch', type: 'docker', request: 'launch', - preLaunchTask: netContainerSdkBuildSymbol, + preLaunchTask: NetSdkTaskFullSymbol, netCore: { appProject: unresolveWorkspaceFolder(options.appProject, context.folder), }, @@ -34,7 +35,7 @@ export class NetSdkDebugHelper extends NetCoreDebugHelper { await commands.executeCommand('vscode-docker.configure'); } - return providers; + return configurations; } /** @@ -44,7 +45,7 @@ export class NetSdkDebugHelper extends NetCoreDebugHelper { * false otherwise */ public isDotnetSdkBuild(preLaunchTask: string): boolean { - return preLaunchTask && preLaunchTask === netContainerSdkBuildSymbol; + return preLaunchTask === NetSdkTaskFullSymbol; } } diff --git a/src/scaffolding/wizard/net/NetContainerBuild.ts b/src/scaffolding/wizard/net/NetContainerBuild.ts index b95afa481d..3187d98e9e 100644 --- a/src/scaffolding/wizard/net/NetContainerBuild.ts +++ b/src/scaffolding/wizard/net/NetContainerBuild.ts @@ -28,5 +28,4 @@ export async function netContainerBuild(wizardContext: Partial('netContainerBuildOptions'); - // only remember if it was .NET SDK, otherwise prompt again - if (containerBuildOptions === 'Use .NET SDK') { + // only remember if it was 'Use .NET SDK', otherwise prompt again + if (containerBuildOptions === NetContainerBuildOptions[1]) { wizardContext.containerBuildOptions = containerBuildOptions; return; } diff --git a/src/tasks/netSdk/NetSdkRunTaskProvider.ts b/src/tasks/netSdk/NetSdkRunTaskProvider.ts index 5753b97e85..d2d22a850b 100644 --- a/src/tasks/netSdk/NetSdkRunTaskProvider.ts +++ b/src/tasks/netSdk/NetSdkRunTaskProvider.ts @@ -3,38 +3,32 @@ * Licensed under the MIT License. See LICENSE.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CancellationToken, CustomExecution, ProviderResult, Task, TaskDefinition, TaskScope } from "vscode"; +import { CancellationToken, CustomExecution, Task, TaskDefinition, TaskScope } from "vscode"; import { DockerPseudoterminal } from "../DockerPseudoterminal"; import { DockerTaskProvider } from '../DockerTaskProvider'; import { DockerTaskExecutionContext } from '../TaskHelper'; -import { NET_SDK_RUN_TASK_SYMBOL, NetSdkTaskHelper } from './NetSdkTaskHelper'; +import { NetSdkRunTaskType, NetSdkTaskHelper } from './NetSdkTaskHelper'; -const netSdkDebugTaskName = 'debug'; +const NetSdkDebugTaskName = 'debug'; export class NetSdkRunTaskProvider extends DockerTaskProvider { - public constructor(protected readonly helper: NetSdkTaskHelper) { super(NET_SDK_RUN_TASK_SYMBOL, undefined); } + public constructor(protected readonly helper: NetSdkTaskHelper) { super(NetSdkRunTaskType, undefined); } - provideTasks(token: CancellationToken): ProviderResult { + public provideTasks(token: CancellationToken): Task[] { // we need to initialize a task first so we can pass it into `DockerPseudoterminal` const task = new Task( - { type: NET_SDK_RUN_TASK_SYMBOL }, + { type: NetSdkRunTaskType }, TaskScope.Workspace, - netSdkDebugTaskName, - NET_SDK_RUN_TASK_SYMBOL + NetSdkDebugTaskName, + NetSdkRunTaskType ); - return [ - new Task( - { type: NET_SDK_RUN_TASK_SYMBOL }, - TaskScope.Workspace, - netSdkDebugTaskName, - NET_SDK_RUN_TASK_SYMBOL, - new CustomExecution( - async (resolvedDefinition: TaskDefinition) => Promise.resolve(new DockerPseudoterminal(this, task, resolvedDefinition)) - ), - ) - ]; + task.execution = new CustomExecution(async (resolvedDefinition: TaskDefinition) => + Promise.resolve(new DockerPseudoterminal(this, task, resolvedDefinition)) + ); + + return [task]; } protected async executeTaskInternal(context: DockerTaskExecutionContext, task: Task): Promise { diff --git a/src/tasks/netSdk/NetSdkTaskHelper.ts b/src/tasks/netSdk/NetSdkTaskHelper.ts index 105678cd69..ae98972b13 100644 --- a/src/tasks/netSdk/NetSdkTaskHelper.ts +++ b/src/tasks/netSdk/NetSdkTaskHelper.ts @@ -32,9 +32,9 @@ export type RidCpuArchitecture = | 's390x' | string; -export const NET_SDK_RUN_TASK_SYMBOL = 'dotnet-container-sdk'; -const IMAGE_TAG = 'dev'; // intentionally default to dev tag for phase 1 of this feature -const ERR_MSG_NO_WORKSPACE_FOLDER = l10n.t(`Unable to determine task scope to execute task ${NET_SDK_RUN_TASK_SYMBOL}. Please open a workspace folder.`); +export const NetSdkRunTaskType = 'dotnet-container-sdk'; +const NetSdkDefaultImageTag = 'dev'; // intentionally default to dev tag for phase 1 of this feature +const ErrMsgNoWorkplaceFolder = l10n.t(`Unable to determine task scope to execute task ${NetSdkRunTaskType}. Please open a workspace folder.`); export class NetSdkTaskHelper { @@ -46,7 +46,7 @@ export class NetSdkTaskHelper { // {@link https://github.com/dotnet/sdk-container-builds/issues/141} this could change in the future const publishFlag = NetCoreTaskHelper.isWebApp(projPath) ? '-p:PublishProfile=DefaultContainer' : '/t:PublishContainer'; - const folderName = await quickPickWorkspaceFolder(context.actionContext, ERR_MSG_NO_WORKSPACE_FOLDER); + const folderName = await quickPickWorkspaceFolder(context.actionContext, ErrMsgNoWorkplaceFolder); const args = composeArgs( withArg('dotnet', 'publish'), @@ -55,7 +55,7 @@ export class NetSdkTaskHelper { withArg(publishFlag), withNamedArg('--configuration', configuration), withNamedArg('-p:ContainerImageName', getValidImageName(folderName.name), { assignValue: true }), - withNamedArg('-p:ContainerImageTag', IMAGE_TAG, { assignValue: true }) + withNamedArg('-p:ContainerImageTag', NetSdkDefaultImageTag, { assignValue: true }) )(); const quotedArgs = Shell.getShellOrDefault().quote(args); @@ -64,15 +64,15 @@ export class NetSdkTaskHelper { public async getNetSdkRunCommand(context: DockerTaskExecutionContext): Promise { const client = await ext.runtimeManager.getClient(); - const folderName = await quickPickWorkspaceFolder(context.actionContext, ERR_MSG_NO_WORKSPACE_FOLDER); + const folderName = await quickPickWorkspaceFolder(context.actionContext, ErrMsgNoWorkplaceFolder); const command = await client.runContainer({ detached: true, publishAllPorts: true, - name: getDefaultContainerName(folderName.name, IMAGE_TAG), + name: getDefaultContainerName(folderName.name, NetSdkDefaultImageTag), environmentVariables: {}, removeOnExit: true, - imageRef: getDefaultImageName(folderName.name, IMAGE_TAG), + imageRef: getDefaultImageName(folderName.name, NetSdkDefaultImageTag), labels: defaultVsCodeLabels, mounts: await this.getRemoteDebuggerMount(), customOptions: '--expose 8080', @@ -88,7 +88,7 @@ export class NetSdkTaskHelper { public async inferProjPath(context: IActionContext, folder: WorkspaceFolder): Promise { const noProjectFileErrMessage = l10n.t('No .csproj file could be found.'); const item = await quickPickProjectFileItem(context, undefined, folder, noProjectFileErrMessage); - return item.absoluteFilePath || ''; + return item.absoluteFilePath; } /** From 2d1defe54554b9adc9aeadf1551811858ff93558 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Wed, 7 Jun 2023 17:03:00 -0400 Subject: [PATCH 38/46] removed redundent duplication method --- .../DockerDebugConfigurationProvider.ts | 24 ++++--------------- src/debugging/netSdk/NetSdkDebugHelper.ts | 4 ++-- .../wizard/net/NetSdkChooseBuildStep.ts | 8 +++---- 3 files changed, 11 insertions(+), 25 deletions(-) diff --git a/src/debugging/DockerDebugConfigurationProvider.ts b/src/debugging/DockerDebugConfigurationProvider.ts index 3832203dbd..9228cebc1d 100644 --- a/src/debugging/DockerDebugConfigurationProvider.ts +++ b/src/debugging/DockerDebugConfigurationProvider.ts @@ -46,7 +46,7 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi public provideDebugConfigurations(folder: WorkspaceFolder | undefined, token?: CancellationToken): ProviderResult { return callWithTelemetryAndErrorHandling( - 'docker-provideDebugConfigurations', //TODO: change this later + 'provideDebugConfigurations', async (actionContext: IActionContext) => { return this.handleEmptyDebugConfig(folder, actionContext); } @@ -73,12 +73,14 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi if (debugConfiguration.type === undefined && debugConfiguration.request === undefined && debugConfiguration.name === undefined) { + const newlyCreatedDebugConfig = await this.handleEmptyDebugConfig(folder, actionContext); - this.copyDebugConfiguration(newlyCreatedDebugConfig, debugConfiguration); // if there is no debugConfiguration, we should return undefined to exit the debug session - if (newlyCreatedDebugConfig.length === 0) { + if (newlyCreatedDebugConfig.length === 0 || !newlyCreatedDebugConfig[0]) { return undefined; } + + debugConfiguration = newlyCreatedDebugConfig[0]; } if (!debugConfiguration.request) { @@ -171,22 +173,6 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi } } - /** - * Copies the first debug configuration from the array to the second one. - */ - private copyDebugConfiguration(fromArray: DockerDebugConfiguration[], to: DockerDebugConfiguration): void { - if (!fromArray || !fromArray[0]) { - return; - } - - const from = fromArray[0]; - for (const key of Object.keys(from)) { - if (from[key] !== undefined) { - to[key] = from[key]; - } - } - } - /** * If the user has an empty debug launch.json, then we will: * 1. check if it's a .NET Core project, if so, we will provide .NET Core debug configurations diff --git a/src/debugging/netSdk/NetSdkDebugHelper.ts b/src/debugging/netSdk/NetSdkDebugHelper.ts index bee0a7bd23..0ed9ac55f6 100644 --- a/src/debugging/netSdk/NetSdkDebugHelper.ts +++ b/src/debugging/netSdk/NetSdkDebugHelper.ts @@ -1,6 +1,6 @@ import { commands } from "vscode"; import { NetChooseBuildTypeContext, netContainerBuild } from "../../scaffolding/wizard/net/NetContainerBuild"; -import { NetContainerBuildOptions } from "../../scaffolding/wizard/net/NetSdkChooseBuildStep"; +import { AllNetContainerBuildOptions } from "../../scaffolding/wizard/net/NetSdkChooseBuildStep"; import { unresolveWorkspaceFolder } from "../../utils/resolveVariables"; import { DockerDebugScaffoldContext } from "../DebugHelper"; import { DockerDebugConfiguration } from "../DockerDebugConfigurationProvider"; @@ -21,7 +21,7 @@ export class NetSdkDebugHelper extends NetCoreDebugHelper { await netContainerBuild(netCoreBuildContext); - if (netCoreBuildContext?.containerBuildOptions === NetContainerBuildOptions[1]) { + if (netCoreBuildContext?.containerBuildOptions === AllNetContainerBuildOptions[1]) { configurations.push({ name: 'Docker .NET Container SDK Launch', type: 'docker', diff --git a/src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts b/src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts index e029860700..89425bc1cb 100644 --- a/src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts +++ b/src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts @@ -9,12 +9,12 @@ import { getFromWorkspaceState, updateWorkspaceState } from '../../../utils/Stat import { TelemetryPromptStep } from '../TelemetryPromptStep'; import { NetChooseBuildTypeContext } from './NetContainerBuild'; -export const NetContainerBuildOptions = [ +export const AllNetContainerBuildOptions = [ vscode.l10n.t('Use a Dockerfile'), vscode.l10n.t('Use .NET SDK') ] as const; -type NetContainerBuildOptionsTuple = typeof NetContainerBuildOptions; +type NetContainerBuildOptionsTuple = typeof AllNetContainerBuildOptions; export type NetContainerBuildOptions = NetContainerBuildOptionsTuple[number]; export class NetSdkChooseBuildStep extends TelemetryPromptStep { @@ -24,7 +24,7 @@ export class NetSdkChooseBuildStep extends TelemetryPromptStep('netContainerBuildOptions'); // only remember if it was 'Use .NET SDK', otherwise prompt again - if (containerBuildOptions === NetContainerBuildOptions[1]) { + if (containerBuildOptions === AllNetContainerBuildOptions[1]) { wizardContext.containerBuildOptions = containerBuildOptions; return; } @@ -35,7 +35,7 @@ export class NetSdkChooseBuildStep extends TelemetryPromptStep >{ label: p, data: p }); const response = await wizardContext.ui.showQuickPick(items, opt); From f96921ad4b2b77f7db914945bfc03cbe3783afab Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Thu, 8 Jun 2023 11:55:24 -0400 Subject: [PATCH 39/46] removed util class that is unnecessary --- src/debugging/netcore/NetCoreDebugHelper.ts | 6 ++++-- .../wizard/net/NetSdkChooseBuildStep.ts | 9 ++++++--- src/utils/StateUtils.ts | 16 ---------------- 3 files changed, 10 insertions(+), 21 deletions(-) delete mode 100644 src/utils/StateUtils.ts diff --git a/src/debugging/netcore/NetCoreDebugHelper.ts b/src/debugging/netcore/NetCoreDebugHelper.ts index 51ac7d7c5f..cf91978025 100644 --- a/src/debugging/netcore/NetCoreDebugHelper.ts +++ b/src/debugging/netcore/NetCoreDebugHelper.ts @@ -9,6 +9,7 @@ import * as path from 'path'; import { DebugConfiguration, MessageItem, ProgressLocation, l10n, window } from 'vscode'; import { ext } from '../../extensionVariables'; import { CommandLineArgs, ContainerOS, VoidCommandResponse, composeArgs, withArg, withQuotedArg } from '../../runtimes/docker'; +import { NetContainerBuildOptionsKey } from '../../scaffolding/wizard/net/NetSdkChooseBuildStep'; import { NetCoreTaskHelper, NetCoreTaskOptions } from '../../tasks/netcore/NetCoreTaskHelper'; import { ContainerTreeItem } from '../../tree/containers/ContainerTreeItem'; import { getNetCoreProjectInfo } from '../../utils/netCoreUtils'; @@ -189,9 +190,10 @@ export class NetCoreDebugHelper implements DebugHelper { if (netSdkDebugHelper.isDotnetSdkBuild(debugConfiguration.preLaunchTask) && projectInfo.length >= 5) { // if .NET has support for SDK Build if (projectInfo[4] === 'true') { // fifth is whether .NET supports SDK Containers return projectInfo[3]; // fourth is output path + } else { + await ext.context.workspaceState.update(NetContainerBuildOptionsKey, ''); // clear the workspace state + throw new Error(l10n.t('Your current version of .NET SDK does not support SDK Container build. Please update to a later version of .NET SDK to use this feature.')); } - - throw new Error(l10n.t('Your current version of .NET SDK does not support SDK Container build. Please update to a later version of .NET SDK to use this feature.')); } return projectInfo[2]; // First line is assembly name, second is target framework, third+ are output path(s) diff --git a/src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts b/src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts index 89425bc1cb..9d86ff743d 100644 --- a/src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts +++ b/src/scaffolding/wizard/net/NetSdkChooseBuildStep.ts @@ -5,10 +5,13 @@ import { IAzureQuickPickItem } from '@microsoft/vscode-azext-utils'; import * as vscode from 'vscode'; -import { getFromWorkspaceState, updateWorkspaceState } from '../../../utils/StateUtils'; +import { ext } from '../../../extensionVariables'; import { TelemetryPromptStep } from '../TelemetryPromptStep'; import { NetChooseBuildTypeContext } from './NetContainerBuild'; +/** Key to .NET Container Build Options workplace momento storage */ +export const NetContainerBuildOptionsKey = 'netContainerBuildOptions'; + export const AllNetContainerBuildOptions = [ vscode.l10n.t('Use a Dockerfile'), vscode.l10n.t('Use .NET SDK') @@ -21,7 +24,7 @@ export class NetSdkChooseBuildStep extends TelemetryPromptStep { // get workspace momento storage - const containerBuildOptions = await getFromWorkspaceState('netContainerBuildOptions'); + const containerBuildOptions = await ext.context.workspaceState.get(NetContainerBuildOptionsKey); // only remember if it was 'Use .NET SDK', otherwise prompt again if (containerBuildOptions === AllNetContainerBuildOptions[1]) { @@ -42,7 +45,7 @@ export class NetSdkChooseBuildStep extends TelemetryPromptStep('netContainerBuildOptions', wizardContext.containerBuildOptions); + await ext.context.workspaceState.update(NetContainerBuildOptionsKey, wizardContext.containerBuildOptions); } public shouldPrompt(wizardContext: NetChooseBuildTypeContext): boolean { diff --git a/src/utils/StateUtils.ts b/src/utils/StateUtils.ts deleted file mode 100644 index e7e38aadcf..0000000000 --- a/src/utils/StateUtils.ts +++ /dev/null @@ -1,16 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See LICENSE.md in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ext } from '../extensionVariables'; - -export async function getFromWorkspaceState(key: string): Promise { - return ext.context.workspaceState.get(key); -} - -export async function updateWorkspaceState(key: string, value: T): Promise { - return ext.context.workspaceState.update(key, value); -} - - From 3d02acd58e3be0639c291c68d042cd8c25998a60 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Tue, 13 Jun 2023 11:26:36 -0400 Subject: [PATCH 40/46] added expose field inside RunContainerCommandOptions --- src/debugging/DockerPlatformHelper.ts | 2 +- src/debugging/netSdk/NetSdkDebugHelper.ts | 2 +- src/debugging/netcore/NetCoreDebugHelper.ts | 4 ++-- .../clients/DockerClientBase/DockerClientBase.ts | 2 ++ .../clients/DockerClientBase/withDockerExposesArg.ts | 10 ++++++++++ src/runtimes/docker/contracts/ContainerClient.ts | 4 ++++ src/tasks/netSdk/NetSdkTaskHelper.ts | 2 +- 7 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 src/runtimes/docker/clients/DockerClientBase/withDockerExposesArg.ts diff --git a/src/debugging/DockerPlatformHelper.ts b/src/debugging/DockerPlatformHelper.ts index de09528e35..17c8db27c0 100644 --- a/src/debugging/DockerPlatformHelper.ts +++ b/src/debugging/DockerPlatformHelper.ts @@ -16,7 +16,7 @@ interface DockerPlatformConfiguration { } export function getPlatform(configuration: T): DockerPlatform | undefined { - if (netSdkDebugHelper.isDotnetSdkBuild(configuration?.preLaunchTask) && configuration.netCore !== undefined) { + if (netSdkDebugHelper.isDotNetSdkBuild(configuration?.preLaunchTask) && configuration.netCore !== undefined) { return 'netSdk'; } else if (configuration.platform === 'netCore' || configuration.netCore !== undefined) { return 'netCore'; diff --git a/src/debugging/netSdk/NetSdkDebugHelper.ts b/src/debugging/netSdk/NetSdkDebugHelper.ts index 0ed9ac55f6..3aae79ed9b 100644 --- a/src/debugging/netSdk/NetSdkDebugHelper.ts +++ b/src/debugging/netSdk/NetSdkDebugHelper.ts @@ -44,7 +44,7 @@ export class NetSdkDebugHelper extends NetCoreDebugHelper { * @returns true if the launch task is using the .NET SDK Container build * false otherwise */ - public isDotnetSdkBuild(preLaunchTask: string): boolean { + public isDotNetSdkBuild(preLaunchTask: string): boolean { return preLaunchTask === NetSdkTaskFullSymbol; } } diff --git a/src/debugging/netcore/NetCoreDebugHelper.ts b/src/debugging/netcore/NetCoreDebugHelper.ts index 23d8b779da..f2828c3256 100644 --- a/src/debugging/netcore/NetCoreDebugHelper.ts +++ b/src/debugging/netcore/NetCoreDebugHelper.ts @@ -92,7 +92,7 @@ export class NetCoreDebugHelper implements DebugHelper { const additionalProbingPathsArgs = NetCoreDebugHelper.getAdditionalProbingPathsArgs(platformOS); - const containerAppOutput = netSdkDebugHelper.isDotnetSdkBuild(debugConfiguration?.preLaunchTask) + const containerAppOutput = netSdkDebugHelper.isDotNetSdkBuild(debugConfiguration?.preLaunchTask) ? appOutput : NetCoreDebugHelper.getContainerAppOutput(debugConfiguration, appOutput, platformOS); @@ -187,7 +187,7 @@ export class NetCoreDebugHelper implements DebugHelper { throw new Error(l10n.t('Unable to determine assembly output path.')); } - if (netSdkDebugHelper.isDotnetSdkBuild(debugConfiguration.preLaunchTask) && projectInfo.length >= 5) { // if .NET has support for SDK Build + if (netSdkDebugHelper.isDotNetSdkBuild(debugConfiguration.preLaunchTask) && projectInfo.length >= 5) { // if .NET has support for SDK Build if (projectInfo[4] === 'true') { // fifth is whether .NET supports SDK Containers return projectInfo[3]; // fourth is output path } else { diff --git a/src/runtimes/docker/clients/DockerClientBase/DockerClientBase.ts b/src/runtimes/docker/clients/DockerClientBase/DockerClientBase.ts index 1c3cfd7c7f..f35b608bf3 100644 --- a/src/runtimes/docker/clients/DockerClientBase/DockerClientBase.ts +++ b/src/runtimes/docker/clients/DockerClientBase/DockerClientBase.ts @@ -106,6 +106,7 @@ import { withContainerPathArg } from './withContainerPathArg'; import { withDockerAddHostArg } from './withDockerAddHostArg'; import { withDockerBuildArg } from './withDockerBuildArg'; import { withDockerEnvArg } from './withDockerEnvArg'; +import { withDockerExposesArg } from './withDockerExposesArg'; import { withDockerBooleanFilterArg, withDockerFilterArg } from './withDockerFilterArg'; import { withDockerIgnoreSizeArg } from './withDockerIgnoreSizeArg'; import { withDockerJsonFormatArg } from "./withDockerJsonFormatArg"; @@ -683,6 +684,7 @@ export abstract class DockerClientBase extends ConfigurableClient implements ICo withDockerEnvArg(options.environmentVariables), withNamedArg('--env-file', options.environmentFiles), withNamedArg('--entrypoint', options.entrypoint), + withDockerExposesArg(options.exposes), withVerbatimArg(options.customOptions), withArg(options.imageRef), typeof options.command === 'string' ? withVerbatimArg(options.command) : withArg(...(toArray(options.command || []))), diff --git a/src/runtimes/docker/clients/DockerClientBase/withDockerExposesArg.ts b/src/runtimes/docker/clients/DockerClientBase/withDockerExposesArg.ts new file mode 100644 index 0000000000..4386798641 --- /dev/null +++ b/src/runtimes/docker/clients/DockerClientBase/withDockerExposesArg.ts @@ -0,0 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { withNamedArg } from "../../utils/commandLineBuilder"; + +export function withDockerExposesArg(ports?: Array) { + return withNamedArg('--expose', ports.toString(), { shouldQuote: false }); +} diff --git a/src/runtimes/docker/contracts/ContainerClient.ts b/src/runtimes/docker/contracts/ContainerClient.ts index 6ebc507c15..5393e1fae0 100644 --- a/src/runtimes/docker/contracts/ContainerClient.ts +++ b/src/runtimes/docker/contracts/ContainerClient.ts @@ -744,6 +744,10 @@ export type RunContainerCommandOptions = CommonCommandOptions & { * Optional command to use in starting the container */ command?: Array | string; + /** + * Optional expose ports for the container + */ + exposes?: Array; /** * Additional custom options to pass */ diff --git a/src/tasks/netSdk/NetSdkTaskHelper.ts b/src/tasks/netSdk/NetSdkTaskHelper.ts index ae98972b13..fc2408a94d 100644 --- a/src/tasks/netSdk/NetSdkTaskHelper.ts +++ b/src/tasks/netSdk/NetSdkTaskHelper.ts @@ -75,7 +75,7 @@ export class NetSdkTaskHelper { imageRef: getDefaultImageName(folderName.name, NetSdkDefaultImageTag), labels: defaultVsCodeLabels, mounts: await this.getRemoteDebuggerMount(), - customOptions: '--expose 8080', + exposes: [8080], // hard coded for now since the default port is 8080 entrypoint: '/bin/sh' }); From e9f462682338708728872232a9376afea4dfa94d Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Tue, 13 Jun 2023 11:36:07 -0400 Subject: [PATCH 41/46] converted netSdkHelper class into methods only --- src/tasks/TaskHelper.ts | 3 +- src/tasks/netSdk/NetSdkRunTaskProvider.ts | 8 +- src/tasks/netSdk/NetSdkTaskHelper.ts | 138 ---------------------- src/tasks/netSdk/netSdkTaskUtils.ts | 133 +++++++++++++++++++++ 4 files changed, 138 insertions(+), 144 deletions(-) delete mode 100644 src/tasks/netSdk/NetSdkTaskHelper.ts create mode 100644 src/tasks/netSdk/netSdkTaskUtils.ts diff --git a/src/tasks/TaskHelper.ts b/src/tasks/TaskHelper.ts index 2cd98dd169..1b7cd8797c 100644 --- a/src/tasks/TaskHelper.ts +++ b/src/tasks/TaskHelper.ts @@ -21,7 +21,6 @@ import { DockerContainerVolume, DockerRunOptions, DockerRunTaskDefinitionBase } import { DockerRunTask, DockerRunTaskDefinition, DockerRunTaskProvider } from './DockerRunTaskProvider'; import { TaskDefinitionBase } from './TaskDefinitionBase'; import { NetSdkRunTaskProvider } from './netSdk/NetSdkRunTaskProvider'; -import { netTaskHelper } from './netSdk/NetSdkTaskHelper'; import { netCoreTaskHelper } from './netcore/NetCoreTaskHelper'; import { nodeTaskHelper } from './node/NodeTaskHelper'; import { pythonTaskHelper } from './python/PythonTaskHelper'; @@ -107,7 +106,7 @@ export function registerTaskProviders(ctx: ExtensionContext): void { ctx.subscriptions.push( tasks.registerTaskProvider( 'dotnet-container-sdk', - new NetSdkRunTaskProvider(netTaskHelper) + new NetSdkRunTaskProvider() ) ); } diff --git a/src/tasks/netSdk/NetSdkRunTaskProvider.ts b/src/tasks/netSdk/NetSdkRunTaskProvider.ts index d2d22a850b..c17ade759c 100644 --- a/src/tasks/netSdk/NetSdkRunTaskProvider.ts +++ b/src/tasks/netSdk/NetSdkRunTaskProvider.ts @@ -7,12 +7,12 @@ import { CancellationToken, CustomExecution, Task, TaskDefinition, TaskScope } f import { DockerPseudoterminal } from "../DockerPseudoterminal"; import { DockerTaskProvider } from '../DockerTaskProvider'; import { DockerTaskExecutionContext } from '../TaskHelper'; -import { NetSdkRunTaskType, NetSdkTaskHelper } from './NetSdkTaskHelper'; +import { NetSdkRunTaskType, getNetSdkBuildCommand, getNetSdkRunCommand } from './netSdkTaskUtils'; const NetSdkDebugTaskName = 'debug'; export class NetSdkRunTaskProvider extends DockerTaskProvider { - public constructor(protected readonly helper: NetSdkTaskHelper) { super(NetSdkRunTaskType, undefined); } + public constructor() { super(NetSdkRunTaskType, undefined); } public provideTasks(token: CancellationToken): Task[] { @@ -34,7 +34,7 @@ export class NetSdkRunTaskProvider extends DockerTaskProvider { protected async executeTaskInternal(context: DockerTaskExecutionContext, task: Task): Promise { // use dotnet to build the image - const buildCommand = await this.helper.getNetSdkBuildCommand(context); + const buildCommand = await getNetSdkBuildCommand(context); await context.terminal.execAsyncInTerminal( buildCommand, { @@ -44,7 +44,7 @@ export class NetSdkRunTaskProvider extends DockerTaskProvider { ); // use docker run to run the image - const runCommand = await this.helper.getNetSdkRunCommand(context); + const runCommand = await getNetSdkRunCommand(context); await context.terminal.execAsyncInTerminal( runCommand, { diff --git a/src/tasks/netSdk/NetSdkTaskHelper.ts b/src/tasks/netSdk/NetSdkTaskHelper.ts deleted file mode 100644 index fc2408a94d..0000000000 --- a/src/tasks/netSdk/NetSdkTaskHelper.ts +++ /dev/null @@ -1,138 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See LICENSE.md in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IActionContext } from "@microsoft/vscode-azext-utils"; -import * as os from 'os'; -import { WorkspaceFolder, l10n } from "vscode"; -import { vsDbgInstallBasePath } from "../../debugging/netcore/VsDbgHelper"; -import { ext } from "../../extensionVariables"; -import { RunContainerBindMount, Shell, composeArgs, withArg, withNamedArg } from "../../runtimes/docker"; -import { getValidImageName } from "../../utils/getValidImageName"; -import { getDockerOSType } from "../../utils/osUtils"; -import { quickPickProjectFileItem } from "../../utils/quickPickFile"; -import { quickPickWorkspaceFolder } from "../../utils/quickPickWorkspaceFolder"; -import { DockerContainerVolume } from "../DockerRunTaskDefinitionBase"; -import { defaultVsCodeLabels } from "../TaskDefinitionBase"; -import { DockerTaskExecutionContext, addVolumeWithoutConflicts, getDefaultContainerName, getDefaultImageName, getMounts } from "../TaskHelper"; -import { NetCoreTaskHelper } from "../netcore/NetCoreTaskHelper"; - -/** - * Native architecture of the current machine in the RID format - * {@link https://github.com/dotnet/runtime/blob/main/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json} - */ -export type RidCpuArchitecture = - | 'x64' - | 'x86' - | 'arm64' - | 'arm' - | 'ppc64le' - | 'mips64' - | 's390x' - | string; - -export const NetSdkRunTaskType = 'dotnet-container-sdk'; -const NetSdkDefaultImageTag = 'dev'; // intentionally default to dev tag for phase 1 of this feature -const ErrMsgNoWorkplaceFolder = l10n.t(`Unable to determine task scope to execute task ${NetSdkRunTaskType}. Please open a workspace folder.`); - -export class NetSdkTaskHelper { - - public async getNetSdkBuildCommand(context: DockerTaskExecutionContext): Promise { - - const configuration = 'Debug'; // intentionally default to Debug configuration for phase 1 of this feature - const projPath = await this.inferProjPath(context.actionContext, context.folder); - - // {@link https://github.com/dotnet/sdk-container-builds/issues/141} this could change in the future - const publishFlag = NetCoreTaskHelper.isWebApp(projPath) ? '-p:PublishProfile=DefaultContainer' : '/t:PublishContainer'; - - const folderName = await quickPickWorkspaceFolder(context.actionContext, ErrMsgNoWorkplaceFolder); - - const args = composeArgs( - withArg('dotnet', 'publish'), - withNamedArg('--os', await this.normalizeOsToRid()), - withNamedArg('--arch', await this.normalizeArchitectureToRid()), - withArg(publishFlag), - withNamedArg('--configuration', configuration), - withNamedArg('-p:ContainerImageName', getValidImageName(folderName.name), { assignValue: true }), - withNamedArg('-p:ContainerImageTag', NetSdkDefaultImageTag, { assignValue: true }) - )(); - - const quotedArgs = Shell.getShellOrDefault().quote(args); - return quotedArgs.join(' '); - } - - public async getNetSdkRunCommand(context: DockerTaskExecutionContext): Promise { - const client = await ext.runtimeManager.getClient(); - const folderName = await quickPickWorkspaceFolder(context.actionContext, ErrMsgNoWorkplaceFolder); - - const command = await client.runContainer({ - detached: true, - publishAllPorts: true, - name: getDefaultContainerName(folderName.name, NetSdkDefaultImageTag), - environmentVariables: {}, - removeOnExit: true, - imageRef: getDefaultImageName(folderName.name, NetSdkDefaultImageTag), - labels: defaultVsCodeLabels, - mounts: await this.getRemoteDebuggerMount(), - exposes: [8080], // hard coded for now since the default port is 8080 - entrypoint: '/bin/sh' - }); - - const quotedArgs = Shell.getShellOrDefault().quote(command.args); - const commandLine = [client.commandName, ...quotedArgs].join(' '); - - return commandLine; - } - - public async inferProjPath(context: IActionContext, folder: WorkspaceFolder): Promise { - const noProjectFileErrMessage = l10n.t('No .csproj file could be found.'); - const item = await quickPickProjectFileItem(context, undefined, folder, noProjectFileErrMessage); - return item.absoluteFilePath; - } - - /** - * This method normalizes the Docker OS type to match the .NET Core SDK conventions. - * {@link https://learn.microsoft.com/en-us/dotnet/core/rid-catalog} - */ - private async normalizeOsToRid(): Promise<'linux' | 'win'> { - const dockerOsType = await getDockerOSType(); - return dockerOsType === 'windows' ? 'win' : 'linux'; - } - - /** - * This method normalizes the native architecture to match the .NET Core SDK conventions. - * {@link https://learn.microsoft.com/en-us/dotnet/core/rid-catalog} - */ - private async normalizeArchitectureToRid(): Promise { - const architecture = os.arch(); - switch (architecture) { - case 'x32': - case 'ia32': - return 'x86'; - default: - return architecture; - } - } - - /** - * This methods returns the mount for the remote debugger ONLY as the SDK built container will have - * everything it needs to run the app already inside. - */ - private async getRemoteDebuggerMount(): Promise { - const volumes: DockerContainerVolume[] = []; - const isLinux = await getDockerOSType() === 'linux'; - - const debuggerVolume: DockerContainerVolume = { - localPath: vsDbgInstallBasePath, - containerPath: isLinux ? '/remote_debugger' : 'C:\\remote_debugger', - permissions: 'ro' - }; - - addVolumeWithoutConflicts(volumes, debuggerVolume); - return getMounts(volumes); - } -} - -export const netTaskHelper = new NetSdkTaskHelper(); - diff --git a/src/tasks/netSdk/netSdkTaskUtils.ts b/src/tasks/netSdk/netSdkTaskUtils.ts new file mode 100644 index 0000000000..beaa834de8 --- /dev/null +++ b/src/tasks/netSdk/netSdkTaskUtils.ts @@ -0,0 +1,133 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE.md in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IActionContext } from '@microsoft/vscode-azext-utils'; +import * as os from 'os'; +import { WorkspaceFolder, l10n } from "vscode"; +import { vsDbgInstallBasePath } from "../../debugging/netcore/VsDbgHelper"; +import { ext } from "../../extensionVariables"; +import { RunContainerBindMount, Shell, composeArgs, withArg, withNamedArg } from "../../runtimes/docker"; +import { getValidImageName } from "../../utils/getValidImageName"; +import { getDockerOSType } from "../../utils/osUtils"; +import { quickPickProjectFileItem } from "../../utils/quickPickFile"; +import { quickPickWorkspaceFolder } from "../../utils/quickPickWorkspaceFolder"; +import { DockerContainerVolume } from "../DockerRunTaskDefinitionBase"; +import { defaultVsCodeLabels } from "../TaskDefinitionBase"; +import { DockerTaskExecutionContext, addVolumeWithoutConflicts, getDefaultContainerName, getDefaultImageName, getMounts } from "../TaskHelper"; +import { NetCoreTaskHelper } from "../netcore/NetCoreTaskHelper"; + +/** + * Native architecture of the current machine in the RID format + * {@link https://github.com/dotnet/runtime/blob/main/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json} + */ +export type RidCpuArchitecture = + | 'x64' + | 'x86' + | 'arm64' + | 'arm' + | 'ppc64le' + | 'mips64' + | 's390x' + | string; + +export const NetSdkRunTaskType = 'dotnet-container-sdk'; +const NetSdkDefaultImageTag = 'dev'; // intentionally default to dev tag for phase 1 of this feature +const ErrMsgNoWorkplaceFolder = l10n.t(`Unable to determine task scope to execute task ${NetSdkRunTaskType}. Please open a workspace folder.`); + +export async function getNetSdkBuildCommand(context: DockerTaskExecutionContext): Promise { + + const configuration = 'Debug'; // intentionally default to Debug configuration for phase 1 of this feature + const projPath = await inferProjPath(context.actionContext, context.folder); + + // {@link https://github.com/dotnet/sdk-container-builds/issues/141} this could change in the future + const publishFlag = NetCoreTaskHelper.isWebApp(projPath) ? '-p:PublishProfile=DefaultContainer' : '/t:PublishContainer'; + + const folderName = await quickPickWorkspaceFolder(context.actionContext, ErrMsgNoWorkplaceFolder); + + const args = composeArgs( + withArg('dotnet', 'publish'), + withNamedArg('--os', await normalizeOsToRid()), + withNamedArg('--arch', await normalizeArchitectureToRid()), + withArg(publishFlag), + withNamedArg('--configuration', configuration), + withNamedArg('-p:ContainerImageName', getValidImageName(folderName.name), { assignValue: true }), + withNamedArg('-p:ContainerImageTag', NetSdkDefaultImageTag, { assignValue: true }) + )(); + + const quotedArgs = Shell.getShellOrDefault().quote(args); + return quotedArgs.join(' '); +} + +export async function getNetSdkRunCommand(context: DockerTaskExecutionContext): Promise { + const client = await ext.runtimeManager.getClient(); + const folderName = await quickPickWorkspaceFolder(context.actionContext, ErrMsgNoWorkplaceFolder); + + const command = await client.runContainer({ + detached: true, + publishAllPorts: true, + name: getDefaultContainerName(folderName.name, NetSdkDefaultImageTag), + environmentVariables: {}, + removeOnExit: true, + imageRef: getDefaultImageName(folderName.name, NetSdkDefaultImageTag), + labels: defaultVsCodeLabels, + mounts: await getRemoteDebuggerMount(), + exposes: [8080], // hard coded for now since the default port is 8080 + entrypoint: '/bin/sh' + }); + + const quotedArgs = Shell.getShellOrDefault().quote(command.args); + const commandLine = [client.commandName, ...quotedArgs].join(' '); + return commandLine; +} + +async function inferProjPath(context: IActionContext, folder: WorkspaceFolder): Promise { + const noProjectFileErrMessage = l10n.t('No .csproj file could be found.'); + const item = await quickPickProjectFileItem(context, undefined, folder, noProjectFileErrMessage); + return item.absoluteFilePath; +} + +/** + * This method normalizes the Docker OS type to match the .NET Core SDK conventions. + * {@link https://learn.microsoft.com/en-us/dotnet/core/rid-catalog} + */ +async function normalizeOsToRid(): Promise<'linux' | 'win'> { + const dockerOsType = await getDockerOSType(); + return dockerOsType === 'windows' ? 'win' : 'linux'; +} + +/** + * This method normalizes the native architecture to match the .NET Core SDK conventions. + * {@link https://learn.microsoft.com/en-us/dotnet/core/rid-catalog} + */ +async function normalizeArchitectureToRid(): Promise { + const architecture = os.arch(); + switch (architecture) { + case 'x32': + case 'ia32': + return 'x86'; + default: + return architecture; + } +} + +/** + * This methods returns the mount for the remote debugger ONLY as the SDK built container will have + * everything it needs to run the app already inside. + */ +async function getRemoteDebuggerMount(): Promise { + const volumes: DockerContainerVolume[] = []; + const isLinux = await getDockerOSType() === 'linux'; + + const debuggerVolume: DockerContainerVolume = { + localPath: vsDbgInstallBasePath, + containerPath: isLinux ? '/remote_debugger' : 'C:\\remote_debugger', + permissions: 'ro' + }; + + addVolumeWithoutConflicts(volumes, debuggerVolume); + return getMounts(volumes); +} + + From 63f86e8bd9cb224a8d31008ba9451b9c7ca19196 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Tue, 13 Jun 2023 12:17:36 -0400 Subject: [PATCH 42/46] minor change to make debugger mount more flexible --- src/tasks/netSdk/netSdkTaskUtils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tasks/netSdk/netSdkTaskUtils.ts b/src/tasks/netSdk/netSdkTaskUtils.ts index beaa834de8..733932eb46 100644 --- a/src/tasks/netSdk/netSdkTaskUtils.ts +++ b/src/tasks/netSdk/netSdkTaskUtils.ts @@ -118,11 +118,11 @@ async function normalizeArchitectureToRid(): Promise { */ async function getRemoteDebuggerMount(): Promise { const volumes: DockerContainerVolume[] = []; - const isLinux = await getDockerOSType() === 'linux'; + const isWindows = await getDockerOSType() === 'windows'; const debuggerVolume: DockerContainerVolume = { localPath: vsDbgInstallBasePath, - containerPath: isLinux ? '/remote_debugger' : 'C:\\remote_debugger', + containerPath: isWindows ? 'C:\\remote_debugger' : '/remote_debugger', permissions: 'ro' }; From f49d5178a9df68e10beb3e8b5fe70bd14edaf29b Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Tue, 13 Jun 2023 15:34:44 -0400 Subject: [PATCH 43/46] simplified logic for mounting debugger --- src/tasks/DockerRunTaskProvider.ts | 18 +++++++++++++++--- src/tasks/TaskHelper.ts | 13 +------------ src/tasks/netSdk/netSdkTaskUtils.ts | 19 +++++++------------ 3 files changed, 23 insertions(+), 27 deletions(-) diff --git a/src/tasks/DockerRunTaskProvider.ts b/src/tasks/DockerRunTaskProvider.ts index b4924dcdff..ded5b83ca8 100644 --- a/src/tasks/DockerRunTaskProvider.ts +++ b/src/tasks/DockerRunTaskProvider.ts @@ -6,13 +6,14 @@ import { l10n, Task } from 'vscode'; import { DockerPlatform } from '../debugging/DockerPlatformHelper'; import { ext } from '../extensionVariables'; +import { RunContainerBindMount } from '../runtimes/docker'; import { cloneObject } from '../utils/cloneObject'; -import { DockerRunOptions } from './DockerRunTaskDefinitionBase'; +import { DockerContainerVolume, DockerRunOptions } from './DockerRunTaskDefinitionBase'; import { DockerTaskProvider } from './DockerTaskProvider'; import { NetCoreRunTaskDefinition } from './netcore/NetCoreTaskHelper'; import { NodeRunTaskDefinition } from './node/NodeTaskHelper'; import { defaultVsCodeLabels, getAggregateLabels } from './TaskDefinitionBase'; -import { DockerRunTaskContext, getAssociatedDockerBuildTask, getMounts, TaskHelper, throwIfCancellationRequested } from './TaskHelper'; +import { DockerRunTaskContext, getAssociatedDockerBuildTask, TaskHelper, throwIfCancellationRequested } from './TaskHelper'; export interface DockerRunTaskDefinition extends NetCoreRunTaskDefinition, NodeRunTaskDefinition { label?: string; @@ -63,7 +64,7 @@ export class DockerRunTaskProvider extends DockerTaskProvider { environmentVariables: options.env, environmentFiles: options.envFiles, labels: getAggregateLabels(options.labels, defaultVsCodeLabels), - mounts: getMounts(options.volumes), + mounts: this.getMounts(options.volumes), ports: options.ports, addHost: options.extraHosts, entrypoint: options.entrypoint, @@ -91,4 +92,15 @@ export class DockerRunTaskProvider extends DockerTaskProvider { throw new Error(l10n.t('No Docker image name was provided or resolved.')); } } + + private getMounts(volumes?: DockerContainerVolume[]): RunContainerBindMount[] | undefined { + return volumes?.map(v => { + return { + source: v.localPath, + destination: v.containerPath, + readOnly: v.permissions === 'ro' || (v.permissions as unknown === 'ro,z'), // Maintain compatibility with old `ro,z` option as much as possible + type: 'bind', + }; + }); + } } diff --git a/src/tasks/TaskHelper.ts b/src/tasks/TaskHelper.ts index 1b7cd8797c..3d0c93dc8e 100644 --- a/src/tasks/TaskHelper.ts +++ b/src/tasks/TaskHelper.ts @@ -9,7 +9,7 @@ import { CancellationToken, ConfigurationTarget, ExtensionContext, QuickPickItem import { DebugConfigurationBase } from '../debugging/DockerDebugConfigurationBase'; import { DockerDebugConfiguration } from '../debugging/DockerDebugConfigurationProvider'; import { DockerPlatform } from '../debugging/DockerPlatformHelper'; -import { ContainerPlatform, RunContainerBindMount } from '../runtimes/docker'; +import { ContainerPlatform } from '../runtimes/docker'; import { getValidImageName, getValidImageNameWithTag } from '../utils/getValidImageName'; import { pathNormalize } from '../utils/pathNormalize'; import { resolveVariables } from '../utils/resolveVariables'; @@ -286,14 +286,3 @@ export function normalizePlatform(platform: string | ContainerPlatform): Contain return platform as ContainerPlatform || undefined; } - -export function getMounts(volumes?: DockerContainerVolume[]): RunContainerBindMount[] | undefined { - return volumes?.map(v => { - return { - source: v.localPath, - destination: v.containerPath, - readOnly: v.permissions === 'ro' || (v.permissions as unknown === 'ro,z'), // Maintain compatibility with old `ro,z` option as much as possible - type: 'bind', - }; - }); -} diff --git a/src/tasks/netSdk/netSdkTaskUtils.ts b/src/tasks/netSdk/netSdkTaskUtils.ts index 733932eb46..eeb45413ed 100644 --- a/src/tasks/netSdk/netSdkTaskUtils.ts +++ b/src/tasks/netSdk/netSdkTaskUtils.ts @@ -13,9 +13,8 @@ import { getValidImageName } from "../../utils/getValidImageName"; import { getDockerOSType } from "../../utils/osUtils"; import { quickPickProjectFileItem } from "../../utils/quickPickFile"; import { quickPickWorkspaceFolder } from "../../utils/quickPickWorkspaceFolder"; -import { DockerContainerVolume } from "../DockerRunTaskDefinitionBase"; import { defaultVsCodeLabels } from "../TaskDefinitionBase"; -import { DockerTaskExecutionContext, addVolumeWithoutConflicts, getDefaultContainerName, getDefaultImageName, getMounts } from "../TaskHelper"; +import { DockerTaskExecutionContext, getDefaultContainerName, getDefaultImageName } from "../TaskHelper"; import { NetCoreTaskHelper } from "../netcore/NetCoreTaskHelper"; /** @@ -117,17 +116,13 @@ async function normalizeArchitectureToRid(): Promise { * everything it needs to run the app already inside. */ async function getRemoteDebuggerMount(): Promise { - const volumes: DockerContainerVolume[] = []; - const isWindows = await getDockerOSType() === 'windows'; - - const debuggerVolume: DockerContainerVolume = { - localPath: vsDbgInstallBasePath, - containerPath: isWindows ? 'C:\\remote_debugger' : '/remote_debugger', - permissions: 'ro' + const debuggerVolume: RunContainerBindMount = { + type: 'bind', + source: vsDbgInstallBasePath, + destination: await getDockerOSType() === 'windows' ? 'C:\\remote_debugger' : '/remote_debugger', + readOnly: true }; - - addVolumeWithoutConflicts(volumes, debuggerVolume); - return getMounts(volumes); + return [debuggerVolume]; } From 2747b83532c7a728855d4ca150ec1b23f738dfde Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Wed, 14 Jun 2023 09:53:50 -0400 Subject: [PATCH 44/46] changed naming of expose ports --- .../docker/clients/DockerClientBase/DockerClientBase.ts | 4 ++-- .../{withDockerExposesArg.ts => withDockerExposePortsArg.ts} | 4 ++-- src/runtimes/docker/contracts/ContainerClient.ts | 2 +- src/tasks/netSdk/netSdkTaskUtils.ts | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) rename src/runtimes/docker/clients/DockerClientBase/{withDockerExposesArg.ts => withDockerExposePortsArg.ts} (70%) diff --git a/src/runtimes/docker/clients/DockerClientBase/DockerClientBase.ts b/src/runtimes/docker/clients/DockerClientBase/DockerClientBase.ts index f35b608bf3..65379de30e 100644 --- a/src/runtimes/docker/clients/DockerClientBase/DockerClientBase.ts +++ b/src/runtimes/docker/clients/DockerClientBase/DockerClientBase.ts @@ -106,7 +106,7 @@ import { withContainerPathArg } from './withContainerPathArg'; import { withDockerAddHostArg } from './withDockerAddHostArg'; import { withDockerBuildArg } from './withDockerBuildArg'; import { withDockerEnvArg } from './withDockerEnvArg'; -import { withDockerExposesArg } from './withDockerExposesArg'; +import { withDockerExposePortsArg } from './withDockerExposePortsArg'; import { withDockerBooleanFilterArg, withDockerFilterArg } from './withDockerFilterArg'; import { withDockerIgnoreSizeArg } from './withDockerIgnoreSizeArg'; import { withDockerJsonFormatArg } from "./withDockerJsonFormatArg"; @@ -684,7 +684,7 @@ export abstract class DockerClientBase extends ConfigurableClient implements ICo withDockerEnvArg(options.environmentVariables), withNamedArg('--env-file', options.environmentFiles), withNamedArg('--entrypoint', options.entrypoint), - withDockerExposesArg(options.exposes), + withDockerExposePortsArg(options.exposePorts), withVerbatimArg(options.customOptions), withArg(options.imageRef), typeof options.command === 'string' ? withVerbatimArg(options.command) : withArg(...(toArray(options.command || []))), diff --git a/src/runtimes/docker/clients/DockerClientBase/withDockerExposesArg.ts b/src/runtimes/docker/clients/DockerClientBase/withDockerExposePortsArg.ts similarity index 70% rename from src/runtimes/docker/clients/DockerClientBase/withDockerExposesArg.ts rename to src/runtimes/docker/clients/DockerClientBase/withDockerExposePortsArg.ts index 4386798641..31d0e43f73 100644 --- a/src/runtimes/docker/clients/DockerClientBase/withDockerExposesArg.ts +++ b/src/runtimes/docker/clients/DockerClientBase/withDockerExposePortsArg.ts @@ -5,6 +5,6 @@ import { withNamedArg } from "../../utils/commandLineBuilder"; -export function withDockerExposesArg(ports?: Array) { - return withNamedArg('--expose', ports.toString(), { shouldQuote: false }); +export function withDockerExposePortsArg(ports?: Array) { + return withNamedArg('--expose', (ports || []).map(port => port.toString()), { shouldQuote: false }); } diff --git a/src/runtimes/docker/contracts/ContainerClient.ts b/src/runtimes/docker/contracts/ContainerClient.ts index 5393e1fae0..417dbd4443 100644 --- a/src/runtimes/docker/contracts/ContainerClient.ts +++ b/src/runtimes/docker/contracts/ContainerClient.ts @@ -747,7 +747,7 @@ export type RunContainerCommandOptions = CommonCommandOptions & { /** * Optional expose ports for the container */ - exposes?: Array; + exposePorts?: Array; /** * Additional custom options to pass */ diff --git a/src/tasks/netSdk/netSdkTaskUtils.ts b/src/tasks/netSdk/netSdkTaskUtils.ts index eeb45413ed..2d5463ea7d 100644 --- a/src/tasks/netSdk/netSdkTaskUtils.ts +++ b/src/tasks/netSdk/netSdkTaskUtils.ts @@ -72,7 +72,7 @@ export async function getNetSdkRunCommand(context: DockerTaskExecutionContext): imageRef: getDefaultImageName(folderName.name, NetSdkDefaultImageTag), labels: defaultVsCodeLabels, mounts: await getRemoteDebuggerMount(), - exposes: [8080], // hard coded for now since the default port is 8080 + exposePorts: [8080], // hard coded for now since the default port is 8080 entrypoint: '/bin/sh' }); From 9d4e45edef75a40088bc07fd4af01741ce4b0960 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Wed, 14 Jun 2023 16:57:17 -0400 Subject: [PATCH 45/46] updated if condition for checking for empty debug config --- src/debugging/DockerDebugConfigurationProvider.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/debugging/DockerDebugConfigurationProvider.ts b/src/debugging/DockerDebugConfigurationProvider.ts index 9228cebc1d..0e4a56e276 100644 --- a/src/debugging/DockerDebugConfigurationProvider.ts +++ b/src/debugging/DockerDebugConfigurationProvider.ts @@ -70,9 +70,7 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi } } - if (debugConfiguration.type === undefined && - debugConfiguration.request === undefined && - debugConfiguration.name === undefined) { + if (Object.keys(debugConfiguration).length === 0) { const newlyCreatedDebugConfig = await this.handleEmptyDebugConfig(folder, actionContext); // if there is no debugConfiguration, we should return undefined to exit the debug session From fd4f75b9599c245546b334ef0d169bdfb712f251 Mon Sep 17 00:00:00 2001 From: alexyaang <59073590+alexyaang@users.noreply.github.com> Date: Thu, 15 Jun 2023 13:11:36 -0400 Subject: [PATCH 46/46] renamed helper methods in sdk task utils --- src/tasks/netSdk/netSdkTaskUtils.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tasks/netSdk/netSdkTaskUtils.ts b/src/tasks/netSdk/netSdkTaskUtils.ts index 2d5463ea7d..d4e062cef2 100644 --- a/src/tasks/netSdk/netSdkTaskUtils.ts +++ b/src/tasks/netSdk/netSdkTaskUtils.ts @@ -47,8 +47,8 @@ export async function getNetSdkBuildCommand(context: DockerTaskExecutionContext) const args = composeArgs( withArg('dotnet', 'publish'), - withNamedArg('--os', await normalizeOsToRid()), - withNamedArg('--arch', await normalizeArchitectureToRid()), + withNamedArg('--os', await normalizeOsToRidOs()), + withNamedArg('--arch', await normalizeArchitectureToRidArchitecture()), withArg(publishFlag), withNamedArg('--configuration', configuration), withNamedArg('-p:ContainerImageName', getValidImageName(folderName.name), { assignValue: true }), @@ -91,7 +91,7 @@ async function inferProjPath(context: IActionContext, folder: WorkspaceFolder): * This method normalizes the Docker OS type to match the .NET Core SDK conventions. * {@link https://learn.microsoft.com/en-us/dotnet/core/rid-catalog} */ -async function normalizeOsToRid(): Promise<'linux' | 'win'> { +async function normalizeOsToRidOs(): Promise<'linux' | 'win'> { const dockerOsType = await getDockerOSType(); return dockerOsType === 'windows' ? 'win' : 'linux'; } @@ -100,7 +100,7 @@ async function normalizeOsToRid(): Promise<'linux' | 'win'> { * This method normalizes the native architecture to match the .NET Core SDK conventions. * {@link https://learn.microsoft.com/en-us/dotnet/core/rid-catalog} */ -async function normalizeArchitectureToRid(): Promise { +async function normalizeArchitectureToRidArchitecture(): Promise { const architecture = os.arch(); switch (architecture) { case 'x32':