Merge branch 'main' into bmw/esbuild

This commit is contained in:
Brandon Waterloo [MSFT] 2023-07-13 10:01:06 -04:00
Родитель 638239b51b 77cc028a19
Коммит 6c2b970277
39 изменённых файлов: 11900 добавлений и 1099 удалений

Просмотреть файл

@ -3,6 +3,8 @@ trigger:
- main
- rel/*
pr: none # Disable PR trigger
# Scheduled nightly build
schedules:
- cron: "0 0 * * *"

Просмотреть файл

@ -1,3 +1,18 @@
## 1.26.0 - 10 July 2023
### Added
* Added support for debugging .NET projects with .NET SDK container build. [#3808](https://github.com/microsoft/vscode-docker/issues/3808)
* Introduced optional status bar item displaying the current Docker context. [#3690](https://github.com/microsoft/vscode-docker/issues/3690)
* Enabled customization of entry point for docker run tasks. [#3831](https://github.com/microsoft/vscode-docker/issues/3831)
### Fixed
* Updated Dockerfile language server to ignore empty continuation lines in COPY instructions and resolve an infinite loop caused by quotes in comments for the semantic highlighter. [#3576](https://github.com/microsoft/vscode-docker/issues/3576), [#3836](https://github.com/microsoft/vscode-docker/issues/3836)
* Resolved the failure to build Windows containers in the Build image command. [#3915](https://github.com/microsoft/vscode-docker/issues/3915)
* Fixed the issue where .NET Debugging with Docker Compose failed to hit breakpoints. [#3912](https://github.com/microsoft/vscode-docker/issues/3912)
## 1.25.2 - 23 June 2023
### Fixed
* Fixed a potential security issue involving Markdown tooltips for containers. [#3983](https://github.com/microsoft/vscode-docker/pull/3983)
## 1.25.1 - 16 May 2023
### Fixed
* The extension was not activating when a Dockerfile was opened. [#3928](https://github.com/microsoft/vscode-docker/pull/3928)

11874
NOTICE.html поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

56
package-lock.json сгенерированный
Просмотреть файл

@ -1,12 +1,12 @@
{
"name": "vscode-docker",
"version": "1.25.5-alpha",
"version": "1.26.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "vscode-docker",
"version": "1.25.5-alpha",
"version": "1.26.0",
"license": "SEE LICENSE IN LICENSE.md",
"dependencies": {
"@azure/arm-authorization": "^9.0.0",
@ -22,7 +22,7 @@
"gradle-to-js": "^2.0.1",
"handlebars": "^4.7.7",
"node-fetch": "^2.6.9",
"semver": "^7.5.0",
"semver": "^7.5.2",
"tar": "^6.1.13",
"tree-kill": "^1.2.2",
"vscode-languageclient": "^8.1.0",
@ -58,6 +58,15 @@
"vscode": "^1.75.0"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
"integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/@azure/abort-controller": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz",
@ -1659,9 +1668,9 @@
}
},
"node_modules/@vscode/vsce/node_modules/semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true,
"bin": {
"semver": "bin/semver"
@ -4803,17 +4812,17 @@
}
},
"node_modules/optionator": {
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
"integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
"version": "0.9.3",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
"integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
"dev": true,
"dependencies": {
"@aashutoshrathi/word-wrap": "^1.2.3",
"deep-is": "^0.1.3",
"fast-levenshtein": "^2.0.6",
"levn": "^0.4.1",
"prelude-ls": "^1.2.1",
"type-check": "^0.4.0",
"word-wrap": "^1.2.3"
"type-check": "^0.4.0"
},
"engines": {
"node": ">= 0.8.0"
@ -4888,9 +4897,9 @@
}
},
"node_modules/parse-semver/node_modules/semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true,
"bin": {
"semver": "bin/semver"
@ -5434,9 +5443,9 @@
}
},
"node_modules/semver": {
"version": "7.5.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz",
"integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==",
"version": "7.5.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz",
"integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==",
"dependencies": {
"lru-cache": "^6.0.0"
},
@ -6442,14 +6451,11 @@
"node": ">= 8"
}
},
"node_modules/word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
"node_modules/wildcard": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz",
"integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==",
"dev": true
},
"node_modules/wordwrap": {
"version": "1.0.0",

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "vscode-docker",
"version": "1.25.5-alpha",
"version": "1.26.0",
"publisher": "ms-azuretools",
"displayName": "Docker",
"description": "Makes it easy to create, manage, and debug containerized applications.",
@ -42,6 +42,10 @@
"contributes": {
"menus": {
"commandPalette": [
{
"command": "vscode-docker.openDockerDownloadPage",
"when": "never"
},
{
"command": "vscode-docker.containers.downloadFile",
"when": "never"
@ -636,6 +640,13 @@
{
"type": "docker",
"label": "Docker: Debug in Container",
"languages": [
"csharp",
"razor",
"aspnetcorerazor",
"vb",
"fsharp"
],
"configurationAttributes": {
"launch": {
"properties": {
@ -1500,6 +1511,35 @@
"required": [
"dockerCompose"
]
},
{
"type": "dotnet-container-sdk",
"properties": {
"netCore": {
"description": "%vscode-docker.debug.netCore.description%",
"properties": {
"appProject": {
"type": "string",
"description": "%vscode-docker.debug.netCore.appProject%"
}
},
"required": [
"appProject"
]
},
"dockerRun": {
"description": "%vscode-docker.tasks.dotnet-container-sdk.dockerRun.description%",
"properties": {
"containerName": {
"type": "string",
"description": "%vscode-docker.tasks.dotnet-container-sdk.dockerRun.containerName%"
}
},
"required": [
"containerName"
]
}
}
}
],
"languages": [
@ -2290,8 +2330,8 @@
"category": "%vscode-docker.commands.category.docker%"
},
{
"command": "vscode-docker.installDocker",
"title": "%vscode-docker.commands.installDocker%",
"command": "vscode-docker.openDockerDownloadPage",
"title": "%vscode-docker.commands.openDockerDownloadPage%",
"category": "%vscode-docker.commands.category.docker%"
},
{
@ -2993,7 +3033,7 @@
"gradle-to-js": "^2.0.1",
"handlebars": "^4.7.7",
"node-fetch": "^2.6.9",
"semver": "^7.5.0",
"semver": "^7.5.2",
"tar": "^6.1.13",
"tree-kill": "^1.2.2",
"vscode-languageclient": "^8.1.0",

Просмотреть файл

@ -123,6 +123,8 @@
"vscode-docker.tasks.docker-compose.dockerCompose.envFile.description": "File of environment variables read in and applied to the Docker containers.",
"vscode-docker.tasks.docker-compose.dockerCompose.files.description": "The docker-compose files to include, in order.",
"vscode-docker.tasks.docker-compose.dockerCompose.projectName.description": "Alternate project name to use when naming and labeling Docker objects. If using an alternate project name when composing up, the same project name must be specified when composing down.",
"vscode-docker.tasks.dotnet-container-sdk.dockerRun.description": "Options for running the Docker container used for debugging.",
"vscode-docker.tasks.dotnet-container-sdk.dockerRun.containerName": "Name of the container used for debugging.",
"vscode-docker.config.docker.promptForRegistryWhenPushingImages": "Prompt for registry selection if the image is not explicitly tagged.",
"vscode-docker.config.template.build.template": "The command template.",
"vscode-docker.config.template.build.label": "The label displayed to the user.",
@ -247,7 +249,7 @@
"vscode-docker.commands.images.runInteractive": "Run Interactive",
"vscode-docker.commands.images.tag": "Tag...",
"vscode-docker.commands.images.copyFullTag": "Copy Full Tag",
"vscode-docker.commands.installDocker": "Install Docker",
"vscode-docker.commands.openDockerDownloadPage": "Learn More About Installing Docker Desktop",
"vscode-docker.commands.networks.configureExplorer": "Configure Explorer...",
"vscode-docker.commands.networks.create": "Create...",
"vscode-docker.commands.networks.inspect": "Inspect",

Просмотреть файл

@ -1,11 +1,21 @@
<Project>
<!-- All the relevant info is in root-level PropertyGroups, so there are no dependent targets to make this work -->
<Target Name="GetProjectProperties">
<PropertyGroup>
<GetProjectPropertiesDependsOn Condition=" '$(SDKContainerSupportEnabled)' == 'true' ">$(GetProjectPropertiesDependsOn);ComputeContainerConfig;</GetProjectPropertiesDependsOn>
</PropertyGroup>
<Target Name="GetProjectProperties" DependsOnTargets="$(GetProjectPropertiesDependsOn)">
<PropertyGroup>
<InferImageName>$(ContainerRepository)</InferImageName>
<InferImageName Condition=" '$(InferImageName)' == '' ">$(ContainerImageName)</InferImageName>
</PropertyGroup>
<WriteLinesToFile
File="$(InfoOutputPath)"
Lines="$(AssemblyName).dll
$(TargetFramework)$(TargetFrameworks.Split(';')[0])
$(OutputPath)$(AssemblyName).dll"
$(OutputPath)$(AssemblyName).dll
$(ContainerWorkingDirectory)/$(AssemblyName).dll
$(SDKContainerSupportEnabled)
$(InferImageName)"
Overwrite="True" />
</Target>
</Project>

Просмотреть файл

@ -1,139 +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 vscode from 'vscode';
import { TaskCommandRunnerFactory } from '../runtimes/runners/TaskCommandRunnerFactory';
import { runtimeInstallStatusProvider } from '../utils/RuntimeInstallStatusProvider';
import { streamToFile } from '../utils/httpRequest';
import { getTempFileName, isArm64Mac, isLinux } from '../utils/osUtils';
export abstract class DockerInstallerBase {
protected abstract downloadUrl: string;
protected abstract fileExtension: string;
protected abstract getInstallCommand(fileName: string): string;
public async downloadAndInstallDocker(context: IActionContext): Promise<void> {
const shouldInstall: boolean = await this.preInstallCheck();
if (shouldInstall) {
const downloadingMessage: string = vscode.l10n.t('Downloading Docker installer...');
const installationMessage: string = vscode.l10n.t('The Docker Desktop installation is started. Complete the installation and then start Docker Desktop.');
let downloadedFileName: string;
context.telemetry.properties.stage = 'download';
try {
downloadedFileName = await vscode.window.withProgress(
{ location: vscode.ProgressLocation.Notification, title: downloadingMessage },
async () => this.downloadInstaller());
} catch (error) {
const message = vscode.l10n.t('Downloading the Docker Desktop installer failed. Do you want to manually download and install?');
const title = vscode.l10n.t('Download');
this.handleError(context, message, title, this.downloadUrl);
throw error;
}
context.telemetry.properties.stage = 'install';
const command = this.getInstallCommand(downloadedFileName);
// eslint-disable-next-line @typescript-eslint/no-floating-promises
vscode.window.showInformationMessage(installationMessage);
try {
await this.install(context, downloadedFileName, command);
} catch (error) {
const message = `${vscode.l10n.t('Docker Desktop installation failed')}. ${error}`;
const title = vscode.l10n.t('Install Instruction');
this.handleError(context, message, title, 'https://aka.ms/AA37qtj');
throw error;
}
}
}
private async preInstallCheck(): Promise<boolean> {
let proceedInstall = true;
if (await runtimeInstallStatusProvider.isRuntimeInstalledRealTimeCheck()) {
const reinstallMessage = vscode.l10n.t('Docker Desktop is already installed. Would you like to reinstall?');
const install = vscode.l10n.t('Reinstall');
const response = await vscode.window.showInformationMessage(reinstallMessage, ...[install]);
proceedInstall = response !== undefined;
}
return proceedInstall;
}
private async downloadInstaller(): Promise<string> {
const fileName = `${getTempFileName()}.${this.fileExtension}`;
await streamToFile(this.downloadUrl, fileName);
return fileName;
}
private handleError(context: IActionContext, message: string, title: string, url: string): void {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
vscode.window.showErrorMessage(message, { title: title }).then(response => { if (response) { vscode.env.openExternal(vscode.Uri.parse(url)); } });
context.errorHandling.suppressReportIssue = true;
context.errorHandling.suppressDisplay = true;
}
protected abstract install(context: IActionContext, fileName: string, cmd: string): Promise<void>;
}
export class WindowsDockerInstaller extends DockerInstallerBase {
protected downloadUrl: string = 'https://aka.ms/download-docker-windows-vscode';
protected fileExtension: string = 'exe';
protected getInstallCommand(fileName: string): string {
// Windows require double quote.
return `"${fileName}"`;
}
protected async install(context: IActionContext, fileName: string): Promise<void> {
const title = vscode.l10n.t('Docker Install');
const command = this.getInstallCommand(fileName);
const taskCRF = new TaskCommandRunnerFactory({
taskName: title,
});
await taskCRF.getCommandRunner()({
command: command,
args: undefined,
});
}
}
export class MacDockerInstaller extends DockerInstallerBase {
protected downloadUrl: string = isArm64Mac() ? 'https://aka.ms/download-docker-arm-mac-vscode' : 'https://aka.ms/download-docker-mac-vscode';
protected fileExtension: string = 'dmg';
protected getInstallCommand(fileName: string): string {
return `chmod +x '${fileName}' && open '${fileName}'`;
}
protected async install(context: IActionContext, fileName: string): Promise<void> {
const title = vscode.l10n.t('Docker Install');
const command = this.getInstallCommand(fileName);
const taskCRF = new TaskCommandRunnerFactory({
taskName: title,
});
await taskCRF.getCommandRunner()({
command: command,
args: undefined,
});
}
}
export async function showDockerInstallNotification(): Promise<void> {
const installMessage = isLinux() ?
vscode.l10n.t('Docker is not installed. Would you like to learn more about installing Docker?') :
vscode.l10n.t('Docker Desktop is not installed. Would you like to install it?');
const learnMore = vscode.l10n.t('Learn more');
const install = vscode.l10n.t('Install');
const confirmationPrompt: vscode.MessageItem = isLinux() ? { title: learnMore } : { title: install };
const response = await vscode.window.showInformationMessage(installMessage, ...[confirmationPrompt]);
if (response) {
await vscode.commands.executeCommand('vscode-docker.installDocker');
}
}

Просмотреть файл

@ -1,19 +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 vscode from 'vscode';
import { isMac, isWindows } from '../utils/osUtils';
import { MacDockerInstaller, WindowsDockerInstaller } from './dockerInstaller';
export async function installDocker(context: IActionContext): Promise<void> {
if (isWindows()) {
await (new WindowsDockerInstaller()).downloadAndInstallDocker(context);
} else if (isMac()) {
await (new MacDockerInstaller()).downloadAndInstallDocker(context);
} else {
await vscode.env.openExternal(vscode.Uri.parse('https://aka.ms/download-docker-linux-vscode'));
}
}

Просмотреть файл

@ -44,14 +44,12 @@ import { runAzureCliImage } from "./images/runAzureCliImage";
import { runImage, runImageInteractive } from "./images/runImage";
import { hideDanglingImages, setInitialDanglingContextValue, showDanglingImages } from "./images/showDanglingImages";
import { tagImage } from "./images/tagImage";
import { installDocker } from "./installDocker";
import { configureNetworksExplorer } from "./networks/configureNetworksExplorer";
import { createNetwork } from "./networks/createNetwork";
import { inspectNetwork } from "./networks/inspectNetwork";
import { pruneNetworks } from "./networks/pruneNetworks";
import { removeNetwork } from "./networks/removeNetwork";
import { pruneSystem } from "./pruneSystem";
import { registerLocalCommand } from "./registerLocalCommand";
import { registerWorkspaceCommand } from "./registerWorkspaceCommand";
import { createAzureRegistry } from "./registries/azure/createAzureRegistry";
import { deleteAzureRegistry } from "./registries/azure/deleteAzureRegistry";
@ -76,6 +74,7 @@ import { logOutOfDockerCli } from "./registries/logOutOfDockerCli";
import { pullImageFromRepository, pullRepository } from "./registries/pullImages";
import { reconnectRegistry } from "./registries/reconnectRegistry";
import { registryHelp } from "./registries/registryHelp";
import { openDockerDownloadPage } from "./showDockerLearnMoreNotification";
import { configureVolumesExplorer } from "./volumes/configureVolumesExplorer";
import { inspectVolume } from "./volumes/inspectVolume";
import { pruneVolumes } from "./volumes/pruneVolumes";
@ -206,8 +205,7 @@ export function registerCommands(): void {
registerCommand('vscode-docker.contexts.remove', removeDockerContext);
registerCommand('vscode-docker.contexts.use', useDockerContext);
registerLocalCommand('vscode-docker.installDocker', installDocker);
registerCommand('vscode-docker.openDockerDownloadPage', openDockerDownloadPage);
registerCommand('vscode-docker.help', help);
registerCommand('vscode-docker.help.openWalkthrough', () => commands.executeCommand('workbench.action.openWalkthrough', 'ms-azuretools.vscode-docker#dockerStart'));
}

Просмотреть файл

@ -0,0 +1,28 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE.md in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { isMac, isWindows } from '../utils/osUtils';
export async function showDockerLearnMoreNotification(): Promise<void> {
const learnMoreMessage = vscode.l10n.t('Docker is not installed. Would you like to learn more about installing Docker?');
const confirmationPrompt = vscode.l10n.t('Learn more');
const response = await vscode.window.showInformationMessage(learnMoreMessage, ...[confirmationPrompt]);
if (response) {
await openDockerDownloadPage();
}
}
export async function openDockerDownloadPage(): Promise<void> {
if (isWindows()) {
await vscode.env.openExternal(vscode.Uri.parse('https://aka.ms/vscode/docker-windows-download'));
} else if (isMac()) {
await vscode.env.openExternal(vscode.Uri.parse('https://aka.ms/vscode/docker-mac-download'));
} else {
await vscode.env.openExternal(vscode.Uri.parse('https://aka.ms/download-docker-linux-vscode'));
}
}

Просмотреть файл

@ -24,6 +24,7 @@ export const DOCKERFILE_GLOB_PATTERN = '**/{*.[dD][oO][cC][kK][eE][rR][fF][iI][l
export const YAML_GLOB_PATTERN = '**/*.{[yY][aA][mM][lL],[yY][mM][lL]}';
export const CSPROJ_GLOB_PATTERN = '**/*.{[cC][sS][pP][rR][oO][jJ]}';
export const FSPROJ_GLOB_PATTERN = '**/*.{[fF][sS][pP][rR][oO][jJ]}';
export const VBPROJ_GLOB_PATTERN = '**/*.{[vV][bB][pP][rR][oO][jJ]}';
// File search max ammout
export const FILE_SEARCH_MAX_RESULT = 1000;

Просмотреть файл

@ -9,9 +9,10 @@ import { DockerRunTaskDefinition } from '../tasks/DockerRunTaskProvider';
import { DockerTaskScaffoldContext, getDefaultContainerName } from '../tasks/TaskHelper';
import { DockerServerReadyAction } from './DockerDebugConfigurationBase';
import { DockerDebugConfiguration, DockerDebugConfigurationProvider } from './DockerDebugConfigurationProvider';
import { DockerPlatform } from './DockerPlatformHelper';
import { DockerPlatform } from './DockerDebugPlatformHelper';
import { registerServerReadyAction } from './DockerServerReadyAction';
import { netCoreDebugHelper } from './netcore/NetCoreDebugHelper';
import { netSdkDebugHelper } from './netSdk/NetSdkDebugHelper';
import { nodeDebugHelper } from './node/NodeDebugHelper';
import { pythonDebugHelper } from './python/PythonDebugHelper';
@ -40,6 +41,7 @@ export interface ResolvedDebugConfiguration extends DebugConfiguration {
export interface DebugHelper {
provideDebugConfigurations(context: DockerDebugScaffoldContext): Promise<DockerDebugConfiguration[]>;
resolveDebugConfiguration(context: DockerDebugContext, debugConfiguration: DockerDebugConfiguration): Promise<ResolvedDebugConfiguration | undefined>;
afterResolveDebugConfiguration?(context: DockerDebugContext, debugConfiguration: DockerDebugConfiguration): Promise<void>;
}
export function registerDebugProvider(ctx: ExtensionContext): void {
@ -51,6 +53,7 @@ export function registerDebugProvider(ctx: ExtensionContext): void {
netCore: netCoreDebugHelper,
node: nodeDebugHelper,
python: pythonDebugHelper,
netSdk: netSdkDebugHelper
}
)
)

Просмотреть файл

@ -3,14 +3,16 @@
* 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 { CancellationToken, commands, debug, DebugConfiguration, DebugConfigurationProvider, DebugSession, l10n, MessageItem, ProviderResult, window, workspace, WorkspaceFolder } from 'vscode';
import { DockerOrchestration } from '../constants';
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, FSPROJ_GLOB_PATTERN } from '../constants';
import { ext } from '../extensionVariables';
import { getAssociatedDockerRunTask } from '../tasks/TaskHelper';
import { resolveFilesOfPattern } from '../utils/quickPickFile';
import { DebugHelper, DockerDebugContext, ResolvedDebugConfiguration } from './DebugHelper';
import { DockerPlatform, getPlatform } from './DockerPlatformHelper';
import { DockerPlatform, getDebugPlatform } from './DockerDebugPlatformHelper';
import { NetCoreDockerDebugConfiguration } from './netcore/NetCoreDebugHelper';
import { netSdkDebugHelper } from './netSdk/NetSdkDebugHelper';
import { NodeDockerDebugConfiguration } from './node/NodeDebugHelper';
export interface DockerDebugConfiguration extends NetCoreDockerDebugConfiguration, NodeDockerDebugConfiguration {
@ -42,21 +44,14 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi
}
public provideDebugConfigurations(folder: WorkspaceFolder | undefined, token?: CancellationToken): ProviderResult<DebugConfiguration[]> {
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 callWithTelemetryAndErrorHandling(
'provideDebugConfigurations',
async (actionContext: IActionContext) => {
return this.handleEmptyDebugConfig(folder, actionContext);
}
);
return [];
}
public resolveDebugConfiguration(folder: WorkspaceFolder | undefined, debugConfiguration: DockerDebugConfiguration, token?: CancellationToken): ProviderResult<DebugConfiguration | undefined> {
@ -75,17 +70,22 @@ 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;
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
if (newlyCreatedDebugConfig.length === 0 || !newlyCreatedDebugConfig[0]) {
return undefined;
}
debugConfiguration = newlyCreatedDebugConfig[0];
}
if (!debugConfiguration.request) {
throw new Error(l10n.t('The property "request" must be specified in the debug config.'));
}
const debugPlatform = getPlatform(debugConfiguration);
const debugPlatform = getDebugPlatform(debugConfiguration);
actionContext.telemetry.properties.dockerPlatform = debugPlatform;
actionContext.telemetry.properties.orchestration = 'single' as DockerOrchestration; // TODO: docker-compose, when support is added
@ -114,6 +114,7 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi
await this.removeDebugContainerIfNeeded(context.actionContext, resolvedConfiguration);
}
await helper.afterResolveDebugConfiguration?.(context, originalConfiguration);
return resolvedConfiguration;
}
@ -170,4 +171,32 @@ export class DockerDebugConfigurationProvider implements DebugConfigurationProvi
}
}
}
/**
* 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(folder: WorkspaceFolder, actionContext: IActionContext): Promise<DockerDebugConfiguration[]> {
// 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, FSPROJ_GLOB_PATTERN]);
if (csProjUris) {
return await netSdkDebugHelper.provideDebugConfigurations(
{
actionContext,
dockerfile: undefined,
folder: folder
}
);
} else {
// for now, we scaffold docker files
await commands.executeCommand('vscode-docker.configure');
throw new UserCancelledError();
}
// TODO: (potentially) in the future, we can add more support for ambient tasks for other types of projects
}
}

Просмотреть файл

@ -3,18 +3,14 @@
* Licensed under the MIT License. See LICENSE.md in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export type DockerPlatform = 'netCore' | 'node' | 'python';
import { DockerDebugConfiguration } from "./DockerDebugConfigurationProvider";
interface DockerPlatformConfiguration {
platform?: DockerPlatform;
netCore?: unknown;
node?: unknown;
python?: unknown;
}
export function getPlatform<T extends DockerPlatformConfiguration>(configuration: T): DockerPlatform | undefined {
export type DockerPlatform = 'netCore' | 'node' | 'python' | 'netSdk';
export function getDebugPlatform(configuration: DockerDebugConfiguration): DockerPlatform | undefined {
if (configuration.platform === 'netCore' || configuration.netCore !== undefined) {
return 'netCore';
return configuration.netCore?.buildWithSdk ? 'netSdk' : 'netCore';
} else if (configuration.platform === 'node' || configuration.node !== undefined) {
return 'node';
} else if (configuration.platform === 'python' || configuration.python !== undefined) {

Просмотреть файл

@ -0,0 +1,144 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE.md in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as path from "path";
import { WorkspaceFolder, commands, l10n, tasks } from "vscode";
import { ext } from "../../extensionVariables";
import { NetChooseBuildTypeContext, netContainerBuild } from "../../scaffolding/wizard/net/NetContainerBuild";
import { AllNetContainerBuildOptions, NetContainerBuildOptionsKey } from "../../scaffolding/wizard/net/NetSdkChooseBuildStep";
import { NetSdkRunTaskDefinition, netSdkRunTaskProvider } from "../../tasks/netSdk/NetSdkRunTaskProvider";
import { normalizeArchitectureToRidArchitecture, normalizeOsToRidOs } from "../../tasks/netSdk/netSdkTaskUtils";
import { NetCoreTaskHelper } from "../../tasks/netcore/NetCoreTaskHelper";
import { getNetCoreProjectInfo } from "../../utils/netCoreUtils";
import { getDockerOSType } from "../../utils/osUtils";
import { PlatformOS } from "../../utils/platform";
import { resolveVariables, unresolveWorkspaceFolder } from "../../utils/resolveVariables";
import { DockerDebugContext, DockerDebugScaffoldContext, ResolvedDebugConfiguration, inferContainerName } from "../DebugHelper";
import { DockerDebugConfiguration } from "../DockerDebugConfigurationProvider";
import { NetCoreDebugHelper, NetCoreDebugScaffoldingOptions, NetCoreProjectProperties } from "../netcore/NetCoreDebugHelper";
interface NetSdkProjectProperties extends NetCoreProjectProperties {
containerWorkingDirectory: string;
isSdkContainerSupportEnabled: boolean;
imageName: string;
}
export class NetSdkDebugHelper extends NetCoreDebugHelper {
public override async provideDebugConfigurations(context: DockerDebugScaffoldContext, options?: NetCoreDebugScaffoldingOptions): Promise<DockerDebugConfiguration[]> {
const configurations: DockerDebugConfiguration[] = [];
const netCoreBuildContext: NetChooseBuildTypeContext = {
...context.actionContext,
scaffoldType: 'debugging',
workspaceFolder: context.folder,
};
await netContainerBuild(netCoreBuildContext); // prompt user whether to use .NET container SDK build
if (netCoreBuildContext?.containerBuildOption === AllNetContainerBuildOptions[1]) {
options = options || {};
options.appProject = options.appProject || await NetCoreTaskHelper.inferAppProject(context); // This method internally checks the user-defined input first
configurations.push({
name: 'Docker .NET Container SDK Launch',
type: 'docker',
request: 'launch',
netCore: {
appProject: unresolveWorkspaceFolder(options.appProject, context.folder),
buildWithSdk: true,
},
});
} else {
await commands.executeCommand('vscode-docker.configure');
}
return configurations;
}
public override async resolveDebugConfiguration(context: DockerDebugContext, debugConfiguration: DockerDebugConfiguration): Promise<ResolvedDebugConfiguration | undefined> {
try {
return await super.resolveDebugConfiguration(context, debugConfiguration);
} catch (error) {
await ext.context.workspaceState.update(NetContainerBuildOptionsKey, '');
throw error;
}
}
public async afterResolveDebugConfiguration(context: DockerDebugContext, debugConfiguration: DockerDebugConfiguration): Promise<void> {
const runDefinition: Omit<NetSdkRunTaskDefinition, "type"> = {
netCore: {
appProject: debugConfiguration.netCore.appProject,
},
dockerRun: {
image: context.runDefinition.dockerRun.image,
}
};
const { task, promise } = netSdkRunTaskProvider.createNetSdkRunTask(runDefinition);
await tasks.executeTask(task);
await promise;
}
protected override async loadExternalInfo(context: DockerDebugContext, debugConfiguration: DockerDebugConfiguration): Promise<{ configureSsl: boolean, containerName: string, platformOS: PlatformOS }> {
const projectProperties = await this.getProjectProperties(debugConfiguration, context.folder);
debugConfiguration.netCore.appOutput = await this.normalizeAppOutput(projectProperties.containerWorkingDirectory, projectProperties.isSdkContainerSupportEnabled);
context.runDefinition = {
...context.runDefinition,
dockerRun: {
containerName: inferContainerName(debugConfiguration, context, projectProperties.imageName, "dev"),
image: projectProperties.imageName,
},
netCore: {
enableDebugging: true,
}
};
return {
configureSsl: false,
containerName: context.runDefinition.dockerRun.containerName,
platformOS: await getDockerOSType() === "windows" ? 'Windows' : 'Linux',
};
}
protected override inferAppContainerOutput(appOutput: string, platformOS: PlatformOS): string {
return appOutput;
}
protected override async getProjectProperties(debugConfiguration: DockerDebugConfiguration, folder?: WorkspaceFolder): Promise<NetSdkProjectProperties> {
const ridOS = await normalizeOsToRidOs();
const ridArchitecture = await normalizeArchitectureToRidArchitecture();
const additionalProperties = `/p:ContainerRuntimeIdentifier="${ridOS}-${ridArchitecture}"`;
const resolvedAppProject = resolveVariables(debugConfiguration.netCore?.appProject, folder);
const projectInfo = await getNetCoreProjectInfo('GetProjectProperties', resolvedAppProject, additionalProperties);
if (projectInfo.length < 6 || !projectInfo[5]) {
throw new Error(l10n.t("Your current project configuration or .NET SDK version doesn't support SDK Container build. Please choose a compatible project or update .NET SDK."));
}
const projectProperties: NetSdkProjectProperties = {
assemblyName: projectInfo[0],
targetFramework: projectInfo[1],
appOutput: projectInfo[2],
containerWorkingDirectory: projectInfo[3],
isSdkContainerSupportEnabled: projectInfo[4] === 'true',
imageName: projectInfo[5],
};
return projectProperties;
}
private async normalizeAppOutput(unnormalizedContainerWorkingDirectory: string, isSdkContainerSupportEnabled: boolean): Promise<string> {
if (isSdkContainerSupportEnabled) {
return await getDockerOSType() === 'windows' // fourth is output path
? path.win32.normalize(unnormalizedContainerWorkingDirectory)
: path.posix.normalize(unnormalizedContainerWorkingDirectory);
} else {
throw new Error(l10n.t("Your current project configuration or .NET SDK version doesn't support SDK Container build. Please choose a compatible project or update .NET SDK."));
}
}
}
export const netSdkDebugHelper = new NetSdkDebugHelper();

Просмотреть файл

@ -24,6 +24,7 @@ import { VsDbgType, installDebuggersIfNecessary, vsDbgInstallBasePath } from './
export interface NetCoreDebugOptions extends NetCoreTaskOptions {
appOutput?: string;
debuggerPath?: string;
buildWithSdk?: boolean;
}
export interface NetCoreDockerDebugConfiguration extends DebugConfiguration {
@ -34,6 +35,12 @@ export interface NetCoreDebugScaffoldingOptions {
appProject?: string;
}
export interface NetCoreProjectProperties {
assemblyName: string;
targetFramework: string;
appOutput: string;
}
export class NetCoreDebugHelper implements DebugHelper {
public async provideDebugConfigurations(context: DockerDebugScaffoldContext, options?: NetCoreDebugScaffoldingOptions): Promise<DockerDebugConfiguration[]> {
options = options || {};
@ -68,7 +75,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);
if (context.cancellationToken && context.cancellationToken.isCancellationRequested) {
// inferAppOutput is slow, give a chance to cancel
return undefined;
@ -90,7 +97,7 @@ export class NetCoreDebugHelper implements DebugHelper {
const additionalProbingPathsArgs = NetCoreDebugHelper.getAdditionalProbingPathsArgs(platformOS);
const containerAppOutput = NetCoreDebugHelper.getContainerAppOutput(debugConfiguration, appOutput, platformOS);
const containerAppOutput = this.inferAppContainerOutput(appOutput, platformOS);
const dockerServerReadyAction = resolveDockerServerReadyAction(
debugConfiguration,
@ -176,16 +183,20 @@ export class NetCoreDebugHelper implements DebugHelper {
};
}
private async inferAppOutput(helperOptions: NetCoreDebugOptions): Promise<string> {
const projectInfo = await getNetCoreProjectInfo('GetProjectProperties', helperOptions.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)
protected async inferAppOutput(debugConfiguration: DockerDebugConfiguration): Promise<string> {
const projectProperties = await this.getProjectProperties(debugConfiguration);
return projectProperties.appOutput;
}
private async loadExternalInfo(context: DockerDebugContext, debugConfiguration: DockerDebugConfiguration): Promise<{ configureSsl: boolean, containerName: string, platformOS: PlatformOS }> {
protected inferAppContainerOutput(appOutput: string, platformOS: PlatformOS): string {
const result = platformOS === 'Windows' ?
path.win32.join('C:\\app', appOutput) :
path.posix.join('/app', appOutput);
return pathNormalize(result, platformOS);
}
protected async loadExternalInfo(context: DockerDebugContext, debugConfiguration: DockerDebugConfiguration): Promise<{ configureSsl: boolean, containerName: string, platformOS: PlatformOS }> {
const associatedTask = context.runDefinition;
return {
@ -195,6 +206,23 @@ export class NetCoreDebugHelper implements DebugHelper {
};
}
protected async getProjectProperties(debugConfiguration: DockerDebugConfiguration): Promise<NetCoreProjectProperties> {
const projectInfo = await getNetCoreProjectInfo('GetProjectProperties', debugConfiguration.netCore?.appProject);
if (projectInfo.length < 3) {
throw new Error(l10n.t('Unable to determine assembly output path.'));
}
// First line is assembly name, second is target framework, third+ are output path(s)
const projectProperties: NetCoreProjectProperties = {
assemblyName: projectInfo[0],
targetFramework: projectInfo[1],
appOutput: projectInfo[2]
};
return projectProperties;
}
private async acquireDebuggers(platformOS: PlatformOS): Promise<void> {
await window.withProgress(
{
@ -257,14 +285,6 @@ export class NetCoreDebugHelper implements DebugHelper {
return additionalProbingPaths.map(probingPath => `--additionalProbingPath ${probingPath}`).join(' ');
}
private static getContainerAppOutput(debugConfiguration: DockerDebugConfiguration, appOutput: string, platformOS: PlatformOS): string {
const result = platformOS === 'Windows' ?
path.win32.join('C:\\app', appOutput) :
path.posix.join('/app', appOutput);
return pathNormalize(result, platformOS);
}
private async copyDebuggerToContainer(context: IActionContext, containerName: string, containerDebuggerDirectory: string, containerOS: ContainerOS): Promise<void> {
if (containerOS === 'windows') {
const inspectInfo = (await ext.runWithDefaults(client =>

Просмотреть файл

@ -106,6 +106,7 @@ import { withContainerPathArg } from './withContainerPathArg';
import { withDockerAddHostArg } from './withDockerAddHostArg';
import { withDockerBuildArg } from './withDockerBuildArg';
import { withDockerEnvArg } from './withDockerEnvArg';
import { withDockerExposePortsArg } from './withDockerExposePortsArg';
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),
withDockerExposePortsArg(options.exposePorts),
withVerbatimArg(options.customOptions),
withArg(options.imageRef),
typeof options.command === 'string' ? withVerbatimArg(options.command) : withArg(...(toArray(options.command || []))),

Просмотреть файл

@ -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 withDockerExposePortsArg(ports?: Array<number>) {
return withNamedArg('--expose', (ports || []).map(port => port.toString()), { shouldQuote: false });
}

Просмотреть файл

@ -18,7 +18,7 @@ export function formatDockerPlatform(platform: ContainerPlatform): string | unde
return `${os}/${architecture}`;
}
/**p
/**
* This method formats the `platform` flag for the Docker CLI.
*
* The `os` and `architecture` properties are extracted and used to create a new `ContainerPlatform`

Просмотреть файл

@ -744,6 +744,10 @@ export type RunContainerCommandOptions = CommonCommandOptions & {
* Optional command to use in starting the container
*/
command?: Array<string> | string;
/**
* Optional expose ports for the container
*/
exposePorts?: Array<number>;
/**
* Additional custom options to pass
*/

Просмотреть файл

@ -0,0 +1,31 @@
/*---------------------------------------------------------------------------------------------
* 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 { NetContainerBuildOption, NetSdkChooseBuildStep } from './NetSdkChooseBuildStep';
export interface NetChooseBuildTypeContext extends ScaffoldingWizardContext {
containerBuildOption?: NetContainerBuildOption;
}
export async function netContainerBuild(wizardContext: Partial<NetChooseBuildTypeContext>, apiInput?: NetChooseBuildTypeContext): Promise<void> {
if (!vscode.workspace.isTrusted) {
throw new UserCancelledError('enforceTrust');
}
const promptSteps: AzureWizardPromptStep<NetChooseBuildTypeContext>[] = [
new NetSdkChooseBuildStep()
];
const wizard = new AzureWizard<NetChooseBuildTypeContext>(wizardContext as NetChooseBuildTypeContext, {
promptSteps: promptSteps,
title: vscode.l10n.t('Initialize for Debugging'),
});
await wizard.prompt();
await wizard.execute();
}

Просмотреть файл

@ -0,0 +1,76 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE.md in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IAzureQuickPickItem } from '@microsoft/vscode-azext-utils';
import * as vscode from 'vscode';
import { ext } from '../../../extensionVariables';
import { TelemetryPromptStep } from '../TelemetryPromptStep';
import { cSharpExtensionId, getMinimumCSharpExtensionExports } from '../netCore/netCoreStepUtils';
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')
] as const;
type NetContainerBuildOptionsTuple = typeof AllNetContainerBuildOptions;
export type NetContainerBuildOption = NetContainerBuildOptionsTuple[number];
export class NetSdkChooseBuildStep extends TelemetryPromptStep<NetChooseBuildTypeContext> {
public async prompt(wizardContext: NetChooseBuildTypeContext): Promise<void> {
await this.ensureCSharpExtension(wizardContext);
// get workspace momento storage
const containerBuildOption = await ext.context.workspaceState.get<NetContainerBuildOption>(NetContainerBuildOptionsKey);
// only remember if it was 'Use .NET SDK', otherwise prompt again
if (containerBuildOption === AllNetContainerBuildOptions[1]) {
wizardContext.containerBuildOption = containerBuildOption;
return;
}
const opt: vscode.QuickPickOptions = {
matchOnDescription: true,
matchOnDetail: true,
placeHolder: vscode.l10n.t('How would you like to build your container image?'),
};
const buildOptions = AllNetContainerBuildOptions as readonly NetContainerBuildOption[];
const items = buildOptions.map(p => <IAzureQuickPickItem<NetContainerBuildOption>>{ label: p, data: p });
const response = await wizardContext.ui.showQuickPick(items, opt);
wizardContext.containerBuildOption = response.data;
// update workspace momento storage
await ext.context.workspaceState.update(NetContainerBuildOptionsKey, wizardContext.containerBuildOption);
}
public shouldPrompt(wizardContext: NetChooseBuildTypeContext): boolean {
return !wizardContext.containerBuildOption;
}
protected setTelemetry(wizardContext: NetChooseBuildTypeContext): void {
wizardContext.telemetry.properties.netSdkBuildStep = wizardContext.containerBuildOption;
}
private async ensureCSharpExtension(wizardContext: NetChooseBuildTypeContext): Promise<void> {
try {
await getMinimumCSharpExtensionExports();
} catch (err) {
// Suppress report issue and rethrow
wizardContext.errorHandling.suppressReportIssue = true;
wizardContext.errorHandling.buttons = [
{
title: vscode.l10n.t('Open Extension'),
callback: async () => vscode.commands.executeCommand('extension.open', cSharpExtensionId),
}
];
throw err;
}
}
}

Просмотреть файл

@ -11,22 +11,15 @@ import { getValidImageNameFromPath } from '../../../utils/getValidImageName';
import { getNetCoreProjectInfo } from '../../../utils/netCoreUtils';
import { GatherInformationStep } from '../GatherInformationStep';
import { NetCoreScaffoldingWizardContext } from './NetCoreScaffoldingWizardContext';
// 1.23.9 contains the fix to not overwrite existing assets
const minCSharpVersionString = '1.23.9';
import { CSharpExtensionExports, cSharpExtensionId, getMinimumCSharpExtensionExports } from './netCoreStepUtils';
// All supported .NET versions no longer have "core" in the name
const aspNetBaseImage = 'mcr.microsoft.com/dotnet/aspnet';
const consoleNetBaseImage = 'mcr.microsoft.com/dotnet/runtime';
const netSdkImage = 'mcr.microsoft.com/dotnet/sdk';
const cSharpExtensionId = 'ms-dotnettools.csharp';
const cSharpConfigId = 'csharp';
const cSharpPromptSetting = 'suppressBuildAssetsNotification';
interface CSharpExtensionExports {
// This is a subset of the C# extension's exports but contains all we care about
initializationFinished(): Promise<void>;
}
export class NetCoreGatherInformationStep extends GatherInformationStep<NetCoreScaffoldingWizardContext> {
private targetFramework: string;
@ -103,7 +96,7 @@ export class NetCoreGatherInformationStep extends GatherInformationStep<NetCoreS
private async ensureNetCoreBuildTasks(wizardContext: NetCoreScaffoldingWizardContext): Promise<void> {
let cSharpExtensionExports: CSharpExtensionExports;
try {
cSharpExtensionExports = await this.getMinimumCSharpExtensionExports();
cSharpExtensionExports = await getMinimumCSharpExtensionExports();
} catch (err) {
// Suppress report issue and rethrow
wizardContext.errorHandling.suppressReportIssue = true;
@ -150,17 +143,4 @@ export class NetCoreGatherInformationStep extends GatherInformationStep<NetCoreS
await cSharpPromptConfig.update(cSharpPromptSetting, oldSuppressSettings.globalValue, vscode.ConfigurationTarget.Global);
}
}
private async getMinimumCSharpExtensionExports(): Promise<CSharpExtensionExports> {
const cSharpExtension: vscode.Extension<CSharpExtensionExports> | undefined = vscode.extensions.getExtension(cSharpExtensionId);
const cSharpExtensionVersion: semver.SemVer | undefined = cSharpExtension ? new semver.SemVer((<{ version: string }>cSharpExtension.packageJSON).version) : undefined;
if (!cSharpExtension || !cSharpExtensionVersion) {
throw new Error(vscode.l10n.t('Cannot generate Dockerfiles for a .NET project unless the C# extension is installed.'));
} else if (semver.lt(cSharpExtensionVersion, minCSharpVersionString)) {
throw new Error(vscode.l10n.t('Cannot generate Dockerfiles for a .NET project unless version {0} or higher of the C# extension is installed.', minCSharpVersionString));
}
return await cSharpExtension.activate();
}
}

Просмотреть файл

@ -0,0 +1,29 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE.md in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as semver from 'semver';
import * as vscode from 'vscode';
// 1.23.9 contains the fix to not overwrite existing assets
export const minCSharpVersionString = '1.23.9';
export const cSharpExtensionId = 'ms-dotnettools.csharp';
export interface CSharpExtensionExports {
// This is a subset of the C# extension's exports but contains all we care about
initializationFinished(): Promise<void>;
}
export async function getMinimumCSharpExtensionExports(): Promise<CSharpExtensionExports> {
const cSharpExtension: vscode.Extension<CSharpExtensionExports> | undefined = vscode.extensions.getExtension(cSharpExtensionId);
const cSharpExtensionVersion: semver.SemVer | undefined = cSharpExtension ? new semver.SemVer((<{ version: string }>cSharpExtension.packageJSON).version) : undefined;
if (!cSharpExtension || !cSharpExtensionVersion) {
throw new Error(vscode.l10n.t('Cannot generate Dockerfiles for a .NET project unless the C# extension is installed.'));
} else if (semver.lt(cSharpExtensionVersion, minCSharpVersionString)) {
throw new Error(vscode.l10n.t('Cannot generate Dockerfiles for a .NET project unless version {0} or higher of the C# extension is installed.', minCSharpVersionString));
}
return await cSharpExtension.activate();
}

Просмотреть файл

@ -6,7 +6,7 @@
import * as fse from 'fs-extra';
import * as path from 'path';
import { l10n, Task } from 'vscode';
import { DockerPlatform } from '../debugging/DockerPlatformHelper';
import { DockerPlatform } from '../debugging/DockerDebugPlatformHelper';
import { ext } from '../extensionVariables';
import { cloneObject } from '../utils/cloneObject';
import { resolveVariables } from '../utils/resolveVariables';

Просмотреть файл

@ -52,9 +52,9 @@ export class DockerPseudoterminal implements Pseudoterminal {
this.closeEmitter.fire(code || 0);
}
public getCommandRunner(options: Omit<ExecuteCommandInTerminalOptions, 'commandResponse'>): <T>(commandResponse: VoidCommandResponse | PromiseCommandResponse<T>) => Promise<T> {
public getCommandRunner(options: Omit<ExecuteCommandResponseInTerminalOptions, 'commandResponse'>): <T>(commandResponse: VoidCommandResponse | PromiseCommandResponse<T>) => Promise<T> {
return async <T>(commandResponse: VoidCommandResponse | PromiseCommandResponse<T>) => {
const output = await this.executeCommandInTerminal({
const output = await this.executeCommandResponseInTerminal({
...options,
commandResponse: commandResponse,
});
@ -96,18 +96,23 @@ export class DockerPseudoterminal implements Pseudoterminal {
this.writeEmitter.fire(`\x1b[${color}${message}\x1b[0m`);
}
private async executeCommandInTerminal(options: ExecuteCommandInTerminalOptions): Promise<ExecAsyncOutput> {
private async executeCommandResponseInTerminal(options: ExecuteCommandResponseInTerminalOptions): Promise<ExecAsyncOutput> {
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<ExecAsyncOutput> {
// 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,
cwd: this.resolvedDefinition.options?.cwd || options.cwd || options.folder.uri.fsPath,
env: withDockerEnvSettings({ ...process.env, ...this.resolvedDefinition.options?.env }),
cancellationToken: options.token,
},
@ -120,10 +125,15 @@ export class DockerPseudoterminal implements Pseudoterminal {
}
);
}
}
type ExecuteCommandInTerminalOptions = {
type ExecuteCommandResponseInTerminalOptions = ExecAsyncInTerminalOptions & {
commandResponse: VoidCommandResponse | PromiseCommandResponse<unknown>;
};
type ExecAsyncInTerminalOptions = {
folder: WorkspaceFolder;
token?: CancellationToken;
cwd?: string;
};

Просмотреть файл

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { l10n, Task } from 'vscode';
import { DockerPlatform } from '../debugging/DockerPlatformHelper';
import { DockerPlatform } from '../debugging/DockerDebugPlatformHelper';
import { ext } from '../extensionVariables';
import { RunContainerBindMount } from '../runtimes/docker';
import { cloneObject } from '../utils/cloneObject';

Просмотреть файл

@ -0,0 +1,20 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE.md in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { DockerPlatform } from "../debugging/DockerDebugPlatformHelper";
import { DockerBuildTaskDefinition } from "./DockerBuildTaskProvider";
import { DockerRunTaskDefinition } from "./DockerRunTaskProvider";
export function getTaskPlatform(definition: DockerBuildTaskDefinition | DockerRunTaskDefinition): DockerPlatform | undefined {
if (definition.platform === 'netCore' || definition.netCore !== undefined) {
return 'netCore';
} else if (definition.platform === 'node' || definition.node !== undefined) {
return 'node';
} else if (definition.platform === 'python' || definition.python !== undefined) {
return 'python';
} else {
return undefined;
}
}

Просмотреть файл

@ -5,12 +5,13 @@
import { callWithTelemetryAndErrorHandling, IActionContext, parseError } from '@microsoft/vscode-azext-utils';
import { CancellationToken, CustomExecution, l10n, ProviderResult, Task, TaskDefinition, TaskProvider } from 'vscode';
import { DockerPlatform, getPlatform } from '../debugging/DockerPlatformHelper';
import { DockerPlatform } from '../debugging/DockerDebugPlatformHelper';
import { ext } from '../extensionVariables';
import { ExecError } from '../utils/execAsync';
import { DockerBuildTask } from './DockerBuildTaskProvider';
import { DockerPseudoterminal } from './DockerPseudoterminal';
import { DockerRunTask } from './DockerRunTaskProvider';
import { getTaskPlatform } from './DockerTaskPlatformHelper';
import { DockerTaskExecutionContext, DockerTaskProviderName, TaskHelper } from './TaskHelper';
export abstract class DockerTaskProvider implements TaskProvider {
@ -46,7 +47,7 @@ export abstract class DockerTaskProvider implements TaskProvider {
}
context.actionContext = actionContext;
context.platform = getPlatform(task.definition);
context.platform = getTaskPlatform(task.definition);
context.actionContext.telemetry.properties.dockerPlatform = context.platform;
await this.executeTaskInternal(context, task);

Просмотреть файл

@ -8,7 +8,7 @@ import * as path from 'path';
import { CancellationToken, ConfigurationTarget, ExtensionContext, QuickPickItem, Task, WorkspaceFolder, l10n, tasks, workspace } from 'vscode';
import { DebugConfigurationBase } from '../debugging/DockerDebugConfigurationBase';
import { DockerDebugConfiguration } from '../debugging/DockerDebugConfigurationProvider';
import { DockerPlatform } from '../debugging/DockerPlatformHelper';
import { DockerPlatform } from '../debugging/DockerDebugPlatformHelper';
import { ContainerPlatform } from '../runtimes/docker';
import { getValidImageName, getValidImageNameWithTag } from '../utils/getValidImageName';
import { pathNormalize } from '../utils/pathNormalize';
@ -20,11 +20,12 @@ import { DockerPseudoterminal } from './DockerPseudoterminal';
import { DockerContainerVolume, DockerRunOptions, DockerRunTaskDefinitionBase } from './DockerRunTaskDefinitionBase';
import { DockerRunTask, DockerRunTaskDefinition, DockerRunTaskProvider } from './DockerRunTaskProvider';
import { TaskDefinitionBase } from './TaskDefinitionBase';
import { NetSdkRunTaskProvider } from './netSdk/NetSdkRunTaskProvider';
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-container-sdk';
export interface DockerTaskContext {
folder: WorkspaceFolder;
@ -77,7 +78,8 @@ export function registerTaskProviders(ctx: ExtensionContext): void {
const helpers = {
netCore: netCoreTaskHelper,
node: nodeTaskHelper,
python: pythonTaskHelper
python: pythonTaskHelper,
netSdk: undefined
};
ctx.subscriptions.push(
@ -100,6 +102,13 @@ export function registerTaskProviders(ctx: ExtensionContext): void {
new DockerComposeTaskProvider()
)
);
ctx.subscriptions.push(
tasks.registerTaskProvider(
'dotnet-container-sdk',
new NetSdkRunTaskProvider()
)
);
}
export function hasTask(taskLabel: string, folder: WorkspaceFolder): boolean {

Просмотреть файл

@ -0,0 +1,92 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE.md in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as path from "path";
import { CancellationToken, CustomExecution, Task, TaskDefinition, TaskScope } from "vscode";
import { DockerPseudoterminal } from "../DockerPseudoterminal";
import { DockerRunTask } from "../DockerRunTaskProvider";
import { DockerTaskProvider } from '../DockerTaskProvider';
import { DockerRunTaskContext } from '../TaskHelper';
import { NetCoreRunTaskDefinition, NetCoreTaskHelper } from "../netcore/NetCoreTaskHelper";
import { NetSdkRunTaskType, getNetSdkBuildCommand, getNetSdkRunCommand } from './netSdkTaskUtils';
const NetSdkDebugTaskName = 'debug';
export type NetSdkRunTaskDefinition = NetCoreRunTaskDefinition;
export class NetSdkRunTaskProvider extends DockerTaskProvider {
public constructor() { super(NetSdkRunTaskType, undefined); }
public provideTasks(token: CancellationToken): Task[] {
return []; // this task is not discoverable this way
}
protected async executeTaskInternal(context: DockerRunTaskContext, task: DockerRunTask): Promise<void> {
const projectPath = task.definition.netCore?.appProject;
const isProjectWebApp = await NetCoreTaskHelper.isWebApp(projectPath);
const projectFolderPath = path.dirname(projectPath);
// use dotnet to build the image
const buildCommand = await getNetSdkBuildCommand(isProjectWebApp, task.definition.dockerRun.image);
await context.terminal.execAsyncInTerminal(
buildCommand,
{
folder: context.folder,
token: context.cancellationToken,
cwd: projectFolderPath,
}
);
// use docker run to run the image
const runCommand = await getNetSdkRunCommand(isProjectWebApp, task.definition.dockerRun.image);
await context.terminal.execAsyncInTerminal(
runCommand,
{
folder: context.folder,
token: context.cancellationToken,
cwd: projectFolderPath,
}
);
return Promise.resolve();
}
public createNetSdkRunTask(options?: Omit<NetSdkRunTaskDefinition, "type">): { task: Task, promise: Promise<number> } {
let task: Task;
const definition = {
...options,
type: NetSdkRunTaskType,
};
const promise = new Promise<number>((resolve, reject) => {
task = new Task(
definition,
TaskScope.Workspace,
NetSdkDebugTaskName,
NetSdkRunTaskType,
new CustomExecution(async (resolveDefinition: TaskDefinition) => {
const pseudoTerminal = new DockerPseudoterminal(new NetSdkRunTaskProvider(), task, resolveDefinition);
const closeEventRegistration = pseudoTerminal.onDidClose((exitCode: number) => {
closeEventRegistration.dispose();
if (exitCode === 0) {
resolve(exitCode);
} else {
reject(exitCode);
}
});
return pseudoTerminal;
}),
);
});
return { task, promise };
}
}
export const netSdkRunTaskProvider = new NetSdkRunTaskProvider();

Просмотреть файл

@ -0,0 +1,116 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE.md in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as os from 'os';
import { vsDbgInstallBasePath } from "../../debugging/netcore/VsDbgHelper";
import { ext } from "../../extensionVariables";
import { RunContainerBindMount, RunContainerCommandOptions, Shell, composeArgs, withArg, withNamedArg } from "../../runtimes/docker";
import { getImageNameWithTag } from '../../utils/getValidImageName';
import { getDockerOSType } from "../../utils/osUtils";
import { defaultVsCodeLabels } from "../TaskDefinitionBase";
import { getDefaultContainerName } from '../TaskHelper';
/**
* 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
export async function getNetSdkBuildCommand(isProjectWebApp: boolean, imageName: string): Promise<string> {
const configuration = 'Debug'; // intentionally default to Debug configuration for phase 1 of this feature
// {@link https://github.com/dotnet/sdk-container-builds/issues/141} this could change in the future
const publishFlag = isProjectWebApp
? '-p:PublishProfile=DefaultContainer'
: '/t:PublishContainer';
const args = composeArgs(
withArg('dotnet', 'publish'),
withNamedArg('--os', await normalizeOsToRidOs()),
withNamedArg('--arch', await normalizeArchitectureToRidArchitecture()),
withArg(publishFlag),
withNamedArg('--configuration', configuration),
withNamedArg('-p:ContainerImageTag', NetSdkDefaultImageTag, { assignValue: true })
)();
const quotedArgs = Shell.getShellOrDefault().quote(args);
return quotedArgs.join(' ');
}
export async function getNetSdkRunCommand(isProjectWebApp: boolean, imageName: string): Promise<string> {
const client = await ext.runtimeManager.getClient();
const options: RunContainerCommandOptions = {
detached: true,
publishAllPorts: true,
name: getDefaultContainerName(imageName, NetSdkDefaultImageTag),
environmentVariables: {},
removeOnExit: true,
imageRef: getImageNameWithTag(imageName, NetSdkDefaultImageTag),
labels: defaultVsCodeLabels,
mounts: await getRemoteDebuggerMount(),
entrypoint: await getDockerOSType() === 'windows' ? 'cmd.exe' : '/bin/sh'
};
if (isProjectWebApp) {
options.exposePorts = [8080, 80]; // the default port is 8080 for .NET 8 and 80 for .NET 7
}
const command = await client.runContainer(options);
const quotedArgs = Shell.getShellOrDefault().quote(command.args);
const commandLine = [client.commandName, ...quotedArgs].join(' ');
return commandLine;
}
/**
* 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}
*/
export async function normalizeOsToRidOs(): 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}
*/
export async function normalizeArchitectureToRidArchitecture(): Promise<RidCpuArchitecture> {
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<RunContainerBindMount[] | undefined> {
const debuggerVolume: RunContainerBindMount = {
type: 'bind',
source: vsDbgInstallBasePath,
destination: await getDockerOSType() === 'windows' ? 'C:\\remote_debugger' : '/remote_debugger',
readOnly: true
};
return [debuggerVolume];
}

Просмотреть файл

@ -4,22 +4,22 @@
*--------------------------------------------------------------------------------------------*/
import { AzExtParentTreeItem, AzExtTreeItem, AzureWizard, GenericTreeItem, IActionContext, parseError } from "@microsoft/vscode-azext-utils";
import { ConfigurationTarget, l10n, ThemeColor, ThemeIcon, workspace, WorkspaceConfiguration } from "vscode";
import { showDockerInstallNotification } from "../commands/dockerInstaller";
import { ConfigurationTarget, ThemeColor, ThemeIcon, WorkspaceConfiguration, l10n, workspace } from "vscode";
import { showDockerLearnMoreNotification } from "../commands/showDockerLearnMoreNotification";
import { configPrefix } from "../constants";
import { ext } from "../extensionVariables";
import { isCommandNotSupportedError, ListContainersItem, ListContextItem, ListImagesItem, ListNetworkItem, ListVolumeItem } from "../runtimes/docker";
import { DockerExtensionKind, getVSCodeRemoteInfo, IVSCodeRemoteInfo, RemoteKind } from "../utils/getVSCodeRemoteInfo";
import { ListContainersItem, ListContextItem, ListImagesItem, ListNetworkItem, ListVolumeItem, isCommandNotSupportedError } from "../runtimes/docker";
import { runtimeInstallStatusProvider } from "../utils/RuntimeInstallStatusProvider";
import { DatedDockerImage } from "./images/ImagesTreeItem";
import { DockerExtensionKind, IVSCodeRemoteInfo, RemoteKind, getVSCodeRemoteInfo } from "../utils/getVSCodeRemoteInfo";
import { LocalGroupTreeItemBase } from "./LocalGroupTreeItemBase";
import { OpenUrlTreeItem } from "./OpenUrlTreeItem";
import { TreePrefix } from "./TreePrefix";
import { DatedDockerImage } from "./images/ImagesTreeItem";
import { CommonGroupBy, CommonProperty, CommonSortBy, sortByProperties } from "./settings/CommonProperties";
import { ITreeArraySettingInfo, ITreeSettingInfo } from "./settings/ITreeSettingInfo";
import { ITreeSettingsWizardContext, ITreeSettingWizardInfo } from "./settings/ITreeSettingsWizardContext";
import { ITreeSettingWizardInfo, ITreeSettingsWizardContext } from "./settings/ITreeSettingsWizardContext";
import { TreeSettingListStep } from "./settings/TreeSettingListStep";
import { TreeSettingStep } from "./settings/TreeSettingStep";
import { TreePrefix } from "./TreePrefix";
type DockerStatus = 'NotInstalled' | 'Installed' | 'Running';
@ -323,7 +323,7 @@ export abstract class LocalRootTreeItemBase<TItem extends AnyContainerObject, TP
if (!dockerInstallNotificationShownToUser && this._currentDockerStatus === 'NotInstalled') {
dockerInstallNotificationShownToUser = true;
// eslint-disable-next-line @typescript-eslint/no-floating-promises
showDockerInstallNotification();
showDockerLearnMoreNotification();
}
}
}

Просмотреть файл

@ -4,8 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { AzExtParentTreeItem, AzExtTreeItem, GenericTreeItem, IActionContext } from "@microsoft/vscode-azext-utils";
import { l10n, ThemeIcon } from "vscode";
import { getThemedIconPath } from '../getThemedIconPath';
import { ThemeIcon, l10n } from "vscode";
import { OpenUrlTreeItem } from "../OpenUrlTreeItem";
export class HelpsTreeItem extends AzExtParentTreeItem {
@ -21,7 +20,7 @@ export class HelpsTreeItem extends AzExtParentTreeItem {
this.openWalkthroughTreeItem,
this.reviewIssuesTreeItem,
this.reportIssuesTreeItem,
this.installDockerTreeItem,
this.learnMoreDownloadDockerTreeItem,
]);
}
@ -115,14 +114,14 @@ export class HelpsTreeItem extends AzExtParentTreeItem {
return node;
}
private get installDockerTreeItem(): AzExtTreeItem {
private get learnMoreDownloadDockerTreeItem(): AzExtTreeItem {
const node = new GenericTreeItem(
this,
{
label: l10n.t('Install Docker'),
contextValue: 'Install Docker',
commandId: 'vscode-docker.installDocker',
iconPath: getThemedIconPath('docker'),
label: l10n.t('Docker Installation'),
contextValue: 'Docker Installation',
commandId: 'vscode-docker.openDockerDownloadPage',
iconPath: new ThemeIcon('link-external'),
includeInTreeItemPicker: true,
}
);

Просмотреть файл

@ -13,7 +13,7 @@ export async function resolveTooltipMarkdown(templateString: string, context: un
const markdownString = template(context);
const result = new MarkdownString(markdownString, true);
result.isTrusted = true;
result.isTrusted = { enabledCommands: ['revealFileInOS'] }; // revealFileInOS is used in container tooltips
return result;
}

Просмотреть файл

@ -5,8 +5,8 @@
import * as cp from 'child_process';
import * as stream from 'stream';
import { AccumulatorStream, Shell, spawnStreamAsync, StreamSpawnOptions } from '../runtimes/docker';
import { CancellationToken } from 'vscode';
import { AccumulatorStream, Shell, spawnStreamAsync, StreamSpawnOptions } from '../runtimes/docker';
type Progress = (content: string, err: boolean) => void;

Просмотреть файл

@ -16,5 +16,9 @@ export function getValidImageNameFromPath(appPath: string, tag?: string): string
}
export function getValidImageNameWithTag(nameHint: string, tag: string): string {
return `${getValidImageName(nameHint)}:${tag}`;
return getImageNameWithTag(getValidImageName(nameHint), tag);
}
export function getImageNameWithTag(name: string, tag: string): string {
return `${name}:${tag}`;
}

Просмотреть файл

@ -11,11 +11,11 @@ import { ext } from '../extensionVariables';
import { execAsync } from './execAsync';
import { getTempFileName } from './osUtils';
export async function getNetCoreProjectInfo(target: 'GetBlazorManifestLocations' | 'GetProjectProperties', project: string): Promise<string[]> {
export async function getNetCoreProjectInfo(target: 'GetBlazorManifestLocations' | 'GetProjectProperties', project: string, additionalProperties?: string): Promise<string[]> {
const targetsFile = path.join(ext.context.asAbsolutePath('resources'), 'netCore', `${target}.targets`);
const outputFile = getTempFileName();
const command = `dotnet build /r:false /t:${target} /p:CustomAfterMicrosoftCommonTargets="${targetsFile}" /p:CustomAfterMicrosoftCommonCrossTargetingTargets="${targetsFile}" /p:InfoOutputPath="${outputFile}" "${project}"`;
const command = `dotnet build /r:false /t:${target} /p:CustomAfterMicrosoftCommonTargets="${targetsFile}" /p:CustomAfterMicrosoftCommonCrossTargetingTargets="${targetsFile}" /p:InfoOutputPath="${outputFile}" ${additionalProperties || ''} "${project}"`;
try {
try {