diff --git a/Tasks/UseDotNetV2/Strings/resources.resjson/en-US/resources.resjson b/Tasks/UseDotNetV2/Strings/resources.resjson/en-US/resources.resjson index cb0a286383d3..8a5206e9d049 100644 --- a/Tasks/UseDotNetV2/Strings/resources.resjson/en-US/resources.resjson +++ b/Tasks/UseDotNetV2/Strings/resources.resjson/en-US/resources.resjson @@ -15,12 +15,16 @@ "loc.input.help.version": "Specify version of .NET Core SDK or runtime to install.
Versions can be given in the following formats
  • 2.x => Install latest in major version.
  • 2.2.x => Install latest in major and minor version
  • 2.2.104 => Install exact version

  • Find the value of `version` for installing SDK/Runtime, from the releases.json. The link to releases.json of that major.minor version can be found in [**releases-index file.**](https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/releases-index.json). Like link to releases.json for 2.2 version is https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/2.2/releases.json", "loc.input.label.vsVersion": "Compatible Visual Studio version", "loc.input.help.vsVersion": "Specify version of compatible visual studio for which .NET core sdk to install. Specifiy complete vs-version like 16.6.4 containing major version, minor version and patch number.Find the value of `version` for installing SDK/Runtime, from the releases.json. The link to releases.json of that major.minor version can be found in [**releases-index file.**](https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/releases-index.json)", + "loc.input.label.checkDotnetCLI": "Check is version installed via dotnet", + "loc.input.help.checkDotnetCLI": "Select if you want to check is version already installed via dotnet CLI", "loc.input.label.includePreviewVersions": "Include Preview Versions", "loc.input.help.includePreviewVersions": "Select if you want preview versions to be included while searching for latest versions, such as while searching 2.2.x. This setting is ignored if you specify an exact version, such as: 3.0.100-preview3-010431", "loc.input.label.installationPath": "Path To Install .Net Core", "loc.input.help.installationPath": "Specify where .Net Core SDK/Runtime should be installed. Different paths can have the following impact on .Net's behavior.
  • $(Agent.ToolsDirectory): This makes the version to be cached on the agent since this directory is not cleanup up across pipelines. All pipelines running on the agent, would have access to the versions installed previously using the agent.
  • $(Agent.TempDirectory): This can ensure that a pipeline doesn't use any cached version of .Net core since this folder is cleaned up after each pipeline.
  • Any other path: You can configure any other path given the agent process has access to the path. This will change the state of the machine and impact all processes running on it.
    Note that you can also configure Multi-Level Lookup setting which can configure .Net host's probing for a suitable version.", "loc.input.label.performMultiLevelLookup": "Perform Multi Level Lookup", "loc.input.help.performMultiLevelLookup": "This input is only applicable to Windows based agents. This configures the behavior of .Net host process for looking up a suitable shared framework.
  • unchecked: Only versions present in the folder specified in this task would be looked by the host process.
  • checked: The host will attempt to look in pre-defined global locations using multi-level lookup.
    The default global locations are:
    For Windows:
    C:\\Program Files\\dotnet (64-bit processes)
    C:\\Program Files (x86)\\dotnet (32-bit process)
  • You can read more about it [**HERE**](https://github.com/dotnet/core-setup/blob/master/Documentation/design-docs/multilevel-sharedfx-lookup.md).
    ", + "loc.input.label.requestTimeout": "Set timeout for package download request", + "loc.input.help.requestTimeout": "Provide a timeout value for HTTP requests that the task makes to obtain the .NET package. The value is in milliseconds. Default is 300000 milliseconds (5 minutes). Cannot be more than 600000 milliseconds (10 minutes).", "loc.messages.ToolFailed": "Tool install failed: %s", "loc.messages.ImplicitVersionNotSupported": "Version should be a valid and explicit version: %s", "loc.messages.getMachinePlatformFailed": "Failed to get machine platform details. Error: %s.", diff --git a/Tasks/UseDotNetV2/task.json b/Tasks/UseDotNetV2/task.json index 7ab9cc97a88b..5149f6761d09 100644 --- a/Tasks/UseDotNetV2/task.json +++ b/Tasks/UseDotNetV2/task.json @@ -13,7 +13,7 @@ "author": "Microsoft Corporation", "version": { "Major": 2, - "Minor": 248, + "Minor": 250, "Patch": 0 }, "satisfies": [ @@ -79,6 +79,15 @@ "groupName": "advanced", "helpMarkDown": "Specify version of compatible visual studio for which .NET core sdk to install. Specifiy complete vs-version like 16.6.4 containing major version, minor version and patch number.Find the value of `version` for installing SDK/Runtime, from the releases.json. The link to releases.json of that major.minor version can be found in [**releases-index file.**](https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/releases-index.json)" }, + { + "name": "checkDotnetCLI", + "type": "boolean", + "label": "Check is version installed via dotnet", + "defaultValue": "false", + "required": false, + "helpMarkDown": "Select if you want to check is version already installed via dotnet CLI", + "groupName": "advanced" + }, { "name": "includePreviewVersions", "type": "boolean", diff --git a/Tasks/UseDotNetV2/task.loc.json b/Tasks/UseDotNetV2/task.loc.json index 65944cef02c9..8d613c9086d8 100644 --- a/Tasks/UseDotNetV2/task.loc.json +++ b/Tasks/UseDotNetV2/task.loc.json @@ -13,7 +13,7 @@ "author": "Microsoft Corporation", "version": { "Major": 2, - "Minor": 248, + "Minor": 250, "Patch": 0 }, "satisfies": [ @@ -79,6 +79,15 @@ "groupName": "advanced", "helpMarkDown": "ms-resource:loc.input.help.vsVersion" }, + { + "name": "checkDotnetCLI", + "type": "boolean", + "label": "ms-resource:loc.input.label.checkDotnetCLI", + "defaultValue": "false", + "required": false, + "helpMarkDown": "ms-resource:loc.input.help.checkDotnetCLI", + "groupName": "advanced" + }, { "name": "includePreviewVersions", "type": "boolean", diff --git a/Tasks/UseDotNetV2/usedotnet.ts b/Tasks/UseDotNetV2/usedotnet.ts index 2964315b5710..d04238ac4fda 100644 --- a/Tasks/UseDotNetV2/usedotnet.ts +++ b/Tasks/UseDotNetV2/usedotnet.ts @@ -18,6 +18,7 @@ function checkVersionForDeprecationAndNotify(versionSpec: string | null): void { async function run() { let useGlobalJson: boolean = tl.getBoolInput('useGlobalJson'); + let checkDotnetCLI: boolean = tl.getBoolInput('checkDotnetCLI'); let packageType = (tl.getInput('packageType') || "sdk").toLowerCase();; let versionSpec = tl.getInput('version'); let vsVersionSpec = tl.getInput('vsVersion'); @@ -31,12 +32,21 @@ async function run() { let performMultiLevelLookup = tl.getBoolInput("performMultiLevelLookup", false); // Check if we want install dotnet if (versionSpec || (useGlobalJson && packageType == "sdk")) { + let isDotnetInstalled = false; + let includePreviewVersions: boolean = tl.getBoolInput('includePreviewVersions'); let workingDirectory: string | null = tl.getPathInput("workingDirectory", false) || null; - await installDotNet(installationPath, packageType, versionSpec, vsVersionSpec, useGlobalJson, workingDirectory, includePreviewVersions); - tl.prependPath(installationPath); - // Set DOTNET_ROOT for dotnet core Apphost to find runtime since it is installed to a non well-known location. - tl.setVariable('DOTNET_ROOT', installationPath); + + // check is dotnet installed via dotnet cli + if (checkDotnetCLI) isDotnetInstalled = await isCompatibleDotnetVersionInstalled(versionSpec, vsVersionSpec, useGlobalJson, packageType, workingDirectory, includePreviewVersions); + + if (!isDotnetInstalled) { + await installDotNet(installationPath, packageType, versionSpec, vsVersionSpec, useGlobalJson, workingDirectory, includePreviewVersions); + tl.prependPath(installationPath); + // Set DOTNET_ROOT for dotnet core Apphost to find runtime since it is installed to a non well-known location. + tl.setVariable('DOTNET_ROOT', installationPath); + } + // By default disable Multi Level Lookup unless user wants it enabled. tl.setVariable("DOTNET_MULTILEVEL_LOOKUP", !performMultiLevelLookup ? "0" : "1"); } @@ -48,6 +58,55 @@ async function run() { await NuGetInstaller.installNuGet(nugetVersion); } +/** + * + * @param versionSpec The version the user want to install. + * @param vsVersionSpec Compatible Visual Studio version. + * @param useGlobalJson A switch so we know if the user have `global.json` files and want use that. If this is true only SDK is possible! + * @param packageType The installation type for the installation. Only `sdk` and `runtime` are valid options + * @param workingDirectory This is only relevant if the `useGlobalJson` switch is `true`. It will set the root directory for the search of `global.json` + * @param includePreviewVersions Define if the installer also search for preview version + * @returns { Promise } - true if dotnet installed, otherwise - false + */ +async function isCompatibleDotnetVersionInstalled(versionSpec: string, vsVersionSpec: string, useGlobalJson: boolean, packageType: string, workingDirectory: string, includePreviewVersions: boolean): Promise { + let versionFetcher = new DotNetCoreVersionFetcher(); + + if (useGlobalJson && packageType == "sdk") { + let globalJsonFetcherInstance = new globalJsonFetcher(workingDirectory); + let versionsToInstall: VersionInfo[] = await globalJsonFetcherInstance.GetVersions(); + return checkVersionInDotnetCLI(versionsToInstall, packageType); + } else if (versionSpec) { + let versionSpecParts = new VersionParts(versionSpec); + let versionInfo: VersionInfo = await versionFetcher.getVersionInfo(versionSpecParts.versionSpec, vsVersionSpec, packageType, includePreviewVersions); + return checkVersionInDotnetCLI(versionInfo, packageType); + } + + return false; +} + +function checkVersionInDotnetCLI(versionInfo: VersionInfo | VersionInfo[], packageType: string): boolean { + let versions: VersionInfo[]; + if (!Array.isArray(versionInfo)) versions = [ versionInfo ]; + else versions = versionInfo; + const dotnetPath = tl.which('dotnet', false); + if (!dotnetPath) return false; + const dotnet = tl.tool(dotnetPath); + + if (packageType === "sdk") { + dotnet.arg('--list-sdks'); + } else { + dotnet.arg('--list-runtimes'); + } + + const result = dotnet.execSync(); + if (result.code !== 0) return false; + const stdout = result.stdout; + + const notFoundedversions = versions.filter(version => !stdout.includes(version.getVersion())); + + return notFoundedversions.length === 0; +} + /** * install dotnet to the installation path. * @param installationPath The installation path. If this is empty it would use {Agent.ToolsDirectory}/dotnet/ diff --git a/_generated/UseDotNetV2.versionmap.txt b/_generated/UseDotNetV2.versionmap.txt index 25a4e874bc74..9059947d0705 100644 --- a/_generated/UseDotNetV2.versionmap.txt +++ b/_generated/UseDotNetV2.versionmap.txt @@ -1,2 +1,2 @@ -Default|2.248.0 -Node20_229_3|2.248.1 +Default|2.250.0 +Node20_229_3|2.250.1 diff --git a/_generated/UseDotNetV2/Strings/resources.resjson/en-US/resources.resjson b/_generated/UseDotNetV2/Strings/resources.resjson/en-US/resources.resjson index ff3675ffca8a..8a5206e9d049 100644 --- a/_generated/UseDotNetV2/Strings/resources.resjson/en-US/resources.resjson +++ b/_generated/UseDotNetV2/Strings/resources.resjson/en-US/resources.resjson @@ -15,6 +15,8 @@ "loc.input.help.version": "Specify version of .NET Core SDK or runtime to install.
    Versions can be given in the following formats
  • 2.x => Install latest in major version.
  • 2.2.x => Install latest in major and minor version
  • 2.2.104 => Install exact version

  • Find the value of `version` for installing SDK/Runtime, from the releases.json. The link to releases.json of that major.minor version can be found in [**releases-index file.**](https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/releases-index.json). Like link to releases.json for 2.2 version is https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/2.2/releases.json", "loc.input.label.vsVersion": "Compatible Visual Studio version", "loc.input.help.vsVersion": "Specify version of compatible visual studio for which .NET core sdk to install. Specifiy complete vs-version like 16.6.4 containing major version, minor version and patch number.Find the value of `version` for installing SDK/Runtime, from the releases.json. The link to releases.json of that major.minor version can be found in [**releases-index file.**](https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/releases-index.json)", + "loc.input.label.checkDotnetCLI": "Check is version installed via dotnet", + "loc.input.help.checkDotnetCLI": "Select if you want to check is version already installed via dotnet CLI", "loc.input.label.includePreviewVersions": "Include Preview Versions", "loc.input.help.includePreviewVersions": "Select if you want preview versions to be included while searching for latest versions, such as while searching 2.2.x. This setting is ignored if you specify an exact version, such as: 3.0.100-preview3-010431", "loc.input.label.installationPath": "Path To Install .Net Core", diff --git a/_generated/UseDotNetV2/task.json b/_generated/UseDotNetV2/task.json index bdaeab8ae0c5..4c5b9bbbf616 100644 --- a/_generated/UseDotNetV2/task.json +++ b/_generated/UseDotNetV2/task.json @@ -13,7 +13,7 @@ "author": "Microsoft Corporation", "version": { "Major": 2, - "Minor": 248, + "Minor": 250, "Patch": 0 }, "satisfies": [ @@ -79,6 +79,15 @@ "groupName": "advanced", "helpMarkDown": "Specify version of compatible visual studio for which .NET core sdk to install. Specifiy complete vs-version like 16.6.4 containing major version, minor version and patch number.Find the value of `version` for installing SDK/Runtime, from the releases.json. The link to releases.json of that major.minor version can be found in [**releases-index file.**](https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/releases-index.json)" }, + { + "name": "checkDotnetCLI", + "type": "boolean", + "label": "Check is version installed via dotnet", + "defaultValue": "false", + "required": false, + "helpMarkDown": "Select if you want to check is version already installed via dotnet CLI", + "groupName": "advanced" + }, { "name": "includePreviewVersions", "type": "boolean", @@ -203,7 +212,8 @@ "DepricatedVersionNetCore": "NET Core version you specfied %s is out of support and will be removed from hosted agents soon. Please refer to https://aka.ms/dotnet-core-support for more information about the .NET support policy." }, "_buildConfigMapping": { - "Default": "2.248.0", - "Node20_229_3": "2.248.1" + "Default": "2.250.0", + "LocalPackages": "2.249.4", + "Node20_229_3": "2.250.1" } } \ No newline at end of file diff --git a/_generated/UseDotNetV2/task.loc.json b/_generated/UseDotNetV2/task.loc.json index bdbc4ecd92ad..bb94d3d62bce 100644 --- a/_generated/UseDotNetV2/task.loc.json +++ b/_generated/UseDotNetV2/task.loc.json @@ -13,7 +13,7 @@ "author": "Microsoft Corporation", "version": { "Major": 2, - "Minor": 248, + "Minor": 250, "Patch": 0 }, "satisfies": [ @@ -79,6 +79,15 @@ "groupName": "advanced", "helpMarkDown": "ms-resource:loc.input.help.vsVersion" }, + { + "name": "checkDotnetCLI", + "type": "boolean", + "label": "ms-resource:loc.input.label.checkDotnetCLI", + "defaultValue": "false", + "required": false, + "helpMarkDown": "ms-resource:loc.input.help.checkDotnetCLI", + "groupName": "advanced" + }, { "name": "includePreviewVersions", "type": "boolean", @@ -203,7 +212,8 @@ "DepricatedVersionNetCore": "ms-resource:loc.messages.DepricatedVersionNetCore" }, "_buildConfigMapping": { - "Default": "2.248.0", - "Node20_229_3": "2.248.1" + "Default": "2.250.0", + "LocalPackages": "2.249.4", + "Node20_229_3": "2.250.1" } } \ No newline at end of file diff --git a/_generated/UseDotNetV2/usedotnet.ts b/_generated/UseDotNetV2/usedotnet.ts index 2964315b5710..d04238ac4fda 100644 --- a/_generated/UseDotNetV2/usedotnet.ts +++ b/_generated/UseDotNetV2/usedotnet.ts @@ -18,6 +18,7 @@ function checkVersionForDeprecationAndNotify(versionSpec: string | null): void { async function run() { let useGlobalJson: boolean = tl.getBoolInput('useGlobalJson'); + let checkDotnetCLI: boolean = tl.getBoolInput('checkDotnetCLI'); let packageType = (tl.getInput('packageType') || "sdk").toLowerCase();; let versionSpec = tl.getInput('version'); let vsVersionSpec = tl.getInput('vsVersion'); @@ -31,12 +32,21 @@ async function run() { let performMultiLevelLookup = tl.getBoolInput("performMultiLevelLookup", false); // Check if we want install dotnet if (versionSpec || (useGlobalJson && packageType == "sdk")) { + let isDotnetInstalled = false; + let includePreviewVersions: boolean = tl.getBoolInput('includePreviewVersions'); let workingDirectory: string | null = tl.getPathInput("workingDirectory", false) || null; - await installDotNet(installationPath, packageType, versionSpec, vsVersionSpec, useGlobalJson, workingDirectory, includePreviewVersions); - tl.prependPath(installationPath); - // Set DOTNET_ROOT for dotnet core Apphost to find runtime since it is installed to a non well-known location. - tl.setVariable('DOTNET_ROOT', installationPath); + + // check is dotnet installed via dotnet cli + if (checkDotnetCLI) isDotnetInstalled = await isCompatibleDotnetVersionInstalled(versionSpec, vsVersionSpec, useGlobalJson, packageType, workingDirectory, includePreviewVersions); + + if (!isDotnetInstalled) { + await installDotNet(installationPath, packageType, versionSpec, vsVersionSpec, useGlobalJson, workingDirectory, includePreviewVersions); + tl.prependPath(installationPath); + // Set DOTNET_ROOT for dotnet core Apphost to find runtime since it is installed to a non well-known location. + tl.setVariable('DOTNET_ROOT', installationPath); + } + // By default disable Multi Level Lookup unless user wants it enabled. tl.setVariable("DOTNET_MULTILEVEL_LOOKUP", !performMultiLevelLookup ? "0" : "1"); } @@ -48,6 +58,55 @@ async function run() { await NuGetInstaller.installNuGet(nugetVersion); } +/** + * + * @param versionSpec The version the user want to install. + * @param vsVersionSpec Compatible Visual Studio version. + * @param useGlobalJson A switch so we know if the user have `global.json` files and want use that. If this is true only SDK is possible! + * @param packageType The installation type for the installation. Only `sdk` and `runtime` are valid options + * @param workingDirectory This is only relevant if the `useGlobalJson` switch is `true`. It will set the root directory for the search of `global.json` + * @param includePreviewVersions Define if the installer also search for preview version + * @returns { Promise } - true if dotnet installed, otherwise - false + */ +async function isCompatibleDotnetVersionInstalled(versionSpec: string, vsVersionSpec: string, useGlobalJson: boolean, packageType: string, workingDirectory: string, includePreviewVersions: boolean): Promise { + let versionFetcher = new DotNetCoreVersionFetcher(); + + if (useGlobalJson && packageType == "sdk") { + let globalJsonFetcherInstance = new globalJsonFetcher(workingDirectory); + let versionsToInstall: VersionInfo[] = await globalJsonFetcherInstance.GetVersions(); + return checkVersionInDotnetCLI(versionsToInstall, packageType); + } else if (versionSpec) { + let versionSpecParts = new VersionParts(versionSpec); + let versionInfo: VersionInfo = await versionFetcher.getVersionInfo(versionSpecParts.versionSpec, vsVersionSpec, packageType, includePreviewVersions); + return checkVersionInDotnetCLI(versionInfo, packageType); + } + + return false; +} + +function checkVersionInDotnetCLI(versionInfo: VersionInfo | VersionInfo[], packageType: string): boolean { + let versions: VersionInfo[]; + if (!Array.isArray(versionInfo)) versions = [ versionInfo ]; + else versions = versionInfo; + const dotnetPath = tl.which('dotnet', false); + if (!dotnetPath) return false; + const dotnet = tl.tool(dotnetPath); + + if (packageType === "sdk") { + dotnet.arg('--list-sdks'); + } else { + dotnet.arg('--list-runtimes'); + } + + const result = dotnet.execSync(); + if (result.code !== 0) return false; + const stdout = result.stdout; + + const notFoundedversions = versions.filter(version => !stdout.includes(version.getVersion())); + + return notFoundedversions.length === 0; +} + /** * install dotnet to the installation path. * @param installationPath The installation path. If this is empty it would use {Agent.ToolsDirectory}/dotnet/ diff --git a/_generated/UseDotNetV2_Node20/.npmrc b/_generated/UseDotNetV2_Node20/.npmrc index 5fca0d518be7..d5c7fef620a3 100644 --- a/_generated/UseDotNetV2_Node20/.npmrc +++ b/_generated/UseDotNetV2_Node20/.npmrc @@ -1 +1,5 @@ scripts-prepend-node-path=true + +registry=https://pkgs.dev.azure.com/mseng/PipelineTools/_packaging/PipelineTools_PublicPackages/npm/registry/ + +always-auth=true \ No newline at end of file diff --git a/_generated/UseDotNetV2_Node20/Strings/resources.resjson/en-US/resources.resjson b/_generated/UseDotNetV2_Node20/Strings/resources.resjson/en-US/resources.resjson index ff3675ffca8a..8a5206e9d049 100644 --- a/_generated/UseDotNetV2_Node20/Strings/resources.resjson/en-US/resources.resjson +++ b/_generated/UseDotNetV2_Node20/Strings/resources.resjson/en-US/resources.resjson @@ -15,6 +15,8 @@ "loc.input.help.version": "Specify version of .NET Core SDK or runtime to install.
    Versions can be given in the following formats
  • 2.x => Install latest in major version.
  • 2.2.x => Install latest in major and minor version
  • 2.2.104 => Install exact version

  • Find the value of `version` for installing SDK/Runtime, from the releases.json. The link to releases.json of that major.minor version can be found in [**releases-index file.**](https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/releases-index.json). Like link to releases.json for 2.2 version is https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/2.2/releases.json", "loc.input.label.vsVersion": "Compatible Visual Studio version", "loc.input.help.vsVersion": "Specify version of compatible visual studio for which .NET core sdk to install. Specifiy complete vs-version like 16.6.4 containing major version, minor version and patch number.Find the value of `version` for installing SDK/Runtime, from the releases.json. The link to releases.json of that major.minor version can be found in [**releases-index file.**](https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/releases-index.json)", + "loc.input.label.checkDotnetCLI": "Check is version installed via dotnet", + "loc.input.help.checkDotnetCLI": "Select if you want to check is version already installed via dotnet CLI", "loc.input.label.includePreviewVersions": "Include Preview Versions", "loc.input.help.includePreviewVersions": "Select if you want preview versions to be included while searching for latest versions, such as while searching 2.2.x. This setting is ignored if you specify an exact version, such as: 3.0.100-preview3-010431", "loc.input.label.installationPath": "Path To Install .Net Core", diff --git a/_generated/UseDotNetV2_Node20/task.json b/_generated/UseDotNetV2_Node20/task.json index b9bce65efa70..f4180a1fe530 100644 --- a/_generated/UseDotNetV2_Node20/task.json +++ b/_generated/UseDotNetV2_Node20/task.json @@ -13,7 +13,7 @@ "author": "Microsoft Corporation", "version": { "Major": 2, - "Minor": 248, + "Minor": 250, "Patch": 1 }, "satisfies": [ @@ -79,6 +79,15 @@ "groupName": "advanced", "helpMarkDown": "Specify version of compatible visual studio for which .NET core sdk to install. Specifiy complete vs-version like 16.6.4 containing major version, minor version and patch number.Find the value of `version` for installing SDK/Runtime, from the releases.json. The link to releases.json of that major.minor version can be found in [**releases-index file.**](https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/releases-index.json)" }, + { + "name": "checkDotnetCLI", + "type": "boolean", + "label": "Check is version installed via dotnet", + "defaultValue": "false", + "required": false, + "helpMarkDown": "Select if you want to check is version already installed via dotnet CLI", + "groupName": "advanced" + }, { "name": "includePreviewVersions", "type": "boolean", @@ -207,7 +216,8 @@ "DepricatedVersionNetCore": "NET Core version you specfied %s is out of support and will be removed from hosted agents soon. Please refer to https://aka.ms/dotnet-core-support for more information about the .NET support policy." }, "_buildConfigMapping": { - "Default": "2.248.0", - "Node20_229_3": "2.248.1" + "Default": "2.250.0", + "LocalPackages": "2.249.4", + "Node20_229_3": "2.250.1" } } \ No newline at end of file diff --git a/_generated/UseDotNetV2_Node20/task.loc.json b/_generated/UseDotNetV2_Node20/task.loc.json index f012e197d3a9..7380abe71941 100644 --- a/_generated/UseDotNetV2_Node20/task.loc.json +++ b/_generated/UseDotNetV2_Node20/task.loc.json @@ -13,7 +13,7 @@ "author": "Microsoft Corporation", "version": { "Major": 2, - "Minor": 248, + "Minor": 250, "Patch": 1 }, "satisfies": [ @@ -79,6 +79,15 @@ "groupName": "advanced", "helpMarkDown": "ms-resource:loc.input.help.vsVersion" }, + { + "name": "checkDotnetCLI", + "type": "boolean", + "label": "ms-resource:loc.input.label.checkDotnetCLI", + "defaultValue": "false", + "required": false, + "helpMarkDown": "ms-resource:loc.input.help.checkDotnetCLI", + "groupName": "advanced" + }, { "name": "includePreviewVersions", "type": "boolean", @@ -207,7 +216,8 @@ "DepricatedVersionNetCore": "ms-resource:loc.messages.DepricatedVersionNetCore" }, "_buildConfigMapping": { - "Default": "2.248.0", - "Node20_229_3": "2.248.1" + "Default": "2.250.0", + "LocalPackages": "2.249.4", + "Node20_229_3": "2.250.1" } } \ No newline at end of file diff --git a/_generated/UseDotNetV2_Node20/usedotnet.ts b/_generated/UseDotNetV2_Node20/usedotnet.ts index 2964315b5710..d04238ac4fda 100644 --- a/_generated/UseDotNetV2_Node20/usedotnet.ts +++ b/_generated/UseDotNetV2_Node20/usedotnet.ts @@ -18,6 +18,7 @@ function checkVersionForDeprecationAndNotify(versionSpec: string | null): void { async function run() { let useGlobalJson: boolean = tl.getBoolInput('useGlobalJson'); + let checkDotnetCLI: boolean = tl.getBoolInput('checkDotnetCLI'); let packageType = (tl.getInput('packageType') || "sdk").toLowerCase();; let versionSpec = tl.getInput('version'); let vsVersionSpec = tl.getInput('vsVersion'); @@ -31,12 +32,21 @@ async function run() { let performMultiLevelLookup = tl.getBoolInput("performMultiLevelLookup", false); // Check if we want install dotnet if (versionSpec || (useGlobalJson && packageType == "sdk")) { + let isDotnetInstalled = false; + let includePreviewVersions: boolean = tl.getBoolInput('includePreviewVersions'); let workingDirectory: string | null = tl.getPathInput("workingDirectory", false) || null; - await installDotNet(installationPath, packageType, versionSpec, vsVersionSpec, useGlobalJson, workingDirectory, includePreviewVersions); - tl.prependPath(installationPath); - // Set DOTNET_ROOT for dotnet core Apphost to find runtime since it is installed to a non well-known location. - tl.setVariable('DOTNET_ROOT', installationPath); + + // check is dotnet installed via dotnet cli + if (checkDotnetCLI) isDotnetInstalled = await isCompatibleDotnetVersionInstalled(versionSpec, vsVersionSpec, useGlobalJson, packageType, workingDirectory, includePreviewVersions); + + if (!isDotnetInstalled) { + await installDotNet(installationPath, packageType, versionSpec, vsVersionSpec, useGlobalJson, workingDirectory, includePreviewVersions); + tl.prependPath(installationPath); + // Set DOTNET_ROOT for dotnet core Apphost to find runtime since it is installed to a non well-known location. + tl.setVariable('DOTNET_ROOT', installationPath); + } + // By default disable Multi Level Lookup unless user wants it enabled. tl.setVariable("DOTNET_MULTILEVEL_LOOKUP", !performMultiLevelLookup ? "0" : "1"); } @@ -48,6 +58,55 @@ async function run() { await NuGetInstaller.installNuGet(nugetVersion); } +/** + * + * @param versionSpec The version the user want to install. + * @param vsVersionSpec Compatible Visual Studio version. + * @param useGlobalJson A switch so we know if the user have `global.json` files and want use that. If this is true only SDK is possible! + * @param packageType The installation type for the installation. Only `sdk` and `runtime` are valid options + * @param workingDirectory This is only relevant if the `useGlobalJson` switch is `true`. It will set the root directory for the search of `global.json` + * @param includePreviewVersions Define if the installer also search for preview version + * @returns { Promise } - true if dotnet installed, otherwise - false + */ +async function isCompatibleDotnetVersionInstalled(versionSpec: string, vsVersionSpec: string, useGlobalJson: boolean, packageType: string, workingDirectory: string, includePreviewVersions: boolean): Promise { + let versionFetcher = new DotNetCoreVersionFetcher(); + + if (useGlobalJson && packageType == "sdk") { + let globalJsonFetcherInstance = new globalJsonFetcher(workingDirectory); + let versionsToInstall: VersionInfo[] = await globalJsonFetcherInstance.GetVersions(); + return checkVersionInDotnetCLI(versionsToInstall, packageType); + } else if (versionSpec) { + let versionSpecParts = new VersionParts(versionSpec); + let versionInfo: VersionInfo = await versionFetcher.getVersionInfo(versionSpecParts.versionSpec, vsVersionSpec, packageType, includePreviewVersions); + return checkVersionInDotnetCLI(versionInfo, packageType); + } + + return false; +} + +function checkVersionInDotnetCLI(versionInfo: VersionInfo | VersionInfo[], packageType: string): boolean { + let versions: VersionInfo[]; + if (!Array.isArray(versionInfo)) versions = [ versionInfo ]; + else versions = versionInfo; + const dotnetPath = tl.which('dotnet', false); + if (!dotnetPath) return false; + const dotnet = tl.tool(dotnetPath); + + if (packageType === "sdk") { + dotnet.arg('--list-sdks'); + } else { + dotnet.arg('--list-runtimes'); + } + + const result = dotnet.execSync(); + if (result.code !== 0) return false; + const stdout = result.stdout; + + const notFoundedversions = versions.filter(version => !stdout.includes(version.getVersion())); + + return notFoundedversions.length === 0; +} + /** * install dotnet to the installation path. * @param installationPath The installation path. If this is empty it would use {Agent.ToolsDirectory}/dotnet/