This commit is contained in:
Danny McCormick 2019-06-20 16:17:52 -04:00
parent 56673a904e
commit c6fce3a672
4 changed files with 629 additions and 262 deletions

View File

@ -2,6 +2,7 @@ import io = require('@actions/io');
import fs = require('fs'); import fs = require('fs');
import os = require('os'); import os = require('os');
import path = require('path'); import path = require('path');
import httpClient = require('typed-rest-client/HttpClient');
const toolDir = path.join(__dirname, 'runner', 'tools'); const toolDir = path.join(__dirname, 'runner', 'tools');
const tempDir = path.join(__dirname, 'runner', 'temp'); const tempDir = path.join(__dirname, 'runner', 'temp');
@ -71,8 +72,55 @@ describe('installer tests', () => {
expect(thrown).toBe(true); expect(thrown).toBe(true);
return; return;
}); });
it('Uses an up to date bash download script', async () => {
var httpCallbackClient = new httpClient.HttpClient(
'setup-dotnet-test',
[],
{}
);
const response: httpClient.HttpClientResponse = await httpCallbackClient.get(
'https://dot.net/v1/dotnet-install.sh'
);
const upToDateContents: string = await response.readBody();
const currentContents: string = fs
.readFileSync(
path.join(__dirname, '..', 'externals', 'install-dotnet.sh')
)
.toString();
expect(normalizeFileContents(currentContents)).toBe(
normalizeFileContents(upToDateContents)
);
});
it('Uses an up to date powershell download script', async () => {
var httpCallbackClient = new httpClient.HttpClient(
'setup-dotnet-test',
[],
{}
);
const response: httpClient.HttpClientResponse = await httpCallbackClient.get(
'https://dot.net/v1/dotnet-install.ps1'
);
const upToDateContents: string = await response.readBody();
const currentContents: string = fs
.readFileSync(
path.join(__dirname, '..', 'externals', 'install-dotnet.ps1')
)
.toString();
expect(normalizeFileContents(currentContents)).toBe(
normalizeFileContents(upToDateContents)
);
});
}); });
function normalizeFileContents(contents: string): string {
return contents
.trim()
.replace(new RegExp('\r\n', 'g'), '\n')
.replace(new RegExp('\r', 'g'), '\n');
}
async function getDotnet(version: string): Promise<void> { async function getDotnet(version: string): Promise<void> {
const dotnetInstaller = new installer.DotnetCoreInstaller(version); const dotnetInstaller = new installer.DotnetCoreInstaller(version);
await dotnetInstaller.installDotnet(); await dotnetInstaller.installDotnet();

View File

@ -15,9 +15,10 @@
- Current - most current release - Current - most current release
- LTS - most current supported release - LTS - most current supported release
- 2-part version in a format A.B - represents a specific release - 2-part version in a format A.B - represents a specific release
examples: 2.0; 1.0 examples: 2.0, 1.0
- Branch name - Branch name
examples: release/2.0.0; Master examples: release/2.0.0, Master
Note: The version parameter overrides the channel parameter.
.PARAMETER Version .PARAMETER Version
Default: latest Default: latest
Represents a build version on specific channel. Possible values: Represents a build version on specific channel. Possible values:
@ -25,17 +26,26 @@
- coherent - most latest coherent build on specific channel - coherent - most latest coherent build on specific channel
coherent applies only to SDK downloads coherent applies only to SDK downloads
- 3-part version in a format A.B.C - represents specific version of build - 3-part version in a format A.B.C - represents specific version of build
examples: 2.0.0-preview2-006120; 1.1.0 examples: 2.0.0-preview2-006120, 1.1.0
.PARAMETER InstallDir .PARAMETER InstallDir
Default: %LocalAppData%\Microsoft\dotnet Default: %LocalAppData%\Microsoft\dotnet
Path to where to install dotnet. Note that binaries will be placed directly in a given directory. Path to where to install dotnet. Note that binaries will be placed directly in a given directory.
.PARAMETER Architecture .PARAMETER Architecture
Default: <auto> - this value represents currently running OS architecture Default: <auto> - this value represents currently running OS architecture
Architecture of dotnet binaries to be installed. Architecture of dotnet binaries to be installed.
Possible values are: <auto>, x64 and x86 Possible values are: <auto>, amd64, x64, x86, arm64, arm
.PARAMETER SharedRuntime .PARAMETER SharedRuntime
This parameter is obsolete and may be removed in a future version of this script.
The recommended alternative is '-Runtime dotnet'.
Default: false Default: false
Installs just the shared runtime bits, not the entire SDK Installs just the shared runtime bits, not the entire SDK.
This is equivalent to specifying `-Runtime dotnet`.
.PARAMETER Runtime
Installs just a shared runtime, not the entire SDK.
Possible values:
- dotnet - the Microsoft.NETCore.App shared runtime
- aspnetcore - the Microsoft.AspNetCore.App shared runtime
.PARAMETER DryRun .PARAMETER DryRun
If set it will not perform installation but instead display what command line to use to consistently install If set it will not perform installation but instead display what command line to use to consistently install
currently requested version of dotnet cli. In example if you specify version 'latest' it will display a link currently requested version of dotnet cli. In example if you specify version 'latest' it will display a link
@ -49,15 +59,23 @@
.PARAMETER AzureFeed .PARAMETER AzureFeed
Default: https://dotnetcli.azureedge.net/dotnet Default: https://dotnetcli.azureedge.net/dotnet
This parameter typically is not changed by the user. This parameter typically is not changed by the user.
It allows to change URL for the Azure feed used by this installer. It allows changing the URL for the Azure feed used by this installer.
.PARAMETER UncachedFeed .PARAMETER UncachedFeed
This parameter typically is not changed by the user. This parameter typically is not changed by the user.
It allows to change URL for the Uncached feed used by this installer. It allows changing the URL for the Uncached feed used by this installer.
.PARAMETER FeedCredential
Used as a query string to append to the Azure feed.
It allows changing the URL to use non-public blob storage accounts.
.PARAMETER ProxyAddress .PARAMETER ProxyAddress
If set, the installer will use the proxy when making web requests If set, the installer will use the proxy when making web requests
.PARAMETER ProxyUseDefaultCredentials .PARAMETER ProxyUseDefaultCredentials
Default: false Default: false
Use default credentials, when using proxy address. Use default credentials, when using proxy address.
.PARAMETER SkipNonVersionedFiles
Default: false
Skips installing non-versioned files if they already exist, such as dotnet.exe.
.PARAMETER NoCdn
Disable downloading from the Azure CDN, and use the uncached feed directly.
#> #>
[cmdletbinding()] [cmdletbinding()]
param( param(
@ -65,27 +83,41 @@ param(
[string]$Version="Latest", [string]$Version="Latest",
[string]$InstallDir="<auto>", [string]$InstallDir="<auto>",
[string]$Architecture="<auto>", [string]$Architecture="<auto>",
[ValidateSet("dotnet", "aspnetcore", IgnoreCase = $false)]
[string]$Runtime,
[Obsolete("This parameter may be removed in a future version of this script. The recommended alternative is '-Runtime dotnet'.")]
[switch]$SharedRuntime, [switch]$SharedRuntime,
[switch]$DryRun, [switch]$DryRun,
[switch]$NoPath, [switch]$NoPath,
[string]$AzureFeed="https://dotnetcli.azureedge.net/dotnet", [string]$AzureFeed="https://dotnetcli.azureedge.net/dotnet",
[string]$UncachedFeed="https://dotnetcli.blob.core.windows.net/dotnet", [string]$UncachedFeed="https://dotnetcli.blob.core.windows.net/dotnet",
[string]$FeedCredential,
[string]$ProxyAddress, [string]$ProxyAddress,
[switch]$ProxyUseDefaultCredentials [switch]$ProxyUseDefaultCredentials,
[switch]$SkipNonVersionedFiles,
[switch]$NoCdn
) )
Set-StrictMode -Version Latest Set-StrictMode -Version Latest
$ErrorActionPreference="Stop" $ErrorActionPreference="Stop"
$ProgressPreference="SilentlyContinue" $ProgressPreference="SilentlyContinue"
if ($NoCdn) {
$AzureFeed = $UncachedFeed
}
$BinFolderRelativePath="" $BinFolderRelativePath=""
if ($SharedRuntime -and (-not $Runtime)) {
$Runtime = "dotnet"
}
# example path with regex: shared/1.0.0-beta-12345/somepath # example path with regex: shared/1.0.0-beta-12345/somepath
$VersionRegEx="/\d+\.\d+[^/]+/" $VersionRegEx="/\d+\.\d+[^/]+/"
$OverrideNonVersionedFiles=$true $OverrideNonVersionedFiles = !$SkipNonVersionedFiles
function Say($str) { function Say($str) {
Write-Output "dotnet-install: $str" Write-Host "dotnet-install: $str"
} }
function Say-Verbose($str) { function Say-Verbose($str) {
@ -120,11 +152,10 @@ function Invoke-With-Retry([ScriptBlock]$ScriptBlock, [int]$MaxAttempts = 3, [in
function Get-Machine-Architecture() { function Get-Machine-Architecture() {
Say-Invocation $MyInvocation Say-Invocation $MyInvocation
# possible values: AMD64, IA64, x86 # possible values: amd64, x64, x86, arm64, arm
return $ENV:PROCESSOR_ARCHITECTURE return $ENV:PROCESSOR_ARCHITECTURE
} }
# TODO: Architecture and CLIArchitecture should be unified
function Get-CLIArchitecture-From-Architecture([string]$Architecture) { function Get-CLIArchitecture-From-Architecture([string]$Architecture) {
Say-Invocation $MyInvocation Say-Invocation $MyInvocation
@ -132,18 +163,27 @@ function Get-CLIArchitecture-From-Architecture([string]$Architecture) {
{ $_ -eq "<auto>" } { return Get-CLIArchitecture-From-Architecture $(Get-Machine-Architecture) } { $_ -eq "<auto>" } { return Get-CLIArchitecture-From-Architecture $(Get-Machine-Architecture) }
{ ($_ -eq "amd64") -or ($_ -eq "x64") } { return "x64" } { ($_ -eq "amd64") -or ($_ -eq "x64") } { return "x64" }
{ $_ -eq "x86" } { return "x86" } { $_ -eq "x86" } { return "x86" }
default { throw "Architecture not supported. If you think this is a bug, please report it at https://github.com/dotnet/cli/issues" } { $_ -eq "arm" } { return "arm" }
{ $_ -eq "arm64" } { return "arm64" }
default { throw "Architecture not supported. If you think this is a bug, report it at https://github.com/dotnet/cli/issues" }
} }
} }
# The version text returned from the feeds is a 1-line or 2-line string:
# For the SDK and the dotnet runtime (2 lines):
# Line 1: # commit_hash
# Line 2: # 4-part version
# For the aspnetcore runtime (1 line):
# Line 1: # 4-part version
function Get-Version-Info-From-Version-Text([string]$VersionText) { function Get-Version-Info-From-Version-Text([string]$VersionText) {
Say-Invocation $MyInvocation Say-Invocation $MyInvocation
$Data = @($VersionText.Split([char[]]@(), [StringSplitOptions]::RemoveEmptyEntries)); $Data = -split $VersionText
$VersionInfo = @{} $VersionInfo = @{
$VersionInfo.CommitHash = $Data[0].Trim() CommitHash = $(if ($Data.Count -gt 1) { $Data[0] })
$VersionInfo.Version = $Data[1].Trim() Version = $Data[-1] # last line is always the version number.
}
return $VersionInfo return $VersionInfo
} }
@ -168,33 +208,39 @@ function GetHTTPResponse([Uri] $Uri)
# HttpClient is used vs Invoke-WebRequest in order to support Nano Server which doesn't support the Invoke-WebRequest cmdlet. # HttpClient is used vs Invoke-WebRequest in order to support Nano Server which doesn't support the Invoke-WebRequest cmdlet.
Load-Assembly -Assembly System.Net.Http Load-Assembly -Assembly System.Net.Http
if(-not $ProxyAddress) if(-not $ProxyAddress) {
{ try {
# Despite no proxy being explicitly specified, we may still be behind a default proxy # Despite no proxy being explicitly specified, we may still be behind a default proxy
$DefaultProxy = [System.Net.WebRequest]::DefaultWebProxy; $DefaultProxy = [System.Net.WebRequest]::DefaultWebProxy;
if($DefaultProxy -and (-not $DefaultProxy.IsBypassed($Uri))){ if($DefaultProxy -and (-not $DefaultProxy.IsBypassed($Uri))) {
$ProxyAddress = $DefaultProxy.GetProxy($Uri).OriginalString $ProxyAddress = $DefaultProxy.GetProxy($Uri).OriginalString
$ProxyUseDefaultCredentials = $true $ProxyUseDefaultCredentials = $true
}
} catch {
# Eat the exception and move forward as the above code is an attempt
# at resolving the DefaultProxy that may not have been a problem.
$ProxyAddress = $null
Say-Verbose("Exception ignored: $_.Exception.Message - moving forward...")
} }
} }
if($ProxyAddress){ if($ProxyAddress) {
$HttpClientHandler = New-Object System.Net.Http.HttpClientHandler $HttpClientHandler = New-Object System.Net.Http.HttpClientHandler
$HttpClientHandler.Proxy = New-Object System.Net.WebProxy -Property @{Address=$ProxyAddress;UseDefaultCredentials=$ProxyUseDefaultCredentials} $HttpClientHandler.Proxy = New-Object System.Net.WebProxy -Property @{Address=$ProxyAddress;UseDefaultCredentials=$ProxyUseDefaultCredentials}
$HttpClient = New-Object System.Net.Http.HttpClient -ArgumentList $HttpClientHandler $HttpClient = New-Object System.Net.Http.HttpClient -ArgumentList $HttpClientHandler
} }
else { else {
$HttpClient = New-Object System.Net.Http.HttpClient $HttpClient = New-Object System.Net.Http.HttpClient
} }
# Default timeout for HttpClient is 100s. For a 50 MB download this assumes 500 KB/s average, any less will time out # Default timeout for HttpClient is 100s. For a 50 MB download this assumes 500 KB/s average, any less will time out
# 10 minutes allows it to work over much slower connections. # 20 minutes allows it to work over much slower connections.
$HttpClient.Timeout = New-TimeSpan -Minutes 10 $HttpClient.Timeout = New-TimeSpan -Minutes 20
$Response = $HttpClient.GetAsync($Uri).Result $Response = $HttpClient.GetAsync("${Uri}${FeedCredential}").Result
if (($Response -eq $null) -or (-not ($Response.IsSuccessStatusCode))) if (($Response -eq $null) -or (-not ($Response.IsSuccessStatusCode))) {
{ # The feed credential is potentially sensitive info. Do not log FeedCredential to console output.
$ErrorMsg = "Failed to download $Uri." $ErrorMsg = "Failed to download $Uri."
if ($Response -ne $null) if ($Response -ne $null) {
{
$ErrorMsg += " $Response" $ErrorMsg += " $Response"
} }
@ -216,10 +262,13 @@ function Get-Latest-Version-Info([string]$AzureFeed, [string]$Channel, [bool]$Co
Say-Invocation $MyInvocation Say-Invocation $MyInvocation
$VersionFileUrl = $null $VersionFileUrl = $null
if ($SharedRuntime) { if ($Runtime -eq "dotnet") {
$VersionFileUrl = "$UncachedFeed/Runtime/$Channel/latest.version" $VersionFileUrl = "$UncachedFeed/Runtime/$Channel/latest.version"
} }
else { elseif ($Runtime -eq "aspnetcore") {
$VersionFileUrl = "$UncachedFeed/aspnetcore/Runtime/$Channel/latest.version"
}
elseif (-not $Runtime) {
if ($Coherent) { if ($Coherent) {
$VersionFileUrl = "$UncachedFeed/Sdk/$Channel/latest.coherent.version" $VersionFileUrl = "$UncachedFeed/Sdk/$Channel/latest.coherent.version"
} }
@ -227,12 +276,19 @@ function Get-Latest-Version-Info([string]$AzureFeed, [string]$Channel, [bool]$Co
$VersionFileUrl = "$UncachedFeed/Sdk/$Channel/latest.version" $VersionFileUrl = "$UncachedFeed/Sdk/$Channel/latest.version"
} }
} }
else {
$Response = GetHTTPResponse -Uri $VersionFileUrl throw "Invalid value for `$Runtime"
}
try {
$Response = GetHTTPResponse -Uri $VersionFileUrl
}
catch {
throw "Could not resolve version information."
}
$StringContent = $Response.Content.ReadAsStringAsync().Result $StringContent = $Response.Content.ReadAsStringAsync().Result
switch ($Response.Content.Headers.ContentType) { switch ($Response.Content.Headers.ContentType) {
{ ($_ -eq "application/octet-stream") } { $VersionText = [Text.Encoding]::UTF8.GetString($StringContent) } { ($_ -eq "application/octet-stream") } { $VersionText = $StringContent }
{ ($_ -eq "text/plain") } { $VersionText = $StringContent } { ($_ -eq "text/plain") } { $VersionText = $StringContent }
{ ($_ -eq "text/plain; charset=UTF-8") } { $VersionText = $StringContent } { ($_ -eq "text/plain; charset=UTF-8") } { $VersionText = $StringContent }
default { throw "``$Response.Content.Headers.ContentType`` is an unknown .version file content type." } default { throw "``$Response.Content.Headers.ContentType`` is an unknown .version file content type." }
@ -260,32 +316,41 @@ function Get-Specific-Version-From-Version([string]$AzureFeed, [string]$Channel,
} }
} }
function Get-Download-Link([string]$AzureFeed, [string]$Channel, [string]$SpecificVersion, [string]$CLIArchitecture) { function Get-Download-Link([string]$AzureFeed, [string]$SpecificVersion, [string]$CLIArchitecture) {
Say-Invocation $MyInvocation Say-Invocation $MyInvocation
if ($SharedRuntime) { if ($Runtime -eq "dotnet") {
$PayloadURL = "$AzureFeed/Runtime/$SpecificVersion/dotnet-runtime-$SpecificVersion-win-$CLIArchitecture.zip" $PayloadURL = "$AzureFeed/Runtime/$SpecificVersion/dotnet-runtime-$SpecificVersion-win-$CLIArchitecture.zip"
} }
else { elseif ($Runtime -eq "aspnetcore") {
$PayloadURL = "$AzureFeed/aspnetcore/Runtime/$SpecificVersion/aspnetcore-runtime-$SpecificVersion-win-$CLIArchitecture.zip"
}
elseif (-not $Runtime) {
$PayloadURL = "$AzureFeed/Sdk/$SpecificVersion/dotnet-sdk-$SpecificVersion-win-$CLIArchitecture.zip" $PayloadURL = "$AzureFeed/Sdk/$SpecificVersion/dotnet-sdk-$SpecificVersion-win-$CLIArchitecture.zip"
} }
else {
throw "Invalid value for `$Runtime"
}
Say-Verbose "Constructed primary payload URL: $PayloadURL" Say-Verbose "Constructed primary named payload URL: $PayloadURL"
return $PayloadURL return $PayloadURL
} }
function Get-LegacyDownload-Link([string]$AzureFeed, [string]$Channel, [string]$SpecificVersion, [string]$CLIArchitecture) { function Get-LegacyDownload-Link([string]$AzureFeed, [string]$SpecificVersion, [string]$CLIArchitecture) {
Say-Invocation $MyInvocation Say-Invocation $MyInvocation
if ($SharedRuntime) { if (-not $Runtime) {
$PayloadURL = "$AzureFeed/Sdk/$SpecificVersion/dotnet-dev-win-$CLIArchitecture.$SpecificVersion.zip"
}
elseif ($Runtime -eq "dotnet") {
$PayloadURL = "$AzureFeed/Runtime/$SpecificVersion/dotnet-win-$CLIArchitecture.$SpecificVersion.zip" $PayloadURL = "$AzureFeed/Runtime/$SpecificVersion/dotnet-win-$CLIArchitecture.$SpecificVersion.zip"
} }
else { else {
$PayloadURL = "$AzureFeed/Sdk/$SpecificVersion/dotnet-dev-win-$CLIArchitecture.$SpecificVersion.zip" return $null
} }
Say-Verbose "Constructed legacy payload URL: $PayloadURL" Say-Verbose "Constructed legacy named payload URL: $PayloadURL"
return $PayloadURL return $PayloadURL
} }
@ -415,11 +480,23 @@ function Extract-Dotnet-Package([string]$ZipPath, [string]$OutPath) {
} }
} }
function DownloadFile([Uri]$Uri, [string]$OutPath) { function DownloadFile($Source, [string]$OutPath) {
if ($Source -notlike "http*") {
# Using System.IO.Path.GetFullPath to get the current directory
# does not work in this context - $pwd gives the current directory
if (![System.IO.Path]::IsPathRooted($Source)) {
$Source = $(Join-Path -Path $pwd -ChildPath $Source)
}
$Source = Get-Absolute-Path $Source
Say "Copying file from $Source to $OutPath"
Copy-Item $Source $OutPath
return
}
$Stream = $null $Stream = $null
try { try {
$Response = GetHTTPResponse -Uri $Uri $Response = GetHTTPResponse -Uri $Source
$Stream = $Response.Content.ReadAsStreamAsync().Result $Stream = $Response.Content.ReadAsStreamAsync().Result
$File = [System.IO.File]::Create($OutPath) $File = [System.IO.File]::Create($OutPath)
$Stream.CopyTo($File) $Stream.CopyTo($File)
@ -435,8 +512,13 @@ function DownloadFile([Uri]$Uri, [string]$OutPath) {
function Prepend-Sdk-InstallRoot-To-Path([string]$InstallRoot, [string]$BinFolderRelativePath) { function Prepend-Sdk-InstallRoot-To-Path([string]$InstallRoot, [string]$BinFolderRelativePath) {
$BinPath = Get-Absolute-Path $(Join-Path -Path $InstallRoot -ChildPath $BinFolderRelativePath) $BinPath = Get-Absolute-Path $(Join-Path -Path $InstallRoot -ChildPath $BinFolderRelativePath)
if (-Not $NoPath) { if (-Not $NoPath) {
Say "Adding to current process PATH: `"$BinPath`". Note: This change will not be visible if PowerShell was run as a child process." $SuffixedBinPath = "$BinPath;"
$env:path = "$BinPath;" + $env:path if (-Not $env:path.Contains($SuffixedBinPath)) {
Say "Adding to current process PATH: `"$BinPath`". Note: This change will not be visible if PowerShell was run as a child process."
$env:path = $SuffixedBinPath + $env:path
} else {
Say-Verbose "Current process PATH already contains `"$BinPath`""
}
} }
else { else {
Say "Binaries of dotnet can be found in $BinPath" Say "Binaries of dotnet can be found in $BinPath"
@ -445,24 +527,55 @@ function Prepend-Sdk-InstallRoot-To-Path([string]$InstallRoot, [string]$BinFolde
$CLIArchitecture = Get-CLIArchitecture-From-Architecture $Architecture $CLIArchitecture = Get-CLIArchitecture-From-Architecture $Architecture
$SpecificVersion = Get-Specific-Version-From-Version -AzureFeed $AzureFeed -Channel $Channel -Version $Version $SpecificVersion = Get-Specific-Version-From-Version -AzureFeed $AzureFeed -Channel $Channel -Version $Version
$DownloadLink = Get-Download-Link -AzureFeed $AzureFeed -Channel $Channel -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture $DownloadLink = Get-Download-Link -AzureFeed $AzureFeed -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture
$LegacyDownloadLink = Get-LegacyDownload-Link -AzureFeed $AzureFeed -Channel $Channel -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture $LegacyDownloadLink = Get-LegacyDownload-Link -AzureFeed $AzureFeed -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture
if ($DryRun) {
Say "Payload URLs:"
Say "Primary - $DownloadLink"
Say "Legacy - $LegacyDownloadLink"
Say "Repeatable invocation: .\$($MyInvocation.MyCommand) -Version $SpecificVersion -Channel $Channel -Architecture $CLIArchitecture -InstallDir $InstallDir"
exit 0
}
$InstallRoot = Resolve-Installation-Path $InstallDir $InstallRoot = Resolve-Installation-Path $InstallDir
Say-Verbose "InstallRoot: $InstallRoot" Say-Verbose "InstallRoot: $InstallRoot"
$ScriptName = $MyInvocation.MyCommand.Name
$IsSdkInstalled = Is-Dotnet-Package-Installed -InstallRoot $InstallRoot -RelativePathToPackage "sdk" -SpecificVersion $SpecificVersion if ($DryRun) {
Say-Verbose ".NET SDK installed? $IsSdkInstalled" Say "Payload URLs:"
if ($IsSdkInstalled) { Say "Primary named payload URL: $DownloadLink"
Say ".NET SDK version $SpecificVersion is already installed." if ($LegacyDownloadLink) {
Say "Legacy named payload URL: $LegacyDownloadLink"
}
$RepeatableCommand = ".\$ScriptName -Version `"$SpecificVersion`" -InstallDir `"$InstallRoot`" -Architecture `"$CLIArchitecture`""
if ($Runtime -eq "dotnet") {
$RepeatableCommand+=" -Runtime `"dotnet`""
}
elseif ($Runtime -eq "aspnetcore") {
$RepeatableCommand+=" -Runtime `"aspnetcore`""
}
foreach ($key in $MyInvocation.BoundParameters.Keys) {
if (-not (@("Architecture","Channel","DryRun","InstallDir","Runtime","SharedRuntime","Version") -contains $key)) {
$RepeatableCommand+=" -$key `"$($MyInvocation.BoundParameters[$key])`""
}
}
Say "Repeatable invocation: $RepeatableCommand"
exit 0
}
if ($Runtime -eq "dotnet") {
$assetName = ".NET Core Runtime"
$dotnetPackageRelativePath = "shared\Microsoft.NETCore.App"
}
elseif ($Runtime -eq "aspnetcore") {
$assetName = "ASP.NET Core Runtime"
$dotnetPackageRelativePath = "shared\Microsoft.AspNetCore.App"
}
elseif (-not $Runtime) {
$assetName = ".NET Core SDK"
$dotnetPackageRelativePath = "sdk"
}
else {
throw "Invalid value for `$Runtime"
}
# Check if the SDK version is already installed.
$isAssetInstalled = Is-Dotnet-Package-Installed -InstallRoot $InstallRoot -RelativePathToPackage $dotnetPackageRelativePath -SpecificVersion $SpecificVersion
if ($isAssetInstalled) {
Say "$assetName version $SpecificVersion is already installed."
Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot -BinFolderRelativePath $BinFolderRelativePath Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot -BinFolderRelativePath $BinFolderRelativePath
exit 0 exit 0
} }
@ -470,31 +583,53 @@ if ($IsSdkInstalled) {
New-Item -ItemType Directory -Force -Path $InstallRoot | Out-Null New-Item -ItemType Directory -Force -Path $InstallRoot | Out-Null
$installDrive = $((Get-Item $InstallRoot).PSDrive.Name); $installDrive = $((Get-Item $InstallRoot).PSDrive.Name);
Write-Output "${installDrive}:"; $diskInfo = Get-PSDrive -Name $installDrive
$free = Get-CimInstance -Class win32_logicaldisk | where Deviceid -eq "${installDrive}:" if ($diskInfo.Free / 1MB -le 100) {
if ($free.Freespace / 1MB -le 100 ) {
Say "There is not enough disk space on drive ${installDrive}:" Say "There is not enough disk space on drive ${installDrive}:"
exit 0 exit 0
} }
$ZipPath = [System.IO.Path]::GetTempFileName() $ZipPath = [System.IO.Path]::combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName())
Say-Verbose "Zip path: $ZipPath" Say-Verbose "Zip path: $ZipPath"
$DownloadFailed = $false
Say "Downloading link: $DownloadLink" Say "Downloading link: $DownloadLink"
try { try {
DownloadFile -Uri $DownloadLink -OutPath $ZipPath DownloadFile -Source $DownloadLink -OutPath $ZipPath
} }
catch { catch {
Say "Cannot download: $DownloadLink" Say "Cannot download: $DownloadLink"
$DownloadLink = $LegacyDownloadLink if ($LegacyDownloadLink) {
$ZipPath = [System.IO.Path]::GetTempFileName() $DownloadLink = $LegacyDownloadLink
Say-Verbose "Legacy zip path: $ZipPath" $ZipPath = [System.IO.Path]::combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName())
Say "Downloading legacy link: $DownloadLink" Say-Verbose "Legacy zip path: $ZipPath"
DownloadFile -Uri $DownloadLink -OutPath $ZipPath Say "Downloading legacy link: $DownloadLink"
try {
DownloadFile -Source $DownloadLink -OutPath $ZipPath
}
catch {
Say "Cannot download: $DownloadLink"
$DownloadFailed = $true
}
}
else {
$DownloadFailed = $true
}
}
if ($DownloadFailed) {
throw "Could not find/download: `"$assetName`" with version = $SpecificVersion`nRefer to: https://aka.ms/dotnet-os-lifecycle for information on .NET Core support"
} }
Say "Extracting zip from $DownloadLink" Say "Extracting zip from $DownloadLink"
Extract-Dotnet-Package -ZipPath $ZipPath -OutPath $InstallRoot Extract-Dotnet-Package -ZipPath $ZipPath -OutPath $InstallRoot
# Check if the SDK version is now installed; if not, fail the installation.
$isAssetInstalled = Is-Dotnet-Package-Installed -InstallRoot $InstallRoot -RelativePathToPackage $dotnetPackageRelativePath -SpecificVersion $SpecificVersion
if (!$isAssetInstalled) {
throw "`"$assetName`" with version = $SpecificVersion failed to install with an unknown error."
}
Remove-Item $ZipPath Remove-Item $ZipPath
Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot -BinFolderRelativePath $BinFolderRelativePath Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot -BinFolderRelativePath $BinFolderRelativePath

View File

@ -22,7 +22,7 @@ exec 3>&1
# Setup some colors to use. These need to work in fairly limited shells, like the Ubuntu Docker container where there are only 8 colors. # Setup some colors to use. These need to work in fairly limited shells, like the Ubuntu Docker container where there are only 8 colors.
# See if stdout is a terminal # See if stdout is a terminal
if [ -t 1 ]; then if [ -t 1 ] && command -v tput > /dev/null; then
# see if it supports colors # see if it supports colors
ncolors=$(tput colors) ncolors=$(tput colors)
if [ -n "$ncolors" ] && [ $ncolors -ge 8 ]; then if [ -n "$ncolors" ] && [ $ncolors -ge 8 ]; then
@ -39,6 +39,10 @@ if [ -t 1 ]; then
fi fi
fi fi
say_warning() {
printf "%b\n" "${yellow:-}dotnet_install: Warning: $1${normal:-}"
}
say_err() { say_err() {
printf "%b\n" "${red:-}dotnet_install: Error: $1${normal:-}" >&2 printf "%b\n" "${red:-}dotnet_install: Error: $1${normal:-}" >&2
} }
@ -55,7 +59,10 @@ say_verbose() {
fi fi
} }
get_os_download_name_from_platform() { # This platform list is finite - if the SDK/Runtime has supported Linux distribution-specific assets,
# then and only then should the Linux distribution appear in this list.
# Adding a Linux distribution to this list does not imply distribution-specific support.
get_legacy_os_name_from_platform() {
eval $invocation eval $invocation
platform="$1" platform="$1"
@ -68,6 +75,10 @@ get_os_download_name_from_platform() {
echo "debian" echo "debian"
return 0 return 0
;; ;;
"debian.9")
echo "debian.9"
return 0
;;
"fedora.23") "fedora.23")
echo "fedora.23" echo "fedora.23"
return 0 return 0
@ -76,6 +87,14 @@ get_os_download_name_from_platform() {
echo "fedora.24" echo "fedora.24"
return 0 return 0
;; ;;
"fedora.27")
echo "fedora.27"
return 0
;;
"fedora.28")
echo "fedora.28"
return 0
;;
"opensuse.13.2") "opensuse.13.2")
echo "opensuse.13.2" echo "opensuse.13.2"
return 0 return 0
@ -84,6 +103,10 @@ get_os_download_name_from_platform() {
echo "opensuse.42.1" echo "opensuse.42.1"
return 0 return 0
;; ;;
"opensuse.42.3")
echo "opensuse.42.3"
return 0
;;
"rhel.7"*) "rhel.7"*)
echo "rhel" echo "rhel"
return 0 return 0
@ -100,6 +123,10 @@ get_os_download_name_from_platform() {
echo "ubuntu.16.10" echo "ubuntu.16.10"
return 0 return 0
;; ;;
"ubuntu.18.04")
echo "ubuntu.18.04"
return 0
;;
"alpine.3.4.3") "alpine.3.4.3")
echo "alpine" echo "alpine"
return 0 return 0
@ -108,6 +135,30 @@ get_os_download_name_from_platform() {
return 1 return 1
} }
get_linux_platform_name() {
eval $invocation
if [ -n "$runtime_id" ]; then
echo "${runtime_id%-*}"
return 0
else
if [ -e /etc/os-release ]; then
. /etc/os-release
echo "$ID.$VERSION_ID"
return 0
elif [ -e /etc/redhat-release ]; then
local redhatRelease=$(</etc/redhat-release)
if [[ $redhatRelease == "CentOS release 6."* || $redhatRelease == "Red Hat Enterprise Linux Server release 6."* ]]; then
echo "rhel.6"
return 0
fi
fi
fi
say_verbose "Linux specific platform name and version could not be detected: UName = $uname"
return 1
}
get_current_os_name() { get_current_os_name() {
eval $invocation eval $invocation
@ -115,18 +166,30 @@ get_current_os_name() {
if [ "$uname" = "Darwin" ]; then if [ "$uname" = "Darwin" ]; then
echo "osx" echo "osx"
return 0 return 0
else elif [ "$uname" = "FreeBSD" ]; then
if [ "$uname" = "Linux" ]; then echo "freebsd"
return 0
elif [ "$uname" = "Linux" ]; then
local linux_platform_name
linux_platform_name="$(get_linux_platform_name)" || { echo "linux" && return 0 ; }
if [[ $linux_platform_name == "rhel.6" ]]; then
echo $linux_platform_name
return 0
elif [[ $linux_platform_name == alpine* ]]; then
echo "linux-musl"
return 0
else
echo "linux" echo "linux"
return 0 return 0
fi fi
fi fi
say_err "OS name could not be detected: $ID.$VERSION_ID" say_err "OS name could not be detected: UName = $uname"
return 1 return 1
} }
get_distro_specific_os_name() { get_legacy_os_name() {
eval $invocation eval $invocation
local uname=$(uname) local uname=$(uname)
@ -134,12 +197,12 @@ get_distro_specific_os_name() {
echo "osx" echo "osx"
return 0 return 0
elif [ -n "$runtime_id" ]; then elif [ -n "$runtime_id" ]; then
echo $(get_os_download_name_from_platform "${runtime_id%-*}" || echo "${runtime_id%-*}") echo $(get_legacy_os_name_from_platform "${runtime_id%-*}" || echo "${runtime_id%-*}")
return 0 return 0
else else
if [ -e /etc/os-release ]; then if [ -e /etc/os-release ]; then
. /etc/os-release . /etc/os-release
os=$(get_os_download_name_from_platform "$ID.$VERSION_ID" || echo "") os=$(get_legacy_os_name_from_platform "$ID.$VERSION_ID" || echo "")
if [ -n "$os" ]; then if [ -n "$os" ]; then
echo "$os" echo "$os"
return 0 return 0
@ -147,7 +210,7 @@ get_distro_specific_os_name() {
fi fi
fi fi
say_verbose "Distribution specific OS name and version could not be detected: $ID.$VERSION_ID" say_verbose "Distribution specific OS name and version could not be detected: UName = $uname"
return 1 return 1
} }
@ -177,27 +240,25 @@ check_min_reqs() {
check_pre_reqs() { check_pre_reqs() {
eval $invocation eval $invocation
local failing=false;
if [ "${DOTNET_INSTALL_SKIP_PREREQS:-}" = "1" ]; then if [ "${DOTNET_INSTALL_SKIP_PREREQS:-}" = "1" ]; then
return 0 return 0
fi fi
if [ "$(uname)" = "Linux" ]; then if [ "$(uname)" = "Linux" ]; then
if ! [ -x "$(command -v ldconfig)" ]; then if [ ! -x "$(command -v ldconfig)" ]; then
echo "ldconfig is not in PATH, trying /sbin/ldconfig." echo "ldconfig is not in PATH, trying /sbin/ldconfig."
LDCONFIG_COMMAND="/sbin/ldconfig" LDCONFIG_COMMAND="/sbin/ldconfig"
else else
LDCONFIG_COMMAND="ldconfig" LDCONFIG_COMMAND="ldconfig"
fi fi
[ -z "$($LDCONFIG_COMMAND -p | grep libunwind)" ] && say_err "Unable to locate libunwind. Install libunwind to continue" && failing=true local librarypath=${LD_LIBRARY_PATH:-}
[ -z "$($LDCONFIG_COMMAND -p | grep libssl)" ] && say_err "Unable to locate libssl. Install libssl to continue" && failing=true LDCONFIG_COMMAND="$LDCONFIG_COMMAND -NXv ${librarypath//:/ }"
[ -z "$($LDCONFIG_COMMAND -p | grep libicu)" ] && say_err "Unable to locate libicu. Install libicu to continue" && failing=true
fi
if [ "$failing" = true ]; then [ -z "$($LDCONFIG_COMMAND 2>/dev/null | grep libunwind)" ] && say_warning "Unable to locate libunwind. Probable prerequisite missing; install libunwind."
return 1 [ -z "$($LDCONFIG_COMMAND 2>/dev/null | grep libssl)" ] && say_warning "Unable to locate libssl. Probable prerequisite missing; install libssl."
[ -z "$($LDCONFIG_COMMAND 2>/dev/null | grep libicu)" ] && say_warning "Unable to locate libicu. Probable prerequisite missing; install libicu."
[ -z "$($LDCONFIG_COMMAND 2>/dev/null | grep -F libcurl.so)" ] && say_warning "Unable to locate libcurl. Probable prerequisite missing; install libcurl."
fi fi
return 0 return 0
@ -217,7 +278,7 @@ to_lowercase() {
remove_trailing_slash() { remove_trailing_slash() {
#eval $invocation #eval $invocation
local input=${1:-} local input="${1:-}"
echo "${input%/}" echo "${input%/}"
return 0 return 0
} }
@ -227,7 +288,7 @@ remove_trailing_slash() {
remove_beginning_slash() { remove_beginning_slash() {
#eval $invocation #eval $invocation
local input=${1:-} local input="${1:-}"
echo "${input#/}" echo "${input#/}"
return 0 return 0
} }
@ -244,8 +305,8 @@ combine_paths() {
return 1 return 1
fi fi
local root_path=$(remove_trailing_slash $1) local root_path="$(remove_trailing_slash "$1")"
local child_path=$(remove_beginning_slash ${2:-}) local child_path="$(remove_beginning_slash "${2:-}")"
say_verbose "combine_paths: root_path=$root_path" say_verbose "combine_paths: root_path=$root_path"
say_verbose "combine_paths: child_path=$child_path" say_verbose "combine_paths: child_path=$child_path"
echo "$root_path/$child_path" echo "$root_path/$child_path"
@ -255,7 +316,21 @@ combine_paths() {
get_machine_architecture() { get_machine_architecture() {
eval $invocation eval $invocation
# Currently the only one supported if command -v uname > /dev/null; then
CPUName=$(uname -m)
case $CPUName in
armv7l)
echo "arm"
return 0
;;
aarch64)
echo "arm64"
return 0
;;
esac
fi
# Always default to 'x64'
echo "x64" echo "x64"
return 0 return 0
} }
@ -265,46 +340,43 @@ get_machine_architecture() {
get_normalized_architecture_from_architecture() { get_normalized_architecture_from_architecture() {
eval $invocation eval $invocation
local architecture=$(to_lowercase $1) local architecture="$(to_lowercase "$1")"
case $architecture in case "$architecture" in
\<auto\>) \<auto\>)
echo "$(get_normalized_architecture_from_architecture $(get_machine_architecture))" echo "$(get_normalized_architecture_from_architecture "$(get_machine_architecture)")"
return 0 return 0
;; ;;
amd64|x64) amd64|x64)
echo "x64" echo "x64"
return 0 return 0
;; ;;
x86) arm)
say_err "Architecture \`x86\` currently not supported" echo "arm"
return 1 return 0
;;
arm64)
echo "arm64"
return 0
;; ;;
esac esac
say_err "Architecture \`$architecture\` not supported. If you think this is a bug, please report it at https://github.com/dotnet/cli/issues" say_err "Architecture \`$architecture\` not supported. If you think this is a bug, report it at https://github.com/dotnet/cli/issues"
return 1 return 1
} }
# version_info is a conceptual two line string representing commit hash and 4-part version # The version text returned from the feeds is a 1-line or 2-line string:
# format: # For the SDK and the dotnet runtime (2 lines):
# Line 1: # commit_hash # Line 1: # commit_hash
# Line 2: # 4-part version # Line 2: # 4-part version
# For the aspnetcore runtime (1 line):
# Line 1: # 4-part version
# args: # args:
# version_text - stdin # version_text - stdin
get_version_from_version_info() { get_version_from_version_info() {
eval $invocation eval $invocation
cat | tail -n 1 cat | tail -n 1 | sed 's/\r$//'
return 0
}
# args:
# version_text - stdin
get_commit_hash_from_version_info() {
eval $invocation
cat | head -n 1
return 0 return 0
} }
@ -315,11 +387,11 @@ get_commit_hash_from_version_info() {
is_dotnet_package_installed() { is_dotnet_package_installed() {
eval $invocation eval $invocation
local install_root=$1 local install_root="$1"
local relative_path_to_package=$2 local relative_path_to_package="$2"
local specific_version=${3//[$'\t\r\n']} local specific_version="${3//[$'\t\r\n']}"
local dotnet_package_path=$(combine_paths $(combine_paths $install_root $relative_path_to_package) $specific_version) local dotnet_package_path="$(combine_paths "$(combine_paths "$install_root" "$relative_path_to_package")" "$specific_version")"
say_verbose "is_dotnet_package_installed: dotnet_package_path=$dotnet_package_path" say_verbose "is_dotnet_package_installed: dotnet_package_path=$dotnet_package_path"
if [ -d "$dotnet_package_path" ]; then if [ -d "$dotnet_package_path" ]; then
@ -333,27 +405,33 @@ is_dotnet_package_installed() {
# azure_feed - $1 # azure_feed - $1
# channel - $2 # channel - $2
# normalized_architecture - $3 # normalized_architecture - $3
# coherent - $4
get_latest_version_info() { get_latest_version_info() {
eval $invocation eval $invocation
local azure_feed=$1 local azure_feed="$1"
local channel=$2 local channel="$2"
local normalized_architecture=$3 local normalized_architecture="$3"
local coherent=$4 local coherent="$4"
local version_file_url=null local version_file_url=null
if [ "$shared_runtime" = true ]; then if [[ "$runtime" == "dotnet" ]]; then
version_file_url="$uncached_feed/Runtime/$channel/latest.version" version_file_url="$uncached_feed/Runtime/$channel/latest.version"
else elif [[ "$runtime" == "aspnetcore" ]]; then
version_file_url="$uncached_feed/aspnetcore/Runtime/$channel/latest.version"
elif [ -z "$runtime" ]; then
if [ "$coherent" = true ]; then if [ "$coherent" = true ]; then
version_file_url="$uncached_feed/Sdk/$channel/latest.coherent.version" version_file_url="$uncached_feed/Sdk/$channel/latest.coherent.version"
else else
version_file_url="$uncached_feed/Sdk/$channel/latest.version" version_file_url="$uncached_feed/Sdk/$channel/latest.version"
fi fi
else
say_err "Invalid value for \$runtime"
return 1
fi fi
say_verbose "get_latest_version_info: latest url: $version_file_url" say_verbose "get_latest_version_info: latest url: $version_file_url"
download $version_file_url download "$version_file_url"
return $? return $?
} }
@ -365,28 +443,28 @@ get_latest_version_info() {
get_specific_version_from_version() { get_specific_version_from_version() {
eval $invocation eval $invocation
local azure_feed=$1 local azure_feed="$1"
local channel=$2 local channel="$2"
local normalized_architecture=$3 local normalized_architecture="$3"
local version=$(to_lowercase $4) local version="$(to_lowercase "$4")"
case $version in case "$version" in
latest) latest)
local version_info local version_info
version_info="$(get_latest_version_info $azure_feed $channel $normalized_architecture false)" || return 1 version_info="$(get_latest_version_info "$azure_feed" "$channel" "$normalized_architecture" false)" || return 1
say_verbose "get_specific_version_from_version: version_info=$version_info" say_verbose "get_specific_version_from_version: version_info=$version_info"
echo "$version_info" | get_version_from_version_info echo "$version_info" | get_version_from_version_info
return 0 return 0
;; ;;
coherent) coherent)
local version_info local version_info
version_info="$(get_latest_version_info $azure_feed $channel $normalized_architecture true)" || return 1 version_info="$(get_latest_version_info "$azure_feed" "$channel" "$normalized_architecture" true)" || return 1
say_verbose "get_specific_version_from_version: version_info=$version_info" say_verbose "get_specific_version_from_version: version_info=$version_info"
echo "$version_info" | get_version_from_version_info echo "$version_info" | get_version_from_version_info
return 0 return 0
;; ;;
*) *)
echo $version echo "$version"
return 0 return 0
;; ;;
esac esac
@ -400,19 +478,23 @@ get_specific_version_from_version() {
construct_download_link() { construct_download_link() {
eval $invocation eval $invocation
local azure_feed=$1 local azure_feed="$1"
local channel=$2 local channel="$2"
local normalized_architecture=$3 local normalized_architecture="$3"
local specific_version=${4//[$'\t\r\n']} local specific_version="${4//[$'\t\r\n']}"
local osname local osname
osname=$(get_current_os_name) || return 1 osname="$(get_current_os_name)" || return 1
local download_link=null local download_link=null
if [ "$shared_runtime" = true ]; then if [[ "$runtime" == "dotnet" ]]; then
download_link="$azure_feed/Runtime/$specific_version/dotnet-runtime-$specific_version-$osname-$normalized_architecture.tar.gz" download_link="$azure_feed/Runtime/$specific_version/dotnet-runtime-$specific_version-$osname-$normalized_architecture.tar.gz"
else elif [[ "$runtime" == "aspnetcore" ]]; then
download_link="$azure_feed/aspnetcore/Runtime/$specific_version/aspnetcore-runtime-$specific_version-$osname-$normalized_architecture.tar.gz"
elif [ -z "$runtime" ]; then
download_link="$azure_feed/Sdk/$specific_version/dotnet-sdk-$specific_version-$osname-$normalized_architecture.tar.gz" download_link="$azure_feed/Sdk/$specific_version/dotnet-sdk-$specific_version-$osname-$normalized_architecture.tar.gz"
else
return 1
fi fi
echo "$download_link" echo "$download_link"
@ -427,19 +509,21 @@ construct_download_link() {
construct_legacy_download_link() { construct_legacy_download_link() {
eval $invocation eval $invocation
local azure_feed=$1 local azure_feed="$1"
local channel=$2 local channel="$2"
local normalized_architecture=$3 local normalized_architecture="$3"
local specific_version=${4//[$'\t\r\n']} local specific_version="${4//[$'\t\r\n']}"
local distro_specific_osname local distro_specific_osname
distro_specific_osname=$(get_distro_specific_os_name) || return 1 distro_specific_osname="$(get_legacy_os_name)" || return 1
local legacy_download_link=null local legacy_download_link=null
if [ "$shared_runtime" = true ]; then if [[ "$runtime" == "dotnet" ]]; then
legacy_download_link="$azure_feed/Runtime/$specific_version/dotnet-$distro_specific_osname-$normalized_architecture.$specific_version.tar.gz" legacy_download_link="$azure_feed/Runtime/$specific_version/dotnet-$distro_specific_osname-$normalized_architecture.$specific_version.tar.gz"
else elif [ -z "$runtime" ]; then
legacy_download_link="$azure_feed/Sdk/$specific_version/dotnet-dev-$distro_specific_osname-$normalized_architecture.$specific_version.tar.gz" legacy_download_link="$azure_feed/Sdk/$specific_version/dotnet-dev-$distro_specific_osname-$normalized_architecture.$specific_version.tar.gz"
else
return 1
fi fi
echo "$legacy_download_link" echo "$legacy_download_link"
@ -450,7 +534,7 @@ get_user_install_path() {
eval $invocation eval $invocation
if [ ! -z "${DOTNET_INSTALL_DIR:-}" ]; then if [ ! -z "${DOTNET_INSTALL_DIR:-}" ]; then
echo $DOTNET_INSTALL_DIR echo "$DOTNET_INSTALL_DIR"
else else
echo "$HOME/.dotnet" echo "$HOME/.dotnet"
fi fi
@ -464,7 +548,7 @@ resolve_installation_path() {
local install_dir=$1 local install_dir=$1
if [ "$install_dir" = "<auto>" ]; then if [ "$install_dir" = "<auto>" ]; then
local user_install_path=$(get_user_install_path) local user_install_path="$(get_user_install_path)"
say_verbose "resolve_installation_path: user_install_path=$user_install_path" say_verbose "resolve_installation_path: user_install_path=$user_install_path"
echo "$user_install_path" echo "$user_install_path"
return 0 return 0
@ -479,11 +563,11 @@ resolve_installation_path() {
get_installed_version_info() { get_installed_version_info() {
eval $invocation eval $invocation
local install_root=$1 local install_root="$1"
local version_file=$(combine_paths "$install_root" "$local_version_file_relative_path") local version_file="$(combine_paths "$install_root" "$local_version_file_relative_path")"
say_verbose "Local version file: $version_file" say_verbose "Local version file: $version_file"
if [ ! -z "$version_file" ] | [ -r "$version_file" ]; then if [ ! -z "$version_file" ] | [ -r "$version_file" ]; then
local version_info="$(cat $version_file)" local version_info="$(cat "$version_file")"
echo "$version_info" echo "$version_info"
return 0 return 0
fi fi
@ -498,7 +582,7 @@ get_absolute_path() {
eval $invocation eval $invocation
local relative_or_absolute_path=$1 local relative_or_absolute_path=$1
echo $(cd $(dirname "$1") && pwd -P)/$(basename "$1") echo "$(cd "$(dirname "$1")" && pwd -P)/$(basename "$1")"
return 0 return 0
} }
@ -510,17 +594,25 @@ get_absolute_path() {
copy_files_or_dirs_from_list() { copy_files_or_dirs_from_list() {
eval $invocation eval $invocation
local root_path=$(remove_trailing_slash $1) local root_path="$(remove_trailing_slash "$1")"
local out_path=$(remove_trailing_slash $2) local out_path="$(remove_trailing_slash "$2")"
local override=$3 local override="$3"
local override_switch=$(if [ "$override" = false ]; then printf -- "-n"; fi) local osname="$(get_current_os_name)"
local override_switch=$(
if [ "$override" = false ]; then
if [[ "$osname" == "linux-musl" ]]; then
printf -- "-u";
else
printf -- "-n";
fi
fi)
cat | uniq | while read -r file_path; do cat | uniq | while read -r file_path; do
local path=$(remove_beginning_slash ${file_path#$root_path}) local path="$(remove_beginning_slash "${file_path#$root_path}")"
local target=$out_path/$path local target="$out_path/$path"
if [ "$override" = true ] || (! ([ -d "$target" ] || [ -e "$target" ])); then if [ "$override" = true ] || (! ([ -d "$target" ] || [ -e "$target" ])); then
mkdir -p $out_path/$(dirname $path) mkdir -p "$out_path/$(dirname "$path")"
cp -R $override_switch $root_path/$path $target cp -R $override_switch "$root_path/$path" "$target"
fi fi
done done
} }
@ -531,19 +623,19 @@ copy_files_or_dirs_from_list() {
extract_dotnet_package() { extract_dotnet_package() {
eval $invocation eval $invocation
local zip_path=$1 local zip_path="$1"
local out_path=$2 local out_path="$2"
local temp_out_path=$(mktemp -d $temporary_file_template) local temp_out_path="$(mktemp -d "$temporary_file_template")"
local failed=false local failed=false
tar -xzf "$zip_path" -C "$temp_out_path" > /dev/null || failed=true tar -xzf "$zip_path" -C "$temp_out_path" > /dev/null || failed=true
local folders_with_version_regex='^.*/[0-9]+\.[0-9]+[^/]+/' local folders_with_version_regex='^.*/[0-9]+\.[0-9]+[^/]+/'
find $temp_out_path -type f | grep -Eo $folders_with_version_regex | copy_files_or_dirs_from_list $temp_out_path $out_path false find "$temp_out_path" -type f | grep -Eo "$folders_with_version_regex" | sort | copy_files_or_dirs_from_list "$temp_out_path" "$out_path" false
find $temp_out_path -type f | grep -Ev $folders_with_version_regex | copy_files_or_dirs_from_list $temp_out_path $out_path true find "$temp_out_path" -type f | grep -Ev "$folders_with_version_regex" | copy_files_or_dirs_from_list "$temp_out_path" "$out_path" "$override_non_versioned_files"
rm -rf $temp_out_path rm -rf "$temp_out_path"
if [ "$failed" = true ]; then if [ "$failed" = true ]; then
say_err "Extraction failed" say_err "Extraction failed"
@ -557,14 +649,19 @@ extract_dotnet_package() {
download() { download() {
eval $invocation eval $invocation
local remote_path=$1 local remote_path="$1"
local out_path=${2:-} local out_path="${2:-}"
if [[ "$remote_path" != "http"* ]]; then
cp "$remote_path" "$out_path"
return $?
fi
local failed=false local failed=false
if machine_has "curl"; then if machine_has "curl"; then
downloadcurl $remote_path $out_path || failed=true downloadcurl "$remote_path" "$out_path" || failed=true
elif machine_has "wget"; then elif machine_has "wget"; then
downloadwget $remote_path $out_path || failed=true downloadwget "$remote_path" "$out_path" || failed=true
else else
failed=true failed=true
fi fi
@ -577,14 +674,17 @@ download() {
downloadcurl() { downloadcurl() {
eval $invocation eval $invocation
local remote_path=$1 local remote_path="$1"
local out_path=${2:-} local out_path="${2:-}"
# Append feed_credential as late as possible before calling curl to avoid logging feed_credential
remote_path="${remote_path}${feed_credential}"
local failed=false local failed=false
if [ -z "$out_path" ]; then if [ -z "$out_path" ]; then
curl --retry 10 -sSL -f --create-dirs $remote_path || failed=true curl --retry 10 -sSL -f --create-dirs "$remote_path" || failed=true
else else
curl --retry 10 -sSL -f --create-dirs -o $out_path $remote_path || failed=true curl --retry 10 -sSL -f --create-dirs -o "$out_path" "$remote_path" || failed=true
fi fi
if [ "$failed" = true ]; then if [ "$failed" = true ]; then
say_verbose "Curl download failed" say_verbose "Curl download failed"
@ -595,14 +695,17 @@ downloadcurl() {
downloadwget() { downloadwget() {
eval $invocation eval $invocation
local remote_path=$1 local remote_path="$1"
local out_path=${2:-} local out_path="${2:-}"
# Append feed_credential as late as possible before calling wget to avoid logging feed_credential
remote_path="${remote_path}${feed_credential}"
local failed=false local failed=false
if [ -z "$out_path" ]; then if [ -z "$out_path" ]; then
wget -q --tries 10 $remote_path || failed=true wget -q --tries 10 -O - "$remote_path" || failed=true
else else
wget -v --tries 10 -O $out_path $remote_path || failed=true wget --tries 10 -O "$out_path" "$remote_path" || failed=true
fi fi
if [ "$failed" = true ]; then if [ "$failed" = true ]; then
say_verbose "Wget download failed" say_verbose "Wget download failed"
@ -615,63 +718,105 @@ calculate_vars() {
eval $invocation eval $invocation
valid_legacy_download_link=true valid_legacy_download_link=true
normalized_architecture=$(get_normalized_architecture_from_architecture "$architecture") normalized_architecture="$(get_normalized_architecture_from_architecture "$architecture")"
say_verbose "normalized_architecture=$normalized_architecture" say_verbose "normalized_architecture=$normalized_architecture"
specific_version=$(get_specific_version_from_version $azure_feed $channel $normalized_architecture $version) specific_version="$(get_specific_version_from_version "$azure_feed" "$channel" "$normalized_architecture" "$version")"
say_verbose "specific_version=$specific_version" say_verbose "specific_version=$specific_version"
if [ -z "$specific_version" ]; then if [ -z "$specific_version" ]; then
say_err "Could not get version information." say_err "Could not resolve version information."
return 1 return 1
fi fi
download_link=$(construct_download_link $azure_feed $channel $normalized_architecture $specific_version) download_link="$(construct_download_link "$azure_feed" "$channel" "$normalized_architecture" "$specific_version")"
say_verbose "download_link=$download_link" say_verbose "Constructed primary named payload URL: $download_link"
legacy_download_link=$(construct_legacy_download_link $azure_feed $channel $normalized_architecture $specific_version) || valid_legacy_download_link=false legacy_download_link="$(construct_legacy_download_link "$azure_feed" "$channel" "$normalized_architecture" "$specific_version")" || valid_legacy_download_link=false
if [ "$valid_legacy_download_link" = true ]; then if [ "$valid_legacy_download_link" = true ]; then
say_verbose "legacy_download_link=$legacy_download_link" say_verbose "Constructed legacy named payload URL: $legacy_download_link"
else else
say_verbose "Cound not construct a legacy_download_link; omitting..." say_verbose "Cound not construct a legacy_download_link; omitting..."
fi fi
install_root=$(resolve_installation_path $install_dir) install_root="$(resolve_installation_path "$install_dir")"
say_verbose "install_root=$install_root" say_verbose "InstallRoot: $install_root"
} }
install_dotnet() { install_dotnet() {
eval $invocation eval $invocation
local download_failed=false local download_failed=false
local asset_name=''
local asset_relative_path=''
if is_dotnet_package_installed $install_root "sdk" $specific_version; then if [[ "$runtime" == "dotnet" ]]; then
say ".NET SDK version $specific_version is already installed." asset_relative_path="shared/Microsoft.NETCore.App"
asset_name=".NET Core Runtime"
elif [[ "$runtime" == "aspnetcore" ]]; then
asset_relative_path="shared/Microsoft.AspNetCore.App"
asset_name="ASP.NET Core Runtime"
elif [ -z "$runtime" ]; then
asset_relative_path="sdk"
asset_name=".NET Core SDK"
else
say_err "Invalid value for \$runtime"
return 1
fi
# Check if the SDK version is already installed.
if is_dotnet_package_installed "$install_root" "$asset_relative_path" "$specific_version"; then
say "$asset_name version $specific_version is already installed."
return 0 return 0
fi fi
mkdir -p $install_root mkdir -p "$install_root"
zip_path=$(mktemp $temporary_file_template) zip_path="$(mktemp "$temporary_file_template")"
say_verbose "Zip path: $zip_path" say_verbose "Zip path: $zip_path"
say "Downloading link: $download_link" say "Downloading link: $download_link"
download "$download_link" $zip_path || download_failed=true
# Failures are normal in the non-legacy case for ultimately legacy downloads.
# Do not output to stderr, since output to stderr is considered an error.
download "$download_link" "$zip_path" 2>&1 || download_failed=true
# if the download fails, download the legacy_download_link # if the download fails, download the legacy_download_link
if [ "$download_failed" = true ] && [ "$valid_legacy_download_link" = true ]; then if [ "$download_failed" = true ]; then
say "Cannot download: $download_link" say "Cannot download: $download_link"
download_link=$legacy_download_link
zip_path=$(mktemp $temporary_file_template) if [ "$valid_legacy_download_link" = true ]; then
say_verbose "Legacy zip path: $zip_path" download_failed=false
say "Downloading legacy link: $download_link" download_link="$legacy_download_link"
download "$download_link" $zip_path zip_path="$(mktemp "$temporary_file_template")"
say_verbose "Legacy zip path: $zip_path"
say "Downloading legacy link: $download_link"
download "$download_link" "$zip_path" 2>&1 || download_failed=true
if [ "$download_failed" = true ]; then
say "Cannot download: $download_link"
fi
fi
fi
if [ "$download_failed" = true ]; then
say_err "Could not find/download: \`$asset_name\` with version = $specific_version"
say_err "Refer to: https://aka.ms/dotnet-os-lifecycle for information on .NET Core support"
return 1
fi fi
say "Extracting zip from $download_link" say "Extracting zip from $download_link"
extract_dotnet_package $zip_path $install_root extract_dotnet_package "$zip_path" "$install_root"
# Check if the SDK version is now installed; if not, fail the installation.
if ! is_dotnet_package_installed "$install_root" "$asset_relative_path" "$specific_version"; then
say_err "\`$asset_name\` with version = $specific_version failed to install with an unknown error."
return 1
fi
return 0 return 0
} }
args=("$@")
local_version_file_relative_path="/.version" local_version_file_relative_path="/.version"
bin_folder_relative_path="" bin_folder_relative_path=""
temporary_file_template="${TMPDIR:-/tmp}/dotnet.XXXXXXXXX" temporary_file_template="${TMPDIR:-/tmp}/dotnet.XXXXXXXXX"
@ -682,19 +827,23 @@ install_dir="<auto>"
architecture="<auto>" architecture="<auto>"
dry_run=false dry_run=false
no_path=false no_path=false
no_cdn=false
azure_feed="https://dotnetcli.azureedge.net/dotnet" azure_feed="https://dotnetcli.azureedge.net/dotnet"
uncached_feed="https://dotnetcli.blob.core.windows.net/dotnet" uncached_feed="https://dotnetcli.blob.core.windows.net/dotnet"
feed_credential=""
verbose=false verbose=false
shared_runtime=false runtime=""
runtime_id="" runtime_id=""
override_non_versioned_files=true
non_dynamic_parameters=""
while [ $# -ne 0 ] while [ $# -ne 0 ]
do do
name=$1 name="$1"
case $name in case "$name" in
-c|--channel|-[Cc]hannel) -c|--channel|-[Cc]hannel)
shift shift
channel=$1 channel="$1"
;; ;;
-v|--version|-[Vv]ersion) -v|--version|-[Vv]ersion)
shift shift
@ -709,31 +858,60 @@ do
architecture="$1" architecture="$1"
;; ;;
--shared-runtime|-[Ss]hared[Rr]untime) --shared-runtime|-[Ss]hared[Rr]untime)
shared_runtime=true say_warning "The --shared-runtime flag is obsolete and may be removed in a future version of this script. The recommended usage is to specify '--runtime dotnet'."
if [ -z "$runtime" ]; then
runtime="dotnet"
fi
;;
--runtime|-[Rr]untime)
shift
runtime="$1"
if [[ "$runtime" != "dotnet" ]] && [[ "$runtime" != "aspnetcore" ]]; then
say_err "Unsupported value for --runtime: '$1'. Valid values are 'dotnet' and 'aspnetcore'."
exit 1
fi
;; ;;
--dry-run|-[Dd]ry[Rr]un) --dry-run|-[Dd]ry[Rr]un)
dry_run=true dry_run=true
;; ;;
--no-path|-[Nn]o[Pp]ath) --no-path|-[Nn]o[Pp]ath)
no_path=true no_path=true
non_dynamic_parameters+=" $name"
;; ;;
--verbose|-[Vv]erbose) --verbose|-[Vv]erbose)
verbose=true verbose=true
non_dynamic_parameters+=" $name"
;;
--no-cdn|-[Nn]o[Cc]dn)
no_cdn=true
non_dynamic_parameters+=" $name"
;; ;;
--azure-feed|-[Aa]zure[Ff]eed) --azure-feed|-[Aa]zure[Ff]eed)
shift shift
azure_feed="$1" azure_feed="$1"
non_dynamic_parameters+=" $name "\""$1"\"""
;; ;;
--uncached-feed|-[Uu]ncached[Ff]eed) --uncached-feed|-[Uu]ncached[Ff]eed)
shift shift
uncached_feed="$1" uncached_feed="$1"
non_dynamic_parameters+=" $name "\""$1"\"""
;;
--feed-credential|-[Ff]eed[Cc]redential)
shift
feed_credential="$1"
non_dynamic_parameters+=" $name "\""$1"\"""
;; ;;
--runtime-id|-[Rr]untime[Ii]d) --runtime-id|-[Rr]untime[Ii]d)
shift shift
runtime_id="$1" runtime_id="$1"
non_dynamic_parameters+=" $name "\""$1"\"""
;;
--skip-non-versioned-files|-[Ss]kip[Nn]on[Vv]ersioned[Ff]iles)
override_non_versioned_files=false
non_dynamic_parameters+=" $name"
;; ;;
-?|--?|-h|--help|-[Hh]elp) -?|--?|-h|--help|-[Hh]elp)
script_name="$(basename $0)" script_name="$(basename "$0")"
echo ".NET Tools Installer" echo ".NET Tools Installer"
echo "Usage: $script_name [-c|--channel <CHANNEL>] [-v|--version <VERSION>] [-p|--prefix <DESTINATION>]" echo "Usage: $script_name [-c|--channel <CHANNEL>] [-v|--version <VERSION>] [-p|--prefix <DESTINATION>]"
echo " $script_name -h|-?|--help" echo " $script_name -h|-?|--help"
@ -741,7 +919,7 @@ do
echo "$script_name is a simple command line interface for obtaining dotnet cli." echo "$script_name is a simple command line interface for obtaining dotnet cli."
echo "" echo ""
echo "Options:" echo "Options:"
echo " -c,--channel <CHANNEL> Download from the CHANNEL specified, Defaults to \`$channel\`." echo " -c,--channel <CHANNEL> Download from the channel specified, Defaults to \`$channel\`."
echo " -Channel" echo " -Channel"
echo " Possible values:" echo " Possible values:"
echo " - Current - most current release" echo " - Current - most current release"
@ -750,6 +928,7 @@ do
echo " examples: 2.0; 1.0" echo " examples: 2.0; 1.0"
echo " - Branch name" echo " - Branch name"
echo " examples: release/2.0.0; Master" echo " examples: release/2.0.0; Master"
echo " Note: The version parameter overrides the channel parameter."
echo " -v,--version <VERSION> Use specific VERSION, Defaults to \`$version\`." echo " -v,--version <VERSION> Use specific VERSION, Defaults to \`$version\`."
echo " -Version" echo " -Version"
echo " Possible values:" echo " Possible values:"
@ -758,20 +937,32 @@ do
echo " coherent applies only to SDK downloads" echo " coherent applies only to SDK downloads"
echo " - 3-part version in a format A.B.C - represents specific version of build" echo " - 3-part version in a format A.B.C - represents specific version of build"
echo " examples: 2.0.0-preview2-006120; 1.1.0" echo " examples: 2.0.0-preview2-006120; 1.1.0"
echo " -i,--install-dir <DIR> Install under specified location (see Install Location below)" echo " -i,--install-dir <DIR> Install under specified location (see Install Location below)"
echo " -InstallDir" echo " -InstallDir"
echo " --architecture <ARCHITECTURE> Architecture of .NET Tools. Currently only x64 is supported." echo " --architecture <ARCHITECTURE> Architecture of dotnet binaries to be installed, Defaults to \`$architecture\`."
echo " --arch,-Architecture,-Arch" echo " --arch,-Architecture,-Arch"
echo " --shared-runtime Installs just the shared runtime bits, not the entire SDK." echo " Possible values: x64, arm, and arm64"
echo " -SharedRuntime" echo " --runtime <RUNTIME> Installs a shared runtime only, without the SDK."
echo " --dry-run,-DryRun Do not perform installation. Display download link." echo " -Runtime"
echo " --no-path, -NoPath Do not set PATH for the current process." echo " Possible values:"
echo " --verbose,-Verbose Display diagnostics information." echo " - dotnet - the Microsoft.NETCore.App shared runtime"
echo " --azure-feed,-AzureFeed Azure feed location. Defaults to $azure_feed, This parameter typically is not changed by the user." echo " - aspnetcore - the Microsoft.AspNetCore.App shared runtime"
echo " --uncached-feed,-UncachedFeed Uncached feed location. This parameter typically is not changed by the user." echo " --skip-non-versioned-files Skips non-versioned files if they already exist, such as the dotnet executable."
echo " --runtime-id Installs the .NET Tools for the given platform (use linux-x64 for portable linux)." echo " -SkipNonVersionedFiles"
echo " --dry-run,-DryRun Do not perform installation. Display download link."
echo " --no-path, -NoPath Do not set PATH for the current process."
echo " --verbose,-Verbose Display diagnostics information."
echo " --azure-feed,-AzureFeed Azure feed location. Defaults to $azure_feed, This parameter typically is not changed by the user."
echo " --uncached-feed,-UncachedFeed Uncached feed location. This parameter typically is not changed by the user."
echo " --no-cdn,-NoCdn Disable downloading from the Azure CDN, and use the uncached feed directly."
echo " --feed-credential,-FeedCredential Azure feed shared access token. This parameter typically is not specified."
echo " --runtime-id Installs the .NET Tools for the given platform (use linux-x64 for portable linux)."
echo " -RuntimeId" echo " -RuntimeId"
echo " -?,--?,-h,--help,-Help Shows this help message" echo " -?,--?,-h,--help,-Help Shows this help message"
echo ""
echo "Obsolete parameters:"
echo " --shared-runtime The recommended alternative is '--runtime dotnet'."
echo " -SharedRuntime Installs just the shared runtime bits, not the entire SDK."
echo "" echo ""
echo "Install Location:" echo "Install Location:"
echo " Location is chosen in following order:" echo " Location is chosen in following order:"
@ -789,25 +980,38 @@ do
shift shift
done done
if [ "$no_cdn" = true ]; then
azure_feed="$uncached_feed"
fi
check_min_reqs check_min_reqs
calculate_vars calculate_vars
script_name=$(basename "$0")
if [ "$dry_run" = true ]; then if [ "$dry_run" = true ]; then
say "Payload URL: $download_link" say "Payload URLs:"
say "Primary named payload URL: $download_link"
if [ "$valid_legacy_download_link" = true ]; then if [ "$valid_legacy_download_link" = true ]; then
say "Legacy payload URL: $legacy_download_link" say "Legacy named payload URL: $legacy_download_link"
fi fi
say "Repeatable invocation: ./$(basename $0) --version $specific_version --channel $channel --install-dir $install_dir" repeatable_command="./$script_name --version "\""$specific_version"\"" --install-dir "\""$install_root"\"" --architecture "\""$normalized_architecture"\"""
if [[ "$runtime" == "dotnet" ]]; then
repeatable_command+=" --runtime "\""dotnet"\"""
elif [[ "$runtime" == "aspnetcore" ]]; then
repeatable_command+=" --runtime "\""aspnetcore"\"""
fi
repeatable_command+="$non_dynamic_parameters"
say "Repeatable invocation: $repeatable_command"
exit 0 exit 0
fi fi
check_pre_reqs check_pre_reqs
install_dotnet install_dotnet
bin_path=$(get_absolute_path $(combine_paths $install_root $bin_folder_relative_path)) bin_path="$(get_absolute_path "$(combine_paths "$install_root" "$bin_folder_relative_path")")"
if [ "$no_path" = false ]; then if [ "$no_path" = false ]; then
say "Adding to current process PATH: \`$bin_path\`. Note: This change will be visible only when sourcing script." say "Adding to current process PATH: \`$bin_path\`. Note: This change will be visible only when sourcing script."
export PATH=$bin_path:$PATH export PATH="$bin_path":"$PATH"
else else
say "Binaries of dotnet can be found in $bin_path" say "Binaries of dotnet can be found in $bin_path"
fi fi

View File

@ -5,7 +5,6 @@ import * as exec from '@actions/exec';
import * as io from '@actions/io'; import * as io from '@actions/io';
import * as tc from '@actions/tool-cache'; import * as tc from '@actions/tool-cache';
import httpClient = require('typed-rest-client/HttpClient'); import httpClient = require('typed-rest-client/HttpClient');
import httpInterfaces = require('typed-rest-client/Interfaces');
import {HttpClientResponse} from 'typed-rest-client/HttpClient'; import {HttpClientResponse} from 'typed-rest-client/HttpClient';
import {chmodSync} from 'fs'; import {chmodSync} from 'fs';
import * as os from 'os'; import * as os from 'os';
@ -61,26 +60,6 @@ export class DotnetCoreInstaller {
// Prepend the tools path. instructs the agent to prepend for future tasks // Prepend the tools path. instructs the agent to prepend for future tasks
core.addPath(toolPath); core.addPath(toolPath);
try {
let globalToolPath: string = '';
if (IS_WINDOWS) {
globalToolPath = path.join(
process.env.USERPROFILE || '',
'.dotnet\\tools'
);
} else {
globalToolPath = path.join(process.env.HOME || '', '.dotnet/tools');
}
await io.mkdirP(globalToolPath);
core.addPath(globalToolPath);
} catch (error) {
//nop
}
// Set DOTNET_ROOT for dotnet core Apphost to find runtime since it is installed to a non well-known location.
core.exportVariable('DOTNET_ROOT', toolPath);
} }
private getLocalTool(): string { private getLocalTool(): string {
@ -140,7 +119,7 @@ export class DotnetCoreInstaller {
} }
if (resultCode != 0) { if (resultCode != 0) {
throw `Failed to detect os with result code ${resultCode}`; throw `Failed to detect os with result code ${resultCode}. Output: ${output}`;
} }
let index; let index;
@ -205,6 +184,7 @@ export class DotnetCoreInstaller {
): Promise<string[]> { ): Promise<string[]> {
let downloadUrls = []; let downloadUrls = [];
let releasesJSON = await this.getReleasesJson(); let releasesJSON = await this.getReleasesJson();
core.debug('Releases: ' + releasesJSON);
let releasesInfo = JSON.parse(await releasesJSON.readBody()); let releasesInfo = JSON.parse(await releasesJSON.readBody());
releasesInfo = releasesInfo.filter((releaseInfo: any) => { releasesInfo = releasesInfo.filter((releaseInfo: any) => {
@ -320,7 +300,7 @@ export class DotnetCoreInstaller {
} }
if (resultCode != 0) { if (resultCode != 0) {
throw `Failed to get download urls with result code ${resultCode}`; throw `Failed to get download urls with result code ${resultCode}. ${output}`;
} }
let primaryUrl: string = ''; let primaryUrl: string = '';