You've already forked setup-dotnet
mirror of
https://github.com/actions/setup-dotnet.git
synced 2025-07-17 12:30:40 +07:00
Compare commits
107 Commits
v3.0.1
...
tool-confi
Author | SHA1 | Date | |
---|---|---|---|
ba848a34bb | |||
aa983c550d | |||
b891376106 | |||
b05a3f26b3 | |||
5fdecd2063 | |||
38b49fb717 | |||
3cf3e230c1 | |||
83a1653fa3 | |||
898aa0ce4d | |||
2f028bc044 | |||
21cf89aa73 | |||
fefaa59d2e | |||
e8501859aa | |||
426d75d071 | |||
0f534f5829 | |||
fbdbede901 | |||
0bc43909e0 | |||
c5a57b219c | |||
6adeb768ce | |||
f425be78f5 | |||
fc8786b149 | |||
7d08dc7593 | |||
e0a32d6459 | |||
255362be61 | |||
50b46b3b1d | |||
e8ac21d503 | |||
a79ce57e6b | |||
180a15970f | |||
b72f430d36 | |||
559e47b01b | |||
7358a44590 | |||
34c30d0e81 | |||
5f570676c2 | |||
aa34a3ceaa | |||
12f70884d7 | |||
0318091611 | |||
f199d27aa1 | |||
660c25a321 | |||
4f6b2f576a | |||
920b830bd1 | |||
abdd14ee80 | |||
1d9f0dad5b | |||
2699274f6e | |||
ca579e0fb2 | |||
c82240598b | |||
926f442022 | |||
c41fd15071 | |||
0c8652569e | |||
3cf27f13bb | |||
ae8edb8fff | |||
82b2b40816 | |||
fe74f1cb7d | |||
e94d154672 | |||
fe67d2f8db | |||
023f7252a0 | |||
3f3ad54c0c | |||
e1d35446fe | |||
11aaa65761 | |||
13abe4777e | |||
aefe5b483f | |||
047f06d086 | |||
014f8c8384 | |||
80c862dc38 | |||
e21107efbd | |||
d8f1ab14a7 | |||
f05a62b1cc | |||
338d4e3bbf | |||
228eec3014 | |||
c483e03222 | |||
a35f420124 | |||
4214866121 | |||
0681939502 | |||
ba8a1f9c02 | |||
09d024bd02 | |||
8ae4c080ce | |||
c5d2f92cae | |||
069c35efca | |||
6a2cd88ae8 | |||
9984a6fa87 | |||
607fce577a | |||
501b34e8f6 | |||
b827fcce4d | |||
239baf3c5b | |||
4d4a70f4a5 | |||
70c3f4d098 | |||
9260643816 | |||
6d6c7c9313 | |||
e753bbf2ff | |||
629365b26e | |||
942a0bea39 | |||
26db2473e9 | |||
467621733d | |||
bdd38d13dc | |||
1d2f8f9eaf | |||
354d280fa3 | |||
0ff311b0d0 | |||
bc65ba63d3 | |||
90642fa8c5 | |||
cf081e76a2 | |||
4ca3c96b49 | |||
cc76dfab99 | |||
1f2c90bb99 | |||
251997c37d | |||
5d7bc0454b | |||
792e988dae | |||
e5034212c9 | |||
0997db20d4 |
6
.eslintignore
Normal file
6
.eslintignore
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# Ignore list
|
||||||
|
/*
|
||||||
|
|
||||||
|
# Do not ignore these folders:
|
||||||
|
!__tests__/
|
||||||
|
!src/
|
51
.eslintrc.js
Normal file
51
.eslintrc.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
// This is a reusable configuration file copied from https://github.com/actions/reusable-workflows/tree/main/reusable-configurations. Please don't make changes to this file as it's the subject of an automatic update.
|
||||||
|
module.exports = {
|
||||||
|
extends: [
|
||||||
|
'eslint:recommended',
|
||||||
|
'plugin:@typescript-eslint/recommended',
|
||||||
|
'plugin:eslint-plugin-jest/recommended',
|
||||||
|
'eslint-config-prettier'
|
||||||
|
],
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
plugins: ['@typescript-eslint', 'eslint-plugin-node', 'eslint-plugin-jest'],
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/no-require-imports': 'error',
|
||||||
|
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||||
|
'@typescript-eslint/no-explicit-any': 'off',
|
||||||
|
'@typescript-eslint/no-empty-function': 'off',
|
||||||
|
'@typescript-eslint/ban-ts-comment': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'ts-ignore': 'allow-with-description'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'no-console': 'error',
|
||||||
|
'yoda': 'error',
|
||||||
|
'prefer-const': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
destructuring: 'all'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'no-control-regex': 'off',
|
||||||
|
'no-constant-condition': ['error', {checkLoops: false}],
|
||||||
|
'node/no-extraneous-import': 'error'
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: ['**/*{test,spec}.ts'],
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/no-unused-vars': 'off',
|
||||||
|
'jest/no-standalone-expect': 'off',
|
||||||
|
'jest/no-conditional-expect': 'off',
|
||||||
|
'no-console': 'off',
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
env: {
|
||||||
|
node: true,
|
||||||
|
es6: true,
|
||||||
|
'jest/globals': true
|
||||||
|
}
|
||||||
|
};
|
3
.gitattributes
vendored
3
.gitattributes
vendored
@ -1 +1,2 @@
|
|||||||
.licenses/** -diff linguist-generated=true
|
* text=auto eol=lf
|
||||||
|
.licenses/** -diff linguist-generated=true
|
||||||
|
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@ -1 +1 @@
|
|||||||
* @actions/virtual-environments-owners
|
* @actions/setup-actions-team
|
||||||
|
17
.github/workflows/basic-validation.yml
vendored
Normal file
17
.github/workflows/basic-validation.yml
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
name: Basic validation
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- releases/*
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
call-basic-validation:
|
||||||
|
name: Basic validation
|
||||||
|
uses: actions/reusable-workflows/.github/workflows/basic-validation.yml@main
|
41
.github/workflows/check-dist.yml
vendored
41
.github/workflows/check-dist.yml
vendored
@ -1,8 +1,3 @@
|
|||||||
# `dist/index.js` is a special file in Actions.
|
|
||||||
# When you reference an action with `uses:` in a workflow,
|
|
||||||
# `index.js` is the code that will run.
|
|
||||||
# For our project, we generate this file through a build process from other source files.
|
|
||||||
# We need to make sure the checked-in `index.js` actually matches what we expect it to be.
|
|
||||||
name: Check dist/
|
name: Check dist/
|
||||||
|
|
||||||
on:
|
on:
|
||||||
@ -17,36 +12,6 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check-dist:
|
call-check-dist:
|
||||||
runs-on: ubuntu-latest
|
name: Check dist/
|
||||||
|
uses: actions/reusable-workflows/.github/workflows/check-dist.yml@main
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Set Node.js 16
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: 16.x
|
|
||||||
cache: npm
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: npm ci --ignore-scripts
|
|
||||||
|
|
||||||
- name: Rebuild the dist/ directory
|
|
||||||
run: npm run build
|
|
||||||
|
|
||||||
- name: Compare the expected and actual dist/ directories
|
|
||||||
run: |
|
|
||||||
if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then
|
|
||||||
echo "Detected uncommitted changes after build. See status below:"
|
|
||||||
git diff
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
id: diff
|
|
||||||
|
|
||||||
# If index.js was different than expected, upload the expected version as an artifact
|
|
||||||
- uses: actions/upload-artifact@v3
|
|
||||||
if: ${{ failure() && steps.diff.conclusion == 'failure' }}
|
|
||||||
with:
|
|
||||||
name: dist
|
|
||||||
path: dist/
|
|
||||||
|
70
.github/workflows/codeql-analysis.yml
vendored
70
.github/workflows/codeql-analysis.yml
vendored
@ -1,70 +1,14 @@
|
|||||||
# For most projects, this workflow file will not need changing; you simply need
|
name: CodeQL analysis
|
||||||
# to commit it to your repository.
|
|
||||||
#
|
|
||||||
# You may wish to alter this file to override the set of languages analyzed,
|
|
||||||
# or to provide custom queries or build logic.
|
|
||||||
#
|
|
||||||
# ******** NOTE ********
|
|
||||||
# We have attempted to detect the languages in your repository. Please check
|
|
||||||
# the `language` matrix defined below to confirm you have the correct set of
|
|
||||||
# supported CodeQL languages.
|
|
||||||
#
|
|
||||||
name: "CodeQL"
|
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ main ]
|
branches: [main]
|
||||||
pull_request:
|
pull_request:
|
||||||
# The branches below must be a subset of the branches above
|
branches: [main]
|
||||||
branches: [ main ]
|
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '23 19 * * 0'
|
- cron: '0 3 * * 0'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
analyze:
|
call-codeQL-analysis:
|
||||||
name: Analyze
|
name: CodeQL analysis
|
||||||
runs-on: ubuntu-latest
|
uses: actions/reusable-workflows/.github/workflows/codeql-analysis.yml@main
|
||||||
permissions:
|
|
||||||
actions: read
|
|
||||||
contents: read
|
|
||||||
security-events: write
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
language: [ 'javascript' ]
|
|
||||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
|
||||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
|
||||||
- name: Initialize CodeQL
|
|
||||||
uses: github/codeql-action/init@v2
|
|
||||||
with:
|
|
||||||
languages: ${{ matrix.language }}
|
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
|
||||||
# By default, queries listed here will override any specified in a config file.
|
|
||||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
|
||||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
|
||||||
|
|
||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
|
||||||
# If this step fails, then you should remove it and run the build manually (see below)
|
|
||||||
- name: Autobuild
|
|
||||||
uses: github/codeql-action/autobuild@v2
|
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
|
||||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
|
||||||
|
|
||||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
|
||||||
# and modify them (or add more) to build your code if your project
|
|
||||||
# uses a compiled language
|
|
||||||
|
|
||||||
#- run: |
|
|
||||||
# make bootstrap
|
|
||||||
# make release
|
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
|
||||||
uses: github/codeql-action/analyze@v2
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
name: Main workflow
|
name: e2e tests
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
@ -12,28 +12,6 @@ on:
|
|||||||
- '**.md'
|
- '**.md'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
|
||||||
runs-on: ${{ matrix.operating-system }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
operating-system: [ubuntu-latest, windows-latest, macOS-latest]
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
- name: Set Node.js 16
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: 16.x
|
|
||||||
cache: npm
|
|
||||||
- run: npm ci --ignore-scripts
|
|
||||||
- run: npm run build
|
|
||||||
- run: npm run format-check
|
|
||||||
- run: npm test
|
|
||||||
- name: Verify no unstaged changes
|
|
||||||
if: runner.os != 'windows'
|
|
||||||
run: __tests__/verify-no-unstaged-changes.sh
|
|
||||||
|
|
||||||
test-setup-multiple-versions:
|
test-setup-multiple-versions:
|
||||||
runs-on: ${{ matrix.operating-system }}
|
runs-on: ${{ matrix.operating-system }}
|
||||||
strategy:
|
strategy:
|
||||||
@ -46,7 +24,7 @@ jobs:
|
|||||||
- name: Clear toolcache
|
- name: Clear toolcache
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
||||||
- name: Setup dotnet 2.2.402 and 3.1.404
|
- name: Setup dotnet 2.2.402, 3.1.404 and 3.0.x
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
dotnet-version: |
|
dotnet-version: |
|
||||||
@ -55,7 +33,7 @@ jobs:
|
|||||||
3.0.x
|
3.0.x
|
||||||
- name: Verify dotnet
|
- name: Verify dotnet
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: __tests__/verify-dotnet.ps1 2.2.402 3.1.404 '3.0'
|
run: __tests__/verify-dotnet.ps1 -Patterns "^2.2.402$", "^3.1.404$", "^3.0"
|
||||||
|
|
||||||
test-setup-full-version:
|
test-setup-full-version:
|
||||||
runs-on: ${{ matrix.operating-system }}
|
runs-on: ${{ matrix.operating-system }}
|
||||||
@ -82,13 +60,9 @@ 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
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: __tests__/verify-dotnet.ps1 3.1.201 2.2.402
|
run: __tests__/verify-dotnet.ps1 -Patterns "^3.1.201$", "^2.2.402$" -CheckNugetConfig
|
||||||
|
|
||||||
test-setup-without-patch-version:
|
test-setup-without-patch-version:
|
||||||
runs-on: ${{ matrix.operating-system }}
|
runs-on: ${{ matrix.operating-system }}
|
||||||
@ -113,7 +87,7 @@ jobs:
|
|||||||
dotnet-version: '2.2'
|
dotnet-version: '2.2'
|
||||||
- name: Verify dotnet
|
- name: Verify dotnet
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: __tests__/verify-dotnet.ps1 3.1 2.2
|
run: __tests__/verify-dotnet.ps1 -Patterns "^3.1", "^2.2"
|
||||||
|
|
||||||
test-setup-prerelease-version:
|
test-setup-prerelease-version:
|
||||||
runs-on: ${{ matrix.operating-system }}
|
runs-on: ${{ matrix.operating-system }}
|
||||||
@ -127,17 +101,13 @@ jobs:
|
|||||||
- name: Clear toolcache
|
- name: Clear toolcache
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
||||||
- name: Setup dotnet '2.2'
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
dotnet-version: '2.2'
|
|
||||||
- name: Setup dotnet '3.1.100-preview1-014459'
|
- name: Setup dotnet '3.1.100-preview1-014459'
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
dotnet-version: '3.1.100-preview1-014459'
|
dotnet-version: '3.1.100-preview1-014459'
|
||||||
- name: Verify dotnet
|
- name: Verify dotnet
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: __tests__/verify-dotnet.ps1 3.1.100-preview1-014459
|
run: __tests__/verify-dotnet.ps1 -Patterns "3.1.100-preview1-014459"
|
||||||
|
|
||||||
test-setup-latest-patch-version:
|
test-setup-latest-patch-version:
|
||||||
runs-on: ${{ matrix.operating-system }}
|
runs-on: ${{ matrix.operating-system }}
|
||||||
@ -161,7 +131,28 @@ jobs:
|
|||||||
dotnet-version: 2.2.X
|
dotnet-version: 2.2.X
|
||||||
- name: Verify dotnet
|
- name: Verify dotnet
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: __tests__/verify-dotnet.ps1 '2.2' '3.1'
|
run: __tests__/verify-dotnet.ps1 -Patterns "^2.2", "^3.1"
|
||||||
|
|
||||||
|
test-ABCxx-syntax:
|
||||||
|
runs-on: ${{ matrix.operating-system }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
operating-system: [ubuntu-latest, windows-latest, macOS-latest]
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Clear toolcache
|
||||||
|
shell: pwsh
|
||||||
|
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
||||||
|
|
||||||
|
- name: Setup dotnet 6.0.4xx
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
dotnet-version: '6.0.4xx'
|
||||||
|
- name: Verify dotnet
|
||||||
|
shell: pwsh
|
||||||
|
run: __tests__/verify-dotnet.ps1 -Patterns "^6\.0\.4\d{2}"
|
||||||
|
|
||||||
test-setup-with-wildcard:
|
test-setup-with-wildcard:
|
||||||
runs-on: ${{ matrix.operating-system }}
|
runs-on: ${{ matrix.operating-system }}
|
||||||
@ -185,7 +176,7 @@ jobs:
|
|||||||
dotnet-version: 2.2.*
|
dotnet-version: 2.2.*
|
||||||
- name: Verify dotnet
|
- name: Verify dotnet
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: __tests__/verify-dotnet.ps1 3.1 2.2
|
run: __tests__/verify-dotnet.ps1 -Patterns "^3.1", "^2.2"
|
||||||
|
|
||||||
test-setup-global-json-specified-and-version:
|
test-setup-global-json-specified-and-version:
|
||||||
runs-on: ${{ matrix.operating-system }}
|
runs-on: ${{ matrix.operating-system }}
|
||||||
@ -203,7 +194,7 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
mkdir subdirectory
|
mkdir subdirectory
|
||||||
echo '{"sdk":{"version": "2.2","rollForward": "latestFeature"}}' > ./subdirectory/global.json
|
echo '{"sdk":{"version": "2.2.207","rollForward": "latestFeature"}}' > ./subdirectory/global.json
|
||||||
- name: Setup dotnet
|
- name: Setup dotnet
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
@ -211,95 +202,117 @@ jobs:
|
|||||||
global-json-file: ./subdirectory/global.json
|
global-json-file: ./subdirectory/global.json
|
||||||
- name: Verify dotnet
|
- name: Verify dotnet
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: __tests__/verify-dotnet.ps1 2.2 3.1
|
run: __tests__/verify-dotnet.ps1 -Patterns "^2.2", "^3.1"
|
||||||
|
|
||||||
|
test-setup-global-json-only:
|
||||||
|
runs-on: ${{ matrix.operating-system }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
operating-system: [ubuntu-latest, windows-latest, macOS-latest]
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Clear toolcache
|
||||||
|
shell: pwsh
|
||||||
|
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
||||||
|
- name: Write global.json
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
mkdir subdirectory
|
||||||
|
echo '{"sdk":{"version": "2.2.207","rollForward": "latestFeature"}}' > ./subdirectory/global.json
|
||||||
|
- name: Setup dotnet
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
global-json-file: ./subdirectory/global.json
|
||||||
|
- name: Verify dotnet
|
||||||
|
shell: pwsh
|
||||||
|
run: __tests__/verify-dotnet.ps1 -Patterns "^2.2"
|
||||||
|
|
||||||
test-setup-with-dotnet-quality:
|
test-setup-with-dotnet-quality:
|
||||||
runs-on: ${{ matrix.operating-system }}
|
runs-on: ${{ matrix.operating-system }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
operating-system: [ubuntu-latest, windows-latest, macOS-latest]
|
operating-system: [ubuntu-latest, windows-latest, macOS-latest]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Clear toolcache
|
- name: Clear toolcache
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
||||||
|
|
||||||
- name: Setup dotnet 7.0 with preview quality
|
- name: Setup dotnet 7.0 with preview quality
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
dotnet-version: "7.0"
|
dotnet-version: '7.0'
|
||||||
dotnet-quality: "preview"
|
dotnet-quality: 'preview'
|
||||||
- name: Verify preview version
|
- name: Verify dotnet
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: |
|
run: __tests__/verify-dotnet.ps1 -Patterns "^7\.0\.\d+-"
|
||||||
$version = & dotnet --version
|
|
||||||
Write-Host "Installed version: $version"
|
|
||||||
if (-not ($version.Contains("preview") -or $version.Contains("rc"))) { throw "Unexpected version" }
|
|
||||||
|
|
||||||
test-dotnet-version-output-during-single-version-installation:
|
test-dotnet-version-output-during-single-version-installation:
|
||||||
runs-on: ${{ matrix.operating-system }}
|
runs-on: ${{ matrix.operating-system }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
operating-system: [ubuntu-latest, windows-latest, macOS-latest]
|
operating-system: [ubuntu-latest, windows-latest, macOS-latest]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Clear toolcache
|
- name: Clear toolcache
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
||||||
|
|
||||||
- name: Setup dotnet 6.0.401
|
- name: Setup dotnet 6.0.401
|
||||||
uses: ./
|
uses: ./
|
||||||
id: step1
|
id: step1
|
||||||
with:
|
with:
|
||||||
dotnet-version: "6.0.401"
|
dotnet-version: '6.0.401'
|
||||||
|
|
||||||
|
- name: Verify value of the dotnet-version output
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
$version = & dotnet --version
|
||||||
|
Write-Host "Installed version: $version"
|
||||||
|
if (-not ($version -eq '${{steps.step1.outputs.dotnet-version}}')) { throw "Unexpected output value" }
|
||||||
|
|
||||||
- name: Verify value of the dotnet-version output
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
$version = & dotnet --version
|
|
||||||
Write-Host "Installed version: $version"
|
|
||||||
if (-not ($version -eq '${{steps.step1.outputs.dotnet-version}}')) { throw "Unexpected output value" }
|
|
||||||
|
|
||||||
test-dotnet-version-output-during-multiple-version-installation:
|
test-dotnet-version-output-during-multiple-version-installation:
|
||||||
runs-on: ${{ matrix.operating-system }}
|
runs-on: ${{ matrix.operating-system }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
operating-system: [ubuntu-latest, windows-latest, macOS-latest]
|
operating-system: [ubuntu-latest, windows-latest, macOS-latest]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Clear toolcache
|
- name: Clear toolcache
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
||||||
|
|
||||||
- name: Setup dotnet 6.0.401, 5.0.408, 7.0.100-rc.1.22431.12
|
|
||||||
uses: ./
|
|
||||||
id: step2
|
|
||||||
with:
|
|
||||||
dotnet-version: |
|
|
||||||
7.0.100-rc.1.22431.12
|
|
||||||
6.0.401
|
|
||||||
5.0.408
|
|
||||||
|
|
||||||
- name: Verify value of the dotnet-version output
|
- name: Setup dotnet 6.0.401, 5.0.408, 7.0.100-rc.1.22431.12
|
||||||
shell: pwsh
|
uses: ./
|
||||||
run: |
|
id: step2
|
||||||
$version = "7.0.100-rc.1.22431.12"
|
with:
|
||||||
if (-not ($version -eq '${{steps.step2.outputs.dotnet-version}}')) { throw "Unexpected output value" }
|
dotnet-version: |
|
||||||
|
7.0.100-rc.1.22431.12
|
||||||
|
6.0.401
|
||||||
|
5.0.408
|
||||||
|
|
||||||
|
- name: Verify value of the dotnet-version output
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
$version = "7.0.100-rc.1.22431.12"
|
||||||
|
if (-not ($version -eq '${{steps.step2.outputs.dotnet-version}}')) { throw "Unexpected output value" }
|
||||||
|
|
||||||
test-proxy:
|
test-proxy:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: mcr.microsoft.com/dotnet/core/runtime-deps:3.0-bionic
|
image: ubuntu:latest
|
||||||
options: --dns 127.0.0.1
|
options: --dns 127.0.0.1
|
||||||
services:
|
services:
|
||||||
squid-proxy:
|
squid-proxy:
|
||||||
image: datadog/squid:latest
|
image: ubuntu/squid:latest
|
||||||
ports:
|
ports:
|
||||||
- 3128:3128
|
- 3128:3128
|
||||||
env:
|
env:
|
||||||
@ -308,21 +321,29 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Clear tool cache
|
- name: Install Powershell
|
||||||
run: rm -rf "/usr/share/dotnet"
|
|
||||||
- name: Install curl
|
|
||||||
run: |
|
run: |
|
||||||
apt update
|
apt-get update
|
||||||
apt -y install curl
|
apt-get install -y wget apt-transport-https software-properties-common
|
||||||
- name: Setup dotnet 3.1.201
|
wget -q "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb"
|
||||||
|
dpkg -i packages-microsoft-prod.deb
|
||||||
|
rm packages-microsoft-prod.deb
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y powershell
|
||||||
|
- name: Clear toolcache
|
||||||
|
shell: pwsh
|
||||||
|
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
||||||
|
- name: Setup dotnet 6.0
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
dotnet-version: 3.1.201
|
dotnet-version: 6.0
|
||||||
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 dotnet
|
- name: Verify dotnet
|
||||||
run: __tests__/verify-dotnet.sh 3.1.201
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
__tests__/verify-dotnet.ps1 -Patterns "^6.0" -CheckNugetConfig
|
||||||
|
|
||||||
test-bypass-proxy:
|
test-bypass-proxy:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@ -332,8 +353,9 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Clear tool cache
|
- name: Clear toolcache
|
||||||
run: rm -rf "/usr/share/dotnet"
|
shell: pwsh
|
||||||
|
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
||||||
- name: Setup dotnet 3.1.201
|
- name: Setup dotnet 3.1.201
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
@ -342,4 +364,5 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
NUGET_AUTH_TOKEN: NOTATOKEN
|
NUGET_AUTH_TOKEN: NOTATOKEN
|
||||||
- name: Verify dotnet
|
- name: Verify dotnet
|
||||||
run: __tests__/verify-dotnet.sh 3.1.201
|
shell: pwsh
|
||||||
|
run: __tests__/verify-dotnet.ps1 -Patterns "^3.1.201$" -CheckNugetConfig
|
16
.github/workflows/licensed.yml
vendored
16
.github/workflows/licensed.yml
vendored
@ -10,16 +10,6 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
call-licensed:
|
||||||
runs-on: ubuntu-latest
|
name: Licensed
|
||||||
name: Check licenses
|
uses: actions/reusable-workflows/.github/workflows/licensed.yml@main
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- run: npm ci --ignore-scripts
|
|
||||||
- name: Install licensed
|
|
||||||
run: |
|
|
||||||
cd $RUNNER_TEMP
|
|
||||||
curl -Lfs -o licensed.tar.gz https://github.com/github/licensed/releases/download/3.4.4/licensed-3.4.4-linux-x64.tar.gz
|
|
||||||
sudo tar -xzf licensed.tar.gz
|
|
||||||
sudo mv licensed /usr/local/bin/licensed
|
|
||||||
- run: licensed status
|
|
||||||
|
13
.github/workflows/release-new-action-version.yml
vendored
13
.github/workflows/release-new-action-version.yml
vendored
@ -1,4 +1,5 @@
|
|||||||
name: Release new action version
|
name: Release new action version
|
||||||
|
|
||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
types: [released]
|
types: [released]
|
||||||
@ -20,9 +21,9 @@ jobs:
|
|||||||
name: releaseNewActionVersion
|
name: releaseNewActionVersion
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Update the ${{ env.TAG_NAME }} tag
|
- name: Update the ${{ env.TAG_NAME }} tag
|
||||||
id: update-major-tag
|
id: update-major-tag
|
||||||
uses: actions/publish-action@v0.2.0
|
uses: actions/publish-action@v0.2.2
|
||||||
with:
|
with:
|
||||||
source-tag: ${{ env.TAG_NAME }}
|
source-tag: ${{ env.TAG_NAME }}
|
||||||
slack-webhook: ${{ secrets.SLACK_WEBHOOK }}
|
slack-webhook: ${{ secrets.SLACK_WEBHOOK }}
|
||||||
|
8
.github/workflows/test-dotnet.yml
vendored
8
.github/workflows/test-dotnet.yml
vendored
@ -18,7 +18,7 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
operating-system: [ubuntu-latest, windows-latest, macOS-latest]
|
operating-system: [ubuntu-latest, windows-latest, macOS-latest]
|
||||||
dotnet-version: ['2.1', '2.2', '3.0', '3.1', '5.0']
|
dotnet-version: ['2.1', '2.2', '3.0', '3.1', '5.0', '6.0', '7.0', '8.0']
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
@ -29,9 +29,7 @@ jobs:
|
|||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
dotnet-version: ${{ matrix.dotnet-version }}
|
dotnet-version: ${{ matrix.dotnet-version }}
|
||||||
- name: Check installed version
|
- name: Verify installed version
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: |
|
run: |
|
||||||
$version = & dotnet --version
|
__tests__/verify-dotnet.ps1 -Patterns "^${{ matrix.dotnet-version }}"
|
||||||
Write-Host "Installed version: $version"
|
|
||||||
if (-not $version.StartsWith("${{ matrix.dotnet-version }}")) { throw "Unexpected version" }
|
|
||||||
|
11
.github/workflows/update-config-files.yml
vendored
Normal file
11
.github/workflows/update-config-files.yml
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
name: Update configuration files
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 3 * * 0'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
call-update-configuration-files:
|
||||||
|
name: Update configuration files
|
||||||
|
uses: actions/reusable-workflows/.github/workflows/update-config-files.yml@main
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -3,8 +3,8 @@ global.json
|
|||||||
lib/
|
lib/
|
||||||
node_modules/
|
node_modules/
|
||||||
__tests__/runner/*
|
__tests__/runner/*
|
||||||
__tests__/sample-csproj/bin/
|
__tests__/e2e-test-csproj/bin/
|
||||||
__tests__/sample-csproj/obj/
|
__tests__/e2e-test-csproj/obj/
|
||||||
|
|
||||||
# Rest of the file pulled from https://github.com/github/gitignore/blob/master/Node.gitignore
|
# Rest of the file pulled from https://github.com/github/gitignore/blob/master/Node.gitignore
|
||||||
# Logs
|
# Logs
|
||||||
|
@ -2,3 +2,4 @@
|
|||||||
. "$(dirname -- "$0")/_/husky.sh"
|
. "$(dirname -- "$0")/_/husky.sh"
|
||||||
|
|
||||||
npm run format
|
npm run format
|
||||||
|
npm run lint:fix
|
||||||
|
@ -3,3 +3,4 @@
|
|||||||
|
|
||||||
# Tests are not run at push time since they can take 2-4 minutes to complete
|
# Tests are not run at push time since they can take 2-4 minutes to complete
|
||||||
npm run format-check
|
npm run format-check
|
||||||
|
npm run lint
|
||||||
|
2
.licenses/npm/@actions/core.dep.yml
generated
2
.licenses/npm/@actions/core.dep.yml
generated
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: "@actions/core"
|
name: "@actions/core"
|
||||||
version: 1.9.1
|
version: 1.10.0
|
||||||
type: npm
|
type: npm
|
||||||
summary: Actions core lib
|
summary: Actions core lib
|
||||||
homepage: https://github.com/actions/toolkit/tree/main/packages/core
|
homepage: https://github.com/actions/toolkit/tree/main/packages/core
|
||||||
|
22
.licenses/npm/fast-xml-parser.dep.yml
generated
22
.licenses/npm/fast-xml-parser.dep.yml
generated
@ -1,27 +1,11 @@
|
|||||||
---
|
---
|
||||||
name: fast-xml-parser
|
name: fast-xml-parser
|
||||||
version: 3.17.4
|
version: 4.0.10
|
||||||
type: npm
|
type: npm
|
||||||
summary: Validate XML or Parse XML to JS/JSON very fast without C/C++ based libraries
|
summary: Validate XML, Parse XML to JS Object, or Build XML from JS Object without C/C++ based libraries and no callback.
|
||||||
homepage: https://github.com/NaturalIntelligence/fast-xml-parser#readme
|
homepage: https://github.com/NaturalIntelligence/fast-xml-parser#readme
|
||||||
license: mit
|
license: mit
|
||||||
licenses:
|
licenses:
|
||||||
- sources: LICENSE
|
- sources: LICENSE
|
||||||
text: "MIT License\n\nCopyright (c) 2017 Amit Kumar Gupta\n\nPermission is hereby
|
text: "MIT License\n\nCopyright (c) 2017 Amit Kumar Gupta\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
|
||||||
granted, free of charge, to any person obtaining a copy\nof this software and
|
|
||||||
associated documentation files (the \"Software\"), to deal\nin the Software without
|
|
||||||
restriction, including without limitation the rights\nto use, copy, modify, merge,
|
|
||||||
publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit
|
|
||||||
persons to whom the Software is\nfurnished to do so, subject to the following
|
|
||||||
conditions:\n\nIf you use this library in a public repository then you give us
|
|
||||||
the right to mention your company name and logo in user's list without further
|
|
||||||
permission required, but you can request them to be taken down within 30 days.
|
|
||||||
\n\nThe above copyright notice and this permission notice shall be included in
|
|
||||||
all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED
|
|
||||||
\"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT
|
|
||||||
LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
|
||||||
FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR
|
|
||||||
THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
|
|
||||||
notices: []
|
notices: []
|
||||||
|
11
.licenses/npm/strnum.dep.yml
generated
Normal file
11
.licenses/npm/strnum.dep.yml
generated
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
name: strnum
|
||||||
|
version: 1.0.5
|
||||||
|
type: npm
|
||||||
|
summary: Parse string into Number based on configuration
|
||||||
|
homepage: https://github.com/NaturalIntelligence/strnum
|
||||||
|
license: mit
|
||||||
|
licenses:
|
||||||
|
- sources: LICENSE
|
||||||
|
text: "MIT License\n\nCopyright (c) 2021 Natural Intelligence\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
|
||||||
|
notices: []
|
24
.licenses/npm/xmlbuilder.dep.yml
generated
24
.licenses/npm/xmlbuilder.dep.yml
generated
@ -1,24 +0,0 @@
|
|||||||
---
|
|
||||||
name: xmlbuilder
|
|
||||||
version: 13.0.2
|
|
||||||
type: npm
|
|
||||||
summary: An XML builder for node.js
|
|
||||||
homepage: http://github.com/oozcitak/xmlbuilder-js
|
|
||||||
license: mit
|
|
||||||
licenses:
|
|
||||||
- sources: LICENSE
|
|
||||||
text: "The MIT License (MIT)\r\n\r\nCopyright (c) 2013 Ozgur Ozcitak\r\n\r\nPermission
|
|
||||||
is hereby granted, free of charge, to any person obtaining a copy\r\nof this software
|
|
||||||
and associated documentation files (the \"Software\"), to deal\r\nin the Software
|
|
||||||
without restriction, including without limitation the rights\r\nto use, copy,
|
|
||||||
modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software,
|
|
||||||
and to permit persons to whom the Software is\r\nfurnished to do so, subject to
|
|
||||||
the following conditions:\r\n\r\nThe above copyright notice and this permission
|
|
||||||
notice shall be included in\r\nall copies or substantial portions of the Software.\r\n\r\nTHE
|
|
||||||
SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED,
|
|
||||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR
|
|
||||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER
|
|
||||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION
|
|
||||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\nTHE SOFTWARE.\r\n"
|
|
||||||
notices: []
|
|
7
.prettierignore
Normal file
7
.prettierignore
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# Ignore list
|
||||||
|
/*
|
||||||
|
|
||||||
|
# Do not ignore these folders:
|
||||||
|
!__tests__/
|
||||||
|
!.github/
|
||||||
|
!src/
|
11
.prettierrc.js
Normal file
11
.prettierrc.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// This is a reusable configuration file copied from https://github.com/actions/reusable-workflows/tree/main/reusable-configurations. Please don't make changes to this file as it's the subject of an automatic update.
|
||||||
|
module.exports = {
|
||||||
|
printWidth: 80,
|
||||||
|
tabWidth: 2,
|
||||||
|
useTabs: false,
|
||||||
|
semi: true,
|
||||||
|
singleQuote: true,
|
||||||
|
trailingComma: 'none',
|
||||||
|
bracketSpacing: false,
|
||||||
|
arrowParens: 'avoid'
|
||||||
|
};
|
@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"printWidth": 80,
|
|
||||||
"tabWidth": 2,
|
|
||||||
"useTabs": false,
|
|
||||||
"semi": true,
|
|
||||||
"singleQuote": true,
|
|
||||||
"trailingComma": "none",
|
|
||||||
"bracketSpacing": false,
|
|
||||||
"arrowParens": "avoid",
|
|
||||||
"parser": "typescript"
|
|
||||||
}
|
|
60
README.md
60
README.md
@ -1,6 +1,7 @@
|
|||||||
# setup-dotnet
|
# setup-dotnet
|
||||||
|
|
||||||
[](https://github.com/actions/setup-dotnet)
|
[](https://github.com/actions/setup-dotnet/actions/workflows/basic-validation.yml)
|
||||||
|
[](https://github.com/actions/setup-dotnet/actions/workflows/e2e-tests.yml)
|
||||||
|
|
||||||
This action sets up a [.NET CLI](https://github.com/dotnet/sdk) environment for use in actions by:
|
This action sets up a [.NET CLI](https://github.com/dotnet/sdk) environment for use in actions by:
|
||||||
|
|
||||||
@ -10,8 +11,8 @@ This action sets up a [.NET CLI](https://github.com/dotnet/sdk) environment for
|
|||||||
|
|
||||||
> **Note**: GitHub hosted runners have some versions of the .NET SDK
|
> **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://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-software)
|
[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
|
||||||
@ -27,6 +28,7 @@ steps:
|
|||||||
dotnet-version: '3.1.x'
|
dotnet-version: '3.1.x'
|
||||||
- run: dotnet build <my project>
|
- run: dotnet build <my project>
|
||||||
```
|
```
|
||||||
|
> **Warning**: Unless a concrete version is specified in the [`global.json`](https://learn.microsoft.com/en-us/dotnet/core/tools/global-json) file, **_the latest .NET version installed on the runner (including preinstalled versions) will be used [by default](https://learn.microsoft.com/en-us/dotnet/core/versions/selection#the-sdk-uses-the-latest-installed-version)_**. Please refer to the [documentation](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-software) for the currently preinstalled .NET SDK versions.
|
||||||
|
|
||||||
**Multiple version installation**:
|
**Multiple version installation**:
|
||||||
```yml
|
```yml
|
||||||
@ -40,8 +42,6 @@ steps:
|
|||||||
5.0.x
|
5.0.x
|
||||||
- run: dotnet build <my project>
|
- run: dotnet build <my project>
|
||||||
```
|
```
|
||||||
> **Note**: In case multiple versions are installed, the latest .NET version will be used by default unless another version is specified in the `global.json` file.
|
|
||||||
|
|
||||||
## Supported version syntax
|
## Supported version syntax
|
||||||
|
|
||||||
The `dotnet-version` input supports following syntax:
|
The `dotnet-version` input supports following syntax:
|
||||||
@ -49,12 +49,13 @@ The `dotnet-version` input supports following syntax:
|
|||||||
- **A.B.C** (e.g 6.0.400, 7.0.100-preview.7.22377.5) - installs exact version of .NET SDK
|
- **A.B.C** (e.g 6.0.400, 7.0.100-preview.7.22377.5) - installs exact version of .NET SDK
|
||||||
- **A.B** or **A.B.x** (e.g. 3.1, 3.1.x) - installs the latest patch version of .NET SDK on the channel `3.1`, including prerelease versions (preview, rc)
|
- **A.B** or **A.B.x** (e.g. 3.1, 3.1.x) - installs the latest patch version of .NET SDK on the channel `3.1`, including prerelease versions (preview, rc)
|
||||||
- **A** or **A.x** (e.g. 3, 3.x) - installs the latest minor version of the specified major tag, including prerelease versions (preview, rc)
|
- **A** or **A.x** (e.g. 3, 3.x) - installs the latest minor version of the specified major tag, including prerelease versions (preview, rc)
|
||||||
|
- **A.B.Cxx** (e.g. 6.0.4xx) - available since `.NET 5.0` release. Installs the latest version of the specific SDK release, including prerelease versions (preview, rc).
|
||||||
|
|
||||||
|
|
||||||
## Using the `dotnet-quality` input
|
## Using the `dotnet-quality` input
|
||||||
This input sets up the action to install the latest build of the specified quality in the channel. The possible values of `dotnet-quality` are: **daily**, **signed**, **validated**, **preview**, **ga**.
|
This input sets up the action to install the latest build of the specified quality in the channel. The possible values of `dotnet-quality` are: **daily**, **signed**, **validated**, **preview**, **ga**.
|
||||||
|
|
||||||
> **Note**: `dotnet-quality` input can be used only with .NET SDK version in 'A.B', 'A.B.x', 'A' and 'A.x' formats where the major version is higher than 5. In other cases, `dotnet-quality` input will be ignored.
|
> **Note**: `dotnet-quality` input can be used only with .NET SDK version in 'A.B', 'A.B.x', 'A', 'A.x' and 'A.B.Cxx' formats where the major version is higher than 5. In other cases, `dotnet-quality` input will be ignored.
|
||||||
|
|
||||||
```yml
|
```yml
|
||||||
steps:
|
steps:
|
||||||
@ -97,7 +98,31 @@ jobs:
|
|||||||
uses: actions/setup-dotnet@v3
|
uses: actions/setup-dotnet@v3
|
||||||
with:
|
with:
|
||||||
dotnet-version: ${{ matrix.dotnet }}
|
dotnet-version: ${{ matrix.dotnet }}
|
||||||
- run: dotnet build <my project>
|
- name: Execute dotnet
|
||||||
|
run: dotnet build <my project>
|
||||||
|
```
|
||||||
|
>**Note**: Unless a concrete version is specified in the [`global.json`](https://learn.microsoft.com/en-us/dotnet/core/tools/global-json) file, the latest .NET version installed on the runner (including preinstalled versions) will be used [by default](https://learn.microsoft.com/en-us/dotnet/core/versions/selection#the-sdk-uses-the-latest-installed-version). To control this behavior you may want to use temporary `global.json` files:
|
||||||
|
|
||||||
|
**Matrix testing with temporary global.json creation**
|
||||||
|
```yml
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
dotnet: [ '2.1.x', '3.1.x', '5.0.x' ]
|
||||||
|
name: Dotnet ${{ matrix.dotnet }} sample
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Setup dotnet
|
||||||
|
uses: actions/setup-dotnet@v3
|
||||||
|
id: stepid
|
||||||
|
with:
|
||||||
|
dotnet-version: ${{ matrix.dotnet }}
|
||||||
|
- name: Create temporary global.json
|
||||||
|
run: echo '{"sdk":{"version": "${{ steps.stepid.outputs.dotnet-version }}"}}' > ./global.json
|
||||||
|
- name: Execute dotnet
|
||||||
|
run: dotnet build <my project>
|
||||||
```
|
```
|
||||||
## Setting up authentication for nuget feeds
|
## Setting up authentication for nuget feeds
|
||||||
|
|
||||||
@ -155,10 +180,10 @@ In case of a single version installation, the `dotnet-version` output contains t
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- uses: actions/setup-dotnet@v3
|
- uses: actions/setup-dotnet@v3
|
||||||
id: cp310
|
id: stepid
|
||||||
with:
|
with:
|
||||||
dotnet-version: 3.1.422
|
dotnet-version: 3.1.422
|
||||||
- run: echo '${{ steps.cp310.outputs.dotnet-version }}' # outputs 3.1.422
|
- run: echo '${{ steps.stepid.outputs.dotnet-version }}' # outputs 3.1.422
|
||||||
```
|
```
|
||||||
|
|
||||||
**Multiple version installation**
|
**Multiple version installation**
|
||||||
@ -167,12 +192,12 @@ In case of a multiple version installation, the `dotnet-version` output contains
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- uses: actions/setup-dotnet@v3
|
- uses: actions/setup-dotnet@v3
|
||||||
id: cp310
|
id: stepid
|
||||||
with:
|
with:
|
||||||
dotnet-version: |
|
dotnet-version: |
|
||||||
3.1.422
|
3.1.422
|
||||||
5.0.408
|
5.0.408
|
||||||
- run: echo '${{ steps.cp310.outputs.dotnet-version }}' # outputs 5.0.408
|
- run: echo '${{ steps.stepid.outputs.dotnet-version }}' # outputs 5.0.408
|
||||||
```
|
```
|
||||||
**Installation from global.json**
|
**Installation from global.json**
|
||||||
|
|
||||||
@ -180,13 +205,13 @@ When the `dotnet-version` input is used along with the `global-json-file` input,
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- uses: actions/setup-dotnet@v3
|
- uses: actions/setup-dotnet@v3
|
||||||
id: cp310
|
id: stepid
|
||||||
with:
|
with:
|
||||||
dotnet-version: |
|
dotnet-version: |
|
||||||
3.1.422
|
3.1.422
|
||||||
5.0.408
|
5.0.408
|
||||||
global-json-file: "./global.json" # contains version 2.2.207
|
global-json-file: "./global.json" # contains version 2.2.207
|
||||||
- run: echo '${{ steps.cp310.outputs.dotnet-version }}' # outputs 2.2.207
|
- run: echo '${{ steps.stepid.outputs.dotnet-version }}' # outputs 2.2.207
|
||||||
```
|
```
|
||||||
|
|
||||||
## Environment variables
|
## Environment variables
|
||||||
@ -195,11 +220,18 @@ Some environment variables may be necessary for your particular case or to impro
|
|||||||
|
|
||||||
| **Env.variable** | **Description** | **Default value** |
|
| **Env.variable** | **Description** | **Default value** |
|
||||||
| ----------- | ----------- | ----------- |
|
| ----------- | ----------- | ----------- |
|
||||||
| DOTNET_INSTALL_DIR |Specifies a directory where .NET SDKs should be installed by the action|*isn't set*|
|
| DOTNET_INSTALL_DIR |Specifies a directory where .NET SDKs should be installed by the action.|*default value for each OS* |
|
||||||
| DOTNET_NOLOGO |Removes logo and telemetry message from first run of dotnet cli|*false*|
|
| DOTNET_NOLOGO |Removes logo and telemetry message from first run of dotnet cli|*false*|
|
||||||
| DOTNET_CLI_TELEMETRY_OPTOUT |Opt-out of telemetry being sent to Microsoft|*false*|
|
| DOTNET_CLI_TELEMETRY_OPTOUT |Opt-out of telemetry being sent to Microsoft|*false*|
|
||||||
| DOTNET_MULTILEVEL_LOOKUP |Configures whether the global install location is used as a fall-back|*true*|
|
| DOTNET_MULTILEVEL_LOOKUP |Configures whether the global install location is used as a fall-back|*true*|
|
||||||
|
|
||||||
|
The default value of the `DOTNET_INSTALL_DIR` environment variable depends on the operation system which is used on a runner:
|
||||||
|
| **Operation system** | **Default value** |
|
||||||
|
| ----------- | ----------- |
|
||||||
|
| **Windows** | `C:\Program Files\dotnet` |
|
||||||
|
| **Ubuntu** | `/usr/share/dotnet` |
|
||||||
|
| **macOS** | `/Users/runner/.dotnet` |
|
||||||
|
|
||||||
**Example usage**:
|
**Example usage**:
|
||||||
```yml
|
```yml
|
||||||
build:
|
build:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`authutil tests Existing config not in repo root, sets up a partial NuGet.config user/PAT for GPR 1`] = `
|
exports[`authutil tests existing config not in repo root, sets up a partial NuGet.config user/PAT for GPR 1`] = `
|
||||||
"<?xml version=\\"1.0\\"?>
|
"<?xml version=\\"1.0\\"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<config>
|
<config>
|
||||||
@ -15,7 +15,7 @@ exports[`authutil tests Existing config not in repo root, sets up a partial NuGe
|
|||||||
</configuration>"
|
</configuration>"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`authutil tests Existing config w/ Azure Artifacts source and NuGet.org, sets up a partial NuGet.config user/PAT for GPR 1`] = `
|
exports[`authutil tests existing config w/ Azure Artifacts source and NuGet.org, sets up a partial NuGet.config user/PAT for GPR 1`] = `
|
||||||
"<?xml version=\\"1.0\\"?>
|
"<?xml version=\\"1.0\\"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<config>
|
<config>
|
||||||
@ -30,7 +30,7 @@ exports[`authutil tests Existing config w/ Azure Artifacts source and NuGet.org,
|
|||||||
</configuration>"
|
</configuration>"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`authutil tests Existing config w/ GPR source and NuGet.org, sets up a partial NuGet.config user/PAT for GPR 1`] = `
|
exports[`authutil tests existing config w/ GPR source and NuGet.org, sets up a partial NuGet.config user/PAT for GPR 1`] = `
|
||||||
"<?xml version=\\"1.0\\"?>
|
"<?xml version=\\"1.0\\"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<config>
|
<config>
|
||||||
@ -45,7 +45,7 @@ exports[`authutil tests Existing config w/ GPR source and NuGet.org, sets up a p
|
|||||||
</configuration>"
|
</configuration>"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`authutil tests Existing config w/ no GPR sources, sets up a full NuGet.config with URL and user/PAT for GPR 1`] = `
|
exports[`authutil tests existing config w/ no GPR sources, sets up a full NuGet.config with URL and user/PAT for GPR 1`] = `
|
||||||
"<?xml version=\\"1.0\\"?>
|
"<?xml version=\\"1.0\\"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<config>
|
<config>
|
||||||
@ -63,7 +63,7 @@ exports[`authutil tests Existing config w/ no GPR sources, sets up a full NuGet.
|
|||||||
</configuration>"
|
</configuration>"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`authutil tests Existing config w/ no sources, sets up a full NuGet.config with URL and user/PAT for GPR 1`] = `
|
exports[`authutil tests existing config w/ no sources, sets up a full NuGet.config with URL and user/PAT for GPR 1`] = `
|
||||||
"<?xml version=\\"1.0\\"?>
|
"<?xml version=\\"1.0\\"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<config>
|
<config>
|
||||||
@ -81,7 +81,7 @@ exports[`authutil tests Existing config w/ no sources, sets up a full NuGet.conf
|
|||||||
</configuration>"
|
</configuration>"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`authutil tests Existing config w/ only Azure Artifacts source, sets up a partial NuGet.config user/PAT for GPR 1`] = `
|
exports[`authutil tests existing config w/ only Azure Artifacts source, sets up a partial NuGet.config user/PAT for GPR 1`] = `
|
||||||
"<?xml version=\\"1.0\\"?>
|
"<?xml version=\\"1.0\\"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<config>
|
<config>
|
||||||
@ -96,7 +96,7 @@ exports[`authutil tests Existing config w/ only Azure Artifacts source, sets up
|
|||||||
</configuration>"
|
</configuration>"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`authutil tests Existing config w/ only GPR source, sets up a partial NuGet.config user/PAT for GPR 1`] = `
|
exports[`authutil tests existing config w/ only GPR source, sets up a partial NuGet.config user/PAT for GPR 1`] = `
|
||||||
"<?xml version=\\"1.0\\"?>
|
"<?xml version=\\"1.0\\"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<config>
|
<config>
|
||||||
@ -111,7 +111,7 @@ exports[`authutil tests Existing config w/ only GPR source, sets up a partial Nu
|
|||||||
</configuration>"
|
</configuration>"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`authutil tests Existing config w/ two GPR sources, sets up a partial NuGet.config user/PAT for GPR 1`] = `
|
exports[`authutil tests existing config w/ two GPR sources, sets up a partial NuGet.config user/PAT for GPR 1`] = `
|
||||||
"<?xml version=\\"1.0\\"?>
|
"<?xml version=\\"1.0\\"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<config>
|
<config>
|
||||||
@ -130,7 +130,7 @@ exports[`authutil tests Existing config w/ two GPR sources, sets up a partial Nu
|
|||||||
</configuration>"
|
</configuration>"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`authutil tests No existing config, sets up a full NuGet.config with URL and other owner/PAT for GPR 1`] = `
|
exports[`authutil tests no existing config, sets up a full NuGet.config with URL and other owner/PAT for GPR 1`] = `
|
||||||
"<?xml version=\\"1.0\\"?>
|
"<?xml version=\\"1.0\\"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<config>
|
<config>
|
||||||
@ -148,7 +148,7 @@ exports[`authutil tests No existing config, sets up a full NuGet.config with URL
|
|||||||
</configuration>"
|
</configuration>"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`authutil tests No existing config, sets up a full NuGet.config with URL and token for other source 1`] = `
|
exports[`authutil tests no existing config, sets up a full NuGet.config with URL and token for other source 1`] = `
|
||||||
"<?xml version=\\"1.0\\"?>
|
"<?xml version=\\"1.0\\"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<config>
|
<config>
|
||||||
@ -166,7 +166,7 @@ exports[`authutil tests No existing config, sets up a full NuGet.config with URL
|
|||||||
</configuration>"
|
</configuration>"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`authutil tests No existing config, sets up a full NuGet.config with URL and user/PAT for GPR 1`] = `
|
exports[`authutil tests no existing config, sets up a full NuGet.config with URL and user/PAT for GPR 1`] = `
|
||||||
"<?xml version=\\"1.0\\"?>
|
"<?xml version=\\"1.0\\"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<config>
|
<config>
|
||||||
|
@ -1,340 +1,336 @@
|
|||||||
import * as io from '@actions/io';
|
import * as io from '@actions/io';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
const fakeSourcesDirForTesting = path.join(
|
const fakeSourcesDirForTesting = path.join(
|
||||||
__dirname,
|
__dirname,
|
||||||
'runner',
|
'runner',
|
||||||
path.join(
|
path.join(Math.random().toString(36).substring(7)),
|
||||||
Math.random()
|
's'
|
||||||
.toString(36)
|
);
|
||||||
.substring(7)
|
|
||||||
),
|
const invalidNuGetConfig = `<?xml version="1.0" encoding="utf-8"?>`;
|
||||||
's'
|
|
||||||
);
|
const emptyNuGetConfig = `<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
const invalidNuGetConfig: string = `<?xml version="1.0" encoding="utf-8"?>`;
|
</configuration>`;
|
||||||
|
|
||||||
const emptyNuGetConfig: string = `<?xml version="1.0" encoding="utf-8"?>
|
const nugetorgNuGetConfig = `<?xml version="1.0" encoding="utf-8"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
</configuration>`;
|
<packageSources>
|
||||||
|
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
|
||||||
const nugetorgNuGetConfig: string = `<?xml version="1.0" encoding="utf-8"?>
|
</packageSources>
|
||||||
<configuration>
|
</configuration>`;
|
||||||
<packageSources>
|
|
||||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
|
const gprnugetorgNuGetConfig = `<?xml version="1.0" encoding="utf-8"?>
|
||||||
</packageSources>
|
<configuration>
|
||||||
</configuration>`;
|
<packageSources>
|
||||||
|
<add key="GPR" value="https://nuget.pkg.github.com/OwnerName/index.json" protocolVersion="3" />
|
||||||
const gprnugetorgNuGetConfig: string = `<?xml version="1.0" encoding="utf-8"?>
|
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
|
||||||
<configuration>
|
</packageSources>
|
||||||
<packageSources>
|
</configuration>`;
|
||||||
<add key="GPR" value="https://nuget.pkg.github.com/OwnerName/index.json" protocolVersion="3" />
|
|
||||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
|
const gprNuGetConfig = `<?xml version="1.0" encoding="utf-8"?>
|
||||||
</packageSources>
|
<configuration>
|
||||||
</configuration>`;
|
<packageSources>
|
||||||
|
<add key="GPR" value="https://nuget.pkg.github.com/OwnerName/index.json" protocolVersion="3" />
|
||||||
const gprNuGetConfig: string = `<?xml version="1.0" encoding="utf-8"?>
|
</packageSources>
|
||||||
<configuration>
|
</configuration>`;
|
||||||
<packageSources>
|
|
||||||
<add key="GPR" value="https://nuget.pkg.github.com/OwnerName/index.json" protocolVersion="3" />
|
const twogprNuGetConfig = `<?xml version="1.0" encoding="utf-8"?>
|
||||||
</packageSources>
|
<configuration>
|
||||||
</configuration>`;
|
<packageSources>
|
||||||
|
<add key="GPR-GitHub" value="https://nuget.pkg.github.com/OwnerName/index.json" protocolVersion="3" />
|
||||||
const twogprNuGetConfig: string = `<?xml version="1.0" encoding="utf-8"?>
|
<add key="GPR-Actions" value="https://nuget.pkg.github.com/actions/index.json" protocolVersion="3" />
|
||||||
<configuration>
|
</packageSources>
|
||||||
<packageSources>
|
</configuration>`;
|
||||||
<add key="GPR-GitHub" value="https://nuget.pkg.github.com/OwnerName/index.json" protocolVersion="3" />
|
|
||||||
<add key="GPR-Actions" value="https://nuget.pkg.github.com/actions/index.json" protocolVersion="3" />
|
const spaceNuGetConfig = `<?xml version="1.0" encoding="utf-8"?>
|
||||||
</packageSources>
|
<configuration>
|
||||||
</configuration>`;
|
<packageSources>
|
||||||
|
<add key="GPR GitHub" value="https://nuget.pkg.github.com/OwnerName/index.json" protocolVersion="3" />
|
||||||
const spaceNuGetConfig: string = `<?xml version="1.0" encoding="utf-8"?>
|
</packageSources>
|
||||||
<configuration>
|
</configuration>`;
|
||||||
<packageSources>
|
|
||||||
<add key="GPR GitHub" value="https://nuget.pkg.github.com/OwnerName/index.json" protocolVersion="3" />
|
const azureartifactsNuGetConfig = `<?xml version="1.0" encoding="utf-8"?>
|
||||||
</packageSources>
|
<configuration>
|
||||||
</configuration>`;
|
<packageSources>
|
||||||
|
<add key="AzureArtifacts" value="https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json" protocolVersion="3" />
|
||||||
const azureartifactsNuGetConfig: string = `<?xml version="1.0" encoding="utf-8"?>
|
</packageSources>
|
||||||
<configuration>
|
</configuration>`;
|
||||||
<packageSources>
|
|
||||||
<add key="AzureArtifacts" value="https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json" protocolVersion="3" />
|
const azureartifactsnugetorgNuGetConfig = `<?xml version="1.0" encoding="utf-8"?>
|
||||||
</packageSources>
|
<configuration>
|
||||||
</configuration>`;
|
<packageSources>
|
||||||
|
<add key="AzureArtifacts" value="https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json" protocolVersion="3" />
|
||||||
const azureartifactsnugetorgNuGetConfig: string = `<?xml version="1.0" encoding="utf-8"?>
|
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
|
||||||
<configuration>
|
</packageSources>
|
||||||
<packageSources>
|
</configuration>`;
|
||||||
<add key="AzureArtifacts" value="https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json" protocolVersion="3" />
|
|
||||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
|
// We want a NuGet.config one level above the sources directory, so it doesn't trample a user's NuGet.config but is still picked up by NuGet/dotnet.
|
||||||
</packageSources>
|
const nugetConfigFile = path.join(fakeSourcesDirForTesting, '../nuget.config');
|
||||||
</configuration>`;
|
|
||||||
|
process.env['GITHUB_REPOSITORY'] = 'OwnerName/repo';
|
||||||
// We want a NuGet.config one level above the sources directory, so it doesn't trample a user's NuGet.config but is still picked up by NuGet/dotnet.
|
import * as auth from '../src/authutil';
|
||||||
const nugetConfigFile = path.join(fakeSourcesDirForTesting, '../nuget.config');
|
|
||||||
|
describe('authutil tests', () => {
|
||||||
process.env['GITHUB_REPOSITORY'] = 'OwnerName/repo';
|
beforeEach(async () => {
|
||||||
import * as auth from '../src/authutil';
|
await io.rmRF(fakeSourcesDirForTesting);
|
||||||
|
await io.mkdirP(fakeSourcesDirForTesting);
|
||||||
describe('authutil tests', () => {
|
}, 30000);
|
||||||
beforeEach(async () => {
|
|
||||||
await io.rmRF(fakeSourcesDirForTesting);
|
afterAll(async () => {
|
||||||
await io.mkdirP(fakeSourcesDirForTesting);
|
await io.rmRF(fakeSourcesDirForTesting);
|
||||||
}, 30000);
|
}, 30000);
|
||||||
|
|
||||||
afterAll(async () => {
|
beforeEach(() => {
|
||||||
await io.rmRF(fakeSourcesDirForTesting);
|
if (fs.existsSync(nugetConfigFile)) {
|
||||||
}, 30000);
|
fs.unlinkSync(nugetConfigFile);
|
||||||
|
}
|
||||||
beforeEach(() => {
|
process.env['INPUT_OWNER'] = '';
|
||||||
if (fs.existsSync(nugetConfigFile)) {
|
process.env['NUGET_AUTH_TOKEN'] = '';
|
||||||
fs.unlinkSync(nugetConfigFile);
|
});
|
||||||
}
|
|
||||||
process.env['INPUT_OWNER'] = '';
|
it('no existing config, sets up a full NuGet.config with URL and user/PAT for GPR', async () => {
|
||||||
process.env['NUGET_AUTH_TOKEN'] = '';
|
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||||
});
|
auth.configAuthentication(
|
||||||
|
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||||
it('No existing config, sets up a full NuGet.config with URL and user/PAT for GPR', async () => {
|
'',
|
||||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
fakeSourcesDirForTesting
|
||||||
await auth.configAuthentication(
|
);
|
||||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||||
'',
|
expect(
|
||||||
fakeSourcesDirForTesting
|
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||||
);
|
).toMatchSnapshot();
|
||||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
});
|
||||||
expect(
|
|
||||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
it('no existing config, auth token environment variable not provided, throws', async () => {
|
||||||
).toMatchSnapshot();
|
let thrown = false;
|
||||||
});
|
try {
|
||||||
|
auth.configAuthentication(
|
||||||
it('No existing config, auth token environment variable not provided, throws', async () => {
|
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||||
let thrown = false;
|
'',
|
||||||
try {
|
fakeSourcesDirForTesting
|
||||||
await auth.configAuthentication(
|
);
|
||||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
} catch {
|
||||||
'',
|
thrown = true;
|
||||||
fakeSourcesDirForTesting
|
}
|
||||||
);
|
expect(thrown).toBe(true);
|
||||||
} catch {
|
});
|
||||||
thrown = true;
|
|
||||||
}
|
it('no existing config, sets up a full NuGet.config with URL and other owner/PAT for GPR', async () => {
|
||||||
expect(thrown).toBe(true);
|
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||||
});
|
process.env['INPUT_OWNER'] = 'otherorg';
|
||||||
|
auth.configAuthentication(
|
||||||
it('No existing config, sets up a full NuGet.config with URL and other owner/PAT for GPR', async () => {
|
'https://nuget.pkg.github.com/otherorg/index.json',
|
||||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
'',
|
||||||
process.env['INPUT_OWNER'] = 'otherorg';
|
fakeSourcesDirForTesting
|
||||||
await auth.configAuthentication(
|
);
|
||||||
'https://nuget.pkg.github.com/otherorg/index.json',
|
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||||
'',
|
expect(
|
||||||
fakeSourcesDirForTesting
|
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||||
);
|
).toMatchSnapshot();
|
||||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
});
|
||||||
expect(
|
|
||||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
it('existing config (invalid), tries to parse an invalid NuGet.config and throws', async () => {
|
||||||
).toMatchSnapshot();
|
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||||
});
|
const inputNuGetConfigPath: string = path.join(
|
||||||
|
fakeSourcesDirForTesting,
|
||||||
it('Existing config (invalid), tries to parse an invalid NuGet.config and throws', async () => {
|
'nuget.config'
|
||||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
);
|
||||||
const inputNuGetConfigPath: string = path.join(
|
fs.writeFileSync(inputNuGetConfigPath, invalidNuGetConfig);
|
||||||
fakeSourcesDirForTesting,
|
let thrown = false;
|
||||||
'nuget.config'
|
try {
|
||||||
);
|
auth.configAuthentication(
|
||||||
fs.writeFileSync(inputNuGetConfigPath, invalidNuGetConfig);
|
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||||
let thrown = false;
|
'',
|
||||||
try {
|
fakeSourcesDirForTesting
|
||||||
await auth.configAuthentication(
|
);
|
||||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
} catch {
|
||||||
'',
|
thrown = true;
|
||||||
fakeSourcesDirForTesting
|
}
|
||||||
);
|
expect(thrown).toBe(true);
|
||||||
} catch {
|
});
|
||||||
thrown = true;
|
|
||||||
}
|
it('existing config w/ no sources, sets up a full NuGet.config with URL and user/PAT for GPR', async () => {
|
||||||
expect(thrown).toBe(true);
|
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||||
});
|
const inputNuGetConfigPath: string = path.join(
|
||||||
|
fakeSourcesDirForTesting,
|
||||||
it('Existing config w/ no sources, sets up a full NuGet.config with URL and user/PAT for GPR', async () => {
|
'nuget.config'
|
||||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
);
|
||||||
const inputNuGetConfigPath: string = path.join(
|
fs.writeFileSync(inputNuGetConfigPath, emptyNuGetConfig);
|
||||||
fakeSourcesDirForTesting,
|
auth.configAuthentication(
|
||||||
'nuget.config'
|
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||||
);
|
'',
|
||||||
fs.writeFileSync(inputNuGetConfigPath, emptyNuGetConfig);
|
fakeSourcesDirForTesting
|
||||||
await auth.configAuthentication(
|
);
|
||||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||||
'',
|
expect(
|
||||||
fakeSourcesDirForTesting
|
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||||
);
|
).toMatchSnapshot();
|
||||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
});
|
||||||
expect(
|
|
||||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
it('existing config w/ no GPR sources, sets up a full NuGet.config with URL and user/PAT for GPR', async () => {
|
||||||
).toMatchSnapshot();
|
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||||
});
|
const inputNuGetConfigPath: string = path.join(
|
||||||
|
fakeSourcesDirForTesting,
|
||||||
it('Existing config w/ no GPR sources, sets up a full NuGet.config with URL and user/PAT for GPR', async () => {
|
'nuget.config'
|
||||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
);
|
||||||
const inputNuGetConfigPath: string = path.join(
|
fs.writeFileSync(inputNuGetConfigPath, nugetorgNuGetConfig);
|
||||||
fakeSourcesDirForTesting,
|
auth.configAuthentication(
|
||||||
'nuget.config'
|
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||||
);
|
'',
|
||||||
fs.writeFileSync(inputNuGetConfigPath, nugetorgNuGetConfig);
|
fakeSourcesDirForTesting
|
||||||
await auth.configAuthentication(
|
);
|
||||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||||
'',
|
expect(
|
||||||
fakeSourcesDirForTesting
|
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||||
);
|
).toMatchSnapshot();
|
||||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
});
|
||||||
expect(
|
|
||||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
it('existing config w/ only GPR source, sets up a partial NuGet.config user/PAT for GPR', async () => {
|
||||||
).toMatchSnapshot();
|
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||||
});
|
const inputNuGetConfigPath: string = path.join(
|
||||||
|
fakeSourcesDirForTesting,
|
||||||
it('Existing config w/ only GPR source, sets up a partial NuGet.config user/PAT for GPR', async () => {
|
'nuget.config'
|
||||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
);
|
||||||
const inputNuGetConfigPath: string = path.join(
|
fs.writeFileSync(inputNuGetConfigPath, gprNuGetConfig);
|
||||||
fakeSourcesDirForTesting,
|
auth.configAuthentication(
|
||||||
'nuget.config'
|
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||||
);
|
'',
|
||||||
fs.writeFileSync(inputNuGetConfigPath, gprNuGetConfig);
|
fakeSourcesDirForTesting
|
||||||
await auth.configAuthentication(
|
);
|
||||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||||
'',
|
expect(
|
||||||
fakeSourcesDirForTesting
|
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||||
);
|
).toMatchSnapshot();
|
||||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
});
|
||||||
expect(
|
|
||||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
it('existing config w/ GPR source and NuGet.org, sets up a partial NuGet.config user/PAT for GPR', async () => {
|
||||||
).toMatchSnapshot();
|
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||||
});
|
const inputNuGetConfigPath: string = path.join(
|
||||||
|
fakeSourcesDirForTesting,
|
||||||
it('Existing config w/ GPR source and NuGet.org, sets up a partial NuGet.config user/PAT for GPR', async () => {
|
'nuget.config'
|
||||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
);
|
||||||
const inputNuGetConfigPath: string = path.join(
|
fs.writeFileSync(inputNuGetConfigPath, gprnugetorgNuGetConfig);
|
||||||
fakeSourcesDirForTesting,
|
auth.configAuthentication(
|
||||||
'nuget.config'
|
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||||
);
|
'',
|
||||||
fs.writeFileSync(inputNuGetConfigPath, gprnugetorgNuGetConfig);
|
fakeSourcesDirForTesting
|
||||||
await auth.configAuthentication(
|
);
|
||||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||||
'',
|
expect(
|
||||||
fakeSourcesDirForTesting
|
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||||
);
|
).toMatchSnapshot();
|
||||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
});
|
||||||
expect(
|
|
||||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
it('existing config w/ two GPR sources, sets up a partial NuGet.config user/PAT for GPR', async () => {
|
||||||
).toMatchSnapshot();
|
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||||
});
|
const inputNuGetConfigPath: string = path.join(
|
||||||
|
fakeSourcesDirForTesting,
|
||||||
it('Existing config w/ two GPR sources, sets up a partial NuGet.config user/PAT for GPR', async () => {
|
'nuget.config'
|
||||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
);
|
||||||
const inputNuGetConfigPath: string = path.join(
|
fs.writeFileSync(inputNuGetConfigPath, twogprNuGetConfig);
|
||||||
fakeSourcesDirForTesting,
|
auth.configAuthentication(
|
||||||
'nuget.config'
|
'https://nuget.pkg.github.com',
|
||||||
);
|
'',
|
||||||
fs.writeFileSync(inputNuGetConfigPath, twogprNuGetConfig);
|
fakeSourcesDirForTesting
|
||||||
await auth.configAuthentication(
|
);
|
||||||
'https://nuget.pkg.github.com',
|
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||||
'',
|
expect(
|
||||||
fakeSourcesDirForTesting
|
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||||
);
|
).toMatchSnapshot();
|
||||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
});
|
||||||
expect(
|
|
||||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
it('existing config w/ spaces in key, throws for now', async () => {
|
||||||
).toMatchSnapshot();
|
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||||
});
|
const inputNuGetConfigPath: string = path.join(
|
||||||
|
fakeSourcesDirForTesting,
|
||||||
it('Existing config w/ spaces in key, throws for now', async () => {
|
'nuget.config'
|
||||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
);
|
||||||
const inputNuGetConfigPath: string = path.join(
|
fs.writeFileSync(inputNuGetConfigPath, spaceNuGetConfig);
|
||||||
fakeSourcesDirForTesting,
|
let thrown = false;
|
||||||
'nuget.config'
|
try {
|
||||||
);
|
auth.configAuthentication(
|
||||||
fs.writeFileSync(inputNuGetConfigPath, spaceNuGetConfig);
|
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||||
let thrown = false;
|
'',
|
||||||
try {
|
fakeSourcesDirForTesting
|
||||||
await auth.configAuthentication(
|
);
|
||||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
} catch {
|
||||||
'',
|
thrown = true;
|
||||||
fakeSourcesDirForTesting
|
}
|
||||||
);
|
expect(thrown).toBe(true);
|
||||||
} catch {
|
});
|
||||||
thrown = true;
|
|
||||||
}
|
it('existing config not in repo root, sets up a partial NuGet.config user/PAT for GPR', async () => {
|
||||||
expect(thrown).toBe(true);
|
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||||
});
|
const inputNuGetConfigDirectory: string = path.join(
|
||||||
|
fakeSourcesDirForTesting,
|
||||||
it('Existing config not in repo root, sets up a partial NuGet.config user/PAT for GPR', async () => {
|
'subfolder'
|
||||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
);
|
||||||
const inputNuGetConfigDirectory: string = path.join(
|
const inputNuGetConfigPath: string = path.join(
|
||||||
fakeSourcesDirForTesting,
|
inputNuGetConfigDirectory,
|
||||||
'subfolder'
|
'nuget.config'
|
||||||
);
|
);
|
||||||
const inputNuGetConfigPath: string = path.join(
|
fs.mkdirSync(inputNuGetConfigDirectory, {recursive: true});
|
||||||
inputNuGetConfigDirectory,
|
fs.writeFileSync(inputNuGetConfigPath, gprNuGetConfig);
|
||||||
'nuget.config'
|
auth.configAuthentication(
|
||||||
);
|
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||||
fs.mkdirSync(inputNuGetConfigDirectory, {recursive: true});
|
'subfolder/nuget.config',
|
||||||
fs.writeFileSync(inputNuGetConfigPath, gprNuGetConfig);
|
fakeSourcesDirForTesting
|
||||||
await auth.configAuthentication(
|
);
|
||||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||||
'subfolder/nuget.config',
|
expect(
|
||||||
fakeSourcesDirForTesting
|
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||||
);
|
).toMatchSnapshot();
|
||||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
});
|
||||||
expect(
|
|
||||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
it('existing config w/ only Azure Artifacts source, sets up a partial NuGet.config user/PAT for GPR', async () => {
|
||||||
).toMatchSnapshot();
|
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||||
});
|
const inputNuGetConfigPath: string = path.join(
|
||||||
|
fakeSourcesDirForTesting,
|
||||||
it('Existing config w/ only Azure Artifacts source, sets up a partial NuGet.config user/PAT for GPR', async () => {
|
'nuget.config'
|
||||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
);
|
||||||
const inputNuGetConfigPath: string = path.join(
|
fs.writeFileSync(inputNuGetConfigPath, azureartifactsNuGetConfig);
|
||||||
fakeSourcesDirForTesting,
|
auth.configAuthentication(
|
||||||
'nuget.config'
|
'https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json',
|
||||||
);
|
'',
|
||||||
fs.writeFileSync(inputNuGetConfigPath, azureartifactsNuGetConfig);
|
fakeSourcesDirForTesting
|
||||||
await auth.configAuthentication(
|
);
|
||||||
'https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json',
|
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||||
'',
|
expect(
|
||||||
fakeSourcesDirForTesting
|
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||||
);
|
).toMatchSnapshot();
|
||||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
});
|
||||||
expect(
|
|
||||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
it('existing config w/ Azure Artifacts source and NuGet.org, sets up a partial NuGet.config user/PAT for GPR', async () => {
|
||||||
).toMatchSnapshot();
|
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||||
});
|
const inputNuGetConfigPath: string = path.join(
|
||||||
|
fakeSourcesDirForTesting,
|
||||||
it('Existing config w/ Azure Artifacts source and NuGet.org, sets up a partial NuGet.config user/PAT for GPR', async () => {
|
'nuget.config'
|
||||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
);
|
||||||
const inputNuGetConfigPath: string = path.join(
|
fs.writeFileSync(inputNuGetConfigPath, azureartifactsnugetorgNuGetConfig);
|
||||||
fakeSourcesDirForTesting,
|
auth.configAuthentication(
|
||||||
'nuget.config'
|
'https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json',
|
||||||
);
|
'',
|
||||||
fs.writeFileSync(inputNuGetConfigPath, azureartifactsnugetorgNuGetConfig);
|
fakeSourcesDirForTesting
|
||||||
await auth.configAuthentication(
|
);
|
||||||
'https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json',
|
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||||
'',
|
expect(
|
||||||
fakeSourcesDirForTesting
|
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||||
);
|
).toMatchSnapshot();
|
||||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
});
|
||||||
expect(
|
|
||||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
it('no existing config, sets up a full NuGet.config with URL and token for other source', async () => {
|
||||||
).toMatchSnapshot();
|
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||||
});
|
auth.configAuthentication(
|
||||||
|
'https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json',
|
||||||
it('No existing config, sets up a full NuGet.config with URL and token for other source', async () => {
|
'',
|
||||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
fakeSourcesDirForTesting
|
||||||
await auth.configAuthentication(
|
);
|
||||||
'https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json',
|
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||||
'',
|
expect(
|
||||||
fakeSourcesDirForTesting
|
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||||
);
|
).toMatchSnapshot();
|
||||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
});
|
||||||
expect(
|
});
|
||||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
|
||||||
).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
@ -1,21 +1,45 @@
|
|||||||
|
import cscFile from '../.github/csc.json';
|
||||||
describe('csc tests', () => {
|
describe('csc tests', () => {
|
||||||
it('Valid regular expression', async () => {
|
test('regular expression in csc.json is valid', async () => {
|
||||||
var cscFile = require('../.github/csc.json');
|
const regexPattern = cscFile['problemMatcher'][0]['pattern'][0]['regexp'];
|
||||||
var regex = cscFile['problemMatcher'][0]['pattern'][0]['regexp'];
|
const regexResultsMap = cscFile['problemMatcher'][0]['pattern'][0];
|
||||||
|
|
||||||
console.log(regex);
|
const regex = new RegExp(regexPattern);
|
||||||
var re = new RegExp(regex);
|
|
||||||
|
|
||||||
// Ideally we would verify that this
|
const stringsToMatch = [
|
||||||
var stringsToMatch = [
|
|
||||||
'Program.cs(10,79): error CS1002: ; expected [/Users/zacharyeisinger/Documents/repo/setup-dotnet/__tests__/sample-broken-csproj/sample.csproj]',
|
'Program.cs(10,79): error CS1002: ; expected [/Users/zacharyeisinger/Documents/repo/setup-dotnet/__tests__/sample-broken-csproj/sample.csproj]',
|
||||||
"S:\\Msbuild\\src\\Build\\Evaluation\\ExpressionShredder.cs(33,7): error CS1003: Syntax error, ',' expected [S:\\msbuild\\src\\Build\\Microsoft.Build.csproj > Properties:prop]"
|
"S:\\Msbuild\\src\\Build\\Evaluation\\ExpressionShredder.cs(33,7): error CS1003: Syntax error, ',' expected [S:\\msbuild\\src\\Build\\Microsoft.Build.csproj > Properties:prop]"
|
||||||
];
|
];
|
||||||
|
// Expected results are calculated according to the csc matcher located in csc.json file
|
||||||
|
const expectedResults = [
|
||||||
|
{
|
||||||
|
file: 'Program.cs',
|
||||||
|
line: '10',
|
||||||
|
severity: 'error',
|
||||||
|
code: 'CS1002',
|
||||||
|
message: '; expected',
|
||||||
|
fromPath:
|
||||||
|
'/Users/zacharyeisinger/Documents/repo/setup-dotnet/__tests__/sample-broken-csproj/sample.csproj'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: 'S:\\Msbuild\\src\\Build\\Evaluation\\ExpressionShredder.cs',
|
||||||
|
line: '33',
|
||||||
|
severity: 'error',
|
||||||
|
code: 'CS1003',
|
||||||
|
message: "Syntax error, ',' expected",
|
||||||
|
fromPath:
|
||||||
|
'S:\\msbuild\\src\\Build\\Microsoft.Build.csproj > Properties:prop'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
stringsToMatch.forEach(string => {
|
stringsToMatch.map((string, index) => {
|
||||||
var matchStr = string.match(re);
|
const matchedResultsArray = string.match(regex);
|
||||||
console.log(matchStr);
|
for (const propName in expectedResults[index]) {
|
||||||
expect(matchStr).toEqual(expect.anything());
|
const propertyIndex = regexResultsMap[propName];
|
||||||
|
const expectedPropValue = expectedResults[index][propName];
|
||||||
|
const matchedPropValue = matchedResultsArray![propertyIndex];
|
||||||
|
expect(matchedPropValue).toEqual(expectedPropValue);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}, 10000);
|
}, 10000);
|
||||||
});
|
});
|
||||||
|
18
__tests__/e2e-test-csproj/Test.cs
Normal file
18
__tests__/e2e-test-csproj/Test.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace test_csproj
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
public class Test
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void TestMethod()
|
||||||
|
{
|
||||||
|
Console.WriteLine("TestMethod");
|
||||||
|
int calculatedResult = 1000 / 25;
|
||||||
|
int expectedResult = 40;
|
||||||
|
Assert.AreEqual(calculatedResult, expectedResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
15
__tests__/e2e-test-csproj/test.csproj
Normal file
15
__tests__/e2e-test-csproj/test.csproj
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>$(TEST_TARGET_FRAMEWORK)</TargetFramework>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<!-- These packages will be downloaded over the network for testing proxy settings -->
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0-preview-20170810-02" />
|
||||||
|
<PackageReference Include="MSTest.TestAdapter" Version="1.1.18" />
|
||||||
|
<PackageReference Include="MSTest.TestFramework" Version="1.1.18" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
65
__tests__/installation-scripts.test.ts
Normal file
65
__tests__/installation-scripts.test.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import path from 'path';
|
||||||
|
import fs from 'fs';
|
||||||
|
import * as hc from '@actions/http-client';
|
||||||
|
|
||||||
|
const HTTP_CLIENT_OPTIONS = {allowRetries: true, maxRetries: 10} as const;
|
||||||
|
const TEST_TIMEOUT = 30000;
|
||||||
|
|
||||||
|
describe('Dotnet installation scripts tests', () => {
|
||||||
|
it(
|
||||||
|
'Uses an up to date bash download script',
|
||||||
|
async () => {
|
||||||
|
const httpCallbackClient = new hc.HttpClient(
|
||||||
|
'setup-dotnet-test',
|
||||||
|
[],
|
||||||
|
HTTP_CLIENT_OPTIONS
|
||||||
|
);
|
||||||
|
const response: hc.HttpClientResponse = await httpCallbackClient.get(
|
||||||
|
'https://dot.net/v1/dotnet-install.sh'
|
||||||
|
);
|
||||||
|
expect(response.message.statusCode).toBe(200);
|
||||||
|
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)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
TEST_TIMEOUT
|
||||||
|
);
|
||||||
|
|
||||||
|
it(
|
||||||
|
'Uses an up to date powershell download script',
|
||||||
|
async () => {
|
||||||
|
const httpCallbackClient = new hc.HttpClient(
|
||||||
|
'setup-dotnet-test',
|
||||||
|
[],
|
||||||
|
HTTP_CLIENT_OPTIONS
|
||||||
|
);
|
||||||
|
const response: hc.HttpClientResponse = await httpCallbackClient.get(
|
||||||
|
'https://dot.net/v1/dotnet-install.ps1'
|
||||||
|
);
|
||||||
|
expect(response.message.statusCode).toBe(200);
|
||||||
|
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)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
TEST_TIMEOUT
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
function normalizeFileContents(contents: string): string {
|
||||||
|
return contents
|
||||||
|
.trim()
|
||||||
|
.replace(new RegExp('\r\n', 'g'), '\n')
|
||||||
|
.replace(new RegExp('\r', 'g'), '\n');
|
||||||
|
}
|
@ -1,290 +1,443 @@
|
|||||||
import * as io from '@actions/io';
|
|
||||||
import * as os from 'os';
|
|
||||||
import fs from 'fs';
|
|
||||||
import path from 'path';
|
|
||||||
import each from 'jest-each';
|
import each from 'jest-each';
|
||||||
import * as hc from '@actions/http-client';
|
import semver from 'semver';
|
||||||
|
import * as exec from '@actions/exec';
|
||||||
|
import * as core from '@actions/core';
|
||||||
|
import * as io from '@actions/io';
|
||||||
import * as installer from '../src/installer';
|
import * as installer from '../src/installer';
|
||||||
import {QualityOptions} from '../src/setup-dotnet';
|
|
||||||
|
|
||||||
import {IS_WINDOWS} from '../src/utils';
|
import {IS_WINDOWS} from '../src/utils';
|
||||||
import {IS_LINUX} from '../src/utils';
|
import {QualityOptions} from '../src/setup-dotnet';
|
||||||
|
|
||||||
let toolDir: string;
|
describe('installer tests', () => {
|
||||||
|
const env = process.env;
|
||||||
|
|
||||||
if (IS_WINDOWS) {
|
beforeEach(() => {
|
||||||
toolDir = path.join(process.env['PROGRAMFILES'] + '', 'dotnet');
|
jest.resetModules();
|
||||||
} else if (IS_LINUX) {
|
process.env = {...env};
|
||||||
toolDir = '/usr/share/dotnet';
|
});
|
||||||
} else {
|
|
||||||
toolDir = path.join(process.env['HOME'] + '', '.dotnet');
|
|
||||||
}
|
|
||||||
const tempDir = path.join(__dirname, 'runner', 'temp');
|
|
||||||
|
|
||||||
process.env['RUNNER_TOOL_CACHE'] = toolDir;
|
describe('DotnetCoreInstaller tests', () => {
|
||||||
process.env['RUNNER_TEMP'] = tempDir;
|
const getExecOutputSpy = jest.spyOn(exec, 'getExecOutput');
|
||||||
|
const warningSpy = jest.spyOn(core, 'warning');
|
||||||
|
const whichSpy = jest.spyOn(io, 'which');
|
||||||
|
const maxSatisfyingSpy = jest.spyOn(semver, 'maxSatisfying');
|
||||||
|
|
||||||
describe('DotnetCoreInstaller tests', () => {
|
describe('installDotnet() tests', () => {
|
||||||
beforeAll(async () => {
|
whichSpy.mockImplementation(() => Promise.resolve('PathToShell'));
|
||||||
process.env.RUNNER_TOOL_CACHE = toolDir;
|
|
||||||
process.env.DOTNET_INSTALL_DIR = toolDir;
|
|
||||||
process.env.RUNNER_TEMP = tempDir;
|
|
||||||
process.env.DOTNET_ROOT = '';
|
|
||||||
try {
|
|
||||||
await io.rmRF(`${toolDir}/*`);
|
|
||||||
await io.rmRF(`${tempDir}/*`);
|
|
||||||
} catch (err) {
|
|
||||||
console.log(
|
|
||||||
`Failed to remove test directories, check the error message:${os.EOL}`,
|
|
||||||
err.message
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}, 30000);
|
|
||||||
|
|
||||||
afterEach(async () => {
|
it('should throw the error in case of non-zero exit code of the installation script. The error message should contain logs.', async () => {
|
||||||
try {
|
const inputVersion = '3.1.100';
|
||||||
await io.rmRF(`${toolDir}/*`);
|
const inputQuality = '' as QualityOptions;
|
||||||
await io.rmRF(`${tempDir}/*`);
|
const errorMessage = 'fictitious error message!';
|
||||||
} catch (err) {
|
getExecOutputSpy.mockImplementation(() => {
|
||||||
console.log(
|
return Promise.resolve({
|
||||||
`Failed to remove test directories, check the error message:${os.EOL}`,
|
exitCode: 1,
|
||||||
err.message
|
stdout: '',
|
||||||
);
|
stderr: errorMessage
|
||||||
}
|
});
|
||||||
}, 30000);
|
});
|
||||||
|
const dotnetInstaller = new installer.DotnetCoreInstaller(
|
||||||
|
inputVersion,
|
||||||
|
inputQuality
|
||||||
|
);
|
||||||
|
await expect(dotnetInstaller.installDotnet()).rejects.toThrow(
|
||||||
|
`Failed to install dotnet, exit code: 1. ${errorMessage}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('Aquires multiple versions of dotnet', async () => {
|
it('should return version of .NET SDK after installation complete', async () => {
|
||||||
const versions = ['2.2.207', '3.1.120'];
|
const inputVersion = '3.1.100';
|
||||||
|
const inputQuality = '' as QualityOptions;
|
||||||
|
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
||||||
|
getExecOutputSpy.mockImplementation(() => {
|
||||||
|
return Promise.resolve({
|
||||||
|
exitCode: 0,
|
||||||
|
stdout: `${stdout}`,
|
||||||
|
stderr: ''
|
||||||
|
});
|
||||||
|
});
|
||||||
|
maxSatisfyingSpy.mockImplementation(() => inputVersion);
|
||||||
|
|
||||||
for (const version of versions) {
|
const dotnetInstaller = new installer.DotnetCoreInstaller(
|
||||||
await getDotnet(version);
|
inputVersion,
|
||||||
}
|
inputQuality
|
||||||
expect(fs.existsSync(path.join(toolDir, 'sdk', '2.2.207'))).toBe(true);
|
);
|
||||||
expect(fs.existsSync(path.join(toolDir, 'sdk', '3.1.120'))).toBe(true);
|
const installedVersion = await dotnetInstaller.installDotnet();
|
||||||
|
|
||||||
if (IS_WINDOWS) {
|
expect(installedVersion).toBe(inputVersion);
|
||||||
expect(fs.existsSync(path.join(toolDir, 'dotnet.exe'))).toBe(true);
|
});
|
||||||
} else {
|
|
||||||
expect(fs.existsSync(path.join(toolDir, 'dotnet'))).toBe(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(process.env.DOTNET_ROOT).toBeDefined;
|
it(`should supply 'version' argument to the installation script if supplied version is in A.B.C syntax`, async () => {
|
||||||
expect(process.env.PATH).toBeDefined;
|
const inputVersion = '6.0.300';
|
||||||
expect(process.env.DOTNET_ROOT).toBe(toolDir);
|
const inputQuality = '' as QualityOptions;
|
||||||
expect(process.env.PATH?.startsWith(toolDir)).toBe(true);
|
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
||||||
}, 600000);
|
|
||||||
|
|
||||||
it('Acquires version of dotnet if no matching version is installed', async () => {
|
getExecOutputSpy.mockImplementation(() => {
|
||||||
await getDotnet('3.1.201');
|
return Promise.resolve({
|
||||||
expect(fs.existsSync(path.join(toolDir, 'sdk', '3.1.201'))).toBe(true);
|
exitCode: 0,
|
||||||
if (IS_WINDOWS) {
|
stdout: `${stdout}`,
|
||||||
expect(fs.existsSync(path.join(toolDir, 'dotnet.exe'))).toBe(true);
|
stderr: ''
|
||||||
} else {
|
});
|
||||||
expect(fs.existsSync(path.join(toolDir, 'dotnet'))).toBe(true);
|
});
|
||||||
}
|
maxSatisfyingSpy.mockImplementation(() => inputVersion);
|
||||||
|
|
||||||
expect(process.env.DOTNET_ROOT).toBeDefined;
|
const dotnetInstaller = new installer.DotnetCoreInstaller(
|
||||||
expect(process.env.PATH).toBeDefined;
|
inputVersion,
|
||||||
expect(process.env.DOTNET_ROOT).toBe(toolDir);
|
inputQuality
|
||||||
expect(process.env.PATH?.startsWith(toolDir)).toBe(true);
|
);
|
||||||
}, 600000); //This needs some time to download on "slower" internet connections
|
|
||||||
|
|
||||||
it('Acquires generic version of dotnet if no matching version is installed', async () => {
|
await dotnetInstaller.installDotnet();
|
||||||
await getDotnet('3.1');
|
|
||||||
var directory = fs
|
|
||||||
.readdirSync(path.join(toolDir, 'sdk'))
|
|
||||||
.filter(fn => fn.startsWith('3.1.'));
|
|
||||||
expect(directory.length > 0).toBe(true);
|
|
||||||
if (IS_WINDOWS) {
|
|
||||||
expect(fs.existsSync(path.join(toolDir, 'dotnet.exe'))).toBe(true);
|
|
||||||
} else {
|
|
||||||
expect(fs.existsSync(path.join(toolDir, 'dotnet'))).toBe(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(process.env.DOTNET_ROOT).toBeDefined;
|
const scriptArguments = (
|
||||||
expect(process.env.PATH).toBeDefined;
|
getExecOutputSpy.mock.calls[0][1] as string[]
|
||||||
expect(process.env.DOTNET_ROOT).toBe(toolDir);
|
).join(' ');
|
||||||
expect(process.env.PATH?.startsWith(toolDir)).toBe(true);
|
const expectedArgument = IS_WINDOWS
|
||||||
}, 600000); //This needs some time to download on "slower" internet connections
|
? `-Version ${inputVersion}`
|
||||||
|
: `--version ${inputVersion}`;
|
||||||
|
|
||||||
it('Returns string with installed SDK version', async () => {
|
expect(scriptArguments).toContain(expectedArgument);
|
||||||
const version = '3.1.120';
|
});
|
||||||
let installedVersion: string;
|
|
||||||
|
|
||||||
installedVersion = await getDotnet(version);
|
it(`should warn if the 'quality' input is set and the supplied version is in A.B.C syntax`, async () => {
|
||||||
|
const inputVersion = '6.0.300';
|
||||||
|
const inputQuality = 'ga' as QualityOptions;
|
||||||
|
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
||||||
|
getExecOutputSpy.mockImplementation(() => {
|
||||||
|
return Promise.resolve({
|
||||||
|
exitCode: 0,
|
||||||
|
stdout: `${stdout}`,
|
||||||
|
stderr: ''
|
||||||
|
});
|
||||||
|
});
|
||||||
|
maxSatisfyingSpy.mockImplementation(() => inputVersion);
|
||||||
|
|
||||||
expect(installedVersion).toBe('3.1.120');
|
const dotnetInstaller = new installer.DotnetCoreInstaller(
|
||||||
}, 600000);
|
inputVersion,
|
||||||
|
inputQuality
|
||||||
|
);
|
||||||
|
|
||||||
it('Throws if no location contains correct dotnet version', async () => {
|
await dotnetInstaller.installDotnet();
|
||||||
await expect(async () => {
|
|
||||||
await getDotnet('1000.0.0');
|
|
||||||
}).rejects.toThrow();
|
|
||||||
}, 30000);
|
|
||||||
|
|
||||||
it('Uses an up to date bash download script', async () => {
|
expect(warningSpy).toHaveBeenCalledWith(
|
||||||
const httpCallbackClient = new hc.HttpClient('setup-dotnet-test', [], {
|
`The 'dotnet-quality' input can be used only with .NET SDK version in A.B, A.B.x, A, A.x and A.B.Cxx formats where the major tag is higher than 5. You specified: ${inputVersion}. 'dotnet-quality' input is ignored.`
|
||||||
allowRetries: true,
|
);
|
||||||
maxRetries: 3
|
});
|
||||||
});
|
|
||||||
const response: hc.HttpClientResponse = await httpCallbackClient.get(
|
|
||||||
'https://dot.net/v1/dotnet-install.sh'
|
|
||||||
);
|
|
||||||
expect(response.message.statusCode).toBe(200);
|
|
||||||
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)
|
|
||||||
);
|
|
||||||
}, 30000);
|
|
||||||
|
|
||||||
it('Uses an up to date powershell download script', async () => {
|
it(`should warn if the 'quality' input is set and version isn't in A.B.C syntax but major tag is lower then 6`, async () => {
|
||||||
var httpCallbackClient = new hc.HttpClient('setup-dotnet-test', [], {
|
const inputVersion = '3.1';
|
||||||
allowRetries: true,
|
const inputQuality = 'ga' as QualityOptions;
|
||||||
maxRetries: 3
|
const stdout = `Fictitious dotnet version 3.1.100 is installed`;
|
||||||
});
|
|
||||||
const response: hc.HttpClientResponse = await httpCallbackClient.get(
|
|
||||||
'https://dot.net/v1/dotnet-install.ps1'
|
|
||||||
);
|
|
||||||
expect(response.message.statusCode).toBe(200);
|
|
||||||
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)
|
|
||||||
);
|
|
||||||
}, 30000);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('DotnetVersionResolver tests', () => {
|
getExecOutputSpy.mockImplementation(() => {
|
||||||
each([
|
return Promise.resolve({
|
||||||
'3.1',
|
exitCode: 0,
|
||||||
'3.x',
|
stdout: `${stdout}`,
|
||||||
'3.1.x',
|
stderr: ''
|
||||||
'3.1.*',
|
});
|
||||||
'3.1.X',
|
});
|
||||||
'3.1.2',
|
maxSatisfyingSpy.mockImplementation(() => inputVersion);
|
||||||
'3.1.0-preview1'
|
|
||||||
]).test(
|
|
||||||
"if valid version: '%s' is supplied, it should return version object with some value",
|
|
||||||
async version => {
|
|
||||||
const dotnetVersionResolver = new installer.DotnetVersionResolver(
|
|
||||||
version
|
|
||||||
);
|
|
||||||
const versionObject = await dotnetVersionResolver.createDotNetVersion();
|
|
||||||
|
|
||||||
expect(!!versionObject.value).toBeTruthy;
|
const dotnetInstaller = new installer.DotnetCoreInstaller(
|
||||||
}
|
inputVersion,
|
||||||
);
|
inputQuality
|
||||||
|
);
|
||||||
|
|
||||||
each([
|
await dotnetInstaller.installDotnet();
|
||||||
'.',
|
|
||||||
'..',
|
expect(warningSpy).toHaveBeenCalledWith(
|
||||||
' . ',
|
`The 'dotnet-quality' input can be used only with .NET SDK version in A.B, A.B.x, A, A.x and A.B.Cxx formats where the major tag is higher than 5. You specified: ${inputVersion}. 'dotnet-quality' input is ignored.`
|
||||||
'. ',
|
);
|
||||||
' .',
|
});
|
||||||
' . . ',
|
|
||||||
' .. ',
|
each(['6', '6.0', '6.0.x', '6.0.*', '6.0.X']).test(
|
||||||
' . ',
|
`should supply 'quality' argument to the installation script if quality input is set and version (%s) is not in A.B.C syntax`,
|
||||||
'-1.-1',
|
async inputVersion => {
|
||||||
'-1',
|
const inputQuality = 'ga' as QualityOptions;
|
||||||
'-1.-1.-1',
|
const exitCode = 0;
|
||||||
'..3',
|
const stdout = `Fictitious dotnet version 6.0.0 is installed`;
|
||||||
'1..3',
|
getExecOutputSpy.mockImplementation(() => {
|
||||||
'1..',
|
return Promise.resolve({
|
||||||
'.2.3',
|
exitCode: exitCode,
|
||||||
'.2.x',
|
stdout: `${stdout}`,
|
||||||
'*.',
|
stderr: ''
|
||||||
'1.2.',
|
});
|
||||||
'1.2.-abc',
|
});
|
||||||
'a.b',
|
maxSatisfyingSpy.mockImplementation(() => inputVersion);
|
||||||
'a.b.c',
|
|
||||||
'a.b.c-preview',
|
const dotnetInstaller = new installer.DotnetCoreInstaller(
|
||||||
' 0 . 1 . 2 ',
|
inputVersion,
|
||||||
'invalid'
|
inputQuality
|
||||||
]).test(
|
);
|
||||||
"if invalid version: '%s' is supplied, it should throw",
|
|
||||||
async version => {
|
await dotnetInstaller.installDotnet();
|
||||||
const dotnetVersionResolver = new installer.DotnetVersionResolver(
|
|
||||||
version
|
const scriptArguments = (
|
||||||
|
getExecOutputSpy.mock.calls[0][1] as string[]
|
||||||
|
).join(' ');
|
||||||
|
const expectedArgument = IS_WINDOWS
|
||||||
|
? `-Quality ${inputQuality}`
|
||||||
|
: `--quality ${inputQuality}`;
|
||||||
|
|
||||||
|
expect(scriptArguments).toContain(expectedArgument);
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
await expect(
|
each(['6', '6.0', '6.0.x', '6.0.*', '6.0.X']).test(
|
||||||
async () => await dotnetVersionResolver.createDotNetVersion()
|
`should supply 'channel' argument to the installation script if version (%s) isn't in A.B.C syntax`,
|
||||||
).rejects.toThrow();
|
async inputVersion => {
|
||||||
}
|
const inputQuality = '' as QualityOptions;
|
||||||
);
|
const exitCode = 0;
|
||||||
|
const stdout = `Fictitious dotnet version 6.0.0 is installed`;
|
||||||
|
getExecOutputSpy.mockImplementation(() => {
|
||||||
|
return Promise.resolve({
|
||||||
|
exitCode: exitCode,
|
||||||
|
stdout: `${stdout}`,
|
||||||
|
stderr: ''
|
||||||
|
});
|
||||||
|
});
|
||||||
|
maxSatisfyingSpy.mockImplementation(() => inputVersion);
|
||||||
|
|
||||||
each(['3.1', '3.1.x', '3.1.*', '3.1.X']).test(
|
const dotnetInstaller = new installer.DotnetCoreInstaller(
|
||||||
"if version: '%s' that can be resolved to 'channel' option is supplied, it should set quality flag to 'true' and type to 'channel' in version object",
|
inputVersion,
|
||||||
async version => {
|
inputQuality
|
||||||
const dotnetVersionResolver = new installer.DotnetVersionResolver(
|
);
|
||||||
version
|
|
||||||
|
await dotnetInstaller.installDotnet();
|
||||||
|
|
||||||
|
const scriptArguments = (
|
||||||
|
getExecOutputSpy.mock.calls[0][1] as string[]
|
||||||
|
).join(' ');
|
||||||
|
const expectedArgument = IS_WINDOWS
|
||||||
|
? `-Channel 6.0`
|
||||||
|
: `--channel 6.0`;
|
||||||
|
|
||||||
|
expect(scriptArguments).toContain(expectedArgument);
|
||||||
|
}
|
||||||
);
|
);
|
||||||
const versionObject = await dotnetVersionResolver.createDotNetVersion();
|
|
||||||
|
|
||||||
expect(versionObject.type.toLowerCase().includes('channel')).toBeTruthy;
|
|
||||||
expect(versionObject.qualityFlag).toBeTruthy;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
each(['3.1.2', '3.1.0-preview1']).test(
|
|
||||||
"if version: '%s' that can be resolved to 'version' option is supplied, it should set quality flag to 'false' and type to 'version' in version object",
|
|
||||||
async version => {
|
|
||||||
const dotnetVersionResolver = new installer.DotnetVersionResolver(
|
|
||||||
version
|
|
||||||
);
|
|
||||||
const versionObject = await dotnetVersionResolver.createDotNetVersion();
|
|
||||||
|
|
||||||
expect(versionObject.type.toLowerCase().includes('version')).toBeTruthy;
|
|
||||||
expect(versionObject.qualityFlag).toBeFalsy;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
each(['3.1.2', '3.1']).test(
|
|
||||||
'it should create proper line arguments for powershell/bash installation scripts',
|
|
||||||
async version => {
|
|
||||||
const dotnetVersionResolver = new installer.DotnetVersionResolver(
|
|
||||||
version
|
|
||||||
);
|
|
||||||
const versionObject = await dotnetVersionResolver.createDotNetVersion();
|
|
||||||
const windowsRegEx = new RegExp(/^-[VC]/);
|
|
||||||
const nonWindowsRegEx = new RegExp(/^--[vc]/);
|
|
||||||
|
|
||||||
if (IS_WINDOWS) {
|
if (IS_WINDOWS) {
|
||||||
expect(windowsRegEx.test(versionObject.type)).toBeTruthy;
|
it(`should supply '-ProxyAddress' argument to the installation script if env.variable 'https_proxy' is set`, async () => {
|
||||||
expect(nonWindowsRegEx.test(versionObject.type)).toBeFalsy;
|
process.env['https_proxy'] = 'https://proxy.com';
|
||||||
} else {
|
const inputVersion = '6.0.100';
|
||||||
expect(nonWindowsRegEx.test(versionObject.type)).toBeTruthy;
|
const inputQuality = '' as QualityOptions;
|
||||||
expect(windowsRegEx.test(versionObject.type)).toBeFalsy;
|
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
||||||
|
|
||||||
|
getExecOutputSpy.mockImplementation(() => {
|
||||||
|
return Promise.resolve({
|
||||||
|
exitCode: 0,
|
||||||
|
stdout: `${stdout}`,
|
||||||
|
stderr: ''
|
||||||
|
});
|
||||||
|
});
|
||||||
|
maxSatisfyingSpy.mockImplementation(() => inputVersion);
|
||||||
|
|
||||||
|
const dotnetInstaller = new installer.DotnetCoreInstaller(
|
||||||
|
inputVersion,
|
||||||
|
inputQuality
|
||||||
|
);
|
||||||
|
|
||||||
|
await dotnetInstaller.installDotnet();
|
||||||
|
|
||||||
|
const scriptArguments = (
|
||||||
|
getExecOutputSpy.mock.calls[0][1] as string[]
|
||||||
|
).join(' ');
|
||||||
|
|
||||||
|
expect(scriptArguments).toContain(
|
||||||
|
`-ProxyAddress ${process.env['https_proxy']}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should supply '-ProxyBypassList' argument to the installation script if env.variable 'no_proxy' is set`, async () => {
|
||||||
|
process.env['no_proxy'] = 'first.url,second.url';
|
||||||
|
const inputVersion = '6.0.100';
|
||||||
|
const inputQuality = '' as QualityOptions;
|
||||||
|
const stdout = `Fictitious dotnet version 6.0.0 is installed`;
|
||||||
|
|
||||||
|
getExecOutputSpy.mockImplementation(() => {
|
||||||
|
return Promise.resolve({
|
||||||
|
exitCode: 0,
|
||||||
|
stdout: `${stdout}`,
|
||||||
|
stderr: ''
|
||||||
|
});
|
||||||
|
});
|
||||||
|
maxSatisfyingSpy.mockImplementation(() => inputVersion);
|
||||||
|
|
||||||
|
const dotnetInstaller = new installer.DotnetCoreInstaller(
|
||||||
|
inputVersion,
|
||||||
|
inputQuality
|
||||||
|
);
|
||||||
|
|
||||||
|
await dotnetInstaller.installDotnet();
|
||||||
|
|
||||||
|
const scriptArguments = (
|
||||||
|
getExecOutputSpy.mock.calls[0][1] as string[]
|
||||||
|
).join(' ');
|
||||||
|
|
||||||
|
expect(scriptArguments).toContain(
|
||||||
|
`-ProxyBypassList ${process.env['no_proxy']}`
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
describe('addToPath() tests', () => {
|
||||||
|
it(`should export DOTNET_ROOT env.var with value from DOTNET_INSTALL_DIR env.var`, async () => {
|
||||||
|
process.env['DOTNET_INSTALL_DIR'] = 'fictitious/dotnet/install/dir';
|
||||||
|
installer.DotnetCoreInstaller.addToPath();
|
||||||
|
const dotnet_root = process.env['DOTNET_ROOT'];
|
||||||
|
expect(dotnet_root).toBe(process.env['DOTNET_INSTALL_DIR']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should export value from DOTNET_INSTALL_DIR env.var to the PATH`, async () => {
|
||||||
|
process.env['DOTNET_INSTALL_DIR'] = 'fictitious/dotnet/install/dir';
|
||||||
|
installer.DotnetCoreInstaller.addToPath();
|
||||||
|
const path = process.env['PATH'];
|
||||||
|
expect(path).toContain(process.env['DOTNET_INSTALL_DIR']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('DotnetVersionResolver tests', () => {
|
||||||
|
describe('createDotNetVersion() tests', () => {
|
||||||
|
each([
|
||||||
|
'3.1',
|
||||||
|
'3.x',
|
||||||
|
'3.1.x',
|
||||||
|
'3.1.*',
|
||||||
|
'3.1.X',
|
||||||
|
'3.1.2',
|
||||||
|
'3.1.0-preview1',
|
||||||
|
'6.0.2xx'
|
||||||
|
]).test(
|
||||||
|
'if valid version is supplied (%s), it should return version object with some value',
|
||||||
|
async version => {
|
||||||
|
const dotnetVersionResolver = new installer.DotnetVersionResolver(
|
||||||
|
version
|
||||||
|
);
|
||||||
|
const versionObject =
|
||||||
|
await dotnetVersionResolver.createDotNetVersion();
|
||||||
|
|
||||||
|
expect(!!versionObject.value).toBe(true);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
each([
|
||||||
|
'.',
|
||||||
|
'..',
|
||||||
|
' . ',
|
||||||
|
'. ',
|
||||||
|
' .',
|
||||||
|
' . . ',
|
||||||
|
' .. ',
|
||||||
|
' . ',
|
||||||
|
'-1.-1',
|
||||||
|
'-1',
|
||||||
|
'-1.-1.-1',
|
||||||
|
'..3',
|
||||||
|
'1..3',
|
||||||
|
'1..',
|
||||||
|
'.2.3',
|
||||||
|
'.2.x',
|
||||||
|
'*.',
|
||||||
|
'1.2.',
|
||||||
|
'1.2.-abc',
|
||||||
|
'a.b',
|
||||||
|
'a.b.c',
|
||||||
|
'a.b.c-preview',
|
||||||
|
' 0 . 1 . 2 ',
|
||||||
|
'invalid'
|
||||||
|
]).test(
|
||||||
|
'if invalid version is supplied (%s), it should throw',
|
||||||
|
async version => {
|
||||||
|
const dotnetVersionResolver = new installer.DotnetVersionResolver(
|
||||||
|
version
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
async () => await dotnetVersionResolver.createDotNetVersion()
|
||||||
|
).rejects.toThrow();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
each(['3', '3.1', '3.1.x', '3.1.*', '3.1.X', '6.0.2xx']).test(
|
||||||
|
"if version that can be resolved to 'channel' option is supplied (%s), it should set type to 'channel' in version object",
|
||||||
|
async version => {
|
||||||
|
const dotnetVersionResolver = new installer.DotnetVersionResolver(
|
||||||
|
version
|
||||||
|
);
|
||||||
|
const versionObject =
|
||||||
|
await dotnetVersionResolver.createDotNetVersion();
|
||||||
|
|
||||||
|
expect(versionObject.type.toLowerCase().includes('channel')).toBe(
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
each(['6.0', '6.0.x', '6.0.*', '6.0.X', '6.0.2xx']).test(
|
||||||
|
"if version that can be resolved to 'channel' option is supplied and its major tag is >= 6 (%s), it should set type to 'channel' and qualityFlag to 'true' in version object",
|
||||||
|
async version => {
|
||||||
|
const dotnetVersionResolver = new installer.DotnetVersionResolver(
|
||||||
|
version
|
||||||
|
);
|
||||||
|
const versionObject =
|
||||||
|
await dotnetVersionResolver.createDotNetVersion();
|
||||||
|
|
||||||
|
expect(versionObject.type.toLowerCase().includes('channel')).toBe(
|
||||||
|
true
|
||||||
|
);
|
||||||
|
expect(versionObject.qualityFlag).toBe(true);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
each(['3.1.2', '3.1.0-preview1']).test(
|
||||||
|
"if version that can be resolved to 'version' option is supplied (%s), it should set quality flag to 'false' and type to 'version' in version object",
|
||||||
|
async version => {
|
||||||
|
const dotnetVersionResolver = new installer.DotnetVersionResolver(
|
||||||
|
version
|
||||||
|
);
|
||||||
|
const versionObject =
|
||||||
|
await dotnetVersionResolver.createDotNetVersion();
|
||||||
|
|
||||||
|
expect(versionObject.type.toLowerCase().includes('version')).toBe(
|
||||||
|
true
|
||||||
|
);
|
||||||
|
expect(versionObject.qualityFlag).toBe(false);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
each(['3.1.2', '3.1']).test(
|
||||||
|
'it should create proper line arguments for powershell/bash installation scripts',
|
||||||
|
async version => {
|
||||||
|
const dotnetVersionResolver = new installer.DotnetVersionResolver(
|
||||||
|
version
|
||||||
|
);
|
||||||
|
const versionObject =
|
||||||
|
await dotnetVersionResolver.createDotNetVersion();
|
||||||
|
const windowsRegEx = new RegExp(/^-(Version|Channel)/);
|
||||||
|
const nonWindowsRegEx = new RegExp(/^--(version|channel)/);
|
||||||
|
|
||||||
|
if (IS_WINDOWS) {
|
||||||
|
expect(windowsRegEx.test(versionObject.type)).toBe(true);
|
||||||
|
expect(nonWindowsRegEx.test(versionObject.type)).toBe(false);
|
||||||
|
} else {
|
||||||
|
expect(nonWindowsRegEx.test(versionObject.type)).toBe(true);
|
||||||
|
expect(windowsRegEx.test(versionObject.type)).toBe(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
it(`should throw if dotnet-version is supplied in A.B.Cxx syntax with major tag lower that 5`, async () => {
|
||||||
|
const version = '3.0.1xx';
|
||||||
|
const dotnetVersionResolver = new installer.DotnetVersionResolver(
|
||||||
|
version
|
||||||
|
);
|
||||||
|
await expect(
|
||||||
|
async () => await dotnetVersionResolver.createDotNetVersion()
|
||||||
|
).rejects.toThrow(
|
||||||
|
`'dotnet-version' was supplied in invalid format: ${version}! The A.B.Cxx syntax is available since the .NET 5.0 release.`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
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,
|
|
||||||
quality: string = ''
|
|
||||||
): Promise<string> {
|
|
||||||
const dotnetInstaller = new installer.DotnetCoreInstaller(
|
|
||||||
version,
|
|
||||||
quality as QualityOptions
|
|
||||||
);
|
|
||||||
const installedVersion = await dotnetInstaller.installDotnet();
|
|
||||||
installer.DotnetCoreInstaller.addToPath();
|
|
||||||
return installedVersion;
|
|
||||||
}
|
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace sample_csproj
|
|
||||||
{
|
|
||||||
[TestClass]
|
|
||||||
public class Program
|
|
||||||
{
|
|
||||||
[TestMethod]
|
|
||||||
public void TestMethod1()
|
|
||||||
{
|
|
||||||
Console.WriteLine("Hello, World!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFrameworks>netcoreapp3.1;netcoreapp3.0;netcoreapp2.2</TargetFrameworks>
|
|
||||||
<RootNamespace>sample_csproj</RootNamespace>
|
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<!-- These packages will be downloaded over the network for testing proxy settings -->
|
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
|
|
||||||
<PackageReference Include="MSTest.TestAdapter" Version="2.1.0" />
|
|
||||||
<PackageReference Include="MSTest.TestFramework" Version="2.1.0" />
|
|
||||||
<PackageReference Include="coverlet.collector" Version="1.2.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
@ -1,98 +1,173 @@
|
|||||||
import * as io from '@actions/io';
|
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import os from 'os';
|
import semver from 'semver';
|
||||||
import path from 'path';
|
import * as auth from '../src/authutil';
|
||||||
|
|
||||||
import * as setup from '../src/setup-dotnet';
|
import * as setup from '../src/setup-dotnet';
|
||||||
import {IS_WINDOWS} from '../src/utils';
|
import {DotnetCoreInstaller} from '../src/installer';
|
||||||
import {IS_LINUX} from '../src/utils';
|
|
||||||
|
|
||||||
let toolDir: string;
|
|
||||||
|
|
||||||
if (IS_WINDOWS) {
|
|
||||||
toolDir = path.join(process.env['PROGRAMFILES'] + '', 'dotnet');
|
|
||||||
} else if (IS_LINUX) {
|
|
||||||
toolDir = '/usr/share/dotnet';
|
|
||||||
} else {
|
|
||||||
toolDir = path.join(process.env['HOME'] + '', '.dotnet');
|
|
||||||
}
|
|
||||||
|
|
||||||
const tempDir = path.join(__dirname, 'runner', 'temp2');
|
|
||||||
|
|
||||||
describe('setup-dotnet tests', () => {
|
describe('setup-dotnet tests', () => {
|
||||||
let getInputSpy = jest.spyOn(core, 'getInput');
|
const inputs = {} as any;
|
||||||
let getMultilineInputSpy = jest.spyOn(core, 'getMultilineInput');
|
|
||||||
let setOutputSpy = jest.spyOn(core, 'setOutput');
|
|
||||||
|
|
||||||
let inputs = {} as any;
|
const getInputSpy = jest.spyOn(core, 'getInput');
|
||||||
|
const getMultilineInputSpy = jest.spyOn(core, 'getMultilineInput');
|
||||||
|
const setFailedSpy = jest.spyOn(core, 'setFailed');
|
||||||
|
const warningSpy = jest.spyOn(core, 'warning');
|
||||||
|
const debugSpy = jest.spyOn(core, 'debug');
|
||||||
|
const infoSpy = jest.spyOn(core, 'info');
|
||||||
|
const setOutputSpy = jest.spyOn(core, 'setOutput');
|
||||||
|
|
||||||
beforeAll(async () => {
|
const existsSyncSpy = jest.spyOn(fs, 'existsSync');
|
||||||
process.env.RUNNER_TOOL_CACHE = toolDir;
|
|
||||||
process.env.DOTNET_INSTALL_DIR = toolDir;
|
|
||||||
process.env.RUNNER_TEMP = tempDir;
|
|
||||||
try {
|
|
||||||
await io.rmRF(`${toolDir}/*`);
|
|
||||||
await io.rmRF(`${tempDir}/*`);
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err.message);
|
|
||||||
console.log('Failed to remove test directories');
|
|
||||||
}
|
|
||||||
}, 30000);
|
|
||||||
|
|
||||||
afterEach(async () => {
|
const maxSatisfyingSpy = jest.spyOn(semver, 'maxSatisfying');
|
||||||
try {
|
|
||||||
await io.rmRF(path.join(process.cwd(), 'global.json'));
|
|
||||||
await io.rmRF(`${toolDir}/*`);
|
|
||||||
await io.rmRF(`${tempDir}/*`);
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err.message);
|
|
||||||
console.log('Failed to remove test directories');
|
|
||||||
}
|
|
||||||
}, 30000);
|
|
||||||
|
|
||||||
it('Acquires version of dotnet from global.json if no matching version is installed', async () => {
|
const installDotnetSpy = jest.spyOn(
|
||||||
const globalJsonPath = path.join(process.cwd(), 'global.json');
|
DotnetCoreInstaller.prototype,
|
||||||
const jsonContents = `{${os.EOL}"sdk": {${os.EOL}"version": "3.1.201"${os.EOL}}${os.EOL}}`;
|
'installDotnet'
|
||||||
if (!fs.existsSync(globalJsonPath)) {
|
);
|
||||||
fs.writeFileSync(globalJsonPath, jsonContents);
|
const addToPathSpy = jest.spyOn(DotnetCoreInstaller, 'addToPath');
|
||||||
}
|
|
||||||
await setup.run();
|
|
||||||
|
|
||||||
expect(fs.existsSync(path.join(toolDir, 'sdk', '3.1.201'))).toBe(true);
|
const configAuthenticationSpy = jest.spyOn(auth, 'configAuthentication');
|
||||||
if (IS_WINDOWS) {
|
|
||||||
expect(fs.existsSync(path.join(toolDir, 'dotnet.exe'))).toBe(true);
|
|
||||||
} else {
|
|
||||||
expect(fs.existsSync(path.join(toolDir, 'dotnet'))).toBe(true);
|
|
||||||
}
|
|
||||||
}, 400000);
|
|
||||||
|
|
||||||
it("Sets output with the latest installed by action version if global.json file isn't specified", async () => {
|
describe('run() tests', () => {
|
||||||
inputs['dotnet-version'] = ['3.1.201', '6.0.401'];
|
beforeEach(() => {
|
||||||
|
getMultilineInputSpy.mockImplementation(input => inputs[input as string]);
|
||||||
|
getInputSpy.mockImplementation(input => inputs[input as string]);
|
||||||
|
});
|
||||||
|
|
||||||
getMultilineInputSpy.mockImplementation(input => inputs[input]);
|
afterEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
jest.resetAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
await setup.run();
|
it('should fail the action if global-json-file input is present, but the file does not exist in the file system', async () => {
|
||||||
|
inputs['global-json-file'] = 'fictitious.json';
|
||||||
|
inputs['dotnet-version'] = [];
|
||||||
|
|
||||||
expect(setOutputSpy).toBeCalledWith('dotnet-version', '6.0.401');
|
const expectedErrorMessage = `The specified global.json file '${inputs['global-json-file']}' does not exist`;
|
||||||
}, 400000);
|
|
||||||
|
|
||||||
it("Sets output with the version specified in global.json, if it's present", async () => {
|
await setup.run();
|
||||||
const globalJsonPath = path.join(process.cwd(), 'global.json');
|
expect(setFailedSpy).toHaveBeenCalledWith(expectedErrorMessage);
|
||||||
const jsonContents = `{${os.EOL}"sdk": {${os.EOL}"version": "3.0.103"${os.EOL}}${os.EOL}}`;
|
});
|
||||||
if (!fs.existsSync(globalJsonPath)) {
|
|
||||||
fs.writeFileSync(globalJsonPath, jsonContents);
|
|
||||||
}
|
|
||||||
|
|
||||||
inputs['dotnet-version'] = ['3.1.201', '6.0.401'];
|
test(`if 'dotnet-version' and 'global-json-file' inputs aren't present, should log into debug output, try to find global.json in the repo root, fail and log message into info output`, async () => {
|
||||||
inputs['global-json-file'] = './global.json';
|
inputs['global-json-file'] = '';
|
||||||
|
inputs['dotnet-version'] = [];
|
||||||
|
|
||||||
getMultilineInputSpy.mockImplementation(input => inputs[input]);
|
maxSatisfyingSpy.mockImplementation(() => null);
|
||||||
|
setOutputSpy.mockImplementation(() => {});
|
||||||
|
|
||||||
getInputSpy.mockImplementation(input => inputs[input]);
|
const expectedDebugMessage =
|
||||||
|
'No version found, trying to find version from global.json';
|
||||||
|
const expectedInfoMessage = `The global.json wasn't found in the root directory. No .NET version will be installed.`;
|
||||||
|
|
||||||
await setup.run();
|
await setup.run();
|
||||||
|
|
||||||
expect(setOutputSpy).toBeCalledWith('dotnet-version', '3.0.103');
|
expect(debugSpy).toHaveBeenCalledWith(expectedDebugMessage);
|
||||||
}, 400000);
|
expect(existsSyncSpy).toHaveBeenCalled();
|
||||||
|
expect(infoSpy).toHaveBeenCalledWith(expectedInfoMessage);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail the action if quality is supplied but its value is not supported', async () => {
|
||||||
|
inputs['global-json-file'] = '';
|
||||||
|
inputs['dotnet-version'] = ['6.0'];
|
||||||
|
inputs['dotnet-quality'] = 'fictitiousQuality';
|
||||||
|
|
||||||
|
const expectedErrorMessage = `Value '${inputs['dotnet-quality']}' is not supported for the 'dotnet-quality' option. Supported values are: daily, signed, validated, preview, ga.`;
|
||||||
|
|
||||||
|
await setup.run();
|
||||||
|
expect(setFailedSpy).toHaveBeenCalledWith(expectedErrorMessage);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call installDotnet() multiple times if dotnet-version multiline input is provided', async () => {
|
||||||
|
inputs['global-json-file'] = '';
|
||||||
|
inputs['dotnet-version'] = ['6.0', '7.0'];
|
||||||
|
inputs['dotnet-quality'] = '';
|
||||||
|
|
||||||
|
installDotnetSpy.mockImplementation(() => Promise.resolve(''));
|
||||||
|
|
||||||
|
await setup.run();
|
||||||
|
expect(installDotnetSpy).toHaveBeenCalledTimes(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call addToPath() after installation complete', async () => {
|
||||||
|
inputs['global-json-file'] = '';
|
||||||
|
inputs['dotnet-version'] = ['6.0', '7.0'];
|
||||||
|
inputs['dotnet-quality'] = '';
|
||||||
|
|
||||||
|
installDotnetSpy.mockImplementation(() => Promise.resolve(''));
|
||||||
|
addToPathSpy.mockImplementation(() => {});
|
||||||
|
|
||||||
|
await setup.run();
|
||||||
|
expect(addToPathSpy).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call auth.configAuthentication() if source-url input is provided', async () => {
|
||||||
|
inputs['global-json-file'] = '';
|
||||||
|
inputs['dotnet-version'] = [];
|
||||||
|
inputs['dotnet-quality'] = '';
|
||||||
|
inputs['source-url'] = 'fictitious.source.url';
|
||||||
|
|
||||||
|
configAuthenticationSpy.mockImplementation(() => {});
|
||||||
|
|
||||||
|
await setup.run();
|
||||||
|
expect(configAuthenticationSpy).toHaveBeenCalledWith(
|
||||||
|
inputs['source-url'],
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call auth.configAuthentication() with proper parameters if source-url and config-file inputs are provided', async () => {
|
||||||
|
inputs['global-json-file'] = '';
|
||||||
|
inputs['dotnet-version'] = [];
|
||||||
|
inputs['dotnet-quality'] = '';
|
||||||
|
inputs['source-url'] = 'fictitious.source.url';
|
||||||
|
inputs['config-file'] = 'fictitious.path';
|
||||||
|
|
||||||
|
configAuthenticationSpy.mockImplementation(() => {});
|
||||||
|
setOutputSpy.mockImplementation(() => {});
|
||||||
|
|
||||||
|
await setup.run();
|
||||||
|
expect(configAuthenticationSpy).toHaveBeenCalledWith(
|
||||||
|
inputs['source-url'],
|
||||||
|
inputs['config-file']
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call setOutput() after installation complete successfully', async () => {
|
||||||
|
inputs['dotnet-version'] = ['6.0.300'];
|
||||||
|
|
||||||
|
installDotnetSpy.mockImplementation(() =>
|
||||||
|
Promise.resolve(`${inputs['dotnet-version']}`)
|
||||||
|
);
|
||||||
|
addToPathSpy.mockImplementation(() => {});
|
||||||
|
|
||||||
|
await setup.run();
|
||||||
|
expect(setOutputSpy).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`shouldn't call setOutput() if parsing dotnet-installer logs failed`, async () => {
|
||||||
|
inputs['dotnet-version'] = ['6.0.300'];
|
||||||
|
const warningMessage = `Failed to output the installed version of .NET. The 'dotnet-version' output will not be set.`;
|
||||||
|
|
||||||
|
installDotnetSpy.mockImplementation(() => Promise.resolve(null));
|
||||||
|
addToPathSpy.mockImplementation(() => {});
|
||||||
|
|
||||||
|
await setup.run();
|
||||||
|
expect(warningSpy).toHaveBeenCalledWith(warningMessage);
|
||||||
|
expect(setOutputSpy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`shouldn't call setOutput() if actions didn't install .NET`, async () => {
|
||||||
|
inputs['dotnet-version'] = [];
|
||||||
|
const warningMessage = `The 'dotnet-version' output will not be set.`;
|
||||||
|
|
||||||
|
addToPathSpy.mockImplementation(() => {});
|
||||||
|
|
||||||
|
await setup.run();
|
||||||
|
|
||||||
|
expect(infoSpy).toHaveBeenCalledWith(warningMessage);
|
||||||
|
expect(setOutputSpy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,73 +1,117 @@
|
|||||||
if (!$args[0])
|
<#
|
||||||
{
|
.DESCRIPTION
|
||||||
throw "Must supply dotnet version argument"
|
Verifies that installed on the machine .NET SDK versions match the input patterns.
|
||||||
|
Optionally checks that the nuget.config file is generated correctly.
|
||||||
|
|
||||||
|
.PARAMETER Patterns
|
||||||
|
Specifies the regular expression patterns that should be matched with the installed
|
||||||
|
on the machine .NET SDK versions. The number of patterns should be equal to the number
|
||||||
|
of installed .NET versions.
|
||||||
|
|
||||||
|
.PARAMETER CheckNugetConfig
|
||||||
|
Switches the check for the existence of the nuget.config file.
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
PS> .\verify-dotnet.ps1 -Paterns "^3.1.200$", "^6.0" -CheckNugetConfig
|
||||||
|
#>
|
||||||
|
|
||||||
|
param(
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string[]]$Patterns,
|
||||||
|
[switch]$CheckNugetConfig
|
||||||
|
)
|
||||||
|
|
||||||
|
$PatternsList = [System.Collections.ArrayList]($Patterns)
|
||||||
|
|
||||||
|
if ($CheckNugetConfig.IsPresent -and !(Test-Path "../nuget.config")) {
|
||||||
|
throw "The nuget.config file is not generated correctly."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Write-Host "These patterns were supplied to the script: $($PatternsList -join ', ')."
|
||||||
$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'"
|
||||||
|
|
||||||
if($args.count -eq 1)
|
# SDKs are listed on multiple lines with the path afterwards in square brackets
|
||||||
|
$Versions = & $dotnet --list-sdks | ForEach-Object { $_.SubString(0, $_.IndexOf('[')).Trim() }
|
||||||
|
Write-Host "Found installed versions: $($Versions -join ', ')."
|
||||||
|
$InstalledVersionCount = $Versions.Count
|
||||||
|
|
||||||
|
foreach($version in $Versions)
|
||||||
{
|
{
|
||||||
$version = & $dotnet --version | Out-String | ForEach-Object { $_.Trim() }
|
foreach($pattern in $PatternsList)
|
||||||
Write-Host "Version $version"
|
|
||||||
if (-not ($version.StartsWith($args[0].ToString())))
|
|
||||||
{
|
{
|
||||||
Write-Host "PATH='$env:PATH'"
|
if ($version -match $pattern)
|
||||||
throw "Unexpected version"
|
{
|
||||||
}
|
$PatternsList.Remove($pattern)
|
||||||
}
|
$InstalledVersionCount--
|
||||||
|
break
|
||||||
if ($args[1])
|
|
||||||
{
|
|
||||||
# SDKs are listed on multiple lines with the path afterwards in square brackets
|
|
||||||
$versions = & $dotnet --list-sdks | ForEach-Object { $_.SubString(0, $_.IndexOf('[')).Trim() }
|
|
||||||
Write-Host "Installed versions: $versions"
|
|
||||||
$InstalledVersionCount = 0
|
|
||||||
foreach($arg in $args){
|
|
||||||
foreach ($version in $versions)
|
|
||||||
{
|
|
||||||
if ($version.StartsWith($arg.ToString()))
|
|
||||||
{
|
|
||||||
$InstalledVersionCount++
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if ( $InstalledVersionCount -ne $args.Count)
|
|
||||||
{
|
|
||||||
Write-Host "PATH='$env:PATH'"
|
|
||||||
throw "Unexpected version"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "Building sample csproj"
|
if ( $InstalledVersionCount -ne 0)
|
||||||
& $dotnet build __tests__/sample-csproj/ --no-cache
|
|
||||||
if ($LASTEXITCODE -ne 0)
|
|
||||||
{
|
{
|
||||||
throw "Unexpected exit code $LASTEXITCODE"
|
throw "An unexpected version of Dotnet is found on the machine, please check the correctness of the -Patterns input."
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "Testing compiled app"
|
$workingDir = Get-Location
|
||||||
$sample_output = "$(dotnet test __tests__/sample-csproj/ --no-build)"
|
$testProjectDir = "./__tests__/e2e-test-csproj"
|
||||||
Write-Host "Sample output: $sample_output"
|
Write-Host "Changing directory to the $testProjectDir"
|
||||||
# For Side-by-Side installs we want to run the tests twice, for a single install the tests will run once
|
Set-Location $testProjectDir
|
||||||
if ($args[1])
|
|
||||||
|
$targetFrameworkVersionMap = @{
|
||||||
|
"1.0" = "netcoreapp1.0";
|
||||||
|
"1.1" = "netcoreapp1.1";
|
||||||
|
"2.0" = "netcoreapp2.0";
|
||||||
|
"2.1" = "netcoreapp2.1";
|
||||||
|
"2.2" = "netcoreapp2.2";
|
||||||
|
"3.0" = "netcoreapp3.0";
|
||||||
|
"3.1" = "netcoreapp3.1";
|
||||||
|
"5.0" = "net5.0";
|
||||||
|
"6.0" = "net6.0";
|
||||||
|
"7.0" = "net7.0";
|
||||||
|
"8.0" = "net8.0";
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($version in $Versions)
|
||||||
{
|
{
|
||||||
if ($sample_output -notlike "*Test Run Successful.*Test Run Successful.*")
|
# Creating temporary global.json file inside e2e-test-csproj dir and setting exact version of .NET inside allows to override default behavior of .NET and run build and tests on that exact version.
|
||||||
|
Write-Host "Creating temporary global.json file for $version .NET version."
|
||||||
|
& $dotnet new globaljson --sdk-version $version --force | Out-Null
|
||||||
|
if (!(Test-Path "./global.json"))
|
||||||
{
|
{
|
||||||
throw "Unexpected output"
|
throw "An error occured while creating the global.json file. Exit code: $LASTEXITCODE"
|
||||||
}
|
}
|
||||||
}
|
Write-Host "The global.json file for the version $version is created. Currently used .NET version is: $(& $dotnet --version)."
|
||||||
if ($args[2])
|
|
||||||
{
|
# Environment variable TEST_TARGET_FRAMEWORK is used inside the test.csproj file to target required framework version
|
||||||
if ($sample_output -notlike "*Test Run Successful.*Test Run Successful.*Test Run Successful.*")
|
$version -match "^(?<key>\d+\.\d+)" | Out-Null
|
||||||
|
if (!($targetFrameworkVersionMap.ContainsKey($Matches.key)))
|
||||||
{
|
{
|
||||||
throw "Unexpected output"
|
throw "The map with the framework targets doesn't contain a target name for the version $version."
|
||||||
}
|
}
|
||||||
}
|
Write-Host "Setting the TEST_TARGET_FRAMEWORK environment variable to $($targetFrameworkVersionMap[$Matches.key])"
|
||||||
else
|
[Environment]::SetEnvironmentVariable('TEST_TARGET_FRAMEWORK', $($targetFrameworkVersionMap[$Matches.key]))
|
||||||
{
|
|
||||||
if ($sample_output -notlike "*Test Run Successful.*")
|
Write-Host "Building test C# project with $version .NET version."
|
||||||
|
& $dotnet build --no-cache
|
||||||
|
if ($LASTEXITCODE -ne 0)
|
||||||
{
|
{
|
||||||
throw "Unexpected output"
|
throw "Building process is not successful, exit code: $LASTEXITCODE"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Write-Host "Testing compiled C# project with $version .NET version."
|
||||||
|
& $dotnet test --no-build
|
||||||
|
if ($LASTEXITCODE -ne 0)
|
||||||
|
{
|
||||||
|
throw "Testing process is not successful, exit code: $LASTEXITCODE"
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Tests are completed successfully!"
|
||||||
|
|
||||||
|
Write-Host "Removing temporary global.json file."
|
||||||
|
Remove-Item ./global.json
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Set-Location $workingDir
|
@ -1,44 +0,0 @@
|
|||||||
if [ -z "$1" ]; then
|
|
||||||
echo "Must supply dotnet version argument"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -f "../nuget.config" ]; then
|
|
||||||
echo "nuget file not generated correctly"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
dotnet_version="$(dotnet --version)"
|
|
||||||
echo "Found dotnet version '$dotnet_version'"
|
|
||||||
if [ -z "$(echo $dotnet_version | grep $1)" ]; then
|
|
||||||
echo "Unexpected version"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "$2" ]; then
|
|
||||||
dotnet_version="$(dotnet --list-sdks)"
|
|
||||||
echo "Found dotnet version '$dotnet_version'"
|
|
||||||
if [ -z "$(echo $dotnet_version | grep $2)" ]; then
|
|
||||||
echo "Unexpected version"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Building sample csproj"
|
|
||||||
dotnet build __tests__/sample-csproj/ --no-cache || exit 1
|
|
||||||
|
|
||||||
echo "Testing compiled app"
|
|
||||||
sample_output=$(dotnet test __tests__/sample-csproj/ --no-build)
|
|
||||||
echo "Sample output: $sample_output"
|
|
||||||
# For Side-by-Side installs we want to run the tests twice, for a single install the tests will run once
|
|
||||||
if [ -n "$2" ]; then
|
|
||||||
if [ -z "$(echo $sample_output | grep "Test Run Successful.*Test Run Successful.")" ]; then
|
|
||||||
echo "Unexpected output"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
if [ -z "$(echo $sample_output | grep "Test Run Successful.")" ]; then
|
|
||||||
echo "Unexpected output"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
@ -1,7 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then
|
|
||||||
echo "Detected uncommitted changes after build. See status below:"
|
|
||||||
git diff
|
|
||||||
exit 1
|
|
||||||
fi
|
|
@ -6,7 +6,7 @@ branding:
|
|||||||
color: green
|
color: green
|
||||||
inputs:
|
inputs:
|
||||||
dotnet-version:
|
dotnet-version:
|
||||||
description: 'Optional SDK version(s) to use. If not provided, will install global.json version when available. Examples: 2.2.104, 3.1, 3.1.x, 3.x'
|
description: 'Optional SDK version(s) to use. If not provided, will install global.json version when available. Examples: 2.2.104, 3.1, 3.1.x, 3.x, 6.0.2xx'
|
||||||
dotnet-quality:
|
dotnet-quality:
|
||||||
description: 'Optional quality of the build. The possible values are: daily, signed, validated, preview, ga.'
|
description: 'Optional quality of the build. The possible values are: daily, signed, validated, preview, ga.'
|
||||||
global-json-file:
|
global-json-file:
|
||||||
|
7937
dist/index.js
vendored
7937
dist/index.js
vendored
File diff suppressed because it is too large
Load Diff
@ -61,12 +61,13 @@ Pull requests are the easiest way to contribute changes to git repos at GitHub.
|
|||||||
|
|
||||||
- To implement new features or fix bugs, you need to make changes to the `.ts` files, which are located in the `src` folder
|
- To implement new features or fix bugs, you need to make changes to the `.ts` files, which are located in the `src` folder
|
||||||
- To comply with the code style, **you need to run the `format` script**
|
- To comply with the code style, **you need to run the `format` script**
|
||||||
|
- To lint the code, **you need to run the `lint:fix` script**
|
||||||
- To transpile source code to `javascript` we use [NCC](https://github.com/vercel/ncc). **It is very important to run the `build` script after making changes**, otherwise your changes will not get into the final `javascript` build
|
- To transpile source code to `javascript` we use [NCC](https://github.com/vercel/ncc). **It is very important to run the `build` script after making changes**, otherwise your changes will not get into the final `javascript` build
|
||||||
|
|
||||||
**Learn more about how to implement tests:**
|
**Learn more about how to implement tests:**
|
||||||
|
|
||||||
Adding or changing tests is an integral part of making a change to the code.
|
Adding or changing tests is an integral part of making a change to the code.
|
||||||
Unit tests are in the `__tests__` folder, and end-to-end tests are in the `workflows` folder, particularly in the [workflow.yml](https://github.com/actions/setup-dotnet/blob/main/.github/workflows/workflow.yml).
|
Unit tests are in the `__tests__` folder, and end-to-end tests are in the `workflows` folder, particularly in the [e2e-tests.yml](https://github.com/actions/setup-dotnet/blob/main/.github/workflows/e2e-tests.yml).
|
||||||
|
|
||||||
- The contributor can add various types of tests (like unit tests or end-to-end tests), which, in his opinion, will be necessary and sufficient for testing new or changed functionality
|
- The contributor can add various types of tests (like unit tests or end-to-end tests), which, in his opinion, will be necessary and sufficient for testing new or changed functionality
|
||||||
- Tests should cover a successful execution, as well as some edge cases and possible errors
|
- Tests should cover a successful execution, as well as some edge cases and possible errors
|
||||||
|
482
externals/install-dotnet.ps1
vendored
482
externals/install-dotnet.ps1
vendored
@ -9,20 +9,27 @@
|
|||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
Installs dotnet cli. If dotnet installation already exists in the given directory
|
Installs dotnet cli. If dotnet installation already exists in the given directory
|
||||||
it will update it only if the requested version differs from the one already installed.
|
it will update it only if the requested version differs from the one already installed.
|
||||||
|
|
||||||
|
Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:
|
||||||
|
- The SDK needs to be installed without user interaction and without admin rights.
|
||||||
|
- The SDK installation doesn't need to persist across multiple CI runs.
|
||||||
|
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.
|
||||||
|
|
||||||
.PARAMETER Channel
|
.PARAMETER Channel
|
||||||
Default: LTS
|
Default: LTS
|
||||||
Download from the Channel specified. Possible values:
|
Download from the Channel specified. Possible values:
|
||||||
- Current - most current release
|
- STS - the most recent Standard Term Support release
|
||||||
- LTS - most current supported release
|
- LTS - the most recent Long Term Support 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
|
||||||
- 3-part version in a format A.B.Cxx - represents a specific SDK release
|
- 3-part version in a format A.B.Cxx - represents a specific SDK release
|
||||||
examples: 5.0.1xx, 5.0.2xx
|
examples: 5.0.1xx, 5.0.2xx
|
||||||
Supported since 5.0 release
|
Supported since 5.0 release
|
||||||
|
Warning: Value "Current" is deprecated for the Channel parameter. Use "STS" instead.
|
||||||
Note: The version parameter overrides the channel parameter when any version other than 'latest' is used.
|
Note: The version parameter overrides the channel parameter when any version other than 'latest' is used.
|
||||||
.PARAMETER Quality
|
.PARAMETER Quality
|
||||||
Download the latest build of specified quality in the channel. The possible values are: daily, signed, validated, preview, GA.
|
Download the latest build of specified quality in the channel. The possible values are: daily, signed, validated, preview, GA.
|
||||||
Works only in combination with channel. Not applicable for current and LTS channels and will be ignored if those channels are used.
|
Works only in combination with channel. Not applicable for STS and LTS channels and will be ignored if those channels are used.
|
||||||
For SDK use channel in A.B.Cxx format: using quality together with channel in A.B format is not supported.
|
For SDK use channel in A.B.Cxx format: using quality together with channel in A.B format is not supported.
|
||||||
Supported since 5.0 release.
|
Supported since 5.0 release.
|
||||||
Note: The version parameter overrides the channel parameter when any version other than 'latest' is used, and therefore overrides the quality.
|
Note: The version parameter overrides the channel parameter when any version other than 'latest' is used, and therefore overrides the quality.
|
||||||
@ -163,6 +170,12 @@ function Say-Verbose($str) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Measure-Action($name, $block) {
|
||||||
|
$time = Measure-Command $block
|
||||||
|
$totalSeconds = $time.TotalSeconds
|
||||||
|
Say-Verbose "⏱ Action '$name' took $totalSeconds seconds"
|
||||||
|
}
|
||||||
|
|
||||||
function Say-Invocation($Invocation) {
|
function Say-Invocation($Invocation) {
|
||||||
$command = $Invocation.MyCommand;
|
$command = $Invocation.MyCommand;
|
||||||
$args = (($Invocation.BoundParameters.Keys | foreach { "-$_ `"$($Invocation.BoundParameters[$_])`"" }) -join " ")
|
$args = (($Invocation.BoundParameters.Keys | foreach { "-$_ `"$($Invocation.BoundParameters[$_])`"" }) -join " ")
|
||||||
@ -277,13 +290,18 @@ function Get-NormalizedChannel([string]$Channel) {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($Channel.Contains("Current")) {
|
||||||
|
Say-Warning 'Value "Current" is deprecated for -Channel option. Use "STS" instead.'
|
||||||
|
}
|
||||||
|
|
||||||
if ($Channel.StartsWith('release/')) {
|
if ($Channel.StartsWith('release/')) {
|
||||||
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, such as "-Channel 5.0 -Quality Daily."'
|
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, such as "-Channel 5.0 -Quality Daily."'
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($Channel) {
|
switch ($Channel) {
|
||||||
{ $_ -eq "lts" } { return "LTS" }
|
{ $_ -eq "lts" } { return "LTS" }
|
||||||
{ $_ -eq "current" } { return "current" }
|
{ $_ -eq "sts" } { return "STS" }
|
||||||
|
{ $_ -eq "current" } { return "STS" }
|
||||||
default { return $Channel.ToLowerInvariant() }
|
default { return $Channel.ToLowerInvariant() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -925,10 +943,10 @@ function PrintDryRunOutput($Invocation, $DownloadLinks)
|
|||||||
function Get-AkaMSDownloadLink([string]$Channel, [string]$Quality, [bool]$Internal, [string]$Product, [string]$Architecture) {
|
function Get-AkaMSDownloadLink([string]$Channel, [string]$Quality, [bool]$Internal, [string]$Product, [string]$Architecture) {
|
||||||
Say-Invocation $MyInvocation
|
Say-Invocation $MyInvocation
|
||||||
|
|
||||||
#quality is not supported for LTS or current channel
|
#quality is not supported for LTS or STS channel
|
||||||
if (![string]::IsNullOrEmpty($Quality) -and (@("LTS", "current") -contains $Channel)) {
|
if (![string]::IsNullOrEmpty($Quality) -and (@("LTS", "STS") -contains $Channel)) {
|
||||||
$Quality = ""
|
$Quality = ""
|
||||||
Say-Warning "Specifying quality for current or LTS channel is not supported, the quality will be ignored."
|
Say-Warning "Specifying quality for STS or LTS channel is not supported, the quality will be ignored."
|
||||||
}
|
}
|
||||||
Say-Verbose "Retrieving primary payload URL from aka.ms link for channel: '$Channel', quality: '$Quality' product: '$Product', os: 'win', architecture: '$Architecture'."
|
Say-Verbose "Retrieving primary payload URL from aka.ms link for channel: '$Channel', quality: '$Quality' product: '$Product', os: 'win', architecture: '$Architecture'."
|
||||||
|
|
||||||
@ -1098,10 +1116,10 @@ function Prepare-Install-Directory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Say "Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:"
|
Say-Verbose "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-Verbose "- 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-Verbose "- 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.`r`n"
|
Say-Verbose "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.`r`n"
|
||||||
|
|
||||||
if ($SharedRuntime -and (-not $Runtime)) {
|
if ($SharedRuntime -and (-not $Runtime)) {
|
||||||
$Runtime = "dotnet"
|
$Runtime = "dotnet"
|
||||||
@ -1109,14 +1127,16 @@ if ($SharedRuntime -and (-not $Runtime)) {
|
|||||||
|
|
||||||
$OverrideNonVersionedFiles = !$SkipNonVersionedFiles
|
$OverrideNonVersionedFiles = !$SkipNonVersionedFiles
|
||||||
|
|
||||||
$CLIArchitecture = Get-CLIArchitecture-From-Architecture $Architecture
|
Measure-Action "Product discovery" {
|
||||||
$NormalizedQuality = Get-NormalizedQuality $Quality
|
$script:CLIArchitecture = Get-CLIArchitecture-From-Architecture $Architecture
|
||||||
Say-Verbose "Normalized quality: '$NormalizedQuality'"
|
$script:NormalizedQuality = Get-NormalizedQuality $Quality
|
||||||
$NormalizedChannel = Get-NormalizedChannel $Channel
|
Say-Verbose "Normalized quality: '$NormalizedQuality'"
|
||||||
Say-Verbose "Normalized channel: '$NormalizedChannel'"
|
$script:NormalizedChannel = Get-NormalizedChannel $Channel
|
||||||
$NormalizedProduct = Get-NormalizedProduct $Runtime
|
Say-Verbose "Normalized channel: '$NormalizedChannel'"
|
||||||
Say-Verbose "Normalized product: '$NormalizedProduct'"
|
$script:NormalizedProduct = Get-NormalizedProduct $Runtime
|
||||||
$FeedCredential = ValidateFeedCredential $FeedCredential
|
Say-Verbose "Normalized product: '$NormalizedProduct'"
|
||||||
|
$script:FeedCredential = ValidateFeedCredential $FeedCredential
|
||||||
|
}
|
||||||
|
|
||||||
$InstallRoot = Resolve-Installation-Path $InstallDir
|
$InstallRoot = Resolve-Installation-Path $InstallDir
|
||||||
Say-Verbose "InstallRoot: $InstallRoot"
|
Say-Verbose "InstallRoot: $InstallRoot"
|
||||||
@ -1127,7 +1147,7 @@ $feeds = Get-Feeds-To-Use
|
|||||||
$DownloadLinks = @()
|
$DownloadLinks = @()
|
||||||
|
|
||||||
if ($Version.ToLowerInvariant() -ne "latest" -and -not [string]::IsNullOrEmpty($Quality)) {
|
if ($Version.ToLowerInvariant() -ne "latest" -and -not [string]::IsNullOrEmpty($Quality)) {
|
||||||
throw "Quality and Version options are not allowed to be specified simultaneously. See https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script#options for details."
|
throw "Quality and Version options are not allowed to be specified simultaneously. See https:// learn.microsoft.com/dotnet/core/tools/dotnet-install-script#options for details."
|
||||||
}
|
}
|
||||||
|
|
||||||
# aka.ms links can only be used if the user did not request a specific version via the command line or a global.json file.
|
# aka.ms links can only be used if the user did not request a specific version via the command line or a global.json file.
|
||||||
@ -1194,7 +1214,7 @@ if ($DryRun) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Prepare-Install-Directory
|
Measure-Action "Installation directory preparation" { Prepare-Install-Directory }
|
||||||
|
|
||||||
$ZipPath = [System.IO.Path]::combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName())
|
$ZipPath = [System.IO.Path]::combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName())
|
||||||
Say-Verbose "Zip path: $ZipPath"
|
Say-Verbose "Zip path: $ZipPath"
|
||||||
@ -1208,7 +1228,7 @@ foreach ($link in $DownloadLinks)
|
|||||||
Say-Verbose "Downloading `"$($link.type)`" link $($link.downloadLink)"
|
Say-Verbose "Downloading `"$($link.type)`" link $($link.downloadLink)"
|
||||||
|
|
||||||
try {
|
try {
|
||||||
DownloadFile -Source $link.downloadLink -OutPath $ZipPath
|
Measure-Action "Package download" { DownloadFile -Source $link.downloadLink -OutPath $ZipPath }
|
||||||
Say-Verbose "Download succeeded."
|
Say-Verbose "Download succeeded."
|
||||||
$DownloadSucceeded = $true
|
$DownloadSucceeded = $true
|
||||||
$DownloadedLink = $link
|
$DownloadedLink = $link
|
||||||
@ -1245,7 +1265,7 @@ if (-not $DownloadSucceeded) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Say "Extracting the archive."
|
Say "Extracting the archive."
|
||||||
Extract-Dotnet-Package -ZipPath $ZipPath -OutPath $InstallRoot
|
Measure-Action "Package extraction" { Extract-Dotnet-Package -ZipPath $ZipPath -OutPath $InstallRoot }
|
||||||
|
|
||||||
# Check if the SDK version is installed; if not, fail the installation.
|
# Check if the SDK version is installed; if not, fail the installation.
|
||||||
$isAssetInstalled = $false
|
$isAssetInstalled = $false
|
||||||
@ -1271,224 +1291,224 @@ if (!$isAssetInstalled) {
|
|||||||
|
|
||||||
SafeRemoveFile -Path $ZipPath
|
SafeRemoveFile -Path $ZipPath
|
||||||
|
|
||||||
Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot
|
Measure-Action "Setting up shell environment" { Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot }
|
||||||
|
|
||||||
Say "Note that the script does not resolve dependencies during installation."
|
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/windows#dependencies"
|
Say "To check the list of dependencies, go to https://learn.microsoft.com/dotnet/core/install/windows#dependencies"
|
||||||
Say "Installed version is $($DownloadedLink.effectiveVersion)"
|
Say "Installed version is $($DownloadedLink.effectiveVersion)"
|
||||||
Say "Installation finished"
|
Say "Installation finished"
|
||||||
|
|
||||||
# SIG # Begin signature block
|
# SIG # Begin signature block
|
||||||
# MIInnQYJKoZIhvcNAQcCoIInjjCCJ4oCAQExDzANBglghkgBZQMEAgEFADB5Bgor
|
# MIInvwYJKoZIhvcNAQcCoIInsDCCJ6wCAQExDzANBglghkgBZQMEAgEFADB5Bgor
|
||||||
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
|
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
|
||||||
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBPbD3vCI+sY1o7
|
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBhfTi3SRn7+vyy
|
||||||
# t+9GwL7gEDtWJk/5Ypegl3ITSKy+X6CCDYEwggX/MIID56ADAgECAhMzAAACzI61
|
# uCXKPjhiawegWZ493EcaOEycbgkZcKCCDXYwggX0MIID3KADAgECAhMzAAACy7d1
|
||||||
# lqa90clOAAAAAALMMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
|
# OfsCcUI2AAAAAALLMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
|
||||||
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
|
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
|
||||||
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
|
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
|
||||||
# bmcgUENBIDIwMTEwHhcNMjIwNTEyMjA0NjAxWhcNMjMwNTExMjA0NjAxWjB0MQsw
|
# bmcgUENBIDIwMTEwHhcNMjIwNTEyMjA0NTU5WhcNMjMwNTExMjA0NTU5WjB0MQsw
|
||||||
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
|
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
|
||||||
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
|
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
|
||||||
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
|
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
|
||||||
# AQCiTbHs68bADvNud97NzcdP0zh0mRr4VpDv68KobjQFybVAuVgiINf9aG2zQtWK
|
# AQC3sN0WcdGpGXPZIb5iNfFB0xZ8rnJvYnxD6Uf2BHXglpbTEfoe+mO//oLWkRxA
|
||||||
# No6+2X2Ix65KGcBXuZyEi0oBUAAGnIe5O5q/Y0Ij0WwDyMWaVad2Te4r1Eic3HWH
|
# wppditsSVOD0oglKbtnh9Wp2DARLcxbGaW4YanOWSB1LyLRpHnnQ5POlh2U5trg4
|
||||||
# UfiiNjF0ETHKg3qa7DCyUqwsR9q5SaXuHlYCwM+m59Nl3jKnYnKLLfzhl13wImV9
|
# 3gQjvlNZlQB3lL+zrPtbNvMA7E0Wkmo+Z6YFnsf7aek+KGzaGboAeFO4uKZjQXY5
|
||||||
# DF8N76ANkRyK6BYoc9I6hHF2MCTQYWbQ4fXgzKhgzj4zeabWgfu+ZJCiFLkogvc0
|
# RmMzE70Bwaz7hvA05jDURdRKH0i/1yK96TDuP7JyRFLOvA3UXNWz00R9w7ppMDcN
|
||||||
# RVb0x3DtyxMbl/3e45Eu+sn/x6EVwbJZVvtQYcmdGF1yAYht+JnNmWwAxL8MgHMz
|
# lXtrmbPigv3xE9FfpfmJRtiOZQKd73K72Wujmj6/Su3+DBTpOq7NgdntW2lJfX3X
|
||||||
# xEcoY1Q1JtstiY3+u3ulGMvhAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE
|
# a6oe4F9Pk9xRhkwHsk7Ju9E/AgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE
|
||||||
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUiLhHjTKWzIqVIp+sM2rOHH11rfQw
|
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUrg/nt/gj+BBLd1jZWYhok7v5/w4w
|
||||||
# UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1
|
# RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW
|
||||||
# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDcwNTI5MB8GA1UdIwQYMBaAFEhu
|
# MBQGA1UEBRMNMjMwMDEyKzQ3MDUyODAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci
|
||||||
# ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu
|
# tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j
|
||||||
# bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w
|
# b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG
|
||||||
# Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3
|
# CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu
|
||||||
# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx
|
# Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0
|
||||||
# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAeA8D
|
# MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBAJL5t6pVjIRlQ8j4dAFJ
|
||||||
# sOAHS53MTIHYu8bbXrO6yQtRD6JfyMWeXaLu3Nc8PDnFc1efYq/F3MGx/aiwNbcs
|
# ZnMke3rRHeQDOPFxswM47HRvgQa2E1jea2aYiMk1WmdqWnYw1bal4IzRlSVf4czf
|
||||||
# J2MU7BKNWTP5JQVBA2GNIeR3mScXqnOsv1XqXPvZeISDVWLaBQzceItdIwgo6B13
|
# zx2vjOIOiaGllW2ByHkfKApngOzJmAQ8F15xSHPRvNMmvpC3PFLvKMf3y5SyPJxh
|
||||||
# vxlkkSYMvB0Dr3Yw7/W9U4Wk5K/RDOnIGvmKqKi3AwyxlV1mpefy729FKaWT7edB
|
# 922TTq0q5epJv1SgZDWlUlHL/Ex1nX8kzBRhHvc6D6F5la+oAO4A3o/ZC05OOgm4
|
||||||
# d3I4+hldMY8sdfDPjWRtJzjMjXZs41OUOwtHccPazjjC7KndzvZHx/0VWL8n0NT/
|
# EJxZP9MqUi5iid2dw4Jg/HvtDpCcLj1GLIhCDaebKegajCJlMhhxnDXrGFLJfX8j
|
||||||
# 404vftnXKifMZkS4p2sB3oK+6kCcsyWsgS/3eYGw1Fe4MOnin1RhgrW1rHPODJTG
|
# 7k7LUvrZDsQniJZ3D66K+3SZTLhvwK7dMGVFuUUJUfDifrlCTjKG9mxsPDllfyck
|
||||||
# AUOmW4wc3Q6KKr2zve7sMDZe9tfylonPwhk971rX8qGw6LkrGFv31IJeJSe/aUbG
|
# 4zGnRZv8Jw9RgE1zAghnU14L0vVUNOzi/4bE7wIsiRyIcCcVoXRneBA3n/frLXvd
|
||||||
# dUDPkbrABbVvPElgoj5eP3REqx5jdfkQw7tOdWkhn0jDUh2uQen9Atj3RkJyHuR0
|
# jDsbb2lpGu78+s1zbO5N0bhHWq4j5WMutrspBxEhqG2PSBjC5Ypi+jhtfu3+x76N
|
||||||
# GUsJVMWFJdkIO/gFwzoOGlHNsmxvpANV86/1qgb1oZXdrURpzJp53MsDaBY/pxOc
|
# mBvsyKuxx9+Hm/ALnlzKxr4KyMR3/z4IRMzA1QyppNk65Ui+jB14g+w4vole33M1
|
||||||
# J0Cvg6uWs3kQWgKk5aBzvsX95BzdItHTpVMtVPW4q41XEvbFmUP1n6oL5rdNdrTM
|
# pVqVckrmSebUkmjnCshCiH12IFgHZF7gRwE4YZrJ7QjxZeoZqHaKsQLRMp653beB
|
||||||
# j/HXMRk1KCksax1Vxo3qv+13cCsZAaQNaIAvt5LvkshZkDZIP//0Hnq7NnWeYR3z
|
# fHfeva9zJPhBSdVcCW7x9q0c2HVPLJHX9YCUU714I+qtLpDGrdbZxD9mikPqL/To
|
||||||
# 4oFiw9N2n3bb9baQWuWPswG0Dq9YT9kb+Cs4qIIwggd6MIIFYqADAgECAgphDpDS
|
# /1lDZ0ch8FtePhME7houuoPcMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq
|
||||||
# AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK
|
# hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x
|
||||||
# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
|
# EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv
|
||||||
# IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0
|
# bjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5
|
||||||
# ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla
|
# IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEwOTA5WjB+MQswCQYDVQQG
|
||||||
# MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS
|
# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG
|
||||||
# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT
|
# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQg
|
||||||
# H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB
|
# Q29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
|
||||||
# AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG
|
# CgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+laUKq4BjgaBEm6f8MMHt03
|
||||||
# OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S
|
# a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc6Whe0t+bU7IKLMOv2akr
|
||||||
# 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz
|
# rnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4Ddato88tt8zpcoRb0Rrrg
|
||||||
# y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7
|
# OGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+lD3v++MrWhAfTVYoonpy
|
||||||
# 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u
|
# 4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nkkDstrjNYxbc+/jLTswM9
|
||||||
# M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33
|
# sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6A4aN91/w0FK/jJSHvMAh
|
||||||
# X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl
|
# dCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmdX4jiJV3TIUs+UsS1Vz8k
|
||||||
# XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP
|
# A/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL5zmhD+kjSbwYuER8ReTB
|
||||||
# 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB
|
# w3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zdsGbiwZeBe+3W7UvnSSmn
|
||||||
# l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF
|
# Eyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3T8HhhUSJxAlMxdSlQy90
|
||||||
# RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM
|
# lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS4NaIjAsCAwEAAaOCAe0w
|
||||||
# CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ
|
# ggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRIbmTlUAXTgqoXNzcitW2o
|
||||||
# BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud
|
# ynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYD
|
||||||
# DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO
|
# VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBDuRQFTuHqp8cx0SOJNDBa
|
||||||
# 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0
|
# BgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny
|
||||||
# LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
|
# bC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3JsMF4GCCsG
|
||||||
# Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p
|
# AQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3dy5taWNyb3NvZnQuY29t
|
||||||
# Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
|
# L3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3J0MIGfBgNV
|
||||||
# Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB
|
# HSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEFBQcCARYzaHR0cDovL3d3
|
||||||
# FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw
|
# dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1hcnljcHMuaHRtMEAGCCsG
|
||||||
# cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA
|
# AQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkAYwB5AF8AcwB0AGEAdABl
|
||||||
# XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY
|
# AG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn8oalmOBUeRou09h0ZyKb
|
||||||
# 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj
|
# C5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7v0epo/Np22O/IjWll11l
|
||||||
# 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd
|
# hJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0bpdS1HXeUOeLpZMlEPXh6
|
||||||
# d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ
|
# I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/KmtYSWMfCWluWpiW5IP0
|
||||||
# Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf
|
# wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvyCInWH8MyGOLwxS3OW560
|
||||||
# wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ
|
# STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBpmLJZiWhub6e3dMNABQam
|
||||||
# aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j
|
# ASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJihsMdYzaXht/a8/jyFqGa
|
||||||
# NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B
|
# J+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYbBL7fQccOKO7eZS/sl/ah
|
||||||
# xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96
|
# XJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbSoqKfenoi+kiVH6v7RyOA
|
||||||
# eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7
|
# 9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sLgOppO6/8MO0ETI7f33Vt
|
||||||
# r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I
|
# Y5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtXcVZOSEXAQsmbdlsKgEhr
|
||||||
# RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIZcjCCGW4CAQEwgZUwfjELMAkG
|
# /Xmfwb1tbWrJUnMTDXpQzTGCGZ8wghmbAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw
|
||||||
# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
|
# EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN
|
||||||
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z
|
# aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp
|
||||||
# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAsyOtZamvdHJTgAAAAACzDAN
|
# Z25pbmcgUENBIDIwMTECEzMAAALLt3U5+wJxQjYAAAAAAsswDQYJYIZIAWUDBAIB
|
||||||
# BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor
|
# BQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO
|
||||||
# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgNQFZgkyG
|
# MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIFmuaTXYQ37AFvsEol24fdW+
|
||||||
# luNzcU2g8/R/8PaAnIpTnmBnw3/0HJQjl9wwQgYKKwYBBAGCNwIBDDE0MDKgFIAS
|
# nRqHcc1fr+VQVdqhXc/vMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8A
|
||||||
# AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN
|
# cwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEB
|
||||||
# BgkqhkiG9w0BAQEFAASCAQABpLusOOxklzXjvllIe1AgDCgkYd0BN4cT3yQ8uULV
|
# BQAEggEAjY5XW5Ly7TJ1OTbeIR98xU+2dmtw7L71ws+ICnQCGhj2xJDUK+5yrTfO
|
||||||
# e+OnVgGOLnPcffCSGZ/SQMgJndoRMBSBd0jH5JxSkSuLXJpEWs1nl4QUg93FxYLr
|
# 8C98l/P4ynFi33Dl8z2YElqUCuqEXbiCzz06lIL4NuibC5DV/X80ZmICR/NYd2v1
|
||||||
# pMdFepMsN733h5JuZGcTFf7P23IOxYaVEC+mKLbkOxIJaxgDQYSgliSg9X2hwLJ2
|
# ww7IH+7dpsHAowBBindCYpVwQ3Ea3kDWgsjPAinAysFFushSOnNWFvrF6vi2smrs
|
||||||
# frCUV4b3ZWL0R495LhGpo65B7Ik/OOeHXWcs8d7vOnE/ObPHFv3fn1QTrq+KvbhA
|
# smbrAAhEhSfLd1Pxxdw73hQ0YjM/D3F3opaybMQ0blpHhOaqtbiyYzvk0doIzBEc
|
||||||
# TWEmL3P9P0Jn7k6gJjrTOxpgcDenr0IE5X63oe7y32LgLlJbr1OjKQUUCPVQ16d9
|
# trSH4NDIc3yLNj5VbjSczpexE+hyQNY4xCtwco4bVtXhONUihv08AIKR8+sIaI7A
|
||||||
# bgkhRp0gghdSAbDKjQuEAQ+e3GTeoNWnzxPlQfMLP0droYIW/DCCFvgGCisGAQQB
|
# mM/SWrrwGYSSSxydKqDei7biKG4jDqGCFykwghclBgorBgEEAYI3AwMBMYIXFTCC
|
||||||
# gjcDAwExghboMIIW5AYJKoZIhvcNAQcCoIIW1TCCFtECAQMxDzANBglghkgBZQME
|
# FxEGCSqGSIb3DQEHAqCCFwIwghb+AgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFZBgsq
|
||||||
# AgEFADCCAVEGCyqGSIb3DQEJEAEEoIIBQASCATwwggE4AgEBBgorBgEEAYRZCgMB
|
# hkiG9w0BCRABBKCCAUgEggFEMIIBQAIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFl
|
||||||
# MDEwDQYJYIZIAWUDBAIBBQAEIGXZSvVWqDs0wjW8JLHjKJ41lgzXHpdGqPCyYSvk
|
# AwQCAQUABCB6Hzt2gUb/WZK8fvVnOocriE4rYr6mscZi3gZnBCpiigIGZBr2iMZU
|
||||||
# gIH0AgZi1XtjQncYEzIwMjIwODAzMTI1NjA1Ljc2OFowBIACAfSggdCkgc0wgcox
|
# GBMyMDIzMDMzMTE1MjEwNi41MTZaMASAAgH0oIHYpIHVMIHSMQswCQYDVQQGEwJV
|
||||||
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
|
# UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE
|
||||||
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNVBAsTHE1p
|
# ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJl
|
||||||
# Y3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJjAkBgNVBAsTHVRoYWxlcyBUU1Mg
|
# bGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNO
|
||||||
# RVNOOjEyQkMtRTNBRS03NEVCMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFt
|
# OjA4NDItNEJFNi1DMjlBMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBT
|
||||||
# cCBTZXJ2aWNloIIRUzCCBwwwggT0oAMCAQICEzMAAAGhAYVVmblUXYoAAQAAAaEw
|
# ZXJ2aWNloIIReDCCBycwggUPoAMCAQICEzMAAAGybkADf26plJIAAQAAAbIwDQYJ
|
||||||
# DQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0
|
# KoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x
|
||||||
# b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh
|
# EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv
|
||||||
# dGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcN
|
# bjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcNMjIw
|
||||||
# MjExMjAyMTkwNTI0WhcNMjMwMjI4MTkwNTI0WjCByjELMAkGA1UEBhMCVVMxEzAR
|
# OTIwMjAyMjAxWhcNMjMxMjE0MjAyMjAxWjCB0jELMAkGA1UEBhMCVVMxEzARBgNV
|
||||||
# BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p
|
# BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv
|
||||||
# Y3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2Eg
|
# c29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0IElyZWxhbmQgT3Bl
|
||||||
# T3BlcmF0aW9uczEmMCQGA1UECxMdVGhhbGVzIFRTUyBFU046MTJCQy1FM0FFLTc0
|
# cmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjowODQyLTRC
|
||||||
# RUIxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggIiMA0G
|
# RTYtQzI5QTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZTCC
|
||||||
# CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDayTxe5WukkrYxxVuHLYW9BEWCD9kk
|
# AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMqiZTIde/lQ4rC+Bml5f/Wu
|
||||||
# jnnHsOKwGddIPbZlLY+l5ovLDNf+BEMQKAZQI3DX91l1yCDuP9X7tOPC48ZRGXA/
|
# q/xKTxrfbG23HofmQ+qZAN4GyO73PF3y9OAfpt7Qf2jcldWOGUB+HzBuwllYyP3f
|
||||||
# bf9ql0FK5438gIl7cV528XeEOFwc/A+UbIUfW296Omg8Z62xaQv3jrG4U/priArF
|
# x4MY8zvuAuB37FvoytnNC2DKnVrVlHOVcGUL9CnmhDNMA2/nskjIf2IoiG9J0qLY
|
||||||
# /er1UA1HNuIGUyqjlygiSPwK2NnFApi1JD+Uef5c47kh7pW1Kj7RnchpFeY9MekP
|
# r8duvHdQJ9Li2Pq9guySb9mvUL60ogslCO9gkh6FiEDwMrwUr8Wja6jFpUTny8tg
|
||||||
# QRia7cEaUYU4sqCiJVdDJpefLvPT9EdthlQx75ldx+AwZf2a9T7uQRSBh8tpxPdI
|
# 0N0cnCN2w4fKkp5qZcbUYFYicLSb/6A7pHCtX6xnjqwhmJoib3vkKJyVxbuFLRhV
|
||||||
# DDkKiWMwjKTrAY09A3I/jidqPuc8PvX+sqxqyZEN2h4GA0Edjmk64nkIukAK18K5
|
# XxH95b0LHeNhifn3jvo2j+/4QV10jEpXVW+iC9BsTtR69xvTjU51ZgP7BR4YDEWq
|
||||||
# nALDLO9SMTxpAwQIHRDtZeTClvAPCEoy1vtPD7f+eqHqStuu+XCkfRjXEpX9+h9f
|
# 7JsylSOv5B5THTDXRf184URzFhTyb8OZQKY7mqMh7c8J8w1sEM4XDUF2UZNy829N
|
||||||
# rsB0/BgD5CBf3ELLAa8TefMfHZWEJRTPNrbXMKizSrUSkVv/3HP/ZsJpwaz5My2R
|
# VCzG2tfdEXZaHxF8RmxpQYBxyhZwY1rotuIS+gfN2eq+hkAT3ipGn8/KmDwDtzAb
|
||||||
# byc3Ah9bT76eBJkyfT5FN9v/KQ0HnxhRMs6HHhTmNx+LztYci+vHf0D3QH1eCjZW
|
# nfuXjApgeZqwgcYJ8pDJ+y/xU6ouzJz1Bve5TTihkiA7wQsQe6R60Zk9dPdNzw0M
|
||||||
# ZRjp1mOyxpPU2mDMG6gelvJse1JzRADo7YIok/J3Ccbm8MbBbm85iogFltFHecHF
|
# K5niRzuQZAt4GI96FhjhlUWcUZOCkv/JXM/OGu/rgSplYwdmPLzzfDtXyuy/GCU5
|
||||||
# EFwrsDGBFnNYHMhcbarQNA+gY2e2l9fAkX3MjI7Uklkoz74/P6KIqe5jcd9FPCbb
|
# I4l08g6iifXypMgoYkkceOAAz4vx1x0BOnZWfI3fSwqNUvoN7ncTT+MB4Vpvf1QB
|
||||||
# SbYH9OLsteeYOQIDAQABo4IBNjCCATIwHQYDVR0OBBYEFBa/IDLbY475VQyKiZSw
|
# ppjBAQUuvui6eCG0MCVNAgMBAAGjggFJMIIBRTAdBgNVHQ4EFgQUmfIngFzZEZlP
|
||||||
# 47l0/cypMB8GA1UdIwQYMBaAFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMF8GA1UdHwRY
|
# kjDOVluBSDDaanEwHwYDVR0jBBgwFoAUn6cVXQBeYl2D9OXSZacbUzUZ6XIwXwYD
|
||||||
# MFYwVKBSoFCGTmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01p
|
# VR0fBFgwVjBUoFKgUIZOaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9j
|
||||||
# Y3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNybDBsBggrBgEF
|
# cmwvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3JsMGwG
|
||||||
# BQcBAQRgMF4wXAYIKwYBBQUHMAKGUGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9w
|
# CCsGAQUFBwEBBGAwXjBcBggrBgEFBQcwAoZQaHR0cDovL3d3dy5taWNyb3NvZnQu
|
||||||
# a2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAo
|
# Y29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIw
|
||||||
# MSkuY3J0MAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwgwDQYJKoZI
|
# MjAxMCgxKS5jcnQwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcD
|
||||||
# hvcNAQELBQADggIBACDDIxElfXlG5YKcKrLPSS+f3JWZprwKEiASvivaHTBRlXtA
|
# CDAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggIBANxHtu3FzIabaDbW
|
||||||
# s+TkadcsEei+9w5vmF5tCUzTH4c0nCI7bZxnsL+S6XsiOs3Z1V4WX+IwoXUJ4zLv
|
# qswdKBlAhKXRCN+5CSMiv2TYa4i2QuWIm+99piwAhDhADfbqor1zyLi95Y6GQnvI
|
||||||
# s0+mT4vjGDtYfKQ/bsmJKar2c99m/fHv1Wm2CTcyaePvi86Jh3UyLjdRILWbtzs4
|
# WUgdeC7oL1ZtZye92zYK+EIfwYZmhS+CH4infAzUvscHZF3wlrJUfPUIDGVP0lCY
|
||||||
# oImFMwwKbzHdPopxrBhgi+C1YZshosWLlgzyuxjUl+qNg1m52MJmf11loI7D9HJo
|
# Vse9mguvG0dqkY4ayQPEHOvJubgZZaOdg/N8dInd6fGeOc+0DoGzB+LieObJ2Q0A
|
||||||
# aQzd+rf928Y8rvULmg2h/G50o+D0UJ1Fa/cJJaHfB3sfKw9X6GrtXYGjmM3+g+Ah
|
# tEt3XN3iX8Cp6+dZTX8xwE/LvhRwPpb/+nKshO7TVuvenwdTwqB/LT6CNPaElwFe
|
||||||
# aVsfupKXNtOFu5tnLKvAH5OIjEDYV1YKmlXuBuhbYassygPFMmNgG2Ank3drEcDc
|
# KxKrqRTPMbHeg+i+KnBLfwmhEXsMg2s1QX7JIxfvT96md0eiMjiMEO22LbOzmLMN
|
||||||
# ZhCXXqpRszNo1F6Gu5JCpQZXbOJM9Ue5PlJKtmImAYIGsw+pnHy/r5ggSYOp4g5Z
|
# d3LINowAnRBAJtX+3/e390B9sMGMHp+a1V+hgs62AopBl0p/00li30DN5wEQ5If3
|
||||||
# 1oU9GhVCM3V0T9adee6OUXBk1rE4dZc/UsPlj0qoiljL+lN1A5gkmmz7k5tIObVG
|
# 5Zk7b/T6pEx6rJUDYCti7zCbikjKTanBnOc99zGMlej5X+fC/k5ExUCrOs3/VzGR
|
||||||
# B7dJdz8J0FwXRE5qYu1AdvauVbZwGQkL1x8aK/svjEQW0NUyJ29znDHiXl5vLoRT
|
# CZt5LvVQSdWqq/QMzTEmim4sbzASK9imEkjNtZZyvC1CsUcD1voFktld4mKMjE+u
|
||||||
# jjFpshUBi2+IY+mNqbLmj24j5eT+bjDlE3HmNtLPpLcMDYqZ1H+6U6YmaiNmac2j
|
# DEV3IddD+DrRk94nVzNPSuZXewfVOnXHSeqG7xM3V7fl2aL4v1OhL2+JwO1Tx3B0
|
||||||
# RXDAaeEE/uoDMt2dArfJP7M+MDv3zzNNTINeuNEtDVgm9zwfgIUCXnDZuVtiMIIH
|
# irO1O9qbNdJk355bntd1RSVKgM22KFBHnoL7Js7pRhBiaKmVTQGoOb+j1Qa7q+ci
|
||||||
# cTCCBVmgAwIBAgITMwAAABXF52ueAptJmQAAAAAAFTANBgkqhkiG9w0BAQsFADCB
|
# xGo48Vh9k35BDsJS/DLoXFSPDl4mMIIHcTCCBVmgAwIBAgITMwAAABXF52ueAptJ
|
||||||
# iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1Jl
|
# mQAAAAAAFTANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT
|
||||||
# ZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMp
|
|
||||||
# TWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMjEw
|
|
||||||
# OTMwMTgyMjI1WhcNMzAwOTMwMTgzMjI1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UE
|
|
||||||
# CBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9z
|
|
||||||
# b2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQ
|
|
||||||
# Q0EgMjAxMDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOThpkzntHIh
|
|
||||||
# C3miy9ckeb0O1YLT/e6cBwfSqWxOdcjKNVf2AX9sSuDivbk+F2Az/1xPx2b3lVNx
|
|
||||||
# WuJ+Slr+uDZnhUYjDLWNE893MsAQGOhgfWpSg0S3po5GawcU88V29YZQ3MFEyHFc
|
|
||||||
# UTE3oAo4bo3t1w/YJlN8OWECesSq/XJprx2rrPY2vjUmZNqYO7oaezOtgFt+jBAc
|
|
||||||
# nVL+tuhiJdxqD89d9P6OU8/W7IVWTe/dvI2k45GPsjksUZzpcGkNyjYtcI4xyDUo
|
|
||||||
# veO0hyTD4MmPfrVUj9z6BVWYbWg7mka97aSueik3rMvrg0XnRm7KMtXAhjBcTyzi
|
|
||||||
# YrLNueKNiOSWrAFKu75xqRdbZ2De+JKRHh09/SDPc31BmkZ1zcRfNN0Sidb9pSB9
|
|
||||||
# fvzZnkXftnIv231fgLrbqn427DZM9ituqBJR6L8FA6PRc6ZNN3SUHDSCD/AQ8rdH
|
|
||||||
# GO2n6Jl8P0zbr17C89XYcz1DTsEzOUyOArxCaC4Q6oRRRuLRvWoYWmEBc8pnol7X
|
|
||||||
# KHYC4jMYctenIPDC+hIK12NvDMk2ZItboKaDIV1fMHSRlJTYuVD5C4lh8zYGNRiE
|
|
||||||
# R9vcG9H9stQcxWv2XFJRXRLbJbqvUAV6bMURHXLvjflSxIUXk8A8FdsaN8cIFRg/
|
|
||||||
# eKtFtvUeh17aj54WcmnGrnu3tz5q4i6tAgMBAAGjggHdMIIB2TASBgkrBgEEAYI3
|
|
||||||
# FQEEBQIDAQABMCMGCSsGAQQBgjcVAgQWBBQqp1L+ZMSavoKRPEY1Kc8Q/y8E7jAd
|
|
||||||
# BgNVHQ4EFgQUn6cVXQBeYl2D9OXSZacbUzUZ6XIwXAYDVR0gBFUwUzBRBgwrBgEE
|
|
||||||
# AYI3TIN9AQEwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29t
|
|
||||||
# L3BraW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMBMGA1UdJQQMMAoGCCsGAQUFBwMI
|
|
||||||
# MBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMB
|
|
||||||
# Af8EBTADAQH/MB8GA1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQW9fOmhjEMFYGA1Ud
|
|
||||||
# HwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3By
|
|
||||||
# b2R1Y3RzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNybDBaBggrBgEFBQcBAQRO
|
|
||||||
# MEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2Vy
|
|
||||||
# dHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3J0MA0GCSqGSIb3DQEBCwUAA4IC
|
|
||||||
# AQCdVX38Kq3hLB9nATEkW+Geckv8qW/qXBS2Pk5HZHixBpOXPTEztTnXwnE2P9pk
|
|
||||||
# bHzQdTltuw8x5MKP+2zRoZQYIu7pZmc6U03dmLq2HnjYNi6cqYJWAAOwBb6J6Gng
|
|
||||||
# ugnue99qb74py27YP0h1AdkY3m2CDPVtI1TkeFN1JFe53Z/zjj3G82jfZfakVqr3
|
|
||||||
# lbYoVSfQJL1AoL8ZthISEV09J+BAljis9/kpicO8F7BUhUKz/AyeixmJ5/ALaoHC
|
|
||||||
# gRlCGVJ1ijbCHcNhcy4sa3tuPywJeBTpkbKpW99Jo3QMvOyRgNI95ko+ZjtPu4b6
|
|
||||||
# MhrZlvSP9pEB9s7GdP32THJvEKt1MMU0sHrYUP4KWN1APMdUbZ1jdEgssU5HLcEU
|
|
||||||
# BHG/ZPkkvnNtyo4JvbMBV0lUZNlz138eW0QBjloZkWsNn6Qo3GcZKCS6OEuabvsh
|
|
||||||
# VGtqRRFHqfG3rsjoiV5PndLQTHa1V1QJsWkBRH58oWFsc/4Ku+xBZj1p/cvBQUl+
|
|
||||||
# fpO+y/g75LcVv7TOPqUxUYS8vwLBgqJ7Fx0ViY1w/ue10CgaiQuPNtq6TPmb/wrp
|
|
||||||
# NPgkNWcr4A245oyZ1uEi6vAnQj0llOZ0dFtq0Z4+7X6gMTN9vMvpe784cETRkPHI
|
|
||||||
# qzqKOghif9lwY1NNje6CbaUFEMFxBmoQtB1VM1izoXBm8qGCAsowggIzAgEBMIH4
|
|
||||||
# oYHQpIHNMIHKMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G
|
|
||||||
# A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUw
|
|
||||||
# IwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMSYwJAYDVQQLEx1U
|
|
||||||
# aGFsZXMgVFNTIEVTTjoxMkJDLUUzQUUtNzRFQjElMCMGA1UEAxMcTWljcm9zb2Z0
|
|
||||||
# IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsOAwIaAxUAG3F2jO4LEMVLwgKG
|
|
||||||
# XdYMN4FBgOCggYMwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu
|
|
||||||
# Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv
|
|
||||||
# cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDAN
|
|
||||||
# BgkqhkiG9w0BAQUFAAIFAOaUaAIwIhgPMjAyMjA4MDMxMTIwMzRaGA8yMDIyMDgw
|
|
||||||
# NDExMjAzNFowczA5BgorBgEEAYRZCgQBMSswKTAKAgUA5pRoAgIBADAGAgEAAgEI
|
|
||||||
# MAcCAQACAhIDMAoCBQDmlbmCAgEAMDYGCisGAQQBhFkKBAIxKDAmMAwGCisGAQQB
|
|
||||||
# hFkKAwKgCjAIAgEAAgMHoSChCjAIAgEAAgMBhqAwDQYJKoZIhvcNAQEFBQADgYEA
|
|
||||||
# bqvBFqohycksQZhSEJZTiCeQ6hwWlYWRXL1PerCFbLmK+4vgr57BkwFsu5KzBE2z
|
|
||||||
# i1eHNrssK4BcBLYyIhDIjMSqqtrvclrB6SSDag1WcxZrz42xatvyhKXZd52a5R5Q
|
|
||||||
# xJw66cvwkDa4UmEtVOnbkaOPyyAql72D9w/XLHY0nmUxggQNMIIECQIBATCBkzB8
|
|
||||||
# MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVk
|
|
||||||
# bW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1N
|
|
||||||
# aWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAAaEBhVWZuVRdigABAAAB
|
|
||||||
# oTANBglghkgBZQMEAgEFAKCCAUowGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEE
|
|
||||||
# MC8GCSqGSIb3DQEJBDEiBCCGB/0CqUv9yvdxWNnaciRCHPCM4WmcYpKBUNiR1Xg+
|
|
||||||
# yjCB+gYLKoZIhvcNAQkQAi8xgeowgecwgeQwgb0EIOsIVPE6gYJoIIKOhHIF7UlJ
|
|
||||||
# Cswl4IJPISvOKInfjtCEMIGYMIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgT
|
|
||||||
# Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m
|
# Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m
|
||||||
# dCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENB
|
# dCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNh
|
||||||
# IDIwMTACEzMAAAGhAYVVmblUXYoAAQAAAaEwIgQgy8rtxrFwV1rcLxTDP8W6Af+y
|
# dGUgQXV0aG9yaXR5IDIwMTAwHhcNMjEwOTMwMTgyMjI1WhcNMzAwOTMwMTgzMjI1
|
||||||
# Za2AaaMVTQY3E9A2eHMwDQYJKoZIhvcNAQELBQAEggIAEJIvjnhqXrrsyJWHHG9i
|
# WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
|
||||||
# gKBBM3d51KglP0nJ0dY1zp7uUIBTQ53LVONE1SFiqbw6akydYum6iTaI7tvFWJRW
|
# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD
|
||||||
# dx5Fq56gt+QY2YO0nsn3zH3ulyUUkhHuMsx5N/pQT6tsEMu6tWCuWucf44JQHlyY
|
# Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCCAiIwDQYJKoZIhvcNAQEB
|
||||||
# x8/C+S5QoA7DId3ugccCFpZWUMb76QWReDtalDz3XY/gNSBT2DTJ8WT78WREcYKu
|
# BQADggIPADCCAgoCggIBAOThpkzntHIhC3miy9ckeb0O1YLT/e6cBwfSqWxOdcjK
|
||||||
# aBO52cUXKKLtr5ZoPcdEElB/TPuctcC6Hh0+J4Y6PCNwOVPodpEmjMSV0tAN8tZp
|
# NVf2AX9sSuDivbk+F2Az/1xPx2b3lVNxWuJ+Slr+uDZnhUYjDLWNE893MsAQGOhg
|
||||||
# T3cyf9YPnwXNdDiaikZlPSO0pXCM5+KjrBm5hnj6+J8qMc+Qc91UMh2J96kZWVmm
|
# fWpSg0S3po5GawcU88V29YZQ3MFEyHFcUTE3oAo4bo3t1w/YJlN8OWECesSq/XJp
|
||||||
# PsWE7YA4DlWrIWn2mdGLtTJP4sOlqRjigP9rdBFo0oG9c1ySKw3rN7zpGTDnFdkS
|
# rx2rrPY2vjUmZNqYO7oaezOtgFt+jBAcnVL+tuhiJdxqD89d9P6OU8/W7IVWTe/d
|
||||||
# vxeCoLWx48BJ4bE3Siwx6cwrYScmIgyobLb1Ztu5FEmFUn8maX5oo8IY9kPsODOG
|
# vI2k45GPsjksUZzpcGkNyjYtcI4xyDUoveO0hyTD4MmPfrVUj9z6BVWYbWg7mka9
|
||||||
# 3y8hPoLOOj2lRdslV9bdjtrbnqeY5Nq/oKuftbX8iD2MYFgWOqeufw3TcQiSz2uF
|
# 7aSueik3rMvrg0XnRm7KMtXAhjBcTyziYrLNueKNiOSWrAFKu75xqRdbZ2De+JKR
|
||||||
# tKGolAePdRf1S7c81CC89g7tcwy1TILR9M2JdWOwosAtpFXxX6Vc1OGiRwPAyXBL
|
# Hh09/SDPc31BmkZ1zcRfNN0Sidb9pSB9fvzZnkXftnIv231fgLrbqn427DZM9itu
|
||||||
# dvDqiTx5zb9k87hfJvwix/oXfo4fNCNdE/i/VbmsAJjcxd+eEBbJ9Oc+oPqC/5zq
|
# qBJR6L8FA6PRc6ZNN3SUHDSCD/AQ8rdHGO2n6Jl8P0zbr17C89XYcz1DTsEzOUyO
|
||||||
# pPtLXUsVfUWX58dPRnYeMAg=
|
# ArxCaC4Q6oRRRuLRvWoYWmEBc8pnol7XKHYC4jMYctenIPDC+hIK12NvDMk2ZItb
|
||||||
|
# oKaDIV1fMHSRlJTYuVD5C4lh8zYGNRiER9vcG9H9stQcxWv2XFJRXRLbJbqvUAV6
|
||||||
|
# bMURHXLvjflSxIUXk8A8FdsaN8cIFRg/eKtFtvUeh17aj54WcmnGrnu3tz5q4i6t
|
||||||
|
# AgMBAAGjggHdMIIB2TASBgkrBgEEAYI3FQEEBQIDAQABMCMGCSsGAQQBgjcVAgQW
|
||||||
|
# BBQqp1L+ZMSavoKRPEY1Kc8Q/y8E7jAdBgNVHQ4EFgQUn6cVXQBeYl2D9OXSZacb
|
||||||
|
# UzUZ6XIwXAYDVR0gBFUwUzBRBgwrBgEEAYI3TIN9AQEwQTA/BggrBgEFBQcCARYz
|
||||||
|
# aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnku
|
||||||
|
# aHRtMBMGA1UdJQQMMAoGCCsGAQUFBwMIMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIA
|
||||||
|
# QwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNX2
|
||||||
|
# VsuP6KJcYmjRPZSQW9fOmhjEMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwu
|
||||||
|
# bWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dF8yMDEw
|
||||||
|
# LTA2LTIzLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93
|
||||||
|
# d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYt
|
||||||
|
# MjMuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQCdVX38Kq3hLB9nATEkW+Geckv8qW/q
|
||||||
|
# XBS2Pk5HZHixBpOXPTEztTnXwnE2P9pkbHzQdTltuw8x5MKP+2zRoZQYIu7pZmc6
|
||||||
|
# U03dmLq2HnjYNi6cqYJWAAOwBb6J6Gngugnue99qb74py27YP0h1AdkY3m2CDPVt
|
||||||
|
# I1TkeFN1JFe53Z/zjj3G82jfZfakVqr3lbYoVSfQJL1AoL8ZthISEV09J+BAljis
|
||||||
|
# 9/kpicO8F7BUhUKz/AyeixmJ5/ALaoHCgRlCGVJ1ijbCHcNhcy4sa3tuPywJeBTp
|
||||||
|
# kbKpW99Jo3QMvOyRgNI95ko+ZjtPu4b6MhrZlvSP9pEB9s7GdP32THJvEKt1MMU0
|
||||||
|
# sHrYUP4KWN1APMdUbZ1jdEgssU5HLcEUBHG/ZPkkvnNtyo4JvbMBV0lUZNlz138e
|
||||||
|
# W0QBjloZkWsNn6Qo3GcZKCS6OEuabvshVGtqRRFHqfG3rsjoiV5PndLQTHa1V1QJ
|
||||||
|
# sWkBRH58oWFsc/4Ku+xBZj1p/cvBQUl+fpO+y/g75LcVv7TOPqUxUYS8vwLBgqJ7
|
||||||
|
# Fx0ViY1w/ue10CgaiQuPNtq6TPmb/wrpNPgkNWcr4A245oyZ1uEi6vAnQj0llOZ0
|
||||||
|
# dFtq0Z4+7X6gMTN9vMvpe784cETRkPHIqzqKOghif9lwY1NNje6CbaUFEMFxBmoQ
|
||||||
|
# tB1VM1izoXBm8qGCAtQwggI9AgEBMIIBAKGB2KSB1TCB0jELMAkGA1UEBhMCVVMx
|
||||||
|
# EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT
|
||||||
|
# FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0IElyZWxh
|
||||||
|
# bmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjow
|
||||||
|
# ODQyLTRCRTYtQzI5QTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vy
|
||||||
|
# dmljZaIjCgEBMAcGBSsOAwIaAxUAjhJ+EeySRfn2KCNsjn9cF9AUSTqggYMwgYCk
|
||||||
|
# fjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
|
||||||
|
# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD
|
||||||
|
# Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIF
|
||||||
|
# AOfRUdUwIhgPMjAyMzAzMzEyMDM0MjlaGA8yMDIzMDQwMTIwMzQyOVowdDA6Bgor
|
||||||
|
# BgEEAYRZCgQBMSwwKjAKAgUA59FR1QIBADAHAgEAAgIKJDAHAgEAAgIRLzAKAgUA
|
||||||
|
# 59KjVQIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAID
|
||||||
|
# B6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAJlOESCa/uRR1x6GunE8
|
||||||
|
# K/WgHWTpSE31EITDOfTMvDcF4ptngCS5aOc4gfzmhNNehWfP6EOrgoSQzJYZ4YCh
|
||||||
|
# fYbHNMk56f18sq8t7y2hgR7KixcEo/4HVzeSdaOclHNc4Gn7kCGpMvpT3Xz9Lzc7
|
||||||
|
# UKWDZ0zkNKnbS8TZLNueVQwfMYIEDTCCBAkCAQEwgZMwfDELMAkGA1UEBhMCVVMx
|
||||||
|
# EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT
|
||||||
|
# FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUt
|
||||||
|
# U3RhbXAgUENBIDIwMTACEzMAAAGybkADf26plJIAAQAAAbIwDQYJYIZIAWUDBAIB
|
||||||
|
# BQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQx
|
||||||
|
# IgQgXhJRuHCXk3arJvifIY3DBe9Ce9EmlP1y6U4XkgL31DkwgfoGCyqGSIb3DQEJ
|
||||||
|
# EAIvMYHqMIHnMIHkMIG9BCBTeM485+E+t4PEVieUoFKX7PVyLo/nzu+htJPCG04+
|
||||||
|
# NTCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw
|
||||||
|
# DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x
|
||||||
|
# JjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABsm5A
|
||||||
|
# A39uqZSSAAEAAAGyMCIEIGGWlnNnYHrB5HguWG0/nJd/WvSrCogze+QCpenu3IM5
|
||||||
|
# MA0GCSqGSIb3DQEBCwUABIICADVOLTuNxeEnBOfZpb7Nv4uf91W/Ho5i99zenDSJ
|
||||||
|
# x5QHVs+bKXmgc3a7/SSsliAT3zygHc7cH4zARbCZePLTivByKmeG08Ka35eyR+FK
|
||||||
|
# awSNrI/X+eVIC6nw/egCwviBC1NAG8jHGkuScbHeiiGajvS6lp3ORML7UexMuE4w
|
||||||
|
# 9SEumoghljCLZMwCSvw+3WxhQoBEZroR8u+PID2RdD0vi85FjKPWcZZijVLqHeFi
|
||||||
|
# TnuFqwRCLTV0MV+dDCbjwXneIqV+AVlnqb9iDMr3ZhISlRcy9XJNpY5vQBj/wqUW
|
||||||
|
# vefrmpdz0LNkdtXYThPkyl3mha2KsoQi5SA9zSjlAjFgY3ppmXvi3Frbfqk+iL+f
|
||||||
|
# l/Qc4+B71jG4t28lTWKteJiHqo+6AUXK2rlAl0d74yvhO6N8lMMtXhdJc8JABYn1
|
||||||
|
# v2/KKZn5RvPFF8QP7Ac1saIe1+gUFNcsYOLaMm/xl8E6kefWwZnm5Rhm606g1AC/
|
||||||
|
# N5Wo08aAs0ymTPH91dEbmOURXLbA3vCyG7kbfgnhCs/j7oQHWaFDzEYuXDIA4ICT
|
||||||
|
# dxPUTltbq3OWdp0PAS8JSEKPQFaOoQEnPa4adrXWxMvOmel8IGqJiQ+BPOaLQG64
|
||||||
|
# Qu2tMkH/5szb1fsEnCe8SJmy5ESF+kmpnLBtJ17Y9o+9nJHF5ddFmvzy+LUaIqDN
|
||||||
|
# cOfH
|
||||||
# SIG # End signature block
|
# SIG # End signature block
|
||||||
|
44
externals/install-dotnet.sh
vendored
44
externals/install-dotnet.sh
vendored
@ -451,6 +451,10 @@ get_normalized_channel() {
|
|||||||
|
|
||||||
local channel="$(to_lowercase "$1")"
|
local channel="$(to_lowercase "$1")"
|
||||||
|
|
||||||
|
if [[ $channel == current ]]; then
|
||||||
|
say_warning 'Value "Current" is deprecated for -Channel option. Use "STS" instead.'
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ $channel == release/* ]]; then
|
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.';
|
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
|
fi
|
||||||
@ -461,6 +465,14 @@ get_normalized_channel() {
|
|||||||
echo "LTS"
|
echo "LTS"
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
|
sts)
|
||||||
|
echo "STS"
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
current)
|
||||||
|
echo "STS"
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
echo "$channel"
|
echo "$channel"
|
||||||
return 0
|
return 0
|
||||||
@ -1127,10 +1139,11 @@ downloadwget() {
|
|||||||
get_download_link_from_aka_ms() {
|
get_download_link_from_aka_ms() {
|
||||||
eval $invocation
|
eval $invocation
|
||||||
|
|
||||||
#quality is not supported for LTS or current channel
|
#quality is not supported for LTS or STS channel
|
||||||
if [[ ! -z "$normalized_quality" && ("$normalized_channel" == "LTS" || "$normalized_channel" == "current") ]]; then
|
#STS maps to current
|
||||||
|
if [[ ! -z "$normalized_quality" && ("$normalized_channel" == "LTS" || "$normalized_channel" == "STS") ]]; then
|
||||||
normalized_quality=""
|
normalized_quality=""
|
||||||
say_warning "Specifying quality for current or LTS channel is not supported, the quality will be ignored."
|
say_warning "Specifying quality for STS or LTS channel is not supported, the quality will be ignored."
|
||||||
fi
|
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'."
|
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'."
|
||||||
@ -1239,7 +1252,7 @@ generate_akams_links() {
|
|||||||
|
|
||||||
normalized_version="$(to_lowercase "$version")"
|
normalized_version="$(to_lowercase "$version")"
|
||||||
if [[ "$normalized_version" != "latest" ]] && [ -n "$normalized_quality" ]; then
|
if [[ "$normalized_version" != "latest" ]] && [ -n "$normalized_quality" ]; then
|
||||||
say_err "Quality and Version options are not allowed to be specified simultaneously. See https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script#options for details."
|
say_err "Quality and Version options are not allowed to be specified simultaneously. See https://learn.microsoft.com/dotnet/core/tools/dotnet-install-script#options for details."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -1604,18 +1617,23 @@ do
|
|||||||
echo " $script_name -h|-?|--help"
|
echo " $script_name -h|-?|--help"
|
||||||
echo ""
|
echo ""
|
||||||
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 " Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:"
|
||||||
|
echo " - The SDK needs to be installed without user interaction and without admin rights."
|
||||||
|
echo " - The SDK installation doesn't need to persist across multiple CI runs."
|
||||||
|
echo " 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."
|
||||||
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 " - STS - the most recent Standard Term Support release"
|
||||||
echo " - LTS - most current supported release"
|
echo " - LTS - the most recent Long Term Support 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 " - 3-part version in a format A.B.Cxx - represents a specific SDK release"
|
echo " - 3-part version in a format A.B.Cxx - represents a specific SDK release"
|
||||||
echo " examples: 5.0.1xx, 5.0.2xx."
|
echo " examples: 5.0.1xx, 5.0.2xx."
|
||||||
echo " Supported since 5.0 release"
|
echo " Supported since 5.0 release"
|
||||||
|
echo " Warning: Value 'Current' is deprecated for the Channel parameter. Use 'STS' instead."
|
||||||
echo " Note: The version parameter overrides the channel parameter when any version other than 'latest' is used."
|
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"
|
||||||
@ -1626,7 +1644,7 @@ do
|
|||||||
echo " -q,--quality <quality> Download the latest build of specified quality in the channel."
|
echo " -q,--quality <quality> Download the latest build of specified quality in the channel."
|
||||||
echo " -Quality"
|
echo " -Quality"
|
||||||
echo " The possible values are: daily, signed, validated, preview, GA."
|
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 " Works only in combination with channel. Not applicable for STS 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 " 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 " 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 " Note: The version parameter overrides the channel parameter when any version other than 'latest' is used, and therefore overrides the quality."
|
||||||
@ -1680,10 +1698,10 @@ do
|
|||||||
shift
|
shift
|
||||||
done
|
done
|
||||||
|
|
||||||
say "Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:"
|
say_verbose "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_verbose "- 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_verbose "- 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"
|
say_verbose "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
|
if [ "$internal" = true ] && [ -z "$(echo $feed_credential)" ]; then
|
||||||
message="Provide credentials via --feed-credential parameter."
|
message="Provide credentials via --feed-credential parameter."
|
||||||
@ -1716,5 +1734,5 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
say "Note that the script does not resolve dependencies during installation."
|
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 "To check the list of dependencies, go to https://learn.microsoft.com/dotnet/core/install, select your operating system and check the \"Dependencies\" section."
|
||||||
say "Installation finished successfully."
|
say "Installation finished successfully."
|
2255
package-lock.json
generated
2255
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
24
package.json
24
package.json
@ -1,13 +1,15 @@
|
|||||||
{
|
{
|
||||||
"name": "setup-dotnet",
|
"name": "setup-dotnet",
|
||||||
"version": "3.0.1",
|
"version": "3.0.2",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "setup dotnet action",
|
"description": "setup dotnet action",
|
||||||
"main": "lib/setup-dotnet.js",
|
"main": "lib/setup-dotnet.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc && ncc build",
|
"build": "tsc && ncc build",
|
||||||
"format": "prettier --write **/*.ts",
|
"format": "prettier --no-error-on-unmatched-pattern --config ./.prettierrc.js --write \"**/*.{ts,yml,yaml}\"",
|
||||||
"format-check": "prettier --check **/*.ts",
|
"format-check": "prettier --no-error-on-unmatched-pattern --config ./.prettierrc.js --check \"**/*.{ts,yml,yaml}\"",
|
||||||
|
"lint": "eslint --config ./.eslintrc.js \"**/*.ts\"",
|
||||||
|
"lint:fix": "eslint --config ./.eslintrc.js \"**/*.ts\" --fix",
|
||||||
"prepare": "husky install",
|
"prepare": "husky install",
|
||||||
"test": "jest --coverage --config ./jest.config.js",
|
"test": "jest --coverage --config ./jest.config.js",
|
||||||
"update-installers": "nwget https://dot.net/v1/dotnet-install.ps1 -O externals/install-dotnet.ps1 && nwget https://dot.net/v1/dotnet-install.sh -O externals/install-dotnet.sh"
|
"update-installers": "nwget https://dot.net/v1/dotnet-install.ps1 -O externals/install-dotnet.ps1 && nwget https://dot.net/v1/dotnet-install.sh -O externals/install-dotnet.sh"
|
||||||
@ -24,26 +26,30 @@
|
|||||||
"author": "GitHub",
|
"author": "GitHub",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.9.1",
|
"@actions/core": "^1.10.0",
|
||||||
"@actions/exec": "^1.0.4",
|
"@actions/exec": "^1.0.4",
|
||||||
"@actions/github": "^1.1.0",
|
"@actions/github": "^1.1.0",
|
||||||
"@actions/http-client": "^2.0.1",
|
"@actions/http-client": "^2.0.1",
|
||||||
"@actions/io": "^1.0.2",
|
"@actions/io": "^1.0.2",
|
||||||
"fast-xml-parser": "^3.15.1",
|
"fast-xml-parser": "^4.0.10",
|
||||||
"semver": "^6.3.0",
|
"semver": "^6.3.0"
|
||||||
"xmlbuilder": "^13.0.2"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "^27.0.2",
|
"@types/jest": "^27.0.2",
|
||||||
"@types/node": "^16.11.25",
|
"@types/node": "^16.11.25",
|
||||||
"@types/semver": "^6.2.2",
|
"@types/semver": "^6.2.2",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||||
|
"@typescript-eslint/parser": "^5.54.0",
|
||||||
"@vercel/ncc": "^0.33.4",
|
"@vercel/ncc": "^0.33.4",
|
||||||
|
"eslint": "^8.35.0",
|
||||||
|
"eslint-config-prettier": "^8.6.0",
|
||||||
|
"eslint-plugin-jest": "^27.2.1",
|
||||||
"husky": "^8.0.1",
|
"husky": "^8.0.1",
|
||||||
"jest": "^27.2.5",
|
"jest": "^27.2.5",
|
||||||
"jest-circus": "^27.2.5",
|
"jest-circus": "^27.2.5",
|
||||||
"prettier": "^1.19.1",
|
"prettier": "^2.8.4",
|
||||||
"ts-jest": "^27.0.5",
|
"ts-jest": "^27.0.5",
|
||||||
"typescript": "^3.9.7",
|
"typescript": "^4.8.4",
|
||||||
"wget-improved": "^3.2.1"
|
"wget-improved": "^3.2.1"
|
||||||
},
|
},
|
||||||
"jest": {
|
"jest": {
|
||||||
|
350
src/authutil.ts
350
src/authutil.ts
@ -1,154 +1,196 @@
|
|||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import * as github from '@actions/github';
|
import * as github from '@actions/github';
|
||||||
import * as xmlbuilder from 'xmlbuilder';
|
import {XMLParser, XMLBuilder} from 'fast-xml-parser';
|
||||||
import * as xmlParser from 'fast-xml-parser';
|
|
||||||
|
export function configAuthentication(
|
||||||
export function configAuthentication(
|
feedUrl: string,
|
||||||
feedUrl: string,
|
existingFileLocation = '',
|
||||||
existingFileLocation: string = '',
|
processRoot: string = process.cwd()
|
||||||
processRoot: string = process.cwd()
|
) {
|
||||||
) {
|
const existingNuGetConfig: string = path.resolve(
|
||||||
const existingNuGetConfig: string = path.resolve(
|
processRoot,
|
||||||
processRoot,
|
existingFileLocation === ''
|
||||||
existingFileLocation === ''
|
? getExistingNugetConfig(processRoot)
|
||||||
? getExistingNugetConfig(processRoot)
|
: existingFileLocation
|
||||||
: existingFileLocation
|
);
|
||||||
);
|
|
||||||
|
const tempNuGetConfig: string = path.resolve(
|
||||||
const tempNuGetConfig: string = path.resolve(
|
processRoot,
|
||||||
processRoot,
|
'../',
|
||||||
'../',
|
'nuget.config'
|
||||||
'nuget.config'
|
);
|
||||||
);
|
|
||||||
|
writeFeedToFile(feedUrl, existingNuGetConfig, tempNuGetConfig);
|
||||||
writeFeedToFile(feedUrl, existingNuGetConfig, tempNuGetConfig);
|
}
|
||||||
}
|
|
||||||
|
function isValidKey(key: string): boolean {
|
||||||
function isValidKey(key: string): boolean {
|
return /^[\w\-.]+$/i.test(key);
|
||||||
return /^[\w\-\.]+$/i.test(key);
|
}
|
||||||
}
|
|
||||||
|
function getExistingNugetConfig(processRoot: string) {
|
||||||
function getExistingNugetConfig(processRoot: string) {
|
const defaultConfigName = 'nuget.config';
|
||||||
const defaultConfigName = 'nuget.config';
|
const configFileNames = fs
|
||||||
const configFileNames = fs
|
.readdirSync(processRoot)
|
||||||
.readdirSync(processRoot)
|
.filter(filename => filename.toLowerCase() === defaultConfigName);
|
||||||
.filter(filename => filename.toLowerCase() === defaultConfigName);
|
if (configFileNames.length) {
|
||||||
if (configFileNames.length) {
|
return configFileNames[0];
|
||||||
return configFileNames[0];
|
}
|
||||||
}
|
return defaultConfigName;
|
||||||
return defaultConfigName;
|
}
|
||||||
}
|
|
||||||
|
function writeFeedToFile(
|
||||||
function writeFeedToFile(
|
feedUrl: string,
|
||||||
feedUrl: string,
|
existingFileLocation: string,
|
||||||
existingFileLocation: string,
|
tempFileLocation: string
|
||||||
tempFileLocation: string
|
) {
|
||||||
) {
|
core.info(
|
||||||
core.info(
|
`dotnet-auth: Finding any source references in ${existingFileLocation}, writing a new temporary configuration file with credentials to ${tempFileLocation}`
|
||||||
`dotnet-auth: Finding any source references in ${existingFileLocation}, writing a new temporary configuration file with credentials to ${tempFileLocation}`
|
);
|
||||||
);
|
const sourceKeys: string[] = [];
|
||||||
let xml: xmlbuilder.XMLElement;
|
let owner: string = core.getInput('owner');
|
||||||
let sourceKeys: string[] = [];
|
const sourceUrl: string = feedUrl;
|
||||||
let owner: string = core.getInput('owner');
|
if (!owner) {
|
||||||
let sourceUrl: string = feedUrl;
|
owner = github.context.repo.owner;
|
||||||
if (!owner) {
|
}
|
||||||
owner = github.context.repo.owner;
|
|
||||||
}
|
if (!process.env.NUGET_AUTH_TOKEN) {
|
||||||
|
throw new Error(
|
||||||
if (!process.env.NUGET_AUTH_TOKEN) {
|
'The NUGET_AUTH_TOKEN environment variable was not provided. In this step, add the following: \r\nenv:\r\n NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}'
|
||||||
throw new Error(
|
);
|
||||||
'The NUGET_AUTH_TOKEN environment variable was not provided. In this step, add the following: \r\nenv:\r\n NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}'
|
}
|
||||||
);
|
|
||||||
}
|
if (fs.existsSync(existingFileLocation)) {
|
||||||
|
// get key from existing NuGet.config so NuGet/dotnet can match credentials
|
||||||
if (fs.existsSync(existingFileLocation)) {
|
const curContents: string = fs.readFileSync(existingFileLocation, 'utf8');
|
||||||
// get key from existing NuGet.config so NuGet/dotnet can match credentials
|
|
||||||
const curContents: string = fs.readFileSync(existingFileLocation, 'utf8');
|
const parserOptions = {
|
||||||
const json = xmlParser.parse(curContents, {ignoreAttributes: false});
|
ignoreAttributes: false
|
||||||
|
};
|
||||||
if (typeof json.configuration === 'undefined') {
|
const parser = new XMLParser(parserOptions);
|
||||||
throw new Error(`The provided NuGet.config seems invalid.`);
|
const json = parser.parse(curContents);
|
||||||
}
|
|
||||||
if (typeof json.configuration.packageSources != 'undefined') {
|
if (typeof json.configuration === 'undefined') {
|
||||||
if (typeof json.configuration.packageSources.add != 'undefined') {
|
throw new Error(`The provided NuGet.config seems invalid.`);
|
||||||
// file has at least one <add>
|
}
|
||||||
if (typeof json.configuration.packageSources.add[0] === 'undefined') {
|
if (json.configuration?.packageSources?.add) {
|
||||||
// file has only one <add>
|
const packageSources = json.configuration.packageSources.add;
|
||||||
if (
|
|
||||||
json.configuration.packageSources.add['@_value']
|
if (Array.isArray(packageSources)) {
|
||||||
.toLowerCase()
|
packageSources.forEach(source => {
|
||||||
.includes(feedUrl.toLowerCase())
|
const value = source['@_value'];
|
||||||
) {
|
core.debug(`source '${value}'`);
|
||||||
const key = json.configuration.packageSources.add['@_key'];
|
if (value.toLowerCase().includes(feedUrl.toLowerCase())) {
|
||||||
sourceKeys.push(key);
|
const key = source['@_key'];
|
||||||
core.debug(`Found a URL with key ${key}`);
|
sourceKeys.push(key);
|
||||||
}
|
core.debug(`Found a URL with key ${key}`);
|
||||||
} else {
|
}
|
||||||
// file has 2+ <add>
|
});
|
||||||
for (
|
} else {
|
||||||
let i = 0;
|
if (
|
||||||
i < json.configuration.packageSources.add.length;
|
packageSources['@_value']
|
||||||
i++
|
.toLowerCase()
|
||||||
) {
|
.includes(feedUrl.toLowerCase())
|
||||||
const source = json.configuration.packageSources.add[i];
|
) {
|
||||||
const value = source['@_value'];
|
const key = packageSources['@_key'];
|
||||||
core.debug(`source '${value}'`);
|
sourceKeys.push(key);
|
||||||
if (value.toLowerCase().includes(feedUrl.toLowerCase())) {
|
core.debug(`Found a URL with key ${key}`);
|
||||||
const key = source['@_key'];
|
}
|
||||||
sourceKeys.push(key);
|
}
|
||||||
core.debug(`Found a URL with key ${key}`);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
const xmlSource: any[] = [
|
||||||
}
|
{
|
||||||
}
|
'?xml': [
|
||||||
}
|
{
|
||||||
|
'#text': ''
|
||||||
xml = xmlbuilder
|
}
|
||||||
.create('configuration')
|
],
|
||||||
.ele('config')
|
':@': {
|
||||||
.ele('add', {key: 'defaultPushSource', value: sourceUrl})
|
'@_version': '1.0'
|
||||||
.up()
|
}
|
||||||
.up();
|
},
|
||||||
|
{
|
||||||
if (!sourceKeys.length) {
|
configuration: [
|
||||||
let keystring = 'Source';
|
{
|
||||||
xml = xml
|
config: [
|
||||||
.ele('packageSources')
|
{
|
||||||
.ele('add', {key: keystring, value: sourceUrl})
|
add: [],
|
||||||
.up()
|
':@': {
|
||||||
.up();
|
'@_key': 'defaultPushSource',
|
||||||
sourceKeys.push(keystring);
|
'@_value': sourceUrl
|
||||||
}
|
}
|
||||||
xml = xml.ele('packageSourceCredentials');
|
}
|
||||||
|
]
|
||||||
sourceKeys.forEach(key => {
|
}
|
||||||
if (!isValidKey(key)) {
|
]
|
||||||
throw new Error(
|
}
|
||||||
"Source name can contain letters, numbers, and '-', '_', '.' symbols only. Please, fix source name in NuGet.config and try again."
|
];
|
||||||
);
|
|
||||||
}
|
if (!sourceKeys.length) {
|
||||||
|
const keystring = 'Source';
|
||||||
xml = xml
|
|
||||||
.ele(key)
|
xmlSource[1].configuration.push({
|
||||||
.ele('add', {key: 'Username', value: owner})
|
packageSources: [
|
||||||
.up()
|
{
|
||||||
.ele('add', {
|
add: [],
|
||||||
key: 'ClearTextPassword',
|
':@': {
|
||||||
value: process.env.NUGET_AUTH_TOKEN
|
'@_key': keystring,
|
||||||
})
|
'@_value': sourceUrl
|
||||||
.up()
|
}
|
||||||
.up();
|
}
|
||||||
});
|
]
|
||||||
|
});
|
||||||
// If NuGet fixes itself such that on Linux it can look for environment variables in the config file (it doesn't seem to work today),
|
|
||||||
// use this for the value above
|
sourceKeys.push(keystring);
|
||||||
// process.platform == 'win32'
|
}
|
||||||
// ? '%NUGET_AUTH_TOKEN%'
|
|
||||||
// : '$NUGET_AUTH_TOKEN'
|
const packageSourceCredentials: any[] = [];
|
||||||
|
sourceKeys.forEach(key => {
|
||||||
const output = xml.end({pretty: true});
|
if (!isValidKey(key)) {
|
||||||
fs.writeFileSync(tempFileLocation, output);
|
throw new Error(
|
||||||
}
|
"Source name can contain letters, numbers, and '-', '_', '.' symbols only. Please, fix source name in NuGet.config and try again."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
packageSourceCredentials.push({
|
||||||
|
[key]: [
|
||||||
|
{
|
||||||
|
add: [],
|
||||||
|
':@': {
|
||||||
|
'@_key': 'Username',
|
||||||
|
'@_value': owner
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
add: [],
|
||||||
|
':@': {
|
||||||
|
'@_key': 'ClearTextPassword',
|
||||||
|
'@_value': process.env.NUGET_AUTH_TOKEN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
xmlSource[1].configuration.push({
|
||||||
|
packageSourceCredentials
|
||||||
|
});
|
||||||
|
|
||||||
|
const xmlBuilderOptions = {
|
||||||
|
format: true,
|
||||||
|
ignoreAttributes: false,
|
||||||
|
preserveOrder: true,
|
||||||
|
allowBooleanAttributes: true,
|
||||||
|
suppressBooleanAttributes: true,
|
||||||
|
suppressEmptyNode: true
|
||||||
|
};
|
||||||
|
|
||||||
|
const builder = new XMLBuilder(xmlBuilderOptions);
|
||||||
|
|
||||||
|
const output = builder.build(xmlSource).trim();
|
||||||
|
|
||||||
|
fs.writeFileSync(tempFileLocation, output);
|
||||||
|
}
|
||||||
|
550
src/installer.ts
550
src/installer.ts
@ -1,272 +1,278 @@
|
|||||||
// Load tempDirectory before it gets wiped by tool-cache
|
// Load tempDirectory before it gets wiped by tool-cache
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import * as exec from '@actions/exec';
|
import * as exec from '@actions/exec';
|
||||||
import * as io from '@actions/io';
|
import * as io from '@actions/io';
|
||||||
import * as hc from '@actions/http-client';
|
import * as hc from '@actions/http-client';
|
||||||
import {chmodSync} from 'fs';
|
import {chmodSync} from 'fs';
|
||||||
import {readdir} from 'fs/promises';
|
import path from 'path';
|
||||||
import path from 'path';
|
import os from 'os';
|
||||||
import semver from 'semver';
|
import semver from 'semver';
|
||||||
import {IS_LINUX, IS_WINDOWS} from './utils';
|
import {IS_LINUX, IS_WINDOWS} from './utils';
|
||||||
import {QualityOptions} from './setup-dotnet';
|
import {QualityOptions} from './setup-dotnet';
|
||||||
|
|
||||||
export interface DotnetVersion {
|
export interface DotnetVersion {
|
||||||
type: string;
|
type: string;
|
||||||
value: string;
|
value: string;
|
||||||
qualityFlag: boolean;
|
qualityFlag: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DotnetVersionResolver {
|
const QUALITY_INPUT_MINIMAL_MAJOR_TAG = 6;
|
||||||
private inputVersion: string;
|
const LATEST_PATCH_SYNTAX_MINIMAL_MAJOR_TAG = 5;
|
||||||
private resolvedArgument: DotnetVersion;
|
export class DotnetVersionResolver {
|
||||||
|
private inputVersion: string;
|
||||||
constructor(version: string) {
|
private resolvedArgument: DotnetVersion;
|
||||||
this.inputVersion = version.trim();
|
|
||||||
this.resolvedArgument = {type: '', value: '', qualityFlag: false};
|
constructor(version: string) {
|
||||||
}
|
this.inputVersion = version.trim();
|
||||||
|
this.resolvedArgument = {type: '', value: '', qualityFlag: false};
|
||||||
private async resolveVersionInput(): Promise<void> {
|
}
|
||||||
if (!semver.validRange(this.inputVersion)) {
|
|
||||||
throw new Error(
|
private async resolveVersionInput(): Promise<void> {
|
||||||
`'dotnet-version' was supplied in invalid format: ${this.inputVersion}! Supported syntax: A.B.C, A.B, A.B.x, A, A.x`
|
if (!semver.validRange(this.inputVersion) && !this.isLatestPatchSyntax()) {
|
||||||
);
|
throw new Error(
|
||||||
}
|
`The 'dotnet-version' was supplied in invalid format: ${this.inputVersion}! Supported syntax: A.B.C, A.B, A.B.x, A, A.x, A.B.Cxx`
|
||||||
if (semver.valid(this.inputVersion)) {
|
);
|
||||||
this.resolvedArgument.type = 'version';
|
}
|
||||||
this.resolvedArgument.value = this.inputVersion;
|
if (semver.valid(this.inputVersion)) {
|
||||||
} else {
|
this.createVersionArgument();
|
||||||
const [major, minor] = this.inputVersion.split('.');
|
} else {
|
||||||
|
await this.createChannelArgument();
|
||||||
if (this.isNumericTag(major)) {
|
}
|
||||||
this.resolvedArgument.type = 'channel';
|
}
|
||||||
if (this.isNumericTag(minor)) {
|
|
||||||
this.resolvedArgument.value = `${major}.${minor}`;
|
private isNumericTag(versionTag): boolean {
|
||||||
} else {
|
return /^\d+$/.test(versionTag);
|
||||||
const httpClient = new hc.HttpClient('actions/setup-dotnet', [], {
|
}
|
||||||
allowRetries: true,
|
|
||||||
maxRetries: 3
|
private isLatestPatchSyntax() {
|
||||||
});
|
const majorTag = this.inputVersion.match(
|
||||||
this.resolvedArgument.value = await this.getLatestVersion(
|
/^(?<majorTag>\d+)\.\d+\.\d{1}x{2}$/
|
||||||
httpClient,
|
)?.groups?.majorTag;
|
||||||
[major, minor]
|
if (
|
||||||
);
|
majorTag &&
|
||||||
}
|
parseInt(majorTag) < LATEST_PATCH_SYNTAX_MINIMAL_MAJOR_TAG
|
||||||
}
|
) {
|
||||||
this.resolvedArgument.qualityFlag = +major >= 6 ? true : false;
|
throw new Error(
|
||||||
}
|
`The 'dotnet-version' was supplied in invalid format: ${this.inputVersion}! The A.B.Cxx syntax is available since the .NET 5.0 release.`
|
||||||
}
|
);
|
||||||
|
}
|
||||||
private isNumericTag(versionTag): boolean {
|
return majorTag ? true : false;
|
||||||
return /^\d+$/.test(versionTag);
|
}
|
||||||
}
|
|
||||||
|
private createVersionArgument() {
|
||||||
public async createDotNetVersion(): Promise<{
|
this.resolvedArgument.type = 'version';
|
||||||
type: string;
|
this.resolvedArgument.value = this.inputVersion;
|
||||||
value: string;
|
}
|
||||||
qualityFlag: boolean;
|
|
||||||
}> {
|
private async createChannelArgument() {
|
||||||
await this.resolveVersionInput();
|
this.resolvedArgument.type = 'channel';
|
||||||
if (!this.resolvedArgument.type) {
|
const [major, minor] = this.inputVersion.split('.');
|
||||||
return this.resolvedArgument;
|
if (this.isLatestPatchSyntax()) {
|
||||||
}
|
this.resolvedArgument.value = this.inputVersion;
|
||||||
if (IS_WINDOWS) {
|
} else if (this.isNumericTag(major) && this.isNumericTag(minor)) {
|
||||||
this.resolvedArgument.type =
|
this.resolvedArgument.value = `${major}.${minor}`;
|
||||||
this.resolvedArgument.type === 'channel' ? '-Channel' : '-Version';
|
} else if (this.isNumericTag(major)) {
|
||||||
} else {
|
this.resolvedArgument.value = await this.getLatestByMajorTag(major);
|
||||||
this.resolvedArgument.type =
|
} else {
|
||||||
this.resolvedArgument.type === 'channel' ? '--channel' : '--version';
|
// If "dotnet-version" is specified as *, x or X resolve latest version of .NET explicitly from LTS channel. The version argument will default to "latest" by install-dotnet script.
|
||||||
}
|
this.resolvedArgument.value = 'LTS';
|
||||||
return this.resolvedArgument;
|
}
|
||||||
}
|
this.resolvedArgument.qualityFlag =
|
||||||
|
parseInt(major) >= QUALITY_INPUT_MINIMAL_MAJOR_TAG ? true : false;
|
||||||
private async getLatestVersion(
|
}
|
||||||
httpClient: hc.HttpClient,
|
|
||||||
versionParts: string[]
|
public async createDotNetVersion(): Promise<DotnetVersion> {
|
||||||
): Promise<string> {
|
await this.resolveVersionInput();
|
||||||
const response = await httpClient.getJson<any>(
|
if (!this.resolvedArgument.type) {
|
||||||
DotnetVersionResolver.DotNetCoreIndexUrl
|
return this.resolvedArgument;
|
||||||
);
|
}
|
||||||
const result = response.result || {};
|
if (IS_WINDOWS) {
|
||||||
let releasesInfo: any[] = result['releases-index'];
|
this.resolvedArgument.type =
|
||||||
|
this.resolvedArgument.type === 'channel' ? '-Channel' : '-Version';
|
||||||
let releaseInfo = releasesInfo.find(info => {
|
} else {
|
||||||
let sdkParts: string[] = info['channel-version'].split('.');
|
this.resolvedArgument.type =
|
||||||
return sdkParts[0] === versionParts[0];
|
this.resolvedArgument.type === 'channel' ? '--channel' : '--version';
|
||||||
});
|
}
|
||||||
|
return this.resolvedArgument;
|
||||||
if (!releaseInfo) {
|
}
|
||||||
throw new Error(
|
|
||||||
`Could not find info for version ${versionParts.join('.')} at ${
|
private async getLatestByMajorTag(majorTag: string): Promise<string> {
|
||||||
DotnetVersionResolver.DotNetCoreIndexUrl
|
const httpClient = new hc.HttpClient('actions/setup-dotnet', [], {
|
||||||
}`
|
allowRetries: true,
|
||||||
);
|
maxRetries: 3
|
||||||
}
|
});
|
||||||
|
const response = await httpClient.getJson<any>(
|
||||||
return releaseInfo['channel-version'];
|
DotnetVersionResolver.DotNetCoreIndexUrl
|
||||||
}
|
);
|
||||||
|
const result = response.result || {};
|
||||||
static DotNetCoreIndexUrl: string =
|
const releasesInfo: any[] = result['releases-index'];
|
||||||
'https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/releases-index.json';
|
|
||||||
}
|
const releaseInfo = releasesInfo.find(info => {
|
||||||
|
const sdkParts: string[] = info['channel-version'].split('.');
|
||||||
export class DotnetCoreInstaller {
|
return sdkParts[0] === majorTag;
|
||||||
private version: string;
|
});
|
||||||
private quality: QualityOptions;
|
|
||||||
private static readonly installationDirectoryWindows = path.join(
|
if (!releaseInfo) {
|
||||||
process.env['PROGRAMFILES'] + '',
|
throw new Error(
|
||||||
'dotnet'
|
`Could not find info for version with major tag: "${majorTag}" at ${DotnetVersionResolver.DotNetCoreIndexUrl}`
|
||||||
);
|
);
|
||||||
private static readonly installationDirectoryLinux = '/usr/share/dotnet';
|
}
|
||||||
private static readonly installationDirectoryMac = path.join(
|
|
||||||
process.env['HOME'] + '',
|
return releaseInfo['channel-version'];
|
||||||
'.dotnet'
|
}
|
||||||
);
|
|
||||||
|
static DotNetCoreIndexUrl =
|
||||||
static addToPath() {
|
'https://dotnetcli.azureedge.net/dotnet/release-metadata/releases-index.json';
|
||||||
if (process.env['DOTNET_INSTALL_DIR']) {
|
}
|
||||||
core.addPath(process.env['DOTNET_INSTALL_DIR']);
|
|
||||||
core.exportVariable('DOTNET_ROOT', process.env['DOTNET_INSTALL_DIR']);
|
export class DotnetCoreInstaller {
|
||||||
} else {
|
private version: string;
|
||||||
if (IS_WINDOWS) {
|
private quality: QualityOptions;
|
||||||
core.addPath(DotnetCoreInstaller.installationDirectoryWindows);
|
|
||||||
core.exportVariable(
|
static {
|
||||||
'DOTNET_ROOT',
|
const installationDirectoryWindows = path.join(
|
||||||
DotnetCoreInstaller.installationDirectoryWindows
|
process.env['PROGRAMFILES'] + '',
|
||||||
);
|
'dotnet'
|
||||||
} else if (IS_LINUX) {
|
);
|
||||||
core.addPath(DotnetCoreInstaller.installationDirectoryLinux);
|
const installationDirectoryLinux = '/usr/share/dotnet';
|
||||||
core.exportVariable(
|
const installationDirectoryMac = path.join(
|
||||||
'DOTNET_ROOT',
|
process.env['HOME'] + '',
|
||||||
DotnetCoreInstaller.installationDirectoryLinux
|
'.dotnet'
|
||||||
);
|
);
|
||||||
} else {
|
const dotnetInstallDir: string | undefined =
|
||||||
// This is the default set in install-dotnet.sh
|
process.env['DOTNET_INSTALL_DIR'];
|
||||||
core.addPath(DotnetCoreInstaller.installationDirectoryMac);
|
if (dotnetInstallDir) {
|
||||||
core.exportVariable(
|
process.env['DOTNET_INSTALL_DIR'] =
|
||||||
'DOTNET_ROOT',
|
this.convertInstallPathToAbsolute(dotnetInstallDir);
|
||||||
DotnetCoreInstaller.installationDirectoryMac
|
} else {
|
||||||
);
|
if (IS_WINDOWS) {
|
||||||
}
|
process.env['DOTNET_INSTALL_DIR'] = installationDirectoryWindows;
|
||||||
}
|
} else {
|
||||||
}
|
process.env['DOTNET_INSTALL_DIR'] = IS_LINUX
|
||||||
|
? installationDirectoryLinux
|
||||||
constructor(version: string, quality: QualityOptions) {
|
: installationDirectoryMac;
|
||||||
this.version = version;
|
}
|
||||||
this.quality = quality;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private setQuality(
|
constructor(version: string, quality: QualityOptions) {
|
||||||
dotnetVersion: DotnetVersion,
|
this.version = version;
|
||||||
scriptArguments: string[]
|
this.quality = quality;
|
||||||
): void {
|
}
|
||||||
const option = IS_WINDOWS ? '-Quality' : '--quality';
|
|
||||||
if (dotnetVersion.qualityFlag) {
|
private static convertInstallPathToAbsolute(installDir: string): string {
|
||||||
scriptArguments.push(option, this.quality);
|
let transformedPath;
|
||||||
} else {
|
if (path.isAbsolute(installDir)) {
|
||||||
core.warning(
|
transformedPath = installDir;
|
||||||
`'dotnet-quality' input can be used only with .NET SDK version in A.B, A.B.x, A and A.x formats where the major tag is higher than 5. You specified: ${this.version}. 'dotnet-quality' input is ignored.`
|
} else {
|
||||||
);
|
transformedPath = installDir.startsWith('~')
|
||||||
}
|
? path.join(os.homedir(), installDir.slice(1))
|
||||||
}
|
: (transformedPath = path.join(process.cwd(), installDir));
|
||||||
|
}
|
||||||
public async installDotnet(): Promise<string> {
|
return path.normalize(transformedPath);
|
||||||
const windowsDefaultOptions = [
|
}
|
||||||
'-NoLogo',
|
|
||||||
'-Sta',
|
static addToPath() {
|
||||||
'-NoProfile',
|
core.addPath(process.env['DOTNET_INSTALL_DIR']!);
|
||||||
'-NonInteractive',
|
core.exportVariable('DOTNET_ROOT', process.env['DOTNET_INSTALL_DIR']);
|
||||||
'-ExecutionPolicy',
|
}
|
||||||
'Unrestricted',
|
|
||||||
'-Command'
|
private setQuality(
|
||||||
];
|
dotnetVersion: DotnetVersion,
|
||||||
const scriptName = IS_WINDOWS ? 'install-dotnet.ps1' : 'install-dotnet.sh';
|
scriptArguments: string[]
|
||||||
const escapedScript = path
|
): void {
|
||||||
.join(__dirname, '..', 'externals', scriptName)
|
const option = IS_WINDOWS ? '-Quality' : '--quality';
|
||||||
.replace(/'/g, "''");
|
if (dotnetVersion.qualityFlag) {
|
||||||
let scriptArguments: string[];
|
scriptArguments.push(option, this.quality);
|
||||||
let scriptPath = '';
|
} else {
|
||||||
|
core.warning(
|
||||||
const versionResolver = new DotnetVersionResolver(this.version);
|
`The 'dotnet-quality' input can be used only with .NET SDK version in A.B, A.B.x, A, A.x and A.B.Cxx formats where the major tag is higher than 5. You specified: ${this.version}. 'dotnet-quality' input is ignored.`
|
||||||
const dotnetVersion = await versionResolver.createDotNetVersion();
|
);
|
||||||
|
}
|
||||||
if (IS_WINDOWS) {
|
}
|
||||||
scriptArguments = ['&', `'${escapedScript}'`];
|
|
||||||
|
public async installDotnet(): Promise<string | null> {
|
||||||
if (dotnetVersion.type) {
|
const windowsDefaultOptions = [
|
||||||
scriptArguments.push(dotnetVersion.type, dotnetVersion.value);
|
'-NoLogo',
|
||||||
}
|
'-Sta',
|
||||||
|
'-NoProfile',
|
||||||
if (this.quality) {
|
'-NonInteractive',
|
||||||
this.setQuality(dotnetVersion, scriptArguments);
|
'-ExecutionPolicy',
|
||||||
}
|
'Unrestricted',
|
||||||
|
'-Command'
|
||||||
if (process.env['https_proxy'] != null) {
|
];
|
||||||
scriptArguments.push(`-ProxyAddress ${process.env['https_proxy']}`);
|
const scriptName = IS_WINDOWS ? 'install-dotnet.ps1' : 'install-dotnet.sh';
|
||||||
}
|
const escapedScript = path
|
||||||
// This is not currently an option
|
.join(__dirname, '..', 'externals', scriptName)
|
||||||
if (process.env['no_proxy'] != null) {
|
.replace(/'/g, "''");
|
||||||
scriptArguments.push(`-ProxyBypassList ${process.env['no_proxy']}`);
|
let scriptArguments: string[];
|
||||||
}
|
let scriptPath = '';
|
||||||
|
|
||||||
if (!process.env['DOTNET_INSTALL_DIR']) {
|
const versionResolver = new DotnetVersionResolver(this.version);
|
||||||
process.env['DOTNET_INSTALL_DIR'] =
|
const dotnetVersion = await versionResolver.createDotNetVersion();
|
||||||
DotnetCoreInstaller.installationDirectoryWindows;
|
|
||||||
}
|
if (IS_WINDOWS) {
|
||||||
|
scriptArguments = ['&', `'${escapedScript}'`];
|
||||||
scriptPath =
|
|
||||||
(await io.which('pwsh', false)) || (await io.which('powershell', true));
|
if (dotnetVersion.type) {
|
||||||
scriptArguments = windowsDefaultOptions.concat(scriptArguments);
|
scriptArguments.push(dotnetVersion.type, dotnetVersion.value);
|
||||||
} else {
|
}
|
||||||
chmodSync(escapedScript, '777');
|
|
||||||
scriptPath = await io.which(escapedScript, true);
|
if (this.quality) {
|
||||||
scriptArguments = [];
|
this.setQuality(dotnetVersion, scriptArguments);
|
||||||
|
}
|
||||||
if (dotnetVersion.type) {
|
|
||||||
scriptArguments.push(dotnetVersion.type, dotnetVersion.value);
|
if (process.env['https_proxy'] != null) {
|
||||||
}
|
scriptArguments.push(`-ProxyAddress ${process.env['https_proxy']}`);
|
||||||
|
}
|
||||||
if (this.quality) {
|
// This is not currently an option
|
||||||
this.setQuality(dotnetVersion, scriptArguments);
|
if (process.env['no_proxy'] != null) {
|
||||||
}
|
scriptArguments.push(`-ProxyBypassList ${process.env['no_proxy']}`);
|
||||||
|
}
|
||||||
if (!process.env['DOTNET_INSTALL_DIR']) {
|
|
||||||
process.env['DOTNET_INSTALL_DIR'] = IS_LINUX
|
scriptPath =
|
||||||
? DotnetCoreInstaller.installationDirectoryLinux
|
(await io.which('pwsh', false)) || (await io.which('powershell', true));
|
||||||
: DotnetCoreInstaller.installationDirectoryMac;
|
scriptArguments = windowsDefaultOptions.concat(scriptArguments);
|
||||||
}
|
} else {
|
||||||
}
|
chmodSync(escapedScript, '777');
|
||||||
// process.env must be explicitly passed in for DOTNET_INSTALL_DIR to be used
|
scriptPath = await io.which(escapedScript, true);
|
||||||
const getExecOutputOptions = {
|
scriptArguments = [];
|
||||||
ignoreReturnCode: true,
|
|
||||||
env: process.env as {string: string}
|
if (dotnetVersion.type) {
|
||||||
};
|
scriptArguments.push(dotnetVersion.type, dotnetVersion.value);
|
||||||
const {exitCode, stdout} = await exec.getExecOutput(
|
}
|
||||||
`"${scriptPath}"`,
|
|
||||||
scriptArguments,
|
if (this.quality) {
|
||||||
getExecOutputOptions
|
this.setQuality(dotnetVersion, scriptArguments);
|
||||||
);
|
}
|
||||||
if (exitCode) {
|
}
|
||||||
throw new Error(`Failed to install dotnet ${exitCode}. ${stdout}`);
|
// process.env must be explicitly passed in for DOTNET_INSTALL_DIR to be used
|
||||||
}
|
const getExecOutputOptions = {
|
||||||
|
ignoreReturnCode: true,
|
||||||
return this.outputDotnetVersion(
|
env: process.env as {string: string}
|
||||||
dotnetVersion.value,
|
};
|
||||||
process.env['DOTNET_INSTALL_DIR']
|
const {exitCode, stdout, stderr} = await exec.getExecOutput(
|
||||||
);
|
`"${scriptPath}"`,
|
||||||
}
|
scriptArguments,
|
||||||
|
getExecOutputOptions
|
||||||
private async outputDotnetVersion(
|
);
|
||||||
version,
|
if (exitCode) {
|
||||||
installationPath
|
throw new Error(
|
||||||
): Promise<string> {
|
`Failed to install dotnet, exit code: ${exitCode}. ${stderr}`
|
||||||
let versionsOnRunner: string[] = await readdir(
|
);
|
||||||
path.join(installationPath.replace(/'/g, ''), 'sdk')
|
}
|
||||||
);
|
|
||||||
|
return this.parseInstalledVersion(stdout);
|
||||||
let installedVersion = semver.maxSatisfying(versionsOnRunner, version, {
|
}
|
||||||
includePrerelease: true
|
|
||||||
})!;
|
private parseInstalledVersion(stdout: string): string | null {
|
||||||
|
const regex = /(?<version>\d+\.\d+\.\d+[a-z0-9._-]*)/gm;
|
||||||
return installedVersion;
|
const matchedResult = regex.exec(stdout);
|
||||||
}
|
|
||||||
}
|
if (!matchedResult) {
|
||||||
|
core.warning(`Failed to parse installed by the script version of .NET`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return matchedResult.groups!.version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -13,7 +13,7 @@ const qualityOptions = [
|
|||||||
'ga'
|
'ga'
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
export type QualityOptions = typeof qualityOptions[number];
|
export type QualityOptions = (typeof qualityOptions)[number];
|
||||||
|
|
||||||
export async function run() {
|
export async function run() {
|
||||||
try {
|
try {
|
||||||
@ -27,11 +27,11 @@ export async function run() {
|
|||||||
// Proxy, auth, (etc) are still set up, even if no version is identified
|
// Proxy, auth, (etc) are still set up, even if no version is identified
|
||||||
//
|
//
|
||||||
const versions = core.getMultilineInput('dotnet-version');
|
const versions = core.getMultilineInput('dotnet-version');
|
||||||
const installedDotnetVersions: string[] = [];
|
const installedDotnetVersions: (string | null)[] = [];
|
||||||
|
|
||||||
const globalJsonFileInput = core.getInput('global-json-file');
|
const globalJsonFileInput = core.getInput('global-json-file');
|
||||||
if (globalJsonFileInput) {
|
if (globalJsonFileInput) {
|
||||||
const globalJsonPath = path.join(process.cwd(), globalJsonFileInput);
|
const globalJsonPath = path.resolve(process.cwd(), globalJsonFileInput);
|
||||||
if (!fs.existsSync(globalJsonPath)) {
|
if (!fs.existsSync(globalJsonPath)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`The specified global.json file '${globalJsonFileInput}' does not exist`
|
`The specified global.json file '${globalJsonFileInput}' does not exist`
|
||||||
@ -46,6 +46,10 @@ 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)) {
|
||||||
versions.push(getVersionFromGlobalJson(globalJsonPath));
|
versions.push(getVersionFromGlobalJson(globalJsonPath));
|
||||||
|
} else {
|
||||||
|
core.info(
|
||||||
|
`The global.json wasn't found in the root directory. No .NET version will be installed.`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +58,7 @@ export async function run() {
|
|||||||
|
|
||||||
if (quality && !qualityOptions.includes(quality)) {
|
if (quality && !qualityOptions.includes(quality)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`${quality} is not a supported value for 'dotnet-quality' option. Supported values are: daily, signed, validated, preview, ga.`
|
`Value '${quality}' is not supported for the 'dotnet-quality' option. Supported values are: daily, signed, validated, preview, ga.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,19 +78,7 @@ export async function run() {
|
|||||||
auth.configAuthentication(sourceUrl, configFile);
|
auth.configAuthentication(sourceUrl, configFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
const comparisonRange: string = globalJsonFileInput
|
outputInstalledVersion(installedDotnetVersions, globalJsonFileInput);
|
||||||
? versions[versions.length - 1]!
|
|
||||||
: '*';
|
|
||||||
|
|
||||||
const versionToOutput = semver.maxSatisfying(
|
|
||||||
installedDotnetVersions,
|
|
||||||
comparisonRange,
|
|
||||||
{
|
|
||||||
includePrerelease: true
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
core.setOutput('dotnet-version', versionToOutput);
|
|
||||||
|
|
||||||
const matchersPath = path.join(__dirname, '..', '.github');
|
const matchersPath = path.join(__dirname, '..', '.github');
|
||||||
core.info(`##[add-matcher]${path.join(matchersPath, 'csc.json')}`);
|
core.info(`##[add-matcher]${path.join(matchersPath, 'csc.json')}`);
|
||||||
@ -96,7 +88,7 @@ export async function run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getVersionFromGlobalJson(globalJsonPath: string): string {
|
function getVersionFromGlobalJson(globalJsonPath: string): string {
|
||||||
let version: string = '';
|
let version = '';
|
||||||
const globalJson = JSON.parse(
|
const globalJson = JSON.parse(
|
||||||
// .trim() is necessary to strip BOM https://github.com/nodejs/node/issues/20649
|
// .trim() is necessary to strip BOM https://github.com/nodejs/node/issues/20649
|
||||||
fs.readFileSync(globalJsonPath, {encoding: 'utf8'}).trim()
|
fs.readFileSync(globalJsonPath, {encoding: 'utf8'}).trim()
|
||||||
@ -112,4 +104,37 @@ function getVersionFromGlobalJson(globalJsonPath: string): string {
|
|||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function outputInstalledVersion(
|
||||||
|
installedVersions: (string | null)[],
|
||||||
|
globalJsonFileInput: string
|
||||||
|
): void {
|
||||||
|
if (!installedVersions.length) {
|
||||||
|
core.info(`The 'dotnet-version' output will not be set.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (installedVersions.includes(null)) {
|
||||||
|
core.warning(
|
||||||
|
`Failed to output the installed version of .NET. The 'dotnet-version' output will not be set.`
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (globalJsonFileInput) {
|
||||||
|
const versionToOutput = installedVersions.at(-1); // .NET SDK version parsed from the global.json file is installed last
|
||||||
|
core.setOutput('dotnet-version', versionToOutput);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const versionToOutput = semver.maxSatisfying(
|
||||||
|
installedVersions as string[],
|
||||||
|
'*',
|
||||||
|
{
|
||||||
|
includePrerelease: true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
core.setOutput('dotnet-version', versionToOutput);
|
||||||
|
}
|
||||||
|
|
||||||
run();
|
run();
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||||
|
|
||||||
/* Additional Checks */
|
/* Additional Checks */
|
||||||
|
"useUnknownInCatchVariables": false, /* Type catch clause variables as 'unknown' instead of 'any'. */
|
||||||
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
||||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||||
@ -48,7 +49,8 @@
|
|||||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||||
// "types": [], /* Type declaration files to be included in compilation. */
|
// "types": [], /* Type declaration files to be included in compilation. */
|
||||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||||
|
"resolveJsonModule": true, /* Allows importing modules with a '.json' extension, which is a common practice in node projects. */
|
||||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user