Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions extensions/vscode-containers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2555,6 +2555,14 @@
"default": true,
"description": "%vscode-containers.config.containers.composeDetached%"
},
"containers.closeComposeTaskTerminal": {
"type": "boolean",
"default": false,
"description": "%vscode-containers.config.containers.closeComposeTaskTerminal%",
"tags": [
"advanced"
]
},
"containers.showRemoteWorkspaceWarning": {
"type": "boolean",
"default": true,
Expand Down
1 change: 1 addition & 0 deletions extensions/vscode-containers/package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@
"vscode-containers.config.docker.languageserver.formatter.ignoreMultilineInstructions": "Controls whether the Dockerfile formatter should ignore instructions that span multiple lines when formatting",
"vscode-containers.config.containers.composeBuild": "Set to true to include --build option when compose command is invoked",
"vscode-containers.config.containers.composeDetached": "Set to true to include --d (detached) option when compose command is invoked",
"vscode-containers.config.containers.closeComposeTaskTerminal": "Automatically close the terminal after a Compose command run by Container Tools is finished.",
"vscode-containers.config.containers.showRemoteWorkspaceWarning": "Set to true to prompt to switch from \"UI\" extension mode to \"Workspace\" extension mode if an operation is not supported in UI mode.",
"vscode-containers.config.containers.scaffolding.templatePath": "The path to use for scaffolding templates.",
"vscode-containers.config.containers.containerCommand": "Command to use for container actions (e.g. `docker` command). If the executable path contains whitespace, it needs to be quoted appropriately. If unset, the extension will attempt to auto-detect the command to use.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ async function compose(context: IActionContext, commands: ('up' | 'down' | 'upSu
const configOptions: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration(configPrefix);
const build: boolean = configOptions.get('composeBuild', true);
const detached: boolean = configOptions.get('composeDetached', true);
const closeTaskTerminal: boolean = configOptions.get('closeComposeTaskTerminal', false);

for (const command of commands) {
if (selectedItems.length === 0) {
Expand Down Expand Up @@ -77,6 +78,7 @@ async function compose(context: IActionContext, commands: ('up' | 'down' | 'upSu
const taskCRF = new TaskCommandRunnerFactory({
taskName: client.displayName,
workspaceFolder: folder,
close: closeTaskTerminal,
});

await taskCRF.getCommandRunner()(terminalCommand);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IActionContext } from '@microsoft/vscode-azext-utils';
import { CommonOrchestratorCommandOptions, IContainerOrchestratorClient, LogsCommandOptions, VoidCommandResponse } from '@microsoft/vscode-container-client';
import * as path from 'path';
import { l10n, Uri, workspace } from 'vscode';
import { configPrefix } from '../../constants';
import { ext } from '../../extensionVariables';
import { TaskCommandRunnerFactory } from '../../runtimes/runners/TaskCommandRunnerFactory';
import { ContainerGroupTreeItem } from '../../tree/containers/ContainerGroupTreeItem';
Expand Down Expand Up @@ -84,6 +85,7 @@ async function composeGroup<TOptions extends CommonOrchestratorCommandOptions>(
const taskCRF = new TaskCommandRunnerFactory({
taskName: client.displayName,
cwd: workingDirectory,
close: workspace.getConfiguration(configPrefix).get<boolean>('closeComposeTaskTerminal', false),
});

await taskCRF.getCommandRunner()(composeCommandCallback(client, options));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ interface TaskCommandRunnerOptions {
alwaysRunNew?: boolean;
rejectOnError?: boolean;
focus?: boolean;
close?: boolean;
env?: never; // Environment is not needed and should not be used, because VSCode adds it already (due to using `ExtensionContext.environmentVariableCollection`)
}

Expand Down Expand Up @@ -57,11 +58,10 @@ async function executeAsTask(options: TaskCommandRunnerOptions, command: string,
task.definition.idRandomizer = Math.random();
}

if (options.focus) {
task.presentationOptions = {
focus: true,
};
}
task.presentationOptions = {
focus: options.focus,
close: options.close,
};

const taskExecution = await vscode.tasks.executeTask(task);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE.md in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { expect } from 'chai';
import * as vscode from 'vscode';
import { TaskCommandRunnerFactory } from '../../../runtimes/runners/TaskCommandRunnerFactory';

suite('(unit) TaskCommandRunnerFactory', () => {
async function executeTask(options: { close?: boolean; focus?: boolean }): Promise<vscode.TaskPresentationOptions> {
const taskName = `TaskCommandRunnerFactory test ${Date.now()} ${Math.random()}`;
let presentationOptions: vscode.TaskPresentationOptions | undefined;
let taskExecution: vscode.TaskExecution | undefined;

const taskStarted = new Promise<void>(resolve => {
const disposable = vscode.tasks.onDidStartTask(event => {
if (event.execution.task.name === taskName) {
presentationOptions = event.execution.task.presentationOptions;
taskExecution = event.execution;
disposable.dispose();
resolve();
}
});
});

const commandResponse = process.platform === 'win32' ?
{ command: process.env.ComSpec ?? 'cmd.exe', args: ['/d', '/c', 'ping', '-n', '30', '127.0.0.1'] } :
{ command: '/bin/sh', args: ['-c', 'sleep 30'] };

const runner = new TaskCommandRunnerFactory({ taskName, alwaysRunNew: true, ...options }).getCommandRunner();
const runnerPromise = runner(commandResponse);
await taskStarted;
await new Promise(resolve => setTimeout(resolve, 100));
taskExecution?.terminate();
await runnerPromise;

expect(presentationOptions).not.to.be.undefined;
return presentationOptions;
}

test('Leaves presentation options unset when they are not provided', async () => {
const presentationOptions = await executeTask({});

expect(presentationOptions.focus).to.be.undefined;
expect(presentationOptions.close).to.be.undefined;
});

test('Preserves explicitly disabled presentation options', async () => {
const presentationOptions = await executeTask({ focus: false, close: false });

expect(presentationOptions.focus).to.equal(false);
expect(presentationOptions.close).to.equal(false);
});

test('Enables terminal closing without changing focus', async () => {
const presentationOptions = await executeTask({ close: true });

expect(presentationOptions.focus).to.be.undefined;
expect(presentationOptions.close).to.equal(true);
});
});