Merge remote-tracking branch 'upstream/main' into dependabot/npm_and_yarn/node-notifier-8.0.1

This commit is contained in:
Vladimir Safonkin 2021-06-28 10:29:43 +03:00
commit b25fa305a3
20 changed files with 1696 additions and 537 deletions

1
.github/CODEOWNERS vendored Normal file
View File

@ -0,0 +1 @@
* @actions/virtual-environments-owners

View File

@ -2,22 +2,31 @@
name: Bug report name: Bug report
about: Create a bug report about: Create a bug report
title: '' title: ''
labels: '' labels: bug, needs triage
assignees: '' assignees: ''
--- ---
### Description **Description:**
A clear and concise description of what the bug is.
<!-- **Task version:**
* Please share short description of the problem Specify the task version
-->
### Details **Platform:**
- [ ] Ubuntu
- [ ] macOS
- [ ] Windows
<!-- **Runner type:**
* Include the relevant yaml, platform, and dotnet versions in use - [ ] Hosted
* If an error occurred on a public action, please share a link - [ ] Self-hosted
* Include any error messages received in text (search does not work for images)
* Was this a regression from previous behavior? **Repro steps:**
--> A description with steps to reproduce the issue. If your have a public example or repo to share, please provide the link.
**Expected behavior:**
A description of what you expected to happen.
**Actual behavior:**
A description of what is actually happening.

View File

@ -1,4 +1,4 @@
blank_issues_enabled: true blank_issues_enabled: false
contact_links: contact_links:
- name: .NET issues - name: .NET issues
url: https://github.com/dotnet/runtime#filing-issues url: https://github.com/dotnet/runtime#filing-issues

View File

@ -0,0 +1,16 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: feature request, needs triage
assignees: ''
---
**Description:**
Describe your proposal.
**Justification:**
Justification or a use case for your proposal.
**Are you willing to submit a PR?**
<!--- We accept contributions! -->

9
.github/pull_request_template.md vendored Normal file
View File

@ -0,0 +1,9 @@
**Description:**
Describe your changes.
**Related issue:**
Add link to the related issue.
**Check list:**
- [ ] Mark if documentation changes are required.
- [ ] Mark if tests were added or updated to cover the changes.

View File

@ -0,0 +1,28 @@
name: Release new action version
on:
release:
types: [released]
workflow_dispatch:
inputs:
TAG_NAME:
description: 'Tag name that the major tag will point to'
required: true
env:
TAG_NAME: ${{ github.event.inputs.TAG_NAME || github.event.release.tag_name }}
permissions:
contents: write
jobs:
update_tag:
name: Update the major tag to include the ${{ github.event.inputs.TAG_NAME || github.event.release.tag_name }} changes
environment:
name: releaseNewActionVersion
runs-on: ubuntu-latest
steps:
- name: Update the ${{ env.TAG_NAME }} tag
id: update-major-tag
uses: actions/publish-action@v0.1.0
with:
source-tag: ${{ env.TAG_NAME }}
slack-webhook: ${{ secrets.SLACK_WEBHOOK }}

37
.github/workflows/test-dotnet.yml vendored Normal file
View File

@ -0,0 +1,37 @@
name: Validate dotnet
on:
pull_request:
paths-ignore:
- '**.md'
push:
branches:
- main
- releases/*
paths-ignore:
- '**.md'
jobs:
setup-version:
runs-on: ${{ matrix.operating-system }}
strategy:
fail-fast: false
matrix:
operating-system: [ubuntu-latest, windows-latest, macOS-latest]
dotnet-version: ['2.1', '2.2', '3.0', '3.1', '5.0']
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Clear toolcache
shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
- name: Setup dotnet ${{ matrix.dotnet-version }}
uses: ./
with:
dotnet-version: ${{ matrix.dotnet-version }}
- name: Check installed version
shell: pwsh
run: |
$version = & dotnet --version
Write-Host "Installed version: $version"
if (-not $version.StartsWith("${{ matrix.dotnet-version }}")) { throw "Unexpected version" }

View File

@ -2,10 +2,14 @@ name: Main workflow
on: on:
pull_request: pull_request:
paths-ignore:
- '**.md'
push: push:
branches: branches:
- main - main
- releases/* - releases/*
paths-ignore:
- '**.md'
jobs: jobs:
build: build:
@ -29,7 +33,7 @@ jobs:
if: runner.os != 'windows' if: runner.os != 'windows'
run: __tests__/verify-no-unstaged-changes.sh run: __tests__/verify-no-unstaged-changes.sh
test: test-setup-full-version:
runs-on: ${{ matrix.operating-system }} runs-on: ${{ matrix.operating-system }}
strategy: strategy:
fail-fast: false fail-fast: false
@ -38,25 +42,9 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Clear tool cache (macOS) - name: Clear toolcache
if: runner.os == 'macos' shell: pwsh
run: | run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
echo $PATH
dotnet --info
rm -rf "/Users/runner/.dotnet"
- name: Clear tool cache (Ubuntu)
if: runner.os == 'linux'
run: |
echo $PATH
dotnet --info
rm -rf "/usr/share/dotnet"
- name: Clear tool cache (Windows)
if: runner.os == 'windows'
run: |
echo $env:PATH
dotnet --info
Remove-Item $env:LocalAppData\Microsoft\dotnet/* -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item "$env:ProgramFiles\dotnet/*" -Recurse -Force -ErrorAction SilentlyContinue
# Side-by-side install of 2.2 and 3.1 used for the test project # Side-by-side install of 2.2 and 3.1 used for the test project
- name: Setup dotnet 2.2.402 - name: Setup dotnet 2.2.402
uses: ./ uses: ./
@ -70,70 +58,86 @@ jobs:
source-url: https://api.nuget.org/v3/index.json source-url: https://api.nuget.org/v3/index.json
env: env:
NUGET_AUTH_TOKEN: NOTATOKEN NUGET_AUTH_TOKEN: NOTATOKEN
- name: Verify nuget config file
shell: pwsh
run: |
if (-Not (Test-Path "../nuget.config")) { throw "nuget file not generated correctly" }
- name: Verify dotnet - name: Verify dotnet
if: runner.os != 'windows' shell: pwsh
run: __tests__/verify-dotnet.sh 3.1.201 2.2.402
- name: Verify dotnet (Windows)
if: runner.os == 'windows'
run: __tests__/verify-dotnet.ps1 3.1.201 2.2.402 run: __tests__/verify-dotnet.ps1 3.1.201 2.2.402
# Set new cache before 2 digit install test-setup-without-patch-version:
- name: Set new tool cache (macOS) runs-on: ${{ matrix.operating-system }}
if: runner.os == 'macos' strategy:
run: | fail-fast: false
echo "DOTNET_INSTALL_DIR=/Users/runner/.dotnet2" >> $GITHUB_ENV matrix:
- name: Set new tool cache (Ubuntu) operating-system: [ubuntu-latest, windows-latest, macOS-latest]
if: runner.os == 'linux' steps:
run: | - name: Checkout
echo "DOTNET_INSTALL_DIR=/home/runner/.dotnet2" >> $GITHUB_ENV uses: actions/checkout@v2
- name: Set new tool cache (Windows) - name: Clear toolcache
if: runner.os == 'windows' shell: pwsh
shell: bash run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
run: |
echo "DOTNET_INSTALL_DIR=$LocalAppData\Microsoft\dotnet2" >> $GITHUB_ENV
# 2.0, 3.0, 5.0 needs to be in single quotes to interpret as a string instead of as an integer # 2.0, 3.0, 5.0 needs to be in single quotes to interpret as a string instead of as an integer
- name: Setup dotnet '2.0' - name: Setup dotnet '3.1'
uses: ./ uses: ./
with: with:
dotnet-version: '2.0' dotnet-version: '3.1'
- name: Setup dotnet '2.2'
uses: ./
with:
dotnet-version: '2.2'
- name: Verify dotnet
shell: pwsh
run: __tests__/verify-dotnet.ps1 3.1 2.2
# Clear cache before .x version install test-setup-latest-patch-version:
- name: Set new tool cache (macOS) runs-on: ${{ matrix.operating-system }}
if: runner.os == 'macos' strategy:
run: | fail-fast: false
echo "DOTNET_INSTALL_DIR=/Users/runner/.dotnet3" >> $GITHUB_ENV matrix:
- name: Set new tool cache (Ubuntu) operating-system: [ubuntu-latest, windows-latest, macOS-latest]
if: runner.os == 'linux' steps:
run: | - name: Checkout
echo "DOTNET_INSTALL_DIR=/home/runner/.dotnet3" >> $GITHUB_ENV uses: actions/checkout@v2
- name: Set new tool cache (Windows) - name: Clear toolcache
if: runner.os == 'windows' shell: pwsh
shell: bash run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
run: | - name: Setup dotnet 3.1.x
echo "DOTNET_INSTALL_DIR=$LocalAppData\Microsoft\dotnet3" >> $GITHUB_ENV
- name: Setup dotnet 2.0.x
uses: ./ uses: ./
with: with:
dotnet-version: 2.0.x dotnet-version: 3.1.x
- name: Setup dotnet 2.2.x
uses: ./
with:
dotnet-version: 2.2.x
- name: Verify dotnet
shell: pwsh
run: __tests__/verify-dotnet.ps1 3.1 2.2
# Clear cache before .* version install test-setup-with-wildcard:
- name: Set new tool cache (macOS) runs-on: ${{ matrix.operating-system }}
if: runner.os == 'macos' strategy:
run: | fail-fast: false
echo "DOTNET_INSTALL_DIR=/Users/runner/.dotnet4" >> $GITHUB_ENV matrix:
- name: Set new tool cache (Ubuntu) operating-system: [ubuntu-latest, windows-latest, macOS-latest]
if: runner.os == 'linux' steps:
run: | - name: Checkout
echo "DOTNET_INSTALL_DIR=/home/runner/.dotnet4" >> $GITHUB_ENV uses: actions/checkout@v2
- name: Set new tool cache (Windows) - name: Clear toolcache
if: runner.os == 'windows' shell: pwsh
shell: bash run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
run: | - name: Setup dotnet 3.1.*
echo "DOTNET_INSTALL_DIR=$LocalAppData\Microsoft\dotnet4" >> $GITHUB_ENV
- name: Setup dotnet 2.0.*
uses: ./ uses: ./
with: with:
dotnet-version: 2.0.* dotnet-version: 3.1.*
- name: Setup dotnet 2.2.*
uses: ./
with:
dotnet-version: 2.2.*
- name: Verify dotnet
shell: pwsh
run: __tests__/verify-dotnet.ps1 3.1 2.2
test-proxy: test-proxy:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@ -13,7 +13,7 @@ This action sets up a [dotnet core cli](https://github.com/dotnet/cli) environme
Please Note: GitHub hosted runners have some versions of the .NET SDK Please Note: GitHub hosted runners have some versions of the .NET SDK
preinstalled. Installed versions are subject to change. Please refer to the preinstalled. Installed versions are subject to change. Please refer to the
documentation documentation
[software installed on github hosted runners](https://help.github.com/en/actions/reference/software-installed-on-github-hosted-runners) [software installed on github hosted runners](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-software)
for .NET SDK versions that are currently available. for .NET SDK versions that are currently available.
# Usage # Usage
@ -23,13 +23,24 @@ See [action.yml](action.yml)
Basic: Basic:
```yaml ```yaml
steps: steps:
- uses: actions/checkout@main - uses: actions/checkout@v2
- uses: actions/setup-dotnet@v1 - uses: actions/setup-dotnet@v1
with: with:
dotnet-version: '3.1.x' # SDK Version to use; x will use the latest version of the 3.1 channel dotnet-version: '3.1.x' # SDK Version to use; x will use the latest version of the 3.1 channel
- run: dotnet build <my project> - run: dotnet build <my project>
``` ```
Preview version:
```yml
steps:
- uses: actions@checkout@v2
- uses: actions/setup-dotnet@v1
with:
dotnet-version: '6.0.x'
include-prerelease: true
- run: dotnet build <my project>
```
Matrix Testing: Matrix Testing:
```yaml ```yaml
jobs: jobs:
@ -37,7 +48,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
dotnet: [ '2.2.103', '3.0', '3.1.x' ] dotnet: [ '2.1.x', '3.1.x', '5.0.x' ]
name: Dotnet ${{ matrix.dotnet }} sample name: Dotnet ${{ matrix.dotnet }} sample
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@ -59,7 +70,7 @@ jobs:
- name: Setup dotnet - name: Setup dotnet
uses: actions/setup-dotnet@v1 uses: actions/setup-dotnet@v1
with: with:
dotnet-version: '2.2.103' dotnet-version: '2.1.x'
- name: Setup dotnet - name: Setup dotnet
uses: actions/setup-dotnet@v1 uses: actions/setup-dotnet@v1
with: with:
@ -85,7 +96,7 @@ steps:
- name: Publish the package to GPR - name: Publish the package to GPR
run: dotnet nuget push <my project>/bin/Release/*.nupkg run: dotnet nuget push <my project>/bin/Release/*.nupkg
# Authticates packages to push to Azure Artifacts # Authenticates packages to push to Azure Artifacts
- uses: actions/setup-dotnet@v1 - uses: actions/setup-dotnet@v1
with: with:
source-url: https://pkgs.dev.azure.com/<your-organization>/_packaging/<your-feed-name>/nuget/v3/index.json source-url: https://pkgs.dev.azure.com/<your-organization>/_packaging/<your-feed-name>/nuget/v3/index.json
@ -93,6 +104,16 @@ steps:
NUGET_AUTH_TOKEN: ${{secrets.AZURE_DEVOPS_PAT}} # Note, create a secret with this name in Settings NUGET_AUTH_TOKEN: ${{secrets.AZURE_DEVOPS_PAT}} # Note, create a secret with this name in Settings
- name: Publish the package to Azure Artifacts - name: Publish the package to Azure Artifacts
run: dotnet nuget push <my project>/bin/Release/*.nupkg run: dotnet nuget push <my project>/bin/Release/*.nupkg
# Authenticates packages to push to nuget.org.
# It's only the way to push a package to nuget.org feed for macOS/Linux machines due to API key config store limitations.
- uses: actions/setup-dotnet@v1
with:
dotnet-version: 3.1.x
- name: Publish the package to nuget.org
run: dotnet nuget push */bin/Release/*.nupkg -k $NUGET_AUTH_TOKEN -s https://api.nuget.org/v3/index.json
env:
NUGET_AUTH_TOKEN: ${{ secrets.NUGET_TOKEN }}
``` ```
## Environment Variables to use with dotnet ## Environment Variables to use with dotnet
@ -113,7 +134,7 @@ build:
- uses: actions/checkout@main - uses: actions/checkout@main
- uses: actions/setup-dotnet@v1 - uses: actions/setup-dotnet@v1
with: with:
dotnet-version: '3.1.100' # SDK Version to use. dotnet-version: '3.1.x' # SDK Version to use.
``` ```
# License # License

View File

@ -0,0 +1,13 @@
$dotnetPaths = @{
Linux = @("/usr/share/dotnet")
macOS = @("$env:HOME/.dotnet")
Windows = @("$env:ProgramFiles\dotnet/*",
"$env:LocalAppData\Microsoft\dotnet/*")
}
foreach ($path in $dotnetPaths[$args[0]]) {
if (Test-Path $path) {
Write-Host "Clear $path path"
Remove-Item $path -Recurse -Force
}
}

View File

@ -3,30 +3,34 @@ if (!$args[0])
throw "Must supply dotnet version argument" throw "Must supply dotnet version argument"
} }
if (-Not (Test-Path "../nuget.config"))
{
throw "nuget file not generated correctly"
}
$dotnet = Get-Command dotnet | Select-Object -First 1 | ForEach-Object { $_.Path } $dotnet = Get-Command dotnet | Select-Object -First 1 | ForEach-Object { $_.Path }
Write-Host "Found '$dotnet'" Write-Host "Found '$dotnet'"
$version = & $dotnet --version | Out-String | ForEach-Object { $_.Trim() } $version = & $dotnet --version | Out-String | ForEach-Object { $_.Trim() }
Write-Host "Version $version" Write-Host "Version $version"
if ($version -ne $args[0]) if (-not ($version.StartsWith($args[0].ToString())))
{ {
Write-Host "PATH='$env:path'" Write-Host "PATH='$env:PATH'"
throw "Unexpected version" throw "Unexpected version"
} }
if ($args[1]) if ($args[1])
{ {
# SDKs are listed on multiple lines with the path afterwards in square brackets # SDKs are listed on multiple lines with the path afterwards in square brackets
$version = & $dotnet --list-sdks | ForEach-Object { $_.SubString(0, $_.IndexOf('[')).Trim() } $versions = & $dotnet --list-sdks | ForEach-Object { $_.SubString(0, $_.IndexOf('[')).Trim() }
Write-Host "Version $version" Write-Host "Installed versions: $versions"
if (-not ($version -contains $args[1])) $isInstalledVersion = $false
foreach ($version in $versions)
{ {
Write-Host "PATH='$env:path'" if ($version.StartsWith($args[1].ToString()))
{
$isInstalledVersion = $true
break
}
}
if (-not $isInstalledVersion)
{
Write-Host "PATH='$env:PATH'"
throw "Unexpected version" throw "Unexpected version"
} }
} }

View File

@ -13,6 +13,8 @@ describe('version tests', () => {
); );
each([ each([
['3.x', '3.x'],
['3.*', '3.*'],
['3.1.x', '3.1'], ['3.1.x', '3.1'],
['1.1.*', '1.1'], ['1.1.*', '1.1'],
['2.0', '2.0'] ['2.0', '2.0']
@ -42,7 +44,6 @@ describe('version tests', () => {
'.2.3', '.2.3',
'.2.x', '.2.x',
'1', '1',
'2.x',
'*.*.1', '*.*.1',
'*.1', '*.1',
'*.', '*.',

View File

@ -1,18 +1,21 @@
name: 'Setup .NET Core SDK' name: 'Setup .NET Core SDK'
description: 'Set up a specific version of the .NET Core CLI in the PATH and set up authentication to a private NuGet repository' description: 'Used to build and publish .NET source. Set up a specific version of the .NET Core CLI in the PATH and set up authentication to a private NuGet repository'
author: 'GitHub' author: 'GitHub'
branding: branding:
icon: play icon: play
color: green color: green
inputs: inputs:
dotnet-version: dotnet-version:
description: 'SDK version to use. Examples: 2.2.104, 3.1, 3.1.x' description: 'Optional SDK version to use. If not provided, will install global.json version when available. Examples: 2.2.104, 3.1, 3.1.x'
source-url: source-url:
description: 'Optional package source for which to set up authentication. Will consult any existing NuGet.config in the root of the repo and provide a temporary NuGet.config using the NUGET_AUTH_TOKEN environment variable as a ClearTextPassword' description: 'Optional package source for which to set up authentication. Will consult any existing NuGet.config in the root of the repo and provide a temporary NuGet.config using the NUGET_AUTH_TOKEN environment variable as a ClearTextPassword'
owner: owner:
description: 'Optional OWNER for using packages from GitHub Package Registry organizations/users other than the current repository''s owner. Only used if a GPR URL is also provided in source-url' description: 'Optional OWNER for using packages from GitHub Package Registry organizations/users other than the current repository''s owner. Only used if a GPR URL is also provided in source-url'
config-file: config-file:
description: 'Optional NuGet.config location, if your NuGet.config isn''t located in the root of the repo.' description: 'Optional NuGet.config location, if your NuGet.config isn''t located in the root of the repo.'
include-prerelease:
description: 'Whether prerelease versions should be matched with non-exact versions (for example 5.0.0-preview.6 being matched by 5, 5.0, 5.x or 5.0.x). Defaults to false if not provided.'
required: False
runs: runs:
using: 'node12' using: 'node12'
main: 'dist/index.js' main: 'dist/index.js'

65
dist/index.js vendored
View File

@ -4840,11 +4840,26 @@ const github = __importStar(__webpack_require__(469));
const xmlbuilder = __importStar(__webpack_require__(312)); const xmlbuilder = __importStar(__webpack_require__(312));
const xmlParser = __importStar(__webpack_require__(989)); const xmlParser = __importStar(__webpack_require__(989));
function configAuthentication(feedUrl, existingFileLocation = '', processRoot = process.cwd()) { function configAuthentication(feedUrl, existingFileLocation = '', processRoot = process.cwd()) {
const existingNuGetConfig = path.resolve(processRoot, existingFileLocation == '' ? 'nuget.config' : existingFileLocation); const existingNuGetConfig = path.resolve(processRoot, existingFileLocation === ''
? getExistingNugetConfig(processRoot)
: existingFileLocation);
const tempNuGetConfig = path.resolve(processRoot, '../', 'nuget.config'); const tempNuGetConfig = path.resolve(processRoot, '../', 'nuget.config');
writeFeedToFile(feedUrl, existingNuGetConfig, tempNuGetConfig); writeFeedToFile(feedUrl, existingNuGetConfig, tempNuGetConfig);
} }
exports.configAuthentication = configAuthentication; exports.configAuthentication = configAuthentication;
function isValidKey(key) {
return /^[\w\-\.]+$/i.test(key);
}
function getExistingNugetConfig(processRoot) {
const defaultConfigName = 'nuget.config';
const configFileNames = fs
.readdirSync(processRoot)
.filter(filename => filename.toLowerCase() === defaultConfigName);
if (configFileNames.length) {
return configFileNames[0];
}
return defaultConfigName;
}
function writeFeedToFile(feedUrl, existingFileLocation, tempFileLocation) { function writeFeedToFile(feedUrl, existingFileLocation, tempFileLocation) {
console.log(`dotnet-auth: Finding any source references in ${existingFileLocation}, writing a new temporary configuration file with credentials to ${tempFileLocation}`); console.log(`dotnet-auth: Finding any source references in ${existingFileLocation}, writing a new temporary configuration file with credentials to ${tempFileLocation}`);
let xml; let xml;
@ -4910,8 +4925,8 @@ function writeFeedToFile(feedUrl, existingFileLocation, tempFileLocation) {
} }
xml = xml.ele('packageSourceCredentials'); xml = xml.ele('packageSourceCredentials');
sourceKeys.forEach(key => { sourceKeys.forEach(key => {
if (key.indexOf(' ') > -1) { if (!isValidKey(key)) {
throw new Error("This action currently can't handle source names with spaces. Remove the space from your repo's NuGet.config and try again."); throw new Error("Source name can contain letters, numbers, and '-', '_', '.' symbols only. Please, fix source name in NuGet.config and try again.");
} }
xml = xml xml = xml
.ele(key) .ele(key)
@ -7814,14 +7829,18 @@ function run() {
core.debug('No version found, trying to find version from global.json'); core.debug('No version found, trying to find version from global.json');
const globalJsonPath = path.join(process.cwd(), 'global.json'); const globalJsonPath = path.join(process.cwd(), 'global.json');
if (fs.existsSync(globalJsonPath)) { if (fs.existsSync(globalJsonPath)) {
const globalJson = JSON.parse(fs.readFileSync(globalJsonPath, { encoding: 'utf8' })); const globalJson = JSON.parse(
// .trim() is necessary to strip BOM https://github.com/nodejs/node/issues/20649
fs.readFileSync(globalJsonPath, { encoding: 'utf8' }).trim());
if (globalJson.sdk && globalJson.sdk.version) { if (globalJson.sdk && globalJson.sdk.version) {
version = globalJson.sdk.version; version = globalJson.sdk.version;
} }
} }
} }
if (version) { if (version) {
const dotnetInstaller = new installer.DotnetCoreInstaller(version); const includePrerelease = (core.getInput('include-prerelease') || 'false').toLowerCase() ===
'true';
const dotnetInstaller = new installer.DotnetCoreInstaller(version, includePrerelease);
yield dotnetInstaller.installDotnet(); yield dotnetInstaller.installDotnet();
} }
const sourceUrl = core.getInput('source-url'); const sourceUrl = core.getInput('source-url');
@ -16868,15 +16887,16 @@ class DotNetVersionInfo {
this.isExactVersionSet = true; this.isExactVersionSet = true;
return; return;
} }
//Note: No support for previews when using generic const parts = version.split('.');
let parts = version.split('.');
if (parts.length < 2 || parts.length > 3) if (parts.length < 2 || parts.length > 3)
this.throwInvalidVersionFormat(); this.throwInvalidVersionFormat();
if (parts.length == 3 && parts[2] !== 'x' && parts[2] !== '*') { if (parts.length == 3 && parts[2] !== 'x' && parts[2] !== '*') {
this.throwInvalidVersionFormat(); this.throwInvalidVersionFormat();
} }
let major = this.getVersionNumberOrThrow(parts[0]); const major = this.getVersionNumberOrThrow(parts[0]);
let minor = this.getVersionNumberOrThrow(parts[1]); const minor = ['x', '*'].includes(parts[1])
? parts[1]
: this.getVersionNumberOrThrow(parts[1]);
this.fullversion = major + '.' + minor; this.fullversion = major + '.' + minor;
} }
getVersionNumberOrThrow(input) { getVersionNumberOrThrow(input) {
@ -16894,7 +16914,7 @@ class DotNetVersionInfo {
} }
} }
throwInvalidVersionFormat() { throwInvalidVersionFormat() {
throw 'Invalid version format! Supported: 1.2.3, 1.2, 1.2.x, 1.2.*'; throw new Error('Invalid version format! Supported: 1.2.3, 1.2, 1.2.x, 1.2.*');
} }
/** /**
* If true exacatly one version should be resolved * If true exacatly one version should be resolved
@ -16908,8 +16928,9 @@ class DotNetVersionInfo {
} }
exports.DotNetVersionInfo = DotNetVersionInfo; exports.DotNetVersionInfo = DotNetVersionInfo;
class DotnetCoreInstaller { class DotnetCoreInstaller {
constructor(version) { constructor(version, includePrerelease = false) {
this.version = version; this.version = version;
this.includePrerelease = includePrerelease;
} }
installDotnet() { installDotnet() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
@ -16997,7 +17018,7 @@ class DotnetCoreInstaller {
} }
console.log(process.env['PATH']); console.log(process.env['PATH']);
if (resultCode != 0) { if (resultCode != 0) {
throw `Failed to install dotnet ${resultCode}. ${output}`; throw new Error(`Failed to install dotnet ${resultCode}. ${output}`);
} }
}); });
} }
@ -17016,16 +17037,24 @@ class DotnetCoreInstaller {
const releasesResult = releasesResponse.result || {}; const releasesResult = releasesResponse.result || {};
let releasesInfo = releasesResult['releases']; let releasesInfo = releasesResult['releases'];
releasesInfo = releasesInfo.filter((releaseInfo) => { releasesInfo = releasesInfo.filter((releaseInfo) => {
return (semver.satisfies(releaseInfo['sdk']['version'], versionInfo.version()) || return (semver.satisfies(releaseInfo['sdk']['version'], versionInfo.version(), {
semver.satisfies(releaseInfo['sdk']['version-display'], versionInfo.version())); includePrerelease: this.includePrerelease
}) ||
semver.satisfies(releaseInfo['sdk']['version-display'], versionInfo.version(), {
includePrerelease: this.includePrerelease
}));
}); });
// Exclude versions that are newer than the latest if using not exact // Exclude versions that are newer than the latest if using not exact
let latestSdk = releasesResult['latest-sdk']; let latestSdk = releasesResult['latest-sdk'];
releasesInfo = releasesInfo.filter((releaseInfo) => semver.lte(releaseInfo['sdk']['version'], latestSdk)); releasesInfo = releasesInfo.filter((releaseInfo) => semver.lte(releaseInfo['sdk']['version'], latestSdk, {
includePrerelease: this.includePrerelease
}));
// Sort for latest version // Sort for latest version
releasesInfo = releasesInfo.sort((a, b) => semver.rcompare(a['sdk']['version'], b['sdk']['version'])); releasesInfo = releasesInfo.sort((a, b) => semver.rcompare(a['sdk']['version'], b['sdk']['version'], {
includePrerelease: this.includePrerelease
}));
if (releasesInfo.length == 0) { if (releasesInfo.length == 0) {
throw `Could not find dotnet core version. Please ensure that specified version ${versionInfo.inputVersion} is valid.`; throw new Error(`Could not find dotnet core version. Please ensure that specified version ${versionInfo.inputVersion} is valid.`);
} }
let release = releasesInfo[0]; let release = releasesInfo[0];
return release['sdk']['version']; return release['sdk']['version'];
@ -17046,7 +17075,7 @@ class DotnetCoreInstaller {
return versionParts[0] == sdkParts[0]; return versionParts[0] == sdkParts[0];
}); });
if (releasesInfo.length === 0) { if (releasesInfo.length === 0) {
throw `Could not find info for version ${versionParts.join('.')} at ${DotNetCoreIndexUrl}`; throw new Error(`Could not find info for version ${versionParts.join('.')} at ${DotNetCoreIndexUrl}`);
} }
return releasesInfo[0]['releases.json']; return releasesInfo[0]['releases.json'];
}); });

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,7 @@ exec 3>&1
# See if stdout is a terminal # See if stdout is a terminal
if [ -t 1 ] && command -v tput > /dev/null; 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 || echo 0)
if [ -n "$ncolors" ] && [ $ncolors -ge 8 ]; then if [ -n "$ncolors" ] && [ $ncolors -ge 8 ]; then
bold="$(tput bold || echo)" bold="$(tput bold || echo)"
normal="$(tput sgr0 || echo)" normal="$(tput sgr0 || echo)"
@ -40,7 +40,7 @@ if [ -t 1 ] && command -v tput > /dev/null; then
fi fi
say_warning() { say_warning() {
printf "%b\n" "${yellow:-}dotnet_install: Warning: $1${normal:-}" printf "%b\n" "${yellow:-}dotnet_install: Warning: $1${normal:-}" >&3
} }
say_err() { say_err() {
@ -183,6 +183,9 @@ get_current_os_name() {
elif is_musl_based_distro; then elif is_musl_based_distro; then
echo "linux-musl" echo "linux-musl"
return 0 return 0
elif [ "$linux_platform_name" = "linux-musl" ]; then
echo "linux-musl"
return 0
else else
echo "linux" echo "linux"
return 0 return 0
@ -241,42 +244,6 @@ check_min_reqs() {
return 0 return 0
} }
check_pre_reqs() {
eval $invocation
if [ "${DOTNET_INSTALL_SKIP_PREREQS:-}" = "1" ]; then
return 0
fi
if [ "$(uname)" = "Linux" ]; then
if is_musl_based_distro; then
if ! command -v scanelf > /dev/null; then
say_warning "scanelf not found, please install pax-utils package."
return 0
fi
LDCONFIG_COMMAND="scanelf --ldpath -BF '%f'"
[ -z "$($LDCONFIG_COMMAND 2>/dev/null | grep libintl)" ] && say_warning "Unable to locate libintl. Probable prerequisite missing; install libintl (or gettext)."
else
if [ ! -x "$(command -v ldconfig)" ]; then
say_verbose "ldconfig is not in PATH, trying /sbin/ldconfig."
LDCONFIG_COMMAND="/sbin/ldconfig"
else
LDCONFIG_COMMAND="ldconfig"
fi
local librarypath=${LD_LIBRARY_PATH:-}
LDCONFIG_COMMAND="$LDCONFIG_COMMAND -NXv ${librarypath//:/ }"
fi
[ -z "$($LDCONFIG_COMMAND 2>/dev/null | grep zlib)" ] && say_warning "Unable to locate zlib. Probable prerequisite missing; install zlib."
[ -z "$($LDCONFIG_COMMAND 2>/dev/null | grep ssl)" ] && 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 lttng)" ] && say_warning "Unable to locate liblttng. Probable prerequisite missing; install libcurl."
[ -z "$($LDCONFIG_COMMAND 2>/dev/null | grep libcurl)" ] && say_warning "Unable to locate libcurl. Probable prerequisite missing; install libcurl."
fi
return 0
}
# args: # args:
# input - $1 # input - $1
to_lowercase() { to_lowercase() {
@ -332,11 +299,11 @@ get_machine_architecture() {
if command -v uname > /dev/null; then if command -v uname > /dev/null; then
CPUName=$(uname -m) CPUName=$(uname -m)
case $CPUName in case $CPUName in
armv7l) armv*l)
echo "arm" echo "arm"
return 0 return 0
;; ;;
aarch64) aarch64|arm64)
echo "arm64" echo "arm64"
return 0 return 0
;; ;;
@ -373,10 +340,103 @@ get_normalized_architecture_from_architecture() {
;; ;;
esac esac
say_err "Architecture \`$architecture\` not supported. If you think this is a bug, report it at https://github.com/dotnet/sdk/issues" say_err "Architecture \`$architecture\` not supported. If you think this is a bug, report it at https://github.com/dotnet/install-scripts/issues"
return 1 return 1
} }
# args:
# user_defined_os - $1
get_normalized_os() {
eval $invocation
local osname="$(to_lowercase "$1")"
if [ ! -z "$osname" ]; then
case "$osname" in
osx | freebsd | rhel.6 | linux-musl | linux)
echo "$osname"
return 0
;;
*)
say_err "'$user_defined_os' is not a supported value for --os option, supported values are: osx, linux, linux-musl, freebsd, rhel.6. If you think this is a bug, report it at https://github.com/dotnet/install-scripts/issues."
return 1
;;
esac
else
osname="$(get_current_os_name)" || return 1
fi
echo "$osname"
return 0
}
# args:
# quality - $1
get_normalized_quality() {
eval $invocation
local quality="$(to_lowercase "$1")"
if [ ! -z "$quality" ]; then
case "$quality" in
daily | signed | validated | preview)
echo "$quality"
return 0
;;
ga)
#ga quality is available without specifying quality, so normalizing it to empty
return 0
;;
*)
say_err "'$quality' is not a supported value for --quality option. Supported values are: daily, signed, validated, preview, ga. If you think this is a bug, report it at https://github.com/dotnet/install-scripts/issues."
return 1
;;
esac
fi
return 0
}
# args:
# channel - $1
get_normalized_channel() {
eval $invocation
local channel="$(to_lowercase "$1")"
if [[ $channel == release/* ]]; then
say_warning 'Using branch name with -Channel option is no longer supported with newer releases. Use -Quality option with a channel in X.Y format instead.';
fi
if [ ! -z "$channel" ]; then
case "$channel" in
lts)
echo "LTS"
return 0
;;
*)
echo "$channel"
return 0
;;
esac
fi
return 0
}
# args:
# runtime - $1
get_normalized_product() {
eval $invocation
local runtime="$(to_lowercase "$1")"
if [[ "$runtime" == "dotnet" ]]; then
product="dotnet-runtime"
elif [[ "$runtime" == "aspnetcore" ]]; then
product="aspnetcore-runtime"
elif [ -z "$runtime" ]; then
product="dotnet-sdk"
fi
echo "$product"
return 0
}
# The version text returned from the feeds is a 1-line or 2-line string: # The version text returned from the feeds is a 1-line or 2-line string:
# For the SDK and the dotnet runtime (2 lines): # For the SDK and the dotnet runtime (2 lines):
# Line 1: # commit_hash # Line 1: # commit_hash
@ -418,14 +478,12 @@ 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 version_file_url=null local version_file_url=null
if [[ "$runtime" == "dotnet" ]]; then if [[ "$runtime" == "dotnet" ]]; then
@ -433,11 +491,7 @@ get_latest_version_info() {
elif [[ "$runtime" == "aspnetcore" ]]; then elif [[ "$runtime" == "aspnetcore" ]]; then
version_file_url="$uncached_feed/aspnetcore/Runtime/$channel/latest.version" version_file_url="$uncached_feed/aspnetcore/Runtime/$channel/latest.version"
elif [ -z "$runtime" ]; then elif [ -z "$runtime" ]; then
if [ "$coherent" = true ]; then
version_file_url="$uncached_feed/Sdk/$channel/latest.coherent.version"
else
version_file_url="$uncached_feed/Sdk/$channel/latest.version" version_file_url="$uncached_feed/Sdk/$channel/latest.version"
fi
else else
say_err "Invalid value for \$runtime" say_err "Invalid value for \$runtime"
return 1 return 1
@ -468,7 +522,6 @@ parse_jsonfile_for_version() {
sdk_list=$(echo $sdk_section | awk -F"[{}]" '{print $2}') sdk_list=$(echo $sdk_section | awk -F"[{}]" '{print $2}')
sdk_list=${sdk_list//[\" ]/} sdk_list=${sdk_list//[\" ]/}
sdk_list=${sdk_list//,/$'\n'} sdk_list=${sdk_list//,/$'\n'}
sdk_list="$(echo -e "${sdk_list}" | tr -d '[[:space:]]')"
local version_info="" local version_info=""
while read -r line; do while read -r line; do
@ -505,26 +558,16 @@ get_specific_version_from_version() {
local json_file="$5" local json_file="$5"
if [ -z "$json_file" ]; then if [ -z "$json_file" ]; then
case "$version" in if [[ "$version" == "latest" ]]; then
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
;; else
coherent)
local version_info
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"
echo "$version_info" | get_version_from_version_info
return 0
;;
*)
echo "$version" echo "$version"
return 0 return 0
;; fi
esac
else else
local version_info local version_info
version_info="$(parse_jsonfile_for_version "$json_file")" || return 1 version_info="$(parse_jsonfile_for_version "$json_file")" || return 1
@ -538,6 +581,7 @@ get_specific_version_from_version() {
# channel - $2 # channel - $2
# normalized_architecture - $3 # normalized_architecture - $3
# specific_version - $4 # specific_version - $4
# normalized_os - $5
construct_download_link() { construct_download_link() {
eval $invocation eval $invocation
@ -545,17 +589,16 @@ construct_download_link() {
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 specific_product_version="$(get_specific_product_version "$1" "$4")"
local osname local osname="$5"
osname="$(get_current_os_name)" || return 1
local download_link=null local download_link=null
if [[ "$runtime" == "dotnet" ]]; 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_product_version-$osname-$normalized_architecture.tar.gz"
elif [[ "$runtime" == "aspnetcore" ]]; then elif [[ "$runtime" == "aspnetcore" ]]; then
download_link="$azure_feed/aspnetcore/Runtime/$specific_version/aspnetcore-runtime-$specific_version-$osname-$normalized_architecture.tar.gz" download_link="$azure_feed/aspnetcore/Runtime/$specific_version/aspnetcore-runtime-$specific_product_version-$osname-$normalized_architecture.tar.gz"
elif [ -z "$runtime" ]; then 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_product_version-$osname-$normalized_architecture.tar.gz"
else else
return 1 return 1
fi fi
@ -564,6 +607,138 @@ construct_download_link() {
return 0 return 0
} }
# args:
# azure_feed - $1
# specific_version - $2
# download link - $3 (optional)
get_specific_product_version() {
# If we find a 'productVersion.txt' at the root of any folder, we'll use its contents
# to resolve the version of what's in the folder, superseding the specified version.
# if 'productVersion.txt' is missing but download link is already available, product version will be taken from download link
eval $invocation
local azure_feed="$1"
local specific_version="${2//[$'\t\r\n']}"
local package_download_link=""
if [ $# -gt 2 ]; then
local package_download_link="$3"
fi
local specific_product_version=null
# Try to get the version number, using the productVersion.txt file located next to the installer file.
local download_links=($(get_specific_product_version_url "$azure_feed" "$specific_version" true "$package_download_link")
$(get_specific_product_version_url "$azure_feed" "$specific_version" false "$package_download_link"))
for download_link in "${download_links[@]}"
do
say_verbose "Checking for the existence of $download_link"
if machine_has "curl"
then
specific_product_version=$(curl -s --fail "${download_link}${feed_credential}")
if [ $? = 0 ]; then
echo "${specific_product_version//[$'\t\r\n']}"
return 0
fi
elif machine_has "wget"
then
specific_product_version=$(wget -qO- "${download_link}${feed_credential}")
if [ $? = 0 ]; then
echo "${specific_product_version//[$'\t\r\n']}"
return 0
fi
fi
done
# Getting the version number with productVersion.txt has failed. Try parsing the download link for a version number.
say_verbose "Failed to get the version using productVersion.txt file. Download link will be parsed instead."
specific_product_version="$(get_product_specific_version_from_download_link "$package_download_link" "$specific_version")"
echo "${specific_product_version//[$'\t\r\n']}"
return 0
}
# args:
# azure_feed - $1
# specific_version - $2
# is_flattened - $3
# download link - $4 (optional)
get_specific_product_version_url() {
eval $invocation
local azure_feed="$1"
local specific_version="$2"
local is_flattened="$3"
local package_download_link=""
if [ $# -gt 3 ]; then
local package_download_link="$4"
fi
local pvFileName="productVersion.txt"
if [ "$is_flattened" = true ]; then
if [ -z "$runtime" ]; then
pvFileName="sdk-productVersion.txt"
elif [[ "$runtime" == "dotnet" ]]; then
pvFileName="runtime-productVersion.txt"
else
pvFileName="$runtime-productVersion.txt"
fi
fi
local download_link=null
if [ -z "$package_download_link" ]; then
if [[ "$runtime" == "dotnet" ]]; then
download_link="$azure_feed/Runtime/$specific_version/${pvFileName}"
elif [[ "$runtime" == "aspnetcore" ]]; then
download_link="$azure_feed/aspnetcore/Runtime/$specific_version/${pvFileName}"
elif [ -z "$runtime" ]; then
download_link="$azure_feed/Sdk/$specific_version/${pvFileName}"
else
return 1
fi
else
download_link="${package_download_link%/*}/${pvFileName}"
fi
say_verbose "Constructed productVersion link: $download_link"
echo "$download_link"
return 0
}
# args:
# download link - $1
# specific version - $2
get_product_specific_version_from_download_link()
{
eval $invocation
local download_link="$1"
local specific_version="$2"
local specific_product_version=""
if [ -z "$download_link" ]; then
echo "$specific_version"
return 0
fi
#get filename
filename="${download_link##*/}"
#product specific version follows the product name
#for filename 'dotnet-sdk-3.1.404-linux-x64.tar.gz': the product version is 3.1.404
IFS='-'
read -ra filename_elems <<< "$filename"
count=${#filename_elems[@]}
if [[ "$count" -gt 2 ]]; then
specific_product_version="${filename_elems[2]}"
else
specific_product_version=$specific_version
fi
unset IFS;
echo "$specific_product_version"
return 0
}
# args: # args:
# azure_feed - $1 # azure_feed - $1
# channel - $2 # channel - $2
@ -684,11 +859,74 @@ extract_dotnet_package() {
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" 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"
rm -f "$zip_path" && say_verbose "Temporary zip file $zip_path was removed"
if [ "$failed" = true ]; then if [ "$failed" = true ]; then
say_err "Extraction failed" say_err "Extraction failed"
return 1 return 1
fi fi
return 0
}
# args:
# remote_path - $1
# disable_feed_credential - $2
get_http_header()
{
eval $invocation
local remote_path="$1"
local disable_feed_credential="$2"
local failed=false
local response
if machine_has "curl"; then
get_http_header_curl $remote_path $disable_feed_credential || failed=true
elif machine_has "wget"; then
get_http_header_wget $remote_path $disable_feed_credential || failed=true
else
failed=true
fi
if [ "$failed" = true ]; then
say_verbose "Failed to get HTTP header: '$remote_path'."
return 1
fi
return 0
}
# args:
# remote_path - $1
# disable_feed_credential - $2
get_http_header_curl() {
eval $invocation
local remote_path="$1"
local disable_feed_credential="$2"
remote_path_with_credential="$remote_path"
if [ "$disable_feed_credential" = false ]; then
remote_path_with_credential+="$feed_credential"
fi
curl_options="-I -sSL --retry 5 --retry-delay 2 --connect-timeout 15 "
curl $curl_options "$remote_path_with_credential" || return 1
return 0
}
# args:
# remote_path - $1
# disable_feed_credential - $2
get_http_header_wget() {
eval $invocation
local remote_path="$1"
local disable_feed_credential="$2"
remote_path_with_credential="$remote_path"
if [ "$disable_feed_credential" = false ]; then
remote_path_with_credential+="$feed_credential"
fi
wget_options="-q -S --spider --tries 5 --waitretry 2 --connect-timeout 15 "
wget $wget_options "$remote_path_with_credential" 2>&1 || return 1
return 0
} }
# args: # args:
@ -706,13 +944,30 @@ download() {
fi fi
local failed=false local failed=false
local attempts=0
while [ $attempts -lt 3 ]; do
attempts=$((attempts+1))
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 say_err "Missing dependency: neither curl nor wget was found."
exit 1
fi fi
if [ "$failed" = false ] || [ $attempts -ge 3 ] || { [ ! -z $http_code ] && [ $http_code = "404" ]; }; then
break
fi
say "Download attempt #$attempts has failed: $http_code $download_error_msg"
say "Attempt #$((attempts+1)) will start in $((attempts*10)) seconds."
sleep $((attempts*10))
done
if [ "$failed" = true ]; then if [ "$failed" = true ]; then
say_verbose "Download failed: $remote_path" say_verbose "Download failed: $remote_path"
return 1 return 1
@ -720,64 +975,187 @@ download() {
return 0 return 0
} }
# Updates global variables $http_code and $download_error_msg
downloadcurl() { downloadcurl() {
eval $invocation eval $invocation
unset http_code
unset download_error_msg
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 # Append feed_credential as late as possible before calling curl to avoid logging feed_credential
remote_path="${remote_path}${feed_credential}" # Avoid passing URI with credentials to functions: note, most of them echoing parameters of invocation in verbose output.
local remote_path_with_credential="${remote_path}${feed_credential}"
local curl_options="--retry 20 --retry-delay 2 --connect-timeout 15 -sSL -f --create-dirs " local curl_options="--retry 20 --retry-delay 2 --connect-timeout 15 -sSL -f --create-dirs "
local failed=false local failed=false
if [ -z "$out_path" ]; then if [ -z "$out_path" ]; then
curl $curl_options "$remote_path" || failed=true curl $curl_options "$remote_path_with_credential" || failed=true
else else
curl $curl_options -o "$out_path" "$remote_path" || failed=true curl $curl_options -o "$out_path" "$remote_path_with_credential" || failed=true
fi fi
if [ "$failed" = true ]; then if [ "$failed" = true ]; then
say_verbose "Curl download failed" local disable_feed_credential=false
local response=$(get_http_header_curl $remote_path $disable_feed_credential)
http_code=$( echo "$response" | awk '/^HTTP/{print $2}' | tail -1 )
download_error_msg="Unable to download $remote_path."
if [[ $http_code != 2* ]]; then
download_error_msg+=" Returned HTTP status code: $http_code."
fi
say_verbose "$download_error_msg"
return 1 return 1
fi fi
return 0 return 0
} }
# Updates global variables $http_code and $download_error_msg
downloadwget() { downloadwget() {
eval $invocation eval $invocation
unset http_code
unset download_error_msg
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 # Append feed_credential as late as possible before calling wget to avoid logging feed_credential
remote_path="${remote_path}${feed_credential}" local remote_path_with_credential="${remote_path}${feed_credential}"
local wget_options="--tries 20 --waitretry 2 --connect-timeout 15 " local wget_options="--tries 20 --waitretry 2 --connect-timeout 15 "
local failed=false local failed=false
if [ -z "$out_path" ]; then if [ -z "$out_path" ]; then
wget -q $wget_options -O - "$remote_path" || failed=true wget -q $wget_options -O - "$remote_path_with_credential" || failed=true
else else
wget $wget_options -O "$out_path" "$remote_path" || failed=true wget $wget_options -O "$out_path" "$remote_path_with_credential" || failed=true
fi fi
if [ "$failed" = true ]; then if [ "$failed" = true ]; then
say_verbose "Wget download failed" local disable_feed_credential=false
local response=$(get_http_header_wget $remote_path $disable_feed_credential)
http_code=$( echo "$response" | awk '/^ HTTP/{print $2}' | tail -1 )
download_error_msg="Unable to download $remote_path."
if [[ $http_code != 2* ]]; then
download_error_msg+=" Returned HTTP status code: $http_code."
fi
say_verbose "$download_error_msg"
return 1 return 1
fi fi
return 0 return 0
} }
get_download_link_from_aka_ms() {
eval $invocation
#quality is not supported for LTS or current channel
if [[ ! -z "$normalized_quality" && ("$normalized_channel" == "LTS" || "$normalized_channel" == "current") ]]; then
normalized_quality=""
say_warning "Specifying quality for current or LTS channel is not supported, the quality will be ignored."
fi
say_verbose "Retrieving primary payload URL from aka.ms for channel: '$normalized_channel', quality: '$normalized_quality', product: '$normalized_product', os: '$normalized_os', architecture: '$normalized_architecture'."
#construct aka.ms link
aka_ms_link="https://aka.ms/dotnet"
if [ "$internal" = true ]; then
aka_ms_link="$aka_ms_link/internal"
fi
aka_ms_link="$aka_ms_link/$normalized_channel"
if [[ ! -z "$normalized_quality" ]]; then
aka_ms_link="$aka_ms_link/$normalized_quality"
fi
aka_ms_link="$aka_ms_link/$normalized_product-$normalized_os-$normalized_architecture.tar.gz"
say_verbose "Constructed aka.ms link: '$aka_ms_link'."
#get HTTP response
#do not pass credentials as a part of the $aka_ms_link and do not apply credentials in the get_http_header function
#otherwise the redirect link would have credentials as well
#it would result in applying credentials twice to the resulting link and thus breaking it, and in echoing credentials to the output as a part of redirect link
disable_feed_credential=true
response="$(get_http_header $aka_ms_link $disable_feed_credential)"
say_verbose "Received response: $response"
# Get results of all the redirects.
http_codes=$( echo "$response" | awk '$1 ~ /^HTTP/ {print $2}' )
# They all need to be 301, otherwise some links are broken (except for the last, which is not a redirect but 200 or 404).
broken_redirects=$( echo "$http_codes" | sed '$d' | grep -v '301' )
# All HTTP codes are 301 (Moved Permanently), the redirect link exists.
if [[ -z "$broken_redirects" ]]; then
aka_ms_download_link=$( echo "$response" | awk '$1 ~ /^Location/{print $2}' | tail -1 | tr -d '\r')
if [[ -z "$aka_ms_download_link" ]]; then
say_verbose "The aka.ms link '$aka_ms_link' is not valid: failed to get redirect location."
return 1
fi
say_verbose "The redirect location retrieved: '$aka_ms_download_link'."
return 0
else
say_verbose "The aka.ms link '$aka_ms_link' is not valid: received HTTP code: $(echo "$broken_redirects" | paste -sd "," -)."
return 1
fi
}
calculate_vars() { calculate_vars() {
eval $invocation eval $invocation
valid_legacy_download_link=true valid_legacy_download_link=true
#normalize input variables
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'."
normalized_os="$(get_normalized_os "$user_defined_os")"
say_verbose "Normalized OS: '$normalized_os'."
normalized_quality="$(get_normalized_quality "$quality")"
say_verbose "Normalized quality: '$normalized_quality'."
normalized_channel="$(get_normalized_channel "$channel")"
say_verbose "Normalized channel: '$normalized_channel'."
normalized_product="$(get_normalized_product "$runtime")"
say_verbose "Normalized product: '$normalized_product'."
#try to get download location from aka.ms link
#not applicable when exact version is specified via command or json file
normalized_version="$(to_lowercase "$version")"
if [[ -z "$json_file" && "$normalized_version" == "latest" ]]; then
valid_aka_ms_link=true;
get_download_link_from_aka_ms || valid_aka_ms_link=false
if [ "$valid_aka_ms_link" == false ]; then
# if quality is specified - exit with error - there is no fallback approach
if [ ! -z "$normalized_quality" ]; then
say_err "Failed to locate the latest version in the channel '$normalized_channel' with '$normalized_quality' quality for '$normalized_product', os: '$normalized_os', architecture: '$normalized_architecture'."
say_err "Refer to: https://aka.ms/dotnet-os-lifecycle for information on .NET Core support."
return 1
fi
say_verbose "Falling back to latest.version file approach."
else
say_verbose "Retrieved primary payload URL from aka.ms link: '$aka_ms_download_link'."
download_link=$aka_ms_download_link
say_verbose "Downloading using legacy url will not be attempted."
valid_legacy_download_link=false
#get version from the path
IFS='/'
read -ra pathElems <<< "$download_link"
count=${#pathElems[@]}
specific_version="${pathElems[count-2]}"
unset IFS;
say_verbose "Version: '$specific_version'."
#Retrieve product specific version
specific_product_version="$(get_specific_product_version "$azure_feed" "$specific_version" "$download_link")"
say_verbose "Product specific version: '$specific_product_version'."
install_root="$(resolve_installation_path "$install_dir")"
say_verbose "InstallRoot: '$install_root'."
return
fi
fi
specific_version="$(get_specific_version_from_version "$azure_feed" "$channel" "$normalized_architecture" "$version" "$json_file")" specific_version="$(get_specific_version_from_version "$azure_feed" "$channel" "$normalized_architecture" "$version" "$json_file")"
specific_product_version="$(get_specific_product_version "$azure_feed" "$specific_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 resolve 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" "$normalized_os")"
say_verbose "Constructed primary named payload URL: $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
@ -822,38 +1200,74 @@ install_dotnet() {
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"
# Failures are normal in the non-legacy case for ultimately legacy downloads. # 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. # Do not output to stderr, since output to stderr is considered an error.
say "Downloading primary link $download_link"
# The download function will set variables $http_code and $download_error_msg in case of failure.
download "$download_link" "$zip_path" 2>&1 || download_failed=true 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 ]; then if [ "$download_failed" = true ]; then
say "Cannot download: $download_link" primary_path_http_code="$http_code"; primary_path_download_error_msg="$download_error_msg"
case $primary_path_http_code in
404)
say "The resource at $download_link is not available."
;;
*)
say "$primary_path_download_error_msg"
;;
esac
rm -f "$zip_path" 2>&1 && say_verbose "Temporary zip file $zip_path was removed"
if [ "$valid_legacy_download_link" = true ]; then if [ "$valid_legacy_download_link" = true ]; then
download_failed=false download_failed=false
download_link="$legacy_download_link" download_link="$legacy_download_link"
zip_path="$(mktemp "$temporary_file_template")" zip_path="$(mktemp "$temporary_file_template")"
say_verbose "Legacy zip path: $zip_path" say_verbose "Legacy zip path: $zip_path"
say "Downloading legacy link: $download_link"
say "Downloading legacy link $download_link"
# The download function will set variables $http_code and $download_error_msg in case of failure.
download "$download_link" "$zip_path" 2>&1 || download_failed=true download "$download_link" "$zip_path" 2>&1 || download_failed=true
if [ "$download_failed" = true ]; then if [ "$download_failed" = true ]; then
say "Cannot download: $download_link" legacy_path_http_code="$http_code"; legacy_path_download_error_msg="$download_error_msg"
case $legacy_path_http_code in
404)
say "The resource at $download_link is not available."
;;
*)
say "$legacy_path_download_error_msg"
;;
esac
rm -f "$zip_path" 2>&1 && say_verbose "Temporary zip file $zip_path was removed"
fi fi
fi fi
fi fi
if [ "$download_failed" = true ]; then if [ "$download_failed" = true ]; then
say_err "Could not find/download: \`$asset_name\` with version = $specific_version" if [[ "$primary_path_http_code" = "404" && ( "$valid_legacy_download_link" = false || "$legacy_path_http_code" = "404") ]]; then
say_err "Could not find \`$asset_name\` with version = $specific_version"
say_err "Refer to: https://aka.ms/dotnet-os-lifecycle for information on .NET Core support" say_err "Refer to: https://aka.ms/dotnet-os-lifecycle for information on .NET Core support"
else
say_err "Could not download: \`$asset_name\` with version = $specific_version"
# 404-NotFound is an expected response if it goes from only one of the links, do not show that error.
# If primary path is available (not 404-NotFound) then show the primary error else show the legacy error.
if [ "$primary_path_http_code" != "404" ]; then
say_err "$primary_path_download_error_msg"
return 1
fi
if [[ "$valid_legacy_download_link" = true && "$legacy_path_http_code" != "404" ]]; then
say_err "$legacy_path_download_error_msg"
return 1
fi
fi
return 1 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" || return 1
# Check if the SDK version is installed; if not, fail the installation. # Check if the SDK version is installed; if not, fail the installation.
# if the version contains "RTM" or "servicing"; check if a 'release-type' SDK version is installed. # if the version contains "RTM" or "servicing"; check if a 'release-type' SDK version is installed.
@ -869,12 +1283,14 @@ install_dotnet() {
fi fi
# Check if the standard SDK version is installed. # Check if the standard SDK version is installed.
say_verbose "Checking installation: version = $specific_version" say_verbose "Checking installation: version = $specific_product_version"
if is_dotnet_package_installed "$install_root" "$asset_relative_path" "$specific_version"; then if is_dotnet_package_installed "$install_root" "$asset_relative_path" "$specific_product_version"; then
return 0 return 0
fi fi
say_err "\`$asset_name\` with version = $specific_version failed to install with an unknown error." # Version verification failed. More likely something is wrong either with the downloaded content or with the verification algorithm.
say_err "Failed to verify the version of installed \`$asset_name\`.\nInstallation source: $download_link.\nInstallation location: $install_root.\nReport the bug at https://github.com/dotnet/install-scripts/issues."
say_err "\`$asset_name\` with version = $specific_product_version failed to install with an unknown error."
return 1 return 1
} }
@ -898,8 +1314,11 @@ feed_credential=""
verbose=false verbose=false
runtime="" runtime=""
runtime_id="" runtime_id=""
quality=""
internal=false
override_non_versioned_files=true override_non_versioned_files=true
non_dynamic_parameters="" non_dynamic_parameters=""
user_defined_os=""
while [ $# -ne 0 ] while [ $# -ne 0 ]
do do
@ -913,6 +1332,14 @@ do
shift shift
version="$1" version="$1"
;; ;;
-q|--quality|-[Qq]uality)
shift
quality="$1"
;;
--internal|-[Ii]nternal)
internal=true
non_dynamic_parameters+=" $name"
;;
-i|--install-dir|-[Ii]nstall[Dd]ir) -i|--install-dir|-[Ii]nstall[Dd]ir)
shift shift
install_dir="$1" install_dir="$1"
@ -921,6 +1348,10 @@ do
shift shift
architecture="$1" architecture="$1"
;; ;;
--os|-[Oo][SS])
shift
user_defined_os="$1"
;;
--shared-runtime|-[Ss]hared[Rr]untime) --shared-runtime|-[Ss]hared[Rr]untime)
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'." 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 if [ -z "$runtime" ]; then
@ -966,12 +1397,15 @@ do
--feed-credential|-[Ff]eed[Cc]redential) --feed-credential|-[Ff]eed[Cc]redential)
shift shift
feed_credential="$1" feed_credential="$1"
non_dynamic_parameters+=" $name "\""$1"\""" #feed_credential should start with "?", for it to be added to the end of the link.
#adding "?" at the beginning of the feed_credential if needed.
[[ -z "$(echo $feed_credential)" ]] || [[ $feed_credential == \?* ]] || feed_credential="?$feed_credential"
;; ;;
--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"\""" non_dynamic_parameters+=" $name "\""$1"\"""
say_warning "Use of --runtime-id is obsolete and should be limited to the versions below 2.1. To override architecture, use --architecture option instead. To override OS, use --os option instead."
;; ;;
--jsonfile|-[Jj][Ss]on[Ff]ile) --jsonfile|-[Jj][Ss]on[Ff]ile)
shift shift
@ -997,22 +1431,36 @@ do
echo " - LTS - most current supported release" echo " - LTS - most current supported release"
echo " - 2-part version in a format A.B - represents a specific release" echo " - 2-part version in a format A.B - represents a specific release"
echo " examples: 2.0; 1.0" echo " examples: 2.0; 1.0"
echo " - Branch name" echo " - 3-part version in a format A.B.Cxx - represents a specific SDK release"
echo " examples: release/2.0.0; Master" echo " examples: 5.0.1xx, 5.0.2xx."
echo " Note: The version parameter overrides the channel parameter." echo " Supported since 5.0 release"
echo " Note: The version parameter overrides the channel parameter when any version other than `latest` is used."
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:"
echo " - latest - most latest build on specific channel" echo " - latest - most latest build on specific channel"
echo " - coherent - most latest coherent build on specific channel"
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 " -q,--quality <quality> Download the latest build of specified quality in the channel."
echo " -Quality"
echo " The possible values are: daily, signed, validated, preview, GA."
echo " Works only in combination with channel. Not applicable for current and LTS channels and will be ignored if those channels are used."
echo " For SDK use channel in A.B.Cxx format. Using quality for SDK together with channel in A.B format is not supported."
echo " Supported since 5.0 release."
echo " Note: The version parameter overrides the channel parameter when any version other than `latest` is used, and therefore overrides the quality."
echo " --internal,-Internal Download internal builds. Requires providing credentials via --feed-credential parameter."
echo " --feed-credential <FEEDCREDENTIAL> Token to access Azure feed. Used as a query string to append to the Azure feed."
echo " -FeedCredential This parameter typically is not specified."
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 dotnet binaries to be installed, Defaults to \`$architecture\`." echo " --architecture <ARCHITECTURE> Architecture of dotnet binaries to be installed, Defaults to \`$architecture\`."
echo " --arch,-Architecture,-Arch" echo " --arch,-Architecture,-Arch"
echo " Possible values: x64, arm, and arm64" echo " Possible values: x64, arm, and arm64"
echo " --os <system> Specifies operating system to be used when selecting the installer."
echo " Overrides the OS determination approach used by the script. Supported values: osx, linux, linux-musl, freebsd, rhel.6."
echo " In case any other value is provided, the platform will be determined by the script based on machine configuration."
echo " Not supported for legacy links. Use --runtime-id to specify platform for legacy links."
echo " Refer to: https://aka.ms/dotnet-os-lifecycle for more information."
echo " --runtime <RUNTIME> Installs a shared runtime only, without the SDK." echo " --runtime <RUNTIME> Installs a shared runtime only, without the SDK."
echo " -Runtime" echo " -Runtime"
echo " Possible values:" echo " Possible values:"
@ -1023,20 +1471,20 @@ do
echo " --verbose,-Verbose Display diagnostics information." 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 " --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 " --uncached-feed,-UncachedFeed Uncached feed location. This parameter typically is not changed by the user."
echo " --feed-credential,-FeedCredential Azure feed shared access token. This parameter typically is not specified."
echo " --skip-non-versioned-files Skips non-versioned files if they already exist, such as the dotnet executable." echo " --skip-non-versioned-files Skips non-versioned files if they already exist, such as the dotnet executable."
echo " -SkipNonVersionedFiles" echo " -SkipNonVersionedFiles"
echo " --no-cdn,-NoCdn Disable downloading from the Azure CDN, and use the uncached feed directly." echo " --no-cdn,-NoCdn Disable downloading from the Azure CDN, and use the uncached feed directly."
echo " --jsonfile <JSONFILE> Determines the SDK version from a user specified global.json file." echo " --jsonfile <JSONFILE> Determines the SDK version from a user specified global.json file."
echo " Note: global.json must have a value for 'SDK:Version'" echo " Note: global.json must have a value for 'SDK:Version'"
echo " --runtime-id Installs the .NET Tools for the given platform (use linux-x64 for portable linux)."
echo " -RuntimeId"
echo " -?,--?,-h,--help,-Help Shows this help message" echo " -?,--?,-h,--help,-Help Shows this help message"
echo "" echo ""
echo "Obsolete parameters:" echo "Obsolete parameters:"
echo " --shared-runtime The recommended alternative is '--runtime dotnet'." echo " --shared-runtime The recommended alternative is '--runtime dotnet'."
echo " This parameter is obsolete and may be removed in a future version of this script." echo " This parameter is obsolete and may be removed in a future version of this script."
echo " Installs just the shared runtime bits, not the entire SDK." echo " Installs just the shared runtime bits, not the entire SDK."
echo " --runtime-id Installs the .NET Tools for the given platform (use linux-x64 for portable linux)."
echo " -RuntimeId" The parameter is obsolete and may be removed in a future version of this script. Should be used only for versions below 2.1.
echo " For primary links to override OS or/and architecture, use --os and --architecture option instead."
echo "" echo ""
echo "Install Location:" echo "Install Location:"
echo " Location is chosen in following order:" echo " Location is chosen in following order:"
@ -1058,28 +1506,53 @@ if [ "$no_cdn" = true ]; then
azure_feed="$uncached_feed" azure_feed="$uncached_feed"
fi fi
say "Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:"
say "- The SDK needs to be installed without user interaction and without admin rights."
say "- The SDK installation doesn't need to persist across multiple CI runs."
say "To set up a development environment or to run apps, use installers rather than this script. Visit https://dotnet.microsoft.com/download to get the installer.\n"
if [ "$internal" = true ] && [ -z "$(echo $feed_credential)" ]; then
message="Provide credentials via --feed-credential parameter."
if [ "$dry_run" = true ]; then
say_warning "$message"
else
say_err "$message"
exit 1
fi
fi
check_min_reqs check_min_reqs
calculate_vars calculate_vars
script_name=$(basename "$0") script_name=$(basename "$0")
if [ "$dry_run" = true ]; then if [ "$dry_run" = true ]; then
say "Payload URLs:" say "Payload URLs:"
say "Primary named payload URL: $download_link" say "Primary named payload URL: ${download_link}"
if [ "$valid_legacy_download_link" = true ]; then if [ "$valid_legacy_download_link" = true ]; then
say "Legacy named payload URL: $legacy_download_link" say "Legacy named payload URL: ${legacy_download_link}"
fi fi
repeatable_command="./$script_name --version "\""$specific_version"\"" --install-dir "\""$install_root"\"" --architecture "\""$normalized_architecture"\""" repeatable_command="./$script_name --version "\""$specific_version"\"" --install-dir "\""$install_root"\"" --architecture "\""$normalized_architecture"\"" --os "\""$normalized_os"\"""
if [ ! -z "$normalized_quality" ]; then
repeatable_command+=" --quality "\""$normalized_quality"\"""
fi
if [[ "$runtime" == "dotnet" ]]; then if [[ "$runtime" == "dotnet" ]]; then
repeatable_command+=" --runtime "\""dotnet"\""" repeatable_command+=" --runtime "\""dotnet"\"""
elif [[ "$runtime" == "aspnetcore" ]]; then elif [[ "$runtime" == "aspnetcore" ]]; then
repeatable_command+=" --runtime "\""aspnetcore"\""" repeatable_command+=" --runtime "\""aspnetcore"\"""
fi fi
repeatable_command+="$non_dynamic_parameters" repeatable_command+="$non_dynamic_parameters"
if [ -n "$feed_credential" ]; then
repeatable_command+=" --feed-credential "\""<feed_credential>"\"""
fi
say "Repeatable invocation: $repeatable_command" say "Repeatable invocation: $repeatable_command"
exit 0 exit 0
fi fi
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")")"
@ -1090,4 +1563,6 @@ else
say "Binaries of dotnet can be found in $bin_path" say "Binaries of dotnet can be found in $bin_path"
fi fi
say "Note that the script does not resolve dependencies during installation."
say "To check the list of dependencies, go to https://docs.microsoft.com/dotnet/core/install, select your operating system and check the \"Dependencies\" section."
say "Installation finished successfully." say "Installation finished successfully."

6
package-lock.json generated
View File

@ -5347,9 +5347,9 @@
"dev": true "dev": true
}, },
"y18n": { "y18n": {
"version": "4.0.0", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz",
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==",
"dev": true "dev": true
}, },
"yallist": { "yallist": {

View File

@ -13,7 +13,9 @@ export function configAuthentication(
) { ) {
const existingNuGetConfig: string = path.resolve( const existingNuGetConfig: string = path.resolve(
processRoot, processRoot,
existingFileLocation == '' ? 'nuget.config' : existingFileLocation existingFileLocation === ''
? getExistingNugetConfig(processRoot)
: existingFileLocation
); );
const tempNuGetConfig: string = path.resolve( const tempNuGetConfig: string = path.resolve(
@ -25,6 +27,21 @@ export function configAuthentication(
writeFeedToFile(feedUrl, existingNuGetConfig, tempNuGetConfig); writeFeedToFile(feedUrl, existingNuGetConfig, tempNuGetConfig);
} }
function isValidKey(key: string): boolean {
return /^[\w\-\.]+$/i.test(key);
}
function getExistingNugetConfig(processRoot: string) {
const defaultConfigName = 'nuget.config';
const configFileNames = fs
.readdirSync(processRoot)
.filter(filename => filename.toLowerCase() === defaultConfigName);
if (configFileNames.length) {
return configFileNames[0];
}
return defaultConfigName;
}
function writeFeedToFile( function writeFeedToFile(
feedUrl: string, feedUrl: string,
existingFileLocation: string, existingFileLocation: string,
@ -109,9 +126,9 @@ function writeFeedToFile(
xml = xml.ele('packageSourceCredentials'); xml = xml.ele('packageSourceCredentials');
sourceKeys.forEach(key => { sourceKeys.forEach(key => {
if (key.indexOf(' ') > -1) { if (!isValidKey(key)) {
throw new Error( throw new Error(
"This action currently can't handle source names with spaces. Remove the space from your repo's NuGet.config and try again." "Source name can contain letters, numbers, and '-', '_', '.' symbols only. Please, fix source name in NuGet.config and try again."
); );
} }

View File

@ -29,8 +29,7 @@ export class DotNetVersionInfo {
return; return;
} }
//Note: No support for previews when using generic const parts: string[] = version.split('.');
let parts: string[] = version.split('.');
if (parts.length < 2 || parts.length > 3) this.throwInvalidVersionFormat(); if (parts.length < 2 || parts.length > 3) this.throwInvalidVersionFormat();
@ -38,8 +37,10 @@ export class DotNetVersionInfo {
this.throwInvalidVersionFormat(); this.throwInvalidVersionFormat();
} }
let major = this.getVersionNumberOrThrow(parts[0]); const major = this.getVersionNumberOrThrow(parts[0]);
let minor = this.getVersionNumberOrThrow(parts[1]); const minor = ['x', '*'].includes(parts[1])
? parts[1]
: this.getVersionNumberOrThrow(parts[1]);
this.fullversion = major + '.' + minor; this.fullversion = major + '.' + minor;
} }
@ -60,7 +61,9 @@ export class DotNetVersionInfo {
} }
private throwInvalidVersionFormat() { private throwInvalidVersionFormat() {
throw 'Invalid version format! Supported: 1.2.3, 1.2, 1.2.x, 1.2.*'; throw new Error(
'Invalid version format! Supported: 1.2.3, 1.2, 1.2.x, 1.2.*'
);
} }
/** /**
@ -76,8 +79,9 @@ export class DotNetVersionInfo {
} }
export class DotnetCoreInstaller { export class DotnetCoreInstaller {
constructor(version: string) { constructor(version: string, includePrerelease: boolean = false) {
this.version = version; this.version = version;
this.includePrerelease = includePrerelease;
} }
public async installDotnet() { public async installDotnet() {
@ -187,7 +191,7 @@ export class DotnetCoreInstaller {
console.log(process.env['PATH']); console.log(process.env['PATH']);
if (resultCode != 0) { if (resultCode != 0) {
throw `Failed to install dotnet ${resultCode}. ${output}`; throw new Error(`Failed to install dotnet ${resultCode}. ${output}`);
} }
} }
@ -212,13 +216,15 @@ export class DotnetCoreInstaller {
let releasesInfo: any[] = releasesResult['releases']; let releasesInfo: any[] = releasesResult['releases'];
releasesInfo = releasesInfo.filter((releaseInfo: any) => { releasesInfo = releasesInfo.filter((releaseInfo: any) => {
return ( return (
semver.satisfies( semver.satisfies(releaseInfo['sdk']['version'], versionInfo.version(), {
releaseInfo['sdk']['version'], includePrerelease: this.includePrerelease
versionInfo.version() }) ||
) ||
semver.satisfies( semver.satisfies(
releaseInfo['sdk']['version-display'], releaseInfo['sdk']['version-display'],
versionInfo.version() versionInfo.version(),
{
includePrerelease: this.includePrerelease
}
) )
); );
}); });
@ -227,16 +233,22 @@ export class DotnetCoreInstaller {
let latestSdk: string = releasesResult['latest-sdk']; let latestSdk: string = releasesResult['latest-sdk'];
releasesInfo = releasesInfo.filter((releaseInfo: any) => releasesInfo = releasesInfo.filter((releaseInfo: any) =>
semver.lte(releaseInfo['sdk']['version'], latestSdk) semver.lte(releaseInfo['sdk']['version'], latestSdk, {
includePrerelease: this.includePrerelease
})
); );
// Sort for latest version // Sort for latest version
releasesInfo = releasesInfo.sort((a, b) => releasesInfo = releasesInfo.sort((a, b) =>
semver.rcompare(a['sdk']['version'], b['sdk']['version']) semver.rcompare(a['sdk']['version'], b['sdk']['version'], {
includePrerelease: this.includePrerelease
})
); );
if (releasesInfo.length == 0) { if (releasesInfo.length == 0) {
throw `Could not find dotnet core version. Please ensure that specified version ${versionInfo.inputVersion} is valid.`; throw new Error(
`Could not find dotnet core version. Please ensure that specified version ${versionInfo.inputVersion} is valid.`
);
} }
let release = releasesInfo[0]; let release = releasesInfo[0];
@ -264,15 +276,18 @@ export class DotnetCoreInstaller {
}); });
if (releasesInfo.length === 0) { if (releasesInfo.length === 0) {
throw `Could not find info for version ${versionParts.join( throw new Error(
`Could not find info for version ${versionParts.join(
'.' '.'
)} at ${DotNetCoreIndexUrl}`; )} at ${DotNetCoreIndexUrl}`
);
} }
return releasesInfo[0]['releases.json']; return releasesInfo[0]['releases.json'];
} }
private version: string; private version: string;
private includePrerelease: boolean;
} }
const DotNetCoreIndexUrl: string = const DotNetCoreIndexUrl: string =

View File

@ -20,7 +20,8 @@ export async function run() {
const globalJsonPath = path.join(process.cwd(), 'global.json'); const globalJsonPath = path.join(process.cwd(), 'global.json');
if (fs.existsSync(globalJsonPath)) { if (fs.existsSync(globalJsonPath)) {
const globalJson = JSON.parse( const globalJson = JSON.parse(
fs.readFileSync(globalJsonPath, {encoding: 'utf8'}) // .trim() is necessary to strip BOM https://github.com/nodejs/node/issues/20649
fs.readFileSync(globalJsonPath, {encoding: 'utf8'}).trim()
); );
if (globalJson.sdk && globalJson.sdk.version) { if (globalJson.sdk && globalJson.sdk.version) {
version = globalJson.sdk.version; version = globalJson.sdk.version;
@ -29,7 +30,14 @@ export async function run() {
} }
if (version) { if (version) {
const dotnetInstaller = new installer.DotnetCoreInstaller(version); const includePrerelease: boolean =
(core.getInput('include-prerelease') || 'false').toLowerCase() ===
'true';
const dotnetInstaller = new installer.DotnetCoreInstaller(
version,
includePrerelease
);
await dotnetInstaller.installDotnet(); await dotnetInstaller.installDotnet();
} }