diff --git a/extensions/resource-deployment/package.json b/extensions/resource-deployment/package.json index 18fb2bdcc1..a62ea711a2 100644 --- a/extensions/resource-deployment/package.json +++ b/extensions/resource-deployment/package.json @@ -29,15 +29,9 @@ { "title": "%deployment.configuration.title%", "properties": { - "deployment.azdataPipInstallUri": { + "deployment.azdataInstallLocation": { "type": "string", - "default": "https://aka.ms/azdata", - "description": "%azdata-pip-install-uri-description%" - }, - "deployment.azdataPipInstallArgs": { - "type": "string", - "default": "", - "description": "%azdata-pip-install-args-description%" + "description": "%azdata-install-location-description%" } } } diff --git a/extensions/resource-deployment/package.nls.json b/extensions/resource-deployment/package.nls.json index cb5635e9a8..14ae349c16 100644 --- a/extensions/resource-deployment/package.nls.json +++ b/extensions/resource-deployment/package.nls.json @@ -49,6 +49,5 @@ "bdc-agreement-azdata-eula": "azdata License Terms", "bdc-agreement-bdc-eula": "SQL Server License Terms", "deployment.configuration.title": "Deployment configuration", - "azdata-pip-install-uri-description": "Location of the azdata package used for the pip install command", - "azdata-pip-install-args-description": "Additional arguments for the pip install azdata command" + "azdata-install-location-description": "Location of the azdata package used for the install command" } diff --git a/extensions/resource-deployment/src/constants.ts b/extensions/resource-deployment/src/constants.ts index eb6af0b9e6..196d1691b5 100644 --- a/extensions/resource-deployment/src/constants.ts +++ b/extensions/resource-deployment/src/constants.ts @@ -4,5 +4,4 @@ *--------------------------------------------------------------------------------------------*/ export const DeploymentConfigurationKey: string = 'deployment'; -export const AzdataPipInstallUriKey: string = 'azdataPipInstallUri'; -export const azdataPipInstallArgsKey: string = 'azdataPipInstallArgs'; +export const AzdataInstallLocationKey: string = 'azdataInstallLocation'; diff --git a/extensions/resource-deployment/src/interfaces.ts b/extensions/resource-deployment/src/interfaces.ts index d6661e3437..bb20fba655 100644 --- a/extensions/resource-deployment/src/interfaces.ts +++ b/extensions/resource-deployment/src/interfaces.ts @@ -248,11 +248,10 @@ export interface ITool { readonly dependencyMessages: string[]; readonly statusDescription: string | undefined; readonly autoInstallSupported: boolean; - readonly autoInstallRequired: boolean; + readonly autoInstallNeeded: boolean; readonly isNotInstalled: boolean; readonly isInstalled: boolean; readonly installationPath: string; - readonly needsInstallation: boolean; readonly outputChannelName: string; readonly fullVersion: string | undefined; readonly onDidUpdateData: vscode.Event; diff --git a/extensions/resource-deployment/src/services/tools/azCliTool.ts b/extensions/resource-deployment/src/services/tools/azCliTool.ts index cdf89ef79e..25b0f533cc 100644 --- a/extensions/resource-deployment/src/services/tools/azCliTool.ts +++ b/extensions/resource-deployment/src/services/tools/azCliTool.ts @@ -39,10 +39,6 @@ export class AzCliTool extends ToolBase { return 'https://docs.microsoft.com/cli/azure/install-azure-cli'; } - get autoInstallSupported(): boolean { - return true; - } - protected async getSearchPaths(): Promise { switch (this.osDistribution) { case OsDistribution.win32: diff --git a/extensions/resource-deployment/src/services/tools/azdataTool.ts b/extensions/resource-deployment/src/services/tools/azdataTool.ts index 9138d48a71..6b2551b2e6 100644 --- a/extensions/resource-deployment/src/services/tools/azdataTool.ts +++ b/extensions/resource-deployment/src/services/tools/azdataTool.ts @@ -7,7 +7,7 @@ import * as path from 'path'; import { SemVer } from 'semver'; import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; -import { azdataPipInstallArgsKey, AzdataPipInstallUriKey, DeploymentConfigurationKey } from '../../constants'; +import { AzdataInstallLocationKey, DeploymentConfigurationKey } from '../../constants'; import { Command, OsDistribution, ToolType } from '../../interfaces'; import { IPlatformService } from '../platformService'; import { dependencyType, ToolBase } from './toolBase'; @@ -62,11 +62,6 @@ export class AzdataTool extends ToolBase { } return version; } - - get autoInstallSupported(): boolean { - return true; - } - protected async getSearchPaths(): Promise { switch (this.osDistribution) { case OsDistribution.win32: @@ -87,109 +82,100 @@ export class AzdataTool extends ToolBase { protected get allInstallationCommands(): Map { return new Map([ - [OsDistribution.debian, debianInstallationCommands], - [OsDistribution.win32, win32InstallationCommands], - [OsDistribution.darwin, macOsInstallationCommands], - [OsDistribution.others, this.defaultInstallationCommands] + [OsDistribution.debian, this.debianInstallationCommands], + [OsDistribution.win32, this.win32InstallationCommands], + [OsDistribution.darwin, this.macOsInstallationCommands], + [OsDistribution.others, []] ]); } - protected get uninstallCommand(): string | undefined { - return this.defaultUninstallCommand; + + private get azdataInstallLocation(): string { + return vscode.workspace.getConfiguration(DeploymentConfigurationKey)[AzdataInstallLocationKey] || this.defaultInstallLocationByDistribution.get(this.osDistribution); } - private get defaultInstallationCommands(): Command[] { - return [ - { - comment: localize('resourceDeployment.Azdata.InstallUpdatePythonRequestsPackage', "installing/updating to latest version of requests python package azdata …"), - command: `pip3 install -U requests` - }, - { - comment: localize('resourceDeployment.Azdata.InstallingAzdata', "installing azdata …"), - command: `pip3 install -r ${this.azdataInstallUri} ${this.azdataInstallAdditionalArgs} --quiet --user` - } - ]; - } - - private get defaultUninstallCommand(): string { - return `pip3 uninstall -r ${this.azdataInstallUri} ${this.azdataInstallAdditionalArgs} -y `; - } - - private get azdataInstallUri(): string { - return vscode.workspace.getConfiguration(DeploymentConfigurationKey)[AzdataPipInstallUriKey]; - } - - private get azdataInstallAdditionalArgs(): string { - return vscode.workspace.getConfiguration(DeploymentConfigurationKey)[azdataPipInstallArgsKey]; - } + private defaultInstallLocationByDistribution: Map = new Map([ + [OsDistribution.debian, 'https://packages.microsoft.com/config/ubuntu/16.04/mssql-server-2019.list'], + [OsDistribution.win32, 'https://aka.ms/azdata-msi'], + [OsDistribution.darwin, 'microsoft/azdata-cli-release'], + [OsDistribution.others, ''] + ]); protected dependenciesByOsType: Map = new Map([ [OsDistribution.debian, []], [OsDistribution.win32, []], - [OsDistribution.darwin, []], - [OsDistribution.others, [dependencyType.PythonAndPip3]] + [OsDistribution.darwin, [dependencyType.Brew]], + [OsDistribution.others, []] ]); -} -const win32InstallationCommands = [ - { - comment: localize('resourceDeployment.Azdata.DeletingPreviousAzdata.msi', "deleting previously downloaded Azdata.msi if one exists …"), - command: `IF EXIST .\\Azdata.msi DEL /F .\\Azdata.msi` - }, - { - sudo: true, - comment: localize('resourceDeployment.Azdata.DownloadingAndInstallingAzdata', "downloading Azdata.msi and installing azdata-cli …"), - command: `powershell -Command "& {(New-Object System.Net.WebClient).DownloadFile('https://aka.ms/azdata-msi', 'Azdata.msi'); Start-Process msiexec.exe -Wait -ArgumentList '/I Azdata.msi /passive /quiet /lvx ADS_AzdataInstall.log'}"` - }, - { - comment: localize('resourceDeployment.Azdata.DisplayingInstallationLog', "displaying the installation log …"), - command: `type ADS_AzdataInstall.log | findstr /i /v ^MSI"`, - ignoreError: true + private get win32InstallationCommands() { + return [ + { + comment: localize('resourceDeployment.Azdata.DeletingPreviousAzdata.msi', "deleting previously downloaded Azdata.msi if one exists …"), + command: `IF EXIST .\\Azdata.msi DEL /F .\\Azdata.msi` + }, + { + sudo: true, + comment: localize('resourceDeployment.Azdata.DownloadingAndInstallingAzdata', "downloading Azdata.msi and installing azdata-cli …"), + command: `powershell -Command "& {(New-Object System.Net.WebClient).DownloadFile('${this.azdataInstallLocation}', 'Azdata.msi'); Start-Process msiexec.exe -Wait -ArgumentList '/I Azdata.msi /passive /quiet /lvx ADS_AzdataInstall.log'}"` + }, + { + comment: localize('resourceDeployment.Azdata.DisplayingInstallationLog', "displaying the installation log …"), + command: `type ADS_AzdataInstall.log | findstr /i /v ^MSI"`, + ignoreError: true + } + ]; } -]; -const macOsInstallationCommands = [ - { - comment: localize('resourceDeployment.Azdata.TappingBrewRepository', "tapping into the brew repository for azdata-cli …"), - command: 'brew tap microsoft/azdata-cli-release' - }, - { - comment: localize('resourceDeployment.Azdata.UpdatingBrewRepository', "updating the brew repository for azdata-cli installation …"), - command: 'brew update' - }, - { - comment: localize('resourceDeployment.Azdata.InstallingAzdata', "installing azdata …"), - command: 'brew install azdata-cli' + + private get macOsInstallationCommands() { + return [ + { + comment: localize('resourceDeployment.Azdata.TappingBrewRepository', "tapping into the brew repository for azdata-cli …"), + command: `brew tap ${this.azdataInstallLocation}` + }, + { + comment: localize('resourceDeployment.Azdata.UpdatingBrewRepository', "updating the brew repository for azdata-cli installation …"), + command: 'brew update' + }, + { + comment: localize('resourceDeployment.Azdata.InstallingAzdata', "installing azdata …"), + command: 'brew install azdata-cli' + } + ]; } -]; -const debianInstallationCommands = [ - { - sudo: true, - comment: localize('resourceDeployment.Azdata.AptGetUpdate', "updating repository information …"), - command: 'apt-get update' - }, - { - sudo: true, - comment: localize('resourceDeployment.Azdata.AptGetPackages', "getting packages needed for azdata installation …"), - command: 'apt-get install gnupg ca-certificates curl apt-transport-https lsb-release -y' - }, - { - sudo: true, - comment: localize('resourceDeployment.Azdata.DownloadAndInstallingSigningKey', "downloading and installing the signing key for azdata …"), - command: 'wget -qO- https://packages.microsoft.com/keys/microsoft.asc | apt-key add -' - }, - { - sudo: true, - comment: localize('resourceDeployment.Azdata.AddingAzdataRepositoryInformation', "adding the azdata repository information …"), - command: 'add-apt-repository "$(wget -qO- https://packages.microsoft.com/config/ubuntu/16.04/mssql-server-2019.list)"' - }, - { - sudo: true, - comment: localize('resourceDeployment.Azdata.AptGetUpdate', "updating repository information …"), - command: 'apt-get update' - }, - { - sudo: true, - comment: localize('resourceDeployment.Azdata.InstallingAzdata', "installing azdata …"), - command: 'apt-get install -y azdata-cli' + + private get debianInstallationCommands() { + return [ + { + sudo: true, + comment: localize('resourceDeployment.Azdata.AptGetUpdate', "updating repository information …"), + command: 'apt-get update' + }, + { + sudo: true, + comment: localize('resourceDeployment.Azdata.AptGetPackages', "getting packages needed for azdata installation …"), + command: 'apt-get install gnupg ca-certificates curl apt-transport-https lsb-release -y' + }, + { + sudo: true, + comment: localize('resourceDeployment.Azdata.DownloadAndInstallingSigningKey', "downloading and installing the signing key for azdata …"), + command: 'wget -qO- https://packages.microsoft.com/keys/microsoft.asc | apt-key add -' + }, + { + sudo: true, + comment: localize('resourceDeployment.Azdata.AddingAzdataRepositoryInformation', "adding the azdata repository information …"), + command: `add-apt-repository "$(wget -qO- ${this.azdataInstallLocation})"` + }, + { + sudo: true, + comment: localize('resourceDeployment.Azdata.AptGetUpdate', "updating repository information …"), + command: 'apt-get update' + }, + { + sudo: true, + comment: localize('resourceDeployment.Azdata.InstallingAzdata', "installing azdata …"), + command: 'apt-get install -y azdata-cli' + } + ]; } -]; +} diff --git a/extensions/resource-deployment/src/services/tools/dockerTool.ts b/extensions/resource-deployment/src/services/tools/dockerTool.ts index f3ab868107..7514a671fd 100644 --- a/extensions/resource-deployment/src/services/tools/dockerTool.ts +++ b/extensions/resource-deployment/src/services/tools/dockerTool.ts @@ -47,11 +47,5 @@ export class DockerTool extends ToolBase { return { command: 'docker version --format "{{json .}}"' }; } - get autoInstallSupported(): boolean { - return false; - } - - protected get allInstallationCommands(): Map { - throw Error('Installation of DockerTool is not supported'); - } + protected readonly allInstallationCommands: Map = new Map(); } diff --git a/extensions/resource-deployment/src/services/tools/kubeCtlTool.ts b/extensions/resource-deployment/src/services/tools/kubeCtlTool.ts index 4a43eac8fb..e7a801d1ec 100644 --- a/extensions/resource-deployment/src/services/tools/kubeCtlTool.ts +++ b/extensions/resource-deployment/src/services/tools/kubeCtlTool.ts @@ -57,11 +57,6 @@ export class KubeCtlTool extends ToolBase { command: this.discoveryCommandString('kubectl') }; } - - get autoInstallSupported(): boolean { - return true; - } - protected async getSearchPaths(): Promise { switch (this.osDistribution) { case OsDistribution.win32: diff --git a/extensions/resource-deployment/src/services/tools/toolBase.ts b/extensions/resource-deployment/src/services/tools/toolBase.ts index 1d01eb9b67..19fa2d42ed 100644 --- a/extensions/resource-deployment/src/services/tools/toolBase.ts +++ b/extensions/resource-deployment/src/services/tools/toolBase.ts @@ -27,17 +27,14 @@ const toolStatusLocalized: Map = new Map ]); export const enum dependencyType { - PythonAndPip3 = 'PythonAndPip3', Brew = 'Brew', Curl = 'Curl' } -const pythonAndPip3Localized = localize('deploymentDialog.ToolInformationalMessage.PythonAndPip3', "• azdata installation needs pip3 and python3 version 3.6 to be pre-installed before necessary tools can be deployed"); const brewLocalized = localize('deploymentDialog.ToolInformationalMessage.Brew', "• brew is needed for deployment of the tools and needs to be pre-installed before necessary tools can be deployed"); const curlLocalized = localize('deploymentDialog.ToolInformationalMessage.Curl', "• curl is needed for installation and needs to be pre-installed before necessary tools can be deployed"); export const messageByDependencyType: Map = new Map([ - [dependencyType.PythonAndPip3, pythonAndPip3Localized], [dependencyType.Brew, brewLocalized], [dependencyType.Curl, curlLocalized] ]); @@ -51,7 +48,6 @@ export abstract class ToolBase implements ITool { abstract description: string; abstract type: ToolType; abstract homePage: string; - abstract autoInstallSupported: boolean; protected abstract readonly allInstallationCommands: Map; protected readonly dependenciesByOsType: Map = new Map(); @@ -100,7 +96,7 @@ export abstract class ToolBase implements ITool { return toolStatusLocalized.get(this._status); } - public get autoInstallRequired(): boolean { + public get autoInstallNeeded(): boolean { return this.status !== ToolStatus.Installed && this.autoInstallSupported; } @@ -116,10 +112,6 @@ export abstract class ToolBase implements ITool { return this.status === ToolStatus.Installing; } - public get needsInstallation(): boolean { - return this.status !== ToolStatus.Installed; - } - public get storagePath(): string { return this._platformService.storagePath(); } @@ -177,6 +169,11 @@ export abstract class ToolBase implements ITool { this._platformService.showOutputChannel(preserveFocus); } + + get autoInstallSupported(): boolean { + return !!this.installationCommands && !!this.installationCommands.length; + } + public async install(): Promise { this._statusDescription = ''; try { @@ -207,7 +204,7 @@ export abstract class ToolBase implements ITool { protected async installCore() { const installationCommands: Command[] | undefined = this.installationCommands; if (!installationCommands || installationCommands.length === 0) { - throw new Error(localize('toolBase.installCore.CannotInstallTool', "Cannot install tool:${0}::${1} as installation commands are unknown", this.displayName, this.description)); + throw new Error(localize('toolBase.installCore.CannotInstallTool', "Cannot install tool:{0}::{1} as installation commands are unknown for your OS distribution, Please install {0} manually before proceeding", this.displayName, this.description)); } for (let i: number = 0; i < installationCommands.length; i++) { await this._platformService.runCommand(installationCommands[i].command, @@ -229,11 +226,9 @@ export abstract class ToolBase implements ITool { if (process.env.PATH) { if (!`${path.delimiter}${process.env.PATH}${path.delimiter}`.includes(`${path.delimiter}${searchPath}${path.delimiter}`)) { process.env.PATH += `${path.delimiter}${searchPath}`; - console.log(`Appending to Path -> '${path.delimiter}${searchPath}'`); } } else { process.env.PATH = searchPath; - console.log(`Setting PATH to -> '${searchPath}'`); } }); } diff --git a/extensions/resource-deployment/src/ui/resourceTypePickerDialog.ts b/extensions/resource-deployment/src/ui/resourceTypePickerDialog.ts index 5eaeee8c04..0ff3892d89 100644 --- a/extensions/resource-deployment/src/ui/resourceTypePickerDialog.ts +++ b/extensions/resource-deployment/src/ui/resourceTypePickerDialog.ts @@ -27,6 +27,7 @@ export class ResourceTypePickerDialog extends DialogBase { private _agreementContainer!: azdata.DivContainer; private _agreementCheckboxChecked: boolean = false; private _installToolButton: azdata.window.Button; + private _installationInProgress: boolean = false; private _tools: ITool[] = []; constructor( @@ -42,6 +43,7 @@ export class ResourceTypePickerDialog extends DialogBase { this._dialogObject.customButtons = [this._installToolButton]; this._installToolButton.hidden = true; this._dialogObject.okButton.label = localize('deploymentDialog.OKButtonText', "Select"); + this._dialogObject.okButton.enabled = false; // this is enabled after all tools are discovered. } initialize() { @@ -216,33 +218,33 @@ export class ResourceTypePickerDialog extends DialogBase { if (this.toolRefreshTimestamp !== currentRefreshTimestamp) { return; } - let installationRequired = false; + let installationNeeded = false; let minVersionCheckFailed = false; const messages: string[] = []; - this._toolsTable.data = toolRequirements.map(toolReq => { - const tool = this.toolsService.getToolByName(toolReq.name)!; + this._toolsTable.data = toolRequirements.map(toolRequirement => { + const tool = this.toolsService.getToolByName(toolRequirement.name)!; // subscribe to onUpdateData event of the tool. this._toDispose.push(tool.onDidUpdateData((t: ITool) => { this.updateToolsDisplayTableData(t); })); if (tool.isNotInstalled && !tool.autoInstallSupported) { - messages.push(localize('deploymentDialog.ToolInformation', "'{0}' [ {1} ]", tool.displayName, tool.homePage)); + messages.push(localize('deploymentDialog.ToolInformation', "'{0}' was not discovered and automated installation is not supported. Kindly install it manually or if installed make sure it is started and discoverable. Once done please restart Azure Data Studio. See [{1}] .", tool.displayName, tool.homePage)); if (tool.statusDescription !== undefined) { console.warn(localize('deploymentDialog.DetailToolStatusDescription', "Additional status information for tool: '{0}' [ {1} ]. {2}", tool.name, tool.homePage, tool.statusDescription)); } - } else if (tool.isInstalled && toolReq.version && !tool.isSameOrNewerThan(toolReq.version)) { + } else if (tool.isInstalled && toolRequirement.version && !tool.isSameOrNewerThan(toolRequirement.version)) { minVersionCheckFailed = true; messages.push(localize('deploymentDialog.ToolDoesNotMeetVersionRequirement', "'{0}' [ {1} ] does not meet the minimum version requirement, please uninstall it and restart Azure Data Studio.", tool.displayName, tool.homePage)); } - installationRequired = installationRequired || tool.autoInstallRequired; - return [tool.displayName, tool.description, tool.displayStatus, tool.fullVersion || '', toolReq.version || '']; + installationNeeded = installationNeeded || tool.autoInstallNeeded; + return [tool.displayName, tool.description, tool.displayStatus, tool.fullVersion || '', toolRequirement.version || '']; }); - this._installToolButton.hidden = minVersionCheckFailed || !installationRequired; - this._dialogObject.okButton.enabled = messages.length === 0 && !minVersionCheckFailed && !installationRequired; + this._installToolButton.hidden = minVersionCheckFailed || !installationNeeded; + this._dialogObject.okButton.enabled = messages.length === 0 && !minVersionCheckFailed && !installationNeeded; if (messages.length !== 0) { if (!minVersionCheckFailed) { - messages.push(localize('deploymentDialog.VersionInformationDebugHint', "You will need to restart Azure Data Studio if the tools are installed by yourself after Azure Data Studio is launched to pick up the updated PATH environment variable. You may find additional details in the debug console by running the 'Toggle Developer Tools' command in the Azure Data Studio Command Palette.")); + messages.push(localize('deploymentDialog.VersionInformationDebugHint', "You will need to restart Azure Data Studio if the tools are installed by yourself after Azure Data Studio is launched to pick up the updated PATH environment variable. You may find additional details in 'Deployments' output channel")); } this._dialogObject.message = { level: azdata.window.MessageLevel.Error, @@ -251,10 +253,10 @@ export class ResourceTypePickerDialog extends DialogBase { ...messages ].join(EOL) }; - } else if (installationRequired) { + } else if (installationNeeded && !this._installationInProgress) { let infoText: string[] = [localize('deploymentDialog.InstallToolsHint', "Some required tools are not installed, you can click the \"{0}\" button to install them.", this._installToolButton.label)]; const informationalMessagesArray = this._tools.reduce((returnArray, currentTool) => { - if (currentTool.needsInstallation) { + if (currentTool.autoInstallNeeded) { returnArray.push(...currentTool.dependencyMessages); } return returnArray; @@ -338,13 +340,15 @@ export class ResourceTypePickerDialog extends DialogBase { private async installTools(): Promise { this._installToolButton.enabled = false; + this._installationInProgress = true; let tool: ITool; try { const toolRequirements = this.getCurrentProvider().requiredTools; + let toolsNotInstalled: ITool[] = []; for (let i: number = 0; i < toolRequirements.length; i++) { const toolReq = toolRequirements[i]; tool = this.toolsService.getToolByName(toolReq.name)!; - if (tool.needsInstallation) { + if (tool.autoInstallNeeded) { // Update the informational message this._dialogObject.message = { level: azdata.window.MessageLevel.Information, @@ -358,14 +362,23 @@ export class ResourceTypePickerDialog extends DialogBase { ) ); } + } else { + toolsNotInstalled.push(tool); } } // Update the informational message - this._dialogObject.message = { - level: azdata.window.MessageLevel.Information, - text: localize('deploymentDialog.InstalledTools', "All required tools are installed now.") - }; - this._dialogObject.okButton.enabled = true; + if (toolsNotInstalled.length === 0) { + this._dialogObject.message = { + level: azdata.window.MessageLevel.Information, + text: localize('deploymentDialog.InstalledTools', "All required tools are installed now.") + }; + this._dialogObject.okButton.enabled = true; + } else { + this._dialogObject.message = { + level: azdata.window.MessageLevel.Information, + text: localize('deploymentDialog.PendingInstallation', "Following tools: {0} were still not discovered. Please make sure that they are installed, running and discoverable", toolsNotInstalled.map(t => t.displayName).join(',')) + }; + } } catch (error) { const errorMessage = tool!.statusDescription || getErrorMessage(error); if (errorMessage) { @@ -377,5 +390,6 @@ export class ResourceTypePickerDialog extends DialogBase { } tool!.showOutputChannel(/*preserverFocus*/false); } + this._installationInProgress = false; } } diff --git a/extensions/resource-deployment/src/utils.ts b/extensions/resource-deployment/src/utils.ts index 7f78ce660a..82d7f0e55e 100644 --- a/extensions/resource-deployment/src/utils.ts +++ b/extensions/resource-deployment/src/utils.ts @@ -32,12 +32,10 @@ export function setEnvironmentVariablesForInstallPaths(tools: ITool[]): void { const envVarName = getRuntimeBinaryPathEnvironmentVariableName(t.name); process.env[envVarName] = t.installationPath; installationPaths.add(path.dirname(t.installationPath)); - console.log(`setting env var:'${envVarName}' to: '${t.installationPath}'`); } }); if (installationPaths.size > 0) { const envVarToolsInstallationPath: string = [...installationPaths.values()].join(path.delimiter); process.env[ToolsInstallPath] = envVarToolsInstallationPath; - console.log(`setting env var:'${ToolsInstallPath}' to: '${envVarToolsInstallationPath}'`); } }