Merge branch 'actions:main' into main
This commit is contained in:
commit
f1ece63234
|
@ -0,0 +1,6 @@
|
|||
# Ignore list
|
||||
/*
|
||||
|
||||
# Do not ignore these folders:
|
||||
!__tests__/
|
||||
!src/
|
|
@ -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
|
||||
}
|
||||
};
|
|
@ -1 +1,2 @@
|
|||
* text=auto eol=lf
|
||||
.licenses/** -diff linguist-generated=true
|
||||
|
|
|
@ -14,4 +14,4 @@ on:
|
|||
jobs:
|
||||
call-basic-validation:
|
||||
name: Basic validation
|
||||
uses: actions/reusable-workflows/.github/workflows/basic-validation.yml@main
|
||||
uses: actions/reusable-workflows/.github/workflows/basic-validation.yml@main
|
||||
|
|
|
@ -14,4 +14,4 @@ on:
|
|||
jobs:
|
||||
call-check-dist:
|
||||
name: Check dist/
|
||||
uses: actions/reusable-workflows/.github/workflows/check-dist.yml@main
|
||||
uses: actions/reusable-workflows/.github/workflows/check-dist.yml@main
|
||||
|
|
|
@ -2,13 +2,13 @@ name: CodeQL analysis
|
|||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
branches: [main]
|
||||
schedule:
|
||||
- cron: '0 3 * * 0'
|
||||
|
||||
jobs:
|
||||
call-codeQL-analysis:
|
||||
name: CodeQL analysis
|
||||
uses: actions/reusable-workflows/.github/workflows/codeql-analysis.yml@main
|
||||
name: CodeQL analysis
|
||||
uses: actions/reusable-workflows/.github/workflows/codeql-analysis.yml@main
|
||||
|
|
|
@ -24,7 +24,7 @@ jobs:
|
|||
- name: Clear toolcache
|
||||
shell: pwsh
|
||||
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: ./
|
||||
with:
|
||||
dotnet-version: |
|
||||
|
@ -33,7 +33,7 @@ jobs:
|
|||
3.0.x
|
||||
- name: Verify dotnet
|
||||
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:
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
|
@ -60,13 +60,9 @@ jobs:
|
|||
source-url: https://api.nuget.org/v3/index.json
|
||||
env:
|
||||
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
|
||||
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:
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
|
@ -91,7 +87,7 @@ jobs:
|
|||
dotnet-version: '2.2'
|
||||
- name: Verify dotnet
|
||||
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:
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
|
@ -105,17 +101,13 @@ jobs:
|
|||
- name: Clear toolcache
|
||||
shell: pwsh
|
||||
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'
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: '3.1.100-preview1-014459'
|
||||
- name: Verify dotnet
|
||||
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:
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
|
@ -139,7 +131,28 @@ jobs:
|
|||
dotnet-version: 2.2.X
|
||||
- name: Verify dotnet
|
||||
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:
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
|
@ -163,7 +176,7 @@ jobs:
|
|||
dotnet-version: 2.2.*
|
||||
- name: Verify dotnet
|
||||
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:
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
|
@ -181,7 +194,7 @@ jobs:
|
|||
shell: bash
|
||||
run: |
|
||||
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
|
||||
uses: ./
|
||||
with:
|
||||
|
@ -189,91 +202,198 @@ jobs:
|
|||
global-json-file: ./subdirectory/global.json
|
||||
- name: Verify dotnet
|
||||
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-global-json-with-comments:
|
||||
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 '/* should support comments */ {"sdk":{"version": "2.2.207","rollForward": "latestFeature"}} // should support comments' > ./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:
|
||||
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 7.0 with preview quality
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: "7.0"
|
||||
dotnet-quality: "preview"
|
||||
- name: Verify preview version
|
||||
shell: pwsh
|
||||
run: |
|
||||
$version = & dotnet --version
|
||||
Write-Host "Installed version: $version"
|
||||
if (-not ($version.Contains("preview") -or $version.Contains("rc"))) { throw "Unexpected version" }
|
||||
|
||||
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 7.0 with preview quality
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: '7.0'
|
||||
dotnet-quality: 'preview'
|
||||
- name: Verify dotnet
|
||||
shell: pwsh
|
||||
run: __tests__/verify-dotnet.ps1 -Patterns "^7\.0\.\d+-"
|
||||
|
||||
test-setup-with-cache:
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
operating-system: [ubuntu-latest, windows-latest, macos-latest]
|
||||
env:
|
||||
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Clear toolcache
|
||||
shell: pwsh
|
||||
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
||||
- name: Copy NuGet lock file to root
|
||||
shell: bash
|
||||
run: cp ./__tests__/e2e-test-csproj/packages.lock.json ./packages.lock.json
|
||||
- name: Setup .NET Core 3.1
|
||||
id: setup-dotnet
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: 3.1
|
||||
cache: true
|
||||
- name: Verify Cache
|
||||
if: steps.setup-dotnet.outputs.cache-hit == 'true'
|
||||
shell: bash
|
||||
run: if [[ -e ${NUGET_PACKAGES} ]]; then exit 0; else exit 1; fi
|
||||
- name: Verify dotnet
|
||||
shell: pwsh
|
||||
run: __tests__/verify-dotnet.ps1 -Patterns "^3.1"
|
||||
|
||||
test-setup-with-cache-dependency-path:
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
operating-system: [ubuntu-latest, windows-latest, macos-latest]
|
||||
env:
|
||||
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Clear toolcache
|
||||
shell: pwsh
|
||||
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
||||
- name: Setup .NET Core 3.1
|
||||
id: setup-dotnet
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: 3.1
|
||||
cache: true
|
||||
cache-dependency-path: './__tests__/e2e-test-csproj/packages.lock.json'
|
||||
- name: Verify Cache
|
||||
if: steps.setup-dotnet.outputs.cache-hit == 'true'
|
||||
shell: bash
|
||||
run: if [[ -e ${NUGET_PACKAGES} ]]; then exit 0; else exit 1; fi
|
||||
- name: Verify dotnet
|
||||
shell: pwsh
|
||||
run: __tests__/verify-dotnet.ps1 -Patterns "^3.1"
|
||||
|
||||
test-dotnet-version-output-during-single-version-installation:
|
||||
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.401
|
||||
uses: ./
|
||||
id: step1
|
||||
with:
|
||||
dotnet-version: "6.0.401"
|
||||
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.401
|
||||
uses: ./
|
||||
id: step1
|
||||
with:
|
||||
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:
|
||||
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.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
|
||||
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: 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" }
|
||||
- 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
|
||||
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:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: mcr.microsoft.com/dotnet/core/runtime-deps:3.0-bionic
|
||||
image: ubuntu:latest
|
||||
options: --dns 127.0.0.1
|
||||
services:
|
||||
squid-proxy:
|
||||
|
@ -286,21 +406,29 @@ jobs:
|
|||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Clear tool cache
|
||||
run: rm -rf "/usr/share/dotnet"
|
||||
- name: Install curl
|
||||
- name: Install Powershell
|
||||
run: |
|
||||
apt update
|
||||
apt -y install curl
|
||||
- name: Setup dotnet 3.1.201
|
||||
apt-get update
|
||||
apt-get install -y wget apt-transport-https software-properties-common
|
||||
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: ./
|
||||
with:
|
||||
dotnet-version: 3.1.201
|
||||
dotnet-version: 6.0
|
||||
source-url: https://api.nuget.org/v3/index.json
|
||||
env:
|
||||
NUGET_AUTH_TOKEN: NOTATOKEN
|
||||
- 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:
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -310,8 +438,9 @@ jobs:
|
|||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Clear tool cache
|
||||
run: rm -rf "/usr/share/dotnet"
|
||||
- name: Clear toolcache
|
||||
shell: pwsh
|
||||
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
||||
- name: Setup dotnet 3.1.201
|
||||
uses: ./
|
||||
with:
|
||||
|
@ -320,4 +449,35 @@ jobs:
|
|||
env:
|
||||
NUGET_AUTH_TOKEN: NOTATOKEN
|
||||
- name: Verify dotnet
|
||||
run: __tests__/verify-dotnet.sh 3.1.201
|
||||
shell: pwsh
|
||||
run: __tests__/verify-dotnet.ps1 -Patterns "^3.1.201$" -CheckNugetConfig
|
||||
|
||||
test-sequential-version-installation:
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
operating-system: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
lower-version: ['3.1.426']
|
||||
higher-version: ['7.0.203']
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Clear toolcache
|
||||
shell: pwsh
|
||||
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
||||
# Install one version, use it for something, then switch to next version
|
||||
- name: Setup dotnet (lower version)
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: ${{ matrix.lower-version }}
|
||||
- name: Verify dotnet (lower version)
|
||||
shell: pwsh
|
||||
run: __tests__/verify-dotnet.ps1 -Patterns "^${{ matrix.lower-version }}$"
|
||||
- name: Setup dotnet (higher version)
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: ${{ matrix.higher-version }}
|
||||
- name: Verify dotnet (higher version)
|
||||
shell: pwsh
|
||||
run: __tests__/verify-dotnet.ps1 -Patterns "^${{ matrix.lower-version }}$", "^${{ matrix.higher-version }}$"
|
||||
|
|
|
@ -12,4 +12,4 @@ on:
|
|||
jobs:
|
||||
call-licensed:
|
||||
name: Licensed
|
||||
uses: actions/reusable-workflows/.github/workflows/licensed.yml@main
|
||||
uses: actions/reusable-workflows/.github/workflows/licensed.yml@main
|
||||
|
|
|
@ -21,9 +21,9 @@ jobs:
|
|||
name: releaseNewActionVersion
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Update the ${{ env.TAG_NAME }} tag
|
||||
id: update-major-tag
|
||||
uses: actions/publish-action@v0.2.1
|
||||
with:
|
||||
source-tag: ${{ env.TAG_NAME }}
|
||||
slack-webhook: ${{ secrets.SLACK_WEBHOOK }}
|
||||
- name: Update the ${{ env.TAG_NAME }} tag
|
||||
id: update-major-tag
|
||||
uses: actions/publish-action@v0.2.2
|
||||
with:
|
||||
source-tag: ${{ env.TAG_NAME }}
|
||||
slack-webhook: ${{ secrets.SLACK_WEBHOOK }}
|
||||
|
|
|
@ -18,7 +18,7 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
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:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
@ -29,9 +29,7 @@ jobs:
|
|||
uses: ./
|
||||
with:
|
||||
dotnet-version: ${{ matrix.dotnet-version }}
|
||||
- name: Check installed version
|
||||
- name: Verify installed version
|
||||
shell: pwsh
|
||||
run: |
|
||||
$version = & dotnet --version
|
||||
Write-Host "Installed version: $version"
|
||||
if (-not $version.StartsWith("${{ matrix.dotnet-version }}")) { throw "Unexpected version" }
|
||||
__tests__/verify-dotnet.ps1 -Patterns "^${{ matrix.dotnet-version }}"
|
||||
|
|
|
@ -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
|
|
@ -3,8 +3,8 @@ global.json
|
|||
lib/
|
||||
node_modules/
|
||||
__tests__/runner/*
|
||||
__tests__/sample-csproj/bin/
|
||||
__tests__/sample-csproj/obj/
|
||||
__tests__/e2e-test-csproj/bin/
|
||||
__tests__/e2e-test-csproj/obj/
|
||||
|
||||
# Rest of the file pulled from https://github.com/github/gitignore/blob/master/Node.gitignore
|
||||
# Logs
|
||||
|
|
|
@ -2,3 +2,4 @@
|
|||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
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
|
||||
npm run format-check
|
||||
npm run lint
|
||||
|
|
|
@ -3,6 +3,7 @@ sources:
|
|||
|
||||
allowed:
|
||||
- apache-2.0
|
||||
- 0bsd
|
||||
- bsd-2-clause
|
||||
- bsd-3-clause
|
||||
- isc
|
||||
|
@ -11,4 +12,5 @@ allowed:
|
|||
- unlicense
|
||||
|
||||
reviewed:
|
||||
npm:
|
||||
npm:
|
||||
- sax # ISC + MIT
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
name: "@actions/cache"
|
||||
version: 3.2.1
|
||||
type: npm
|
||||
summary: Actions cache lib
|
||||
homepage: https://github.com/actions/toolkit/tree/main/packages/cache
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE.md
|
||||
text: |-
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright 2019 GitHub
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
notices: []
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
name: "@actions/glob"
|
||||
version: 0.1.2
|
||||
type: npm
|
||||
summary: Actions glob lib
|
||||
homepage: https://github.com/actions/toolkit/tree/main/packages/glob
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE.md
|
||||
text: |-
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright 2019 GitHub
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
notices: []
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
name: "@actions/glob"
|
||||
version: 0.3.0
|
||||
type: npm
|
||||
summary: Actions glob lib
|
||||
homepage: https://github.com/actions/toolkit/tree/main/packages/glob
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE.md
|
||||
text: |-
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright 2019 GitHub
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
notices: []
|
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
name: "@azure/abort-controller"
|
||||
version: 1.1.0
|
||||
type: npm
|
||||
summary: Microsoft Azure SDK for JavaScript - Aborter
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/abort-controller/README.md
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Microsoft
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
notices: []
|
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
name: "@azure/core-auth"
|
||||
version: 1.4.0
|
||||
type: npm
|
||||
summary: Provides low-level interfaces and helper methods for authentication in Azure
|
||||
SDK
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-auth/README.md
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Microsoft
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
notices: []
|
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
name: "@azure/core-http"
|
||||
version: 3.0.1
|
||||
type: npm
|
||||
summary: Isomorphic client Runtime for Typescript/node.js/browser javascript client
|
||||
libraries generated using AutoRest
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-http/README.md
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Microsoft
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
notices: []
|
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
name: "@azure/core-lro"
|
||||
version: 2.5.2
|
||||
type: npm
|
||||
summary: Isomorphic client library for supporting long-running operations in node.js
|
||||
and browser.
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-lro/README.md
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Microsoft
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
notices: []
|
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
name: "@azure/core-paging"
|
||||
version: 1.5.0
|
||||
type: npm
|
||||
summary: Core types for paging async iterable iterators
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/core-paging/README.md
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Microsoft
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
notices: []
|
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
name: "@azure/core-tracing"
|
||||
version: 1.0.0-preview.13
|
||||
type: npm
|
||||
summary: Provides low-level interfaces and helper methods for tracing in Azure SDK
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-tracing/README.md
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Microsoft
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
notices: []
|
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
name: "@azure/core-util"
|
||||
version: 1.3.1
|
||||
type: npm
|
||||
summary: Core library for shared utility methods
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-util/
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Microsoft
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
notices: []
|
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
name: "@azure/logger"
|
||||
version: 1.0.4
|
||||
type: npm
|
||||
summary: Microsoft Azure SDK for JavaScript - Logger
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/logger/README.md
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Microsoft
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
notices: []
|
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
name: "@azure/ms-rest-js"
|
||||
version: 2.7.0
|
||||
type: npm
|
||||
summary: Isomorphic client Runtime for Typescript/node.js/browser javascript client
|
||||
libraries generated using AutoRest
|
||||
homepage: https://github.com/Azure/ms-rest-js
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |2
|
||||
MIT License
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE
|
||||
notices: []
|
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
name: "@azure/storage-blob"
|
||||
version: 12.14.0
|
||||
type: npm
|
||||
summary: Microsoft Azure Storage SDK for JavaScript - Blob
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/storage/storage-blob/
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Microsoft
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
notices: []
|
|
@ -0,0 +1,223 @@
|
|||
---
|
||||
name: "@opentelemetry/api"
|
||||
version: 1.4.1
|
||||
type: npm
|
||||
summary: Public API for OpenTelemetry
|
||||
homepage: https://github.com/open-telemetry/opentelemetry-js/tree/main/api
|
||||
license: apache-2.0
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |2
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
- sources: README.md
|
||||
text: |-
|
||||
Apache 2.0 - See [LICENSE][license-url] for more information.
|
||||
|
||||
[opentelemetry-js]: https://github.com/open-telemetry/opentelemetry-js
|
||||
|
||||
[discussions-url]: https://github.com/open-telemetry/opentelemetry-js/discussions
|
||||
[license-url]: https://github.com/open-telemetry/opentelemetry-js/blob/main/api/LICENSE
|
||||
[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat
|
||||
[docs-tracing]: https://github.com/open-telemetry/opentelemetry-js/blob/main/doc/tracing.md
|
||||
[docs-sdk-registration]: https://github.com/open-telemetry/opentelemetry-js/blob/main/doc/sdk-registration.md
|
||||
notices: []
|
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
name: "@types/node-fetch"
|
||||
version: 2.6.3
|
||||
type: npm
|
||||
summary: TypeScript definitions for node-fetch
|
||||
homepage: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node-fetch
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |2
|
||||
MIT License
|
||||
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE
|
||||
notices: []
|
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
name: "@types/node"
|
||||
version: 16.11.25
|
||||
type: npm
|
||||
summary: TypeScript definitions for Node.js
|
||||
homepage: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |2
|
||||
MIT License
|
||||
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE
|
||||
notices: []
|
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
name: "@types/tunnel"
|
||||
version: 0.0.3
|
||||
type: npm
|
||||
summary: TypeScript definitions for tunnel
|
||||
homepage: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/tunnel
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |2
|
||||
MIT License
|
||||
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE
|
||||
notices: []
|
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
name: abort-controller
|
||||
version: 3.0.0
|
||||
type: npm
|
||||
summary: An implementation of WHATWG AbortController interface.
|
||||
homepage: https://github.com/mysticatea/abort-controller#readme
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Toru Nagashima
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
notices: []
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
name: asynckit
|
||||
version: 0.4.0
|
||||
type: npm
|
||||
summary: Minimal async jobs utility library, with streams support
|
||||
homepage: https://github.com/alexindigo/asynckit#readme
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Alex Indigo
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
- sources: README.md
|
||||
text: AsyncKit is licensed under the MIT license.
|
||||
notices: []
|
|
@ -0,0 +1,55 @@
|
|||
---
|
||||
name: balanced-match
|
||||
version: 1.0.2
|
||||
type: npm
|
||||
summary: Match balanced character pairs, like "{" and "}"
|
||||
homepage: https://github.com/juliangruber/balanced-match
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE.md
|
||||
text: |
|
||||
(MIT)
|
||||
|
||||
Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
- sources: README.md
|
||||
text: |-
|
||||
(MIT)
|
||||
|
||||
Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
notices: []
|
|
@ -0,0 +1,55 @@
|
|||
---
|
||||
name: brace-expansion
|
||||
version: 1.1.11
|
||||
type: npm
|
||||
summary: Brace expansion as known from sh/bash
|
||||
homepage: https://github.com/juliangruber/brace-expansion
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
- sources: README.md
|
||||
text: |-
|
||||
(MIT)
|
||||
|
||||
Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
notices: []
|
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
name: combined-stream
|
||||
version: 1.0.8
|
||||
type: npm
|
||||
summary: A stream that emits multiple other streams one after another.
|
||||
homepage: https://github.com/felixge/node-combined-stream
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: License
|
||||
text: |
|
||||
Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
- sources: Readme.md
|
||||
text: combined-stream is licensed under the MIT license.
|
||||
notices: []
|
|
@ -0,0 +1,31 @@
|
|||
---
|
||||
name: concat-map
|
||||
version: 0.0.1
|
||||
type: npm
|
||||
summary: concatenative mapdashery
|
||||
homepage:
|
||||
license: other
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
This software is released under the MIT license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
- sources: README.markdown
|
||||
text: MIT
|
||||
notices: []
|
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
name: delayed-stream
|
||||
version: 1.0.0
|
||||
type: npm
|
||||
summary: Buffers events from a stream until you are ready to handle them.
|
||||
homepage: https://github.com/felixge/node-delayed-stream
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: License
|
||||
text: |
|
||||
Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
- sources: Readme.md
|
||||
text: delayed-stream is licensed under the MIT license.
|
||||
notices: []
|
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
name: event-target-shim
|
||||
version: 5.0.1
|
||||
type: npm
|
||||
summary: An implementation of WHATWG EventTarget interface.
|
||||
homepage: https://github.com/mysticatea/event-target-shim
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |+
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Toru Nagashima
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
notices: []
|
|
@ -0,0 +1,38 @@
|
|||
---
|
||||
name: events
|
||||
version: 3.3.0
|
||||
type: npm
|
||||
summary: Node's event emitter for all engines.
|
||||
homepage:
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
MIT
|
||||
|
||||
Copyright Joyent, Inc. and other Node contributors.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
persons to whom the Software is furnished to do so, subject to the
|
||||
following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
- sources: Readme.md
|
||||
text: |-
|
||||
[MIT](./LICENSE)
|
||||
|
||||
[node.js docs]: https://nodejs.org/dist/v11.13.0/docs/api/events.html
|
||||
notices: []
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
name: fast-xml-parser
|
||||
version: 4.0.10
|
||||
version: 4.2.5
|
||||
type: npm
|
||||
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
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
name: form-data
|
||||
version: 2.5.1
|
||||
type: npm
|
||||
summary: A library to create readable "multipart/form-data" streams. Can be used to
|
||||
submit forms and file uploads to other web applications.
|
||||
homepage:
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: License
|
||||
text: |
|
||||
Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
- sources: README.md
|
||||
text: Form-Data is released under the [MIT](License) license.
|
||||
notices: []
|
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
name: form-data
|
||||
version: 3.0.1
|
||||
type: npm
|
||||
summary: A library to create readable "multipart/form-data" streams. Can be used to
|
||||
submit forms and file uploads to other web applications.
|
||||
homepage:
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: License
|
||||
text: |
|
||||
Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
- sources: Readme.md
|
||||
text: Form-Data is released under the [MIT](License) license.
|
||||
notices: []
|
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
name: form-data
|
||||
version: 4.0.0
|
||||
type: npm
|
||||
summary: A library to create readable "multipart/form-data" streams. Can be used to
|
||||
submit forms and file uploads to other web applications.
|
||||
homepage:
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: License
|
||||
text: |
|
||||
Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
- sources: Readme.md
|
||||
text: Form-Data is released under the [MIT](License) license.
|
||||
notices: []
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
name: ip-regex
|
||||
version: 2.1.0
|
||||
type: npm
|
||||
summary: Regular expression for matching IP addresses (IPv4 & IPv6)
|
||||
homepage:
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: license
|
||||
text: |
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
- sources: readme.md
|
||||
text: MIT © [Sindre Sorhus](https://sindresorhus.com)
|
||||
notices: []
|
|
@ -0,0 +1,36 @@
|
|||
---
|
||||
name: json5
|
||||
version: 2.2.3
|
||||
type: npm
|
||||
summary: JSON for Humans
|
||||
homepage: http://json5.org/
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE.md
|
||||
text: |
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2012-2018 Aseem Kishore, and [others].
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
[others]: https://github.com/json5/json5/contributors
|
||||
- sources: README.md
|
||||
text: MIT. See [LICENSE.md](./LICENSE.md) for details.
|
||||
notices: []
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
name: mime-db
|
||||
version: 1.52.0
|
||||
type: npm
|
||||
summary: Media Type Database
|
||||
homepage:
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2014 Jonathan Ong <me@jongleberry.com>
|
||||
Copyright (c) 2015-2022 Douglas Christopher Wilson <doug@somethingdoug.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
'Software'), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
notices: []
|
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
name: mime-types
|
||||
version: 2.1.35
|
||||
type: npm
|
||||
summary: The ultimate javascript content-type utility.
|
||||
homepage:
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2014 Jonathan Ong <me@jongleberry.com>
|
||||
Copyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
'Software'), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
- sources: README.md
|
||||
text: |-
|
||||
[MIT](LICENSE)
|
||||
|
||||
[ci-image]: https://badgen.net/github/checks/jshttp/mime-types/master?label=ci
|
||||
[ci-url]: https://github.com/jshttp/mime-types/actions/workflows/ci.yml
|
||||
[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/mime-types/master
|
||||
[coveralls-url]: https://coveralls.io/r/jshttp/mime-types?branch=master
|
||||
[node-version-image]: https://badgen.net/npm/node/mime-types
|
||||
[node-version-url]: https://nodejs.org/en/download
|
||||
[npm-downloads-image]: https://badgen.net/npm/dm/mime-types
|
||||
[npm-url]: https://npmjs.org/package/mime-types
|
||||
[npm-version-image]: https://badgen.net/npm/v/mime-types
|
||||
notices: []
|
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
name: minimatch
|
||||
version: 3.1.2
|
||||
type: npm
|
||||
summary: a glob matcher in javascript
|
||||
homepage:
|
||||
license: isc
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
notices: []
|
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
name: process
|
||||
version: 0.11.10
|
||||
type: npm
|
||||
summary: process information for node.js and browsers
|
||||
homepage:
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2013 Roman Shtylman <shtylman@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
'Software'), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
notices: []
|
|
@ -0,0 +1,43 @@
|
|||
---
|
||||
name: psl
|
||||
version: 1.9.0
|
||||
type: npm
|
||||
summary: Domain name parser based on the Public Suffix List
|
||||
homepage:
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 Lupo Montero lupomontero@gmail.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
- sources: README.md
|
||||
text: |-
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 Lupo Montero <lupomontero@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
notices: []
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
name: punycode
|
||||
version: 2.1.1
|
||||
type: npm
|
||||
summary: A robust Punycode converter that fully complies to RFC 3492 and RFC 5891,
|
||||
and works on nearly all JavaScript platforms.
|
||||
homepage: https://mths.be/punycode
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE-MIT.txt
|
||||
text: |
|
||||
Copyright Mathias Bynens <https://mathiasbynens.be/>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
- sources: README.md
|
||||
text: Punycode.js is available under the [MIT](https://mths.be/mit) license.
|
||||
notices: []
|
|
@ -0,0 +1,52 @@
|
|||
---
|
||||
name: sax
|
||||
version: 1.2.4
|
||||
type: npm
|
||||
summary: An evented streaming XML parser in JavaScript
|
||||
homepage:
|
||||
license: other
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
====
|
||||
|
||||
`String.fromCodePoint` by Mathias Bynens used according to terms of MIT
|
||||
License, as follows:
|
||||
|
||||
Copyright Mathias Bynens <https://mathiasbynens.be/>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
notices: []
|
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
name: semver
|
||||
version: 6.3.1
|
||||
type: npm
|
||||
summary: The semantic version parser used by npm.
|
||||
homepage: https://github.com/npm/node-semver#readme
|
||||
license: isc
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
notices: []
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
name: signal-exit
|
||||
version: 3.0.2
|
||||
version: 3.0.7
|
||||
type: npm
|
||||
summary: when you want to fire an event no matter how a process exits.
|
||||
homepage: https://github.com/tapjs/signal-exit
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
name: tough-cookie
|
||||
version: 3.0.1
|
||||
type: npm
|
||||
summary: RFC6265 Cookies and Cookie Jar for node.js
|
||||
homepage: https://github.com/salesforce/tough-cookie
|
||||
license: bsd-3-clause
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
Copyright (c) 2015, Salesforce.com, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
notices: []
|
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
name: tslib
|
||||
version: 1.14.1
|
||||
type: npm
|
||||
summary: Runtime library for TypeScript helper functions
|
||||
homepage: https://www.typescriptlang.org/
|
||||
license: 0bsd
|
||||
licenses:
|
||||
- sources: LICENSE.txt
|
||||
text: |-
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
notices:
|
||||
- sources: CopyrightNotice.txt
|
||||
text: "/*! *****************************************************************************\r\nCopyright
|
||||
(c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute
|
||||
this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE
|
||||
SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD
|
||||
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR
|
||||
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE,
|
||||
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS
|
||||
ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS
|
||||
SOFTWARE.\r\n*****************************************************************************
|
||||
*/"
|
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
name: tslib
|
||||
version: 2.5.0
|
||||
type: npm
|
||||
summary: Runtime library for TypeScript helper functions
|
||||
homepage: https://www.typescriptlang.org/
|
||||
license: 0bsd
|
||||
licenses:
|
||||
- sources: LICENSE.txt
|
||||
text: |-
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
notices: []
|
|
@ -3,8 +3,8 @@ name: universal-user-agent
|
|||
version: 4.0.0
|
||||
type: npm
|
||||
summary: Get a user agent string in both browser and node
|
||||
homepage: https://github.com/gr2m/universal-user-agent#readme
|
||||
license: other
|
||||
homepage:
|
||||
license: isc
|
||||
licenses:
|
||||
- sources: LICENSE.md
|
||||
text: |
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
---
|
||||
name: uuid
|
||||
version: 3.4.0
|
||||
type: npm
|
||||
summary: RFC4122 (v1, v4, and v5) UUIDs
|
||||
homepage:
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE.md
|
||||
text: |
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2010-2016 Robert Kieffer and other contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
notices:
|
||||
- sources: AUTHORS
|
||||
text: |-
|
||||
Robert Kieffer <robert@broofa.com>
|
||||
Christoph Tavan <dev@tavan.de>
|
||||
AJ ONeal <coolaj86@gmail.com>
|
||||
Vincent Voyer <vincent@zeroload.net>
|
||||
Roman Shtylman <shtylman@gmail.com>
|
|
@ -0,0 +1,30 @@
|
|||
---
|
||||
name: xml2js
|
||||
version: 0.5.0
|
||||
type: npm
|
||||
summary: Simple XML to JavaScript object converter.
|
||||
homepage: https://github.com/Leonidas-from-XIV/node-xml2js
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
Copyright 2010, 2011, 2012, 2013. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
notices: []
|
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
name: xmlbuilder
|
||||
version: 11.0.1
|
||||
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)
|
||||
|
||||
Copyright (c) 2013 Ozgur Ozcitak
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
notices: []
|
|
@ -0,0 +1,7 @@
|
|||
# Ignore list
|
||||
/*
|
||||
|
||||
# Do not ignore these folders:
|
||||
!__tests__/
|
||||
!.github/
|
||||
!src/
|
|
@ -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,12 +0,0 @@
|
|||
{
|
||||
"printWidth": 80,
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"bracketSpacing": false,
|
||||
"arrowParens": "avoid",
|
||||
"parser": "typescript",
|
||||
"endOfLine": "auto"
|
||||
}
|
83
README.md
83
README.md
|
@ -1,6 +1,7 @@
|
|||
# setup-dotnet
|
||||
|
||||
[![GitHub Actions Status](https://github.com/actions/setup-dotnet/workflows/Main%20workflow/badge.svg)](https://github.com/actions/setup-dotnet)
|
||||
[![Basic validation](https://github.com/actions/setup-dotnet/actions/workflows/basic-validation.yml/badge.svg?branch=main)](https://github.com/actions/setup-dotnet/actions/workflows/basic-validation.yml)
|
||||
[![e2e tests](https://github.com/actions/setup-dotnet/actions/workflows/e2e-tests.yml/badge.svg?branch=main)](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:
|
||||
|
||||
|
@ -48,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** 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.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
|
||||
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
|
||||
steps:
|
||||
|
@ -80,6 +82,63 @@ steps:
|
|||
working-directory: csharp
|
||||
```
|
||||
|
||||
## Caching NuGet Packages
|
||||
The action has a built-in functionality for caching and restoring dependencies. It uses [toolkit/cache](https://github.com/actions/toolkit/tree/main/packages/cache) under the hood for caching global packages data but requires less configuration settings. The `cache` input is optional, and caching is turned off by default.
|
||||
|
||||
The action searches for [NuGet Lock files](https://learn.microsoft.com/nuget/consume-packages/package-references-in-project-files#locking-dependencies) (`packages.lock.json`) in the repository root, calculates their hash and uses it as a part of the cache key. If lock file does not exist, this action throws error. Use `cache-dependency-path` for cases when multiple dependency files are used, or they are located in different subdirectories.
|
||||
|
||||
> **Warning**: Caching NuGet packages is available since .NET SDK 2.1.500 and 2.2.100 as the NuGet lock file [is available](https://learn.microsoft.com/nuget/consume-packages/package-references-in-project-files#locking-dependencies) only for NuGet 4.9 and above.
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: 6.x
|
||||
cache: true
|
||||
- run: dotnet restore --locked-mode
|
||||
```
|
||||
|
||||
> **Note**: This action will only restore `global-packages` folder, so you will probably get the [NU1403](https://learn.microsoft.com/nuget/reference/errors-and-warnings/nu1403) error when running `dotnet restore`.
|
||||
> To avoid this, you can use [`DisableImplicitNuGetFallbackFolder`](https://github.com/dotnet/reproducible-builds/blob/abfe986832aa28597d3340b92469d1a702013d23/Documentation/Reproducible-MSBuild/Techniques/DisableImplicitNuGetFallbackFolder.md) option.
|
||||
|
||||
```xml
|
||||
<PropertyGroup>
|
||||
<DisableImplicitNuGetFallbackFolder>true</DisableImplicitNuGetFallbackFolder>
|
||||
</PropertyGroup>
|
||||
```
|
||||
|
||||
### Reduce caching size
|
||||
|
||||
> **Note**: Use [`NUGET_PACKAGES`](https://learn.microsoft.com/nuget/reference/cli-reference/cli-ref-environment-variables) environment variable if available. Some action runners already has huge libraries. (ex. Xamarin)
|
||||
|
||||
```yaml
|
||||
env:
|
||||
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: 6.x
|
||||
cache: true
|
||||
- run: dotnet restore --locked-mode
|
||||
```
|
||||
|
||||
### Caching NuGet packages in monorepos
|
||||
|
||||
```yaml
|
||||
env:
|
||||
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: 6.x
|
||||
cache: true
|
||||
cache-dependency-path: subdir/packages.lock.json
|
||||
- run: dotnet restore --locked-mode
|
||||
```
|
||||
|
||||
## Matrix Testing
|
||||
Using `setup-dotnet` it's possible to use [matrix syntax](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrix) to install several versions of .NET SDK:
|
||||
```yml
|
||||
|
@ -212,6 +271,9 @@ When the `dotnet-version` input is used along with the `global-json-file` input,
|
|||
- run: echo '${{ steps.stepid.outputs.dotnet-version }}' # outputs 2.2.207
|
||||
```
|
||||
|
||||
### `cache-hit`
|
||||
A boolean value to indicate an exact match was found for the cache key (follows [actions/cache](https://github.com/actions/cache#outputs))
|
||||
|
||||
## Environment variables
|
||||
|
||||
Some environment variables may be necessary for your particular case or to improve logging. Some examples are listed below, but the full list with complete details can be found here: https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-environment-variables
|
||||
|
@ -222,25 +284,28 @@ Some environment variables may be necessary for your particular case or to impro
|
|||
| 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_MULTILEVEL_LOOKUP |Configures whether the global install location is used as a fall-back|*true*|
|
||||
| NUGET_PACKAGES |Configures a path to the [NuGet `global-packages` folder](https://learn.microsoft.com/nuget/consume-packages/managing-the-global-packages-and-cache-folders)|*default value for each OS* |
|
||||
|
||||
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` |
|
||||
The default values of the `DOTNET_INSTALL_DIR` and `NUGET_PACKAGES` environment variables depend on the operation system which is used on a runner:
|
||||
| **Operation system** | `DOTNET_INSTALL_DIR` | `NUGET_PACKAGES` |
|
||||
| ----------- | ----------- | ----------- |
|
||||
| **Windows** | `C:\Program Files\dotnet` | `%userprofile%\.nuget\packages` |
|
||||
| **Ubuntu** | `/usr/share/dotnet` | `~/.nuget/packages` |
|
||||
| **macOS** | `/Users/runner/.dotnet` | `~/.nuget/packages` |
|
||||
|
||||
**Example usage**:
|
||||
**Example usage of environment variable**:
|
||||
```yml
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOTNET_INSTALL_DIR: "path/to/directory"
|
||||
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
|
||||
steps:
|
||||
- uses: actions/checkout@main
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '3.1.x'
|
||||
cache: true
|
||||
```
|
||||
|
||||
## License
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// 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\\"?>
|
||||
<configuration>
|
||||
<config>
|
||||
|
@ -15,7 +15,7 @@ exports[`authutil tests Existing config not in repo root, sets up a partial NuGe
|
|||
</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\\"?>
|
||||
<configuration>
|
||||
<config>
|
||||
|
@ -30,7 +30,7 @@ exports[`authutil tests Existing config w/ Azure Artifacts source and NuGet.org,
|
|||
</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\\"?>
|
||||
<configuration>
|
||||
<config>
|
||||
|
@ -45,7 +45,7 @@ exports[`authutil tests Existing config w/ GPR source and NuGet.org, sets up a p
|
|||
</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\\"?>
|
||||
<configuration>
|
||||
<config>
|
||||
|
@ -63,7 +63,7 @@ exports[`authutil tests Existing config w/ no GPR sources, sets up a full NuGet.
|
|||
</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\\"?>
|
||||
<configuration>
|
||||
<config>
|
||||
|
@ -81,7 +81,7 @@ exports[`authutil tests Existing config w/ no sources, sets up a full NuGet.conf
|
|||
</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\\"?>
|
||||
<configuration>
|
||||
<config>
|
||||
|
@ -96,7 +96,7 @@ exports[`authutil tests Existing config w/ only Azure Artifacts source, sets up
|
|||
</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\\"?>
|
||||
<configuration>
|
||||
<config>
|
||||
|
@ -111,7 +111,7 @@ exports[`authutil tests Existing config w/ only GPR source, sets up a partial Nu
|
|||
</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\\"?>
|
||||
<configuration>
|
||||
<config>
|
||||
|
@ -130,7 +130,7 @@ exports[`authutil tests Existing config w/ two GPR sources, sets up a partial Nu
|
|||
</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\\"?>
|
||||
<configuration>
|
||||
<config>
|
||||
|
@ -148,7 +148,7 @@ exports[`authutil tests No existing config, sets up a full NuGet.config with URL
|
|||
</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\\"?>
|
||||
<configuration>
|
||||
<config>
|
||||
|
@ -166,7 +166,7 @@ exports[`authutil tests No existing config, sets up a full NuGet.config with URL
|
|||
</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\\"?>
|
||||
<configuration>
|
||||
<config>
|
||||
|
|
|
@ -1,336 +1,336 @@
|
|||
import * as io from '@actions/io';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
const fakeSourcesDirForTesting = path.join(
|
||||
__dirname,
|
||||
'runner',
|
||||
path.join(Math.random().toString(36).substring(7)),
|
||||
's'
|
||||
);
|
||||
|
||||
const invalidNuGetConfig: string = `<?xml version="1.0" encoding="utf-8"?>`;
|
||||
|
||||
const emptyNuGetConfig: string = `<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
</configuration>`;
|
||||
|
||||
const nugetorgNuGetConfig: string = `<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
|
||||
</packageSources>
|
||||
</configuration>`;
|
||||
|
||||
const gprnugetorgNuGetConfig: string = `<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<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" />
|
||||
</packageSources>
|
||||
</configuration>`;
|
||||
|
||||
const gprNuGetConfig: string = `<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="GPR" value="https://nuget.pkg.github.com/OwnerName/index.json" protocolVersion="3" />
|
||||
</packageSources>
|
||||
</configuration>`;
|
||||
|
||||
const twogprNuGetConfig: string = `<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<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" />
|
||||
</packageSources>
|
||||
</configuration>`;
|
||||
|
||||
const spaceNuGetConfig: string = `<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="GPR GitHub" value="https://nuget.pkg.github.com/OwnerName/index.json" protocolVersion="3" />
|
||||
</packageSources>
|
||||
</configuration>`;
|
||||
|
||||
const azureartifactsNuGetConfig: string = `<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="AzureArtifacts" value="https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json" protocolVersion="3" />
|
||||
</packageSources>
|
||||
</configuration>`;
|
||||
|
||||
const azureartifactsnugetorgNuGetConfig: string = `<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<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" />
|
||||
</packageSources>
|
||||
</configuration>`;
|
||||
|
||||
// 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.
|
||||
const nugetConfigFile = path.join(fakeSourcesDirForTesting, '../nuget.config');
|
||||
|
||||
process.env['GITHUB_REPOSITORY'] = 'OwnerName/repo';
|
||||
import * as auth from '../src/authutil';
|
||||
|
||||
describe('authutil tests', () => {
|
||||
beforeEach(async () => {
|
||||
await io.rmRF(fakeSourcesDirForTesting);
|
||||
await io.mkdirP(fakeSourcesDirForTesting);
|
||||
}, 30000);
|
||||
|
||||
afterAll(async () => {
|
||||
await io.rmRF(fakeSourcesDirForTesting);
|
||||
}, 30000);
|
||||
|
||||
beforeEach(() => {
|
||||
if (fs.existsSync(nugetConfigFile)) {
|
||||
fs.unlinkSync(nugetConfigFile);
|
||||
}
|
||||
process.env['INPUT_OWNER'] = '';
|
||||
process.env['NUGET_AUTH_TOKEN'] = '';
|
||||
});
|
||||
|
||||
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';
|
||||
await auth.configAuthentication(
|
||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||
expect(
|
||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('No existing config, auth token environment variable not provided, throws', async () => {
|
||||
let thrown = false;
|
||||
try {
|
||||
await auth.configAuthentication(
|
||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
} catch {
|
||||
thrown = true;
|
||||
}
|
||||
expect(thrown).toBe(true);
|
||||
});
|
||||
|
||||
it('No existing config, sets up a full NuGet.config with URL and other owner/PAT for GPR', async () => {
|
||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||
process.env['INPUT_OWNER'] = 'otherorg';
|
||||
await auth.configAuthentication(
|
||||
'https://nuget.pkg.github.com/otherorg/index.json',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||
expect(
|
||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('Existing config (invalid), tries to parse an invalid NuGet.config and throws', async () => {
|
||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||
const inputNuGetConfigPath: string = path.join(
|
||||
fakeSourcesDirForTesting,
|
||||
'nuget.config'
|
||||
);
|
||||
fs.writeFileSync(inputNuGetConfigPath, invalidNuGetConfig);
|
||||
let thrown = false;
|
||||
try {
|
||||
await auth.configAuthentication(
|
||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
} catch {
|
||||
thrown = true;
|
||||
}
|
||||
expect(thrown).toBe(true);
|
||||
});
|
||||
|
||||
it('Existing config w/ no sources, sets up a full NuGet.config with URL and user/PAT for GPR', async () => {
|
||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||
const inputNuGetConfigPath: string = path.join(
|
||||
fakeSourcesDirForTesting,
|
||||
'nuget.config'
|
||||
);
|
||||
fs.writeFileSync(inputNuGetConfigPath, emptyNuGetConfig);
|
||||
await auth.configAuthentication(
|
||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||
expect(
|
||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('Existing config w/ no GPR sources, sets up a full NuGet.config with URL and user/PAT for GPR', async () => {
|
||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||
const inputNuGetConfigPath: string = path.join(
|
||||
fakeSourcesDirForTesting,
|
||||
'nuget.config'
|
||||
);
|
||||
fs.writeFileSync(inputNuGetConfigPath, nugetorgNuGetConfig);
|
||||
await auth.configAuthentication(
|
||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||
expect(
|
||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('Existing config w/ only GPR source, sets up a partial NuGet.config user/PAT for GPR', async () => {
|
||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||
const inputNuGetConfigPath: string = path.join(
|
||||
fakeSourcesDirForTesting,
|
||||
'nuget.config'
|
||||
);
|
||||
fs.writeFileSync(inputNuGetConfigPath, gprNuGetConfig);
|
||||
await auth.configAuthentication(
|
||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||
expect(
|
||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('Existing config w/ GPR source and NuGet.org, sets up a partial NuGet.config user/PAT for GPR', async () => {
|
||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||
const inputNuGetConfigPath: string = path.join(
|
||||
fakeSourcesDirForTesting,
|
||||
'nuget.config'
|
||||
);
|
||||
fs.writeFileSync(inputNuGetConfigPath, gprnugetorgNuGetConfig);
|
||||
await auth.configAuthentication(
|
||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||
expect(
|
||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('Existing config w/ two GPR sources, sets up a partial NuGet.config user/PAT for GPR', async () => {
|
||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||
const inputNuGetConfigPath: string = path.join(
|
||||
fakeSourcesDirForTesting,
|
||||
'nuget.config'
|
||||
);
|
||||
fs.writeFileSync(inputNuGetConfigPath, twogprNuGetConfig);
|
||||
await auth.configAuthentication(
|
||||
'https://nuget.pkg.github.com',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||
expect(
|
||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('Existing config w/ spaces in key, throws for now', async () => {
|
||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||
const inputNuGetConfigPath: string = path.join(
|
||||
fakeSourcesDirForTesting,
|
||||
'nuget.config'
|
||||
);
|
||||
fs.writeFileSync(inputNuGetConfigPath, spaceNuGetConfig);
|
||||
let thrown = false;
|
||||
try {
|
||||
await auth.configAuthentication(
|
||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
} catch {
|
||||
thrown = true;
|
||||
}
|
||||
expect(thrown).toBe(true);
|
||||
});
|
||||
|
||||
it('Existing config not in repo root, sets up a partial NuGet.config user/PAT for GPR', async () => {
|
||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||
const inputNuGetConfigDirectory: string = path.join(
|
||||
fakeSourcesDirForTesting,
|
||||
'subfolder'
|
||||
);
|
||||
const inputNuGetConfigPath: string = path.join(
|
||||
inputNuGetConfigDirectory,
|
||||
'nuget.config'
|
||||
);
|
||||
fs.mkdirSync(inputNuGetConfigDirectory, {recursive: true});
|
||||
fs.writeFileSync(inputNuGetConfigPath, gprNuGetConfig);
|
||||
await auth.configAuthentication(
|
||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||
'subfolder/nuget.config',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||
expect(
|
||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('Existing config w/ only Azure Artifacts source, sets up a partial NuGet.config user/PAT for GPR', async () => {
|
||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||
const inputNuGetConfigPath: string = path.join(
|
||||
fakeSourcesDirForTesting,
|
||||
'nuget.config'
|
||||
);
|
||||
fs.writeFileSync(inputNuGetConfigPath, azureartifactsNuGetConfig);
|
||||
await auth.configAuthentication(
|
||||
'https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||
expect(
|
||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('Existing config w/ Azure Artifacts source and NuGet.org, sets up a partial NuGet.config user/PAT for GPR', async () => {
|
||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||
const inputNuGetConfigPath: string = path.join(
|
||||
fakeSourcesDirForTesting,
|
||||
'nuget.config'
|
||||
);
|
||||
fs.writeFileSync(inputNuGetConfigPath, azureartifactsnugetorgNuGetConfig);
|
||||
await auth.configAuthentication(
|
||||
'https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||
expect(
|
||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
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';
|
||||
await auth.configAuthentication(
|
||||
'https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||
expect(
|
||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
import * as io from '@actions/io';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
const fakeSourcesDirForTesting = path.join(
|
||||
__dirname,
|
||||
'runner',
|
||||
path.join(Math.random().toString(36).substring(7)),
|
||||
's'
|
||||
);
|
||||
|
||||
const invalidNuGetConfig = `<?xml version="1.0" encoding="utf-8"?>`;
|
||||
|
||||
const emptyNuGetConfig = `<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
</configuration>`;
|
||||
|
||||
const nugetorgNuGetConfig = `<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
|
||||
</packageSources>
|
||||
</configuration>`;
|
||||
|
||||
const gprnugetorgNuGetConfig = `<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<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" />
|
||||
</packageSources>
|
||||
</configuration>`;
|
||||
|
||||
const gprNuGetConfig = `<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="GPR" value="https://nuget.pkg.github.com/OwnerName/index.json" protocolVersion="3" />
|
||||
</packageSources>
|
||||
</configuration>`;
|
||||
|
||||
const twogprNuGetConfig = `<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<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" />
|
||||
</packageSources>
|
||||
</configuration>`;
|
||||
|
||||
const spaceNuGetConfig = `<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="GPR GitHub" value="https://nuget.pkg.github.com/OwnerName/index.json" protocolVersion="3" />
|
||||
</packageSources>
|
||||
</configuration>`;
|
||||
|
||||
const azureartifactsNuGetConfig = `<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="AzureArtifacts" value="https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json" protocolVersion="3" />
|
||||
</packageSources>
|
||||
</configuration>`;
|
||||
|
||||
const azureartifactsnugetorgNuGetConfig = `<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<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" />
|
||||
</packageSources>
|
||||
</configuration>`;
|
||||
|
||||
// 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.
|
||||
const nugetConfigFile = path.join(fakeSourcesDirForTesting, '../nuget.config');
|
||||
|
||||
process.env['GITHUB_REPOSITORY'] = 'OwnerName/repo';
|
||||
import * as auth from '../src/authutil';
|
||||
|
||||
describe('authutil tests', () => {
|
||||
beforeEach(async () => {
|
||||
await io.rmRF(fakeSourcesDirForTesting);
|
||||
await io.mkdirP(fakeSourcesDirForTesting);
|
||||
}, 30000);
|
||||
|
||||
afterAll(async () => {
|
||||
await io.rmRF(fakeSourcesDirForTesting);
|
||||
}, 30000);
|
||||
|
||||
beforeEach(() => {
|
||||
if (fs.existsSync(nugetConfigFile)) {
|
||||
fs.unlinkSync(nugetConfigFile);
|
||||
}
|
||||
process.env['INPUT_OWNER'] = '';
|
||||
process.env['NUGET_AUTH_TOKEN'] = '';
|
||||
});
|
||||
|
||||
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';
|
||||
auth.configAuthentication(
|
||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||
expect(
|
||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('no existing config, auth token environment variable not provided, throws', async () => {
|
||||
let thrown = false;
|
||||
try {
|
||||
auth.configAuthentication(
|
||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
} catch {
|
||||
thrown = true;
|
||||
}
|
||||
expect(thrown).toBe(true);
|
||||
});
|
||||
|
||||
it('no existing config, sets up a full NuGet.config with URL and other owner/PAT for GPR', async () => {
|
||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||
process.env['INPUT_OWNER'] = 'otherorg';
|
||||
auth.configAuthentication(
|
||||
'https://nuget.pkg.github.com/otherorg/index.json',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||
expect(
|
||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('existing config (invalid), tries to parse an invalid NuGet.config and throws', async () => {
|
||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||
const inputNuGetConfigPath: string = path.join(
|
||||
fakeSourcesDirForTesting,
|
||||
'nuget.config'
|
||||
);
|
||||
fs.writeFileSync(inputNuGetConfigPath, invalidNuGetConfig);
|
||||
let thrown = false;
|
||||
try {
|
||||
auth.configAuthentication(
|
||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
} catch {
|
||||
thrown = true;
|
||||
}
|
||||
expect(thrown).toBe(true);
|
||||
});
|
||||
|
||||
it('existing config w/ no sources, sets up a full NuGet.config with URL and user/PAT for GPR', async () => {
|
||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||
const inputNuGetConfigPath: string = path.join(
|
||||
fakeSourcesDirForTesting,
|
||||
'nuget.config'
|
||||
);
|
||||
fs.writeFileSync(inputNuGetConfigPath, emptyNuGetConfig);
|
||||
auth.configAuthentication(
|
||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||
expect(
|
||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('existing config w/ no GPR sources, sets up a full NuGet.config with URL and user/PAT for GPR', async () => {
|
||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||
const inputNuGetConfigPath: string = path.join(
|
||||
fakeSourcesDirForTesting,
|
||||
'nuget.config'
|
||||
);
|
||||
fs.writeFileSync(inputNuGetConfigPath, nugetorgNuGetConfig);
|
||||
auth.configAuthentication(
|
||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||
expect(
|
||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('existing config w/ only GPR source, sets up a partial NuGet.config user/PAT for GPR', async () => {
|
||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||
const inputNuGetConfigPath: string = path.join(
|
||||
fakeSourcesDirForTesting,
|
||||
'nuget.config'
|
||||
);
|
||||
fs.writeFileSync(inputNuGetConfigPath, gprNuGetConfig);
|
||||
auth.configAuthentication(
|
||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||
expect(
|
||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('existing config w/ GPR source and NuGet.org, sets up a partial NuGet.config user/PAT for GPR', async () => {
|
||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||
const inputNuGetConfigPath: string = path.join(
|
||||
fakeSourcesDirForTesting,
|
||||
'nuget.config'
|
||||
);
|
||||
fs.writeFileSync(inputNuGetConfigPath, gprnugetorgNuGetConfig);
|
||||
auth.configAuthentication(
|
||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||
expect(
|
||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('existing config w/ two GPR sources, sets up a partial NuGet.config user/PAT for GPR', async () => {
|
||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||
const inputNuGetConfigPath: string = path.join(
|
||||
fakeSourcesDirForTesting,
|
||||
'nuget.config'
|
||||
);
|
||||
fs.writeFileSync(inputNuGetConfigPath, twogprNuGetConfig);
|
||||
auth.configAuthentication(
|
||||
'https://nuget.pkg.github.com',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||
expect(
|
||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('existing config w/ spaces in key, throws for now', async () => {
|
||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||
const inputNuGetConfigPath: string = path.join(
|
||||
fakeSourcesDirForTesting,
|
||||
'nuget.config'
|
||||
);
|
||||
fs.writeFileSync(inputNuGetConfigPath, spaceNuGetConfig);
|
||||
let thrown = false;
|
||||
try {
|
||||
auth.configAuthentication(
|
||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
} catch {
|
||||
thrown = true;
|
||||
}
|
||||
expect(thrown).toBe(true);
|
||||
});
|
||||
|
||||
it('existing config not in repo root, sets up a partial NuGet.config user/PAT for GPR', async () => {
|
||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||
const inputNuGetConfigDirectory: string = path.join(
|
||||
fakeSourcesDirForTesting,
|
||||
'subfolder'
|
||||
);
|
||||
const inputNuGetConfigPath: string = path.join(
|
||||
inputNuGetConfigDirectory,
|
||||
'nuget.config'
|
||||
);
|
||||
fs.mkdirSync(inputNuGetConfigDirectory, {recursive: true});
|
||||
fs.writeFileSync(inputNuGetConfigPath, gprNuGetConfig);
|
||||
auth.configAuthentication(
|
||||
'https://nuget.pkg.github.com/OwnerName/index.json',
|
||||
'subfolder/nuget.config',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||
expect(
|
||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('existing config w/ only Azure Artifacts source, sets up a partial NuGet.config user/PAT for GPR', async () => {
|
||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||
const inputNuGetConfigPath: string = path.join(
|
||||
fakeSourcesDirForTesting,
|
||||
'nuget.config'
|
||||
);
|
||||
fs.writeFileSync(inputNuGetConfigPath, azureartifactsNuGetConfig);
|
||||
auth.configAuthentication(
|
||||
'https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||
expect(
|
||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('existing config w/ Azure Artifacts source and NuGet.org, sets up a partial NuGet.config user/PAT for GPR', async () => {
|
||||
process.env['NUGET_AUTH_TOKEN'] = 'TEST_FAKE_AUTH_TOKEN';
|
||||
const inputNuGetConfigPath: string = path.join(
|
||||
fakeSourcesDirForTesting,
|
||||
'nuget.config'
|
||||
);
|
||||
fs.writeFileSync(inputNuGetConfigPath, azureartifactsnugetorgNuGetConfig);
|
||||
auth.configAuthentication(
|
||||
'https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||
expect(
|
||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
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';
|
||||
auth.configAuthentication(
|
||||
'https://pkgs.dev.azure.com/amullans/_packaging/GitHubBuilds/nuget/v3/index.json',
|
||||
'',
|
||||
fakeSourcesDirForTesting
|
||||
);
|
||||
expect(fs.existsSync(nugetConfigFile)).toBe(true);
|
||||
expect(
|
||||
fs.readFileSync(nugetConfigFile, {encoding: 'utf8'})
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
import {readdir} from 'node:fs/promises';
|
||||
import * as cache from '@actions/cache';
|
||||
import * as core from '@actions/core';
|
||||
import * as glob from '@actions/glob';
|
||||
import {restoreCache} from '../src/cache-restore';
|
||||
import {getNuGetFolderPath} from '../src/cache-utils';
|
||||
import {lockFilePatterns} from '../src/constants';
|
||||
|
||||
jest.mock('node:fs/promises');
|
||||
jest.mock('@actions/cache');
|
||||
jest.mock('@actions/core');
|
||||
jest.mock('@actions/glob');
|
||||
jest.mock('../src/cache-utils');
|
||||
|
||||
describe('cache-restore tests', () => {
|
||||
describe.each(lockFilePatterns)('restoreCache("%s")', lockFilePattern => {
|
||||
/** Store original process.env.GITHUB_WORKSPACE */
|
||||
let githubWorkspace: string | undefined;
|
||||
beforeAll(() => {
|
||||
githubWorkspace = process.env.GITHUB_WORKSPACE;
|
||||
jest.mocked(getNuGetFolderPath).mockResolvedValue({
|
||||
'global-packages': 'global-packages',
|
||||
'http-cache': 'http-cache',
|
||||
temp: 'temp',
|
||||
'plugins-cache': 'plugins-cache'
|
||||
});
|
||||
});
|
||||
beforeEach(() => {
|
||||
process.env.GITHUB_WORKSPACE = './';
|
||||
jest.mocked(glob.hashFiles).mockClear();
|
||||
jest.mocked(core.saveState).mockClear();
|
||||
jest.mocked(core.setOutput).mockClear();
|
||||
jest.mocked(cache.restoreCache).mockClear();
|
||||
});
|
||||
afterEach(() => (process.env.GITHUB_WORKSPACE = githubWorkspace));
|
||||
|
||||
it('throws error when lock file is not found', async () => {
|
||||
jest.mocked(glob.hashFiles).mockResolvedValue('');
|
||||
|
||||
await expect(restoreCache(lockFilePattern)).rejects.toThrow();
|
||||
|
||||
expect(jest.mocked(core.saveState)).not.toHaveBeenCalled();
|
||||
expect(jest.mocked(core.setOutput)).not.toHaveBeenCalled();
|
||||
expect(jest.mocked(cache.restoreCache)).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does not call core.saveState("CACHE_RESULT") when cache.restoreCache() returns falsy', async () => {
|
||||
jest.mocked(glob.hashFiles).mockResolvedValue('hash');
|
||||
jest.mocked(cache.restoreCache).mockResolvedValue(undefined);
|
||||
|
||||
await restoreCache(lockFilePattern);
|
||||
|
||||
const expectedKey = `dotnet-cache-${process.env.RUNNER_OS}-hash`;
|
||||
expect(jest.mocked(core.saveState)).toHaveBeenCalledWith(
|
||||
'CACHE_KEY',
|
||||
expectedKey
|
||||
);
|
||||
expect(jest.mocked(core.saveState)).not.toHaveBeenCalledWith(
|
||||
'CACHE_RESULT',
|
||||
expectedKey
|
||||
);
|
||||
expect(jest.mocked(core.setOutput)).toHaveBeenCalledWith(
|
||||
'cache-hit',
|
||||
false
|
||||
);
|
||||
});
|
||||
|
||||
it('calls core.saveState("CACHE_RESULT") when cache.restoreCache() returns key', async () => {
|
||||
const expectedKey = `dotnet-cache-${process.env.RUNNER_OS}-hash`;
|
||||
jest.mocked(glob.hashFiles).mockResolvedValue('hash');
|
||||
jest.mocked(cache.restoreCache).mockResolvedValue(expectedKey);
|
||||
|
||||
await restoreCache(lockFilePattern);
|
||||
|
||||
expect(jest.mocked(core.saveState)).toHaveBeenCalledWith(
|
||||
'CACHE_KEY',
|
||||
expectedKey
|
||||
);
|
||||
expect(jest.mocked(core.saveState)).toHaveBeenCalledWith(
|
||||
'CACHE_RESULT',
|
||||
expectedKey
|
||||
);
|
||||
expect(jest.mocked(core.setOutput)).toHaveBeenCalledWith(
|
||||
'cache-hit',
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
it('calls glob.hashFiles("/packages.lock.json") if cacheDependencyPath is falsy', async () => {
|
||||
const expectedKey = `dotnet-cache-${process.env.RUNNER_OS}-hash`;
|
||||
jest.mocked(glob.hashFiles).mockResolvedValue('hash');
|
||||
jest.mocked(cache.restoreCache).mockResolvedValue(expectedKey);
|
||||
jest.mocked(readdir).mockResolvedValue([lockFilePattern] as any);
|
||||
|
||||
await restoreCache('');
|
||||
|
||||
expect(jest.mocked(glob.hashFiles)).not.toHaveBeenCalledWith('');
|
||||
expect(jest.mocked(glob.hashFiles)).toHaveBeenCalledWith(lockFilePattern);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,87 @@
|
|||
import * as cache from '@actions/cache';
|
||||
import * as core from '@actions/core';
|
||||
import fs from 'node:fs';
|
||||
import {run} from '../src/cache-save';
|
||||
import {getNuGetFolderPath} from '../src/cache-utils';
|
||||
|
||||
jest.mock('@actions/cache');
|
||||
jest.mock('@actions/core');
|
||||
jest.mock('node:fs');
|
||||
jest.mock('../src/cache-utils');
|
||||
|
||||
describe('cache-save tests', () => {
|
||||
beforeAll(() => {
|
||||
jest.mocked(getNuGetFolderPath).mockResolvedValue({
|
||||
'global-packages': 'global-packages',
|
||||
'http-cache': 'http-cache',
|
||||
temp: 'temp',
|
||||
'plugins-cache': 'plugins-cache'
|
||||
});
|
||||
});
|
||||
beforeEach(() => {
|
||||
jest.mocked(core.setFailed).mockClear();
|
||||
jest.mocked(core.getState).mockClear();
|
||||
jest.mocked(core.setOutput).mockClear();
|
||||
jest.mocked(cache.saveCache).mockClear();
|
||||
jest.mocked(fs.existsSync).mockClear();
|
||||
});
|
||||
|
||||
it('does not save cache when inputs:cache === false', async () => {
|
||||
jest.mocked(core.getBooleanInput).mockReturnValue(false);
|
||||
|
||||
await run();
|
||||
|
||||
expect(jest.mocked(core.setFailed)).not.toHaveBeenCalled();
|
||||
expect(jest.mocked(core.getState)).not.toHaveBeenCalled();
|
||||
expect(jest.mocked(fs.existsSync)).not.toHaveBeenCalled();
|
||||
expect(jest.mocked(cache.saveCache)).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does not save cache when core.getState("CACHE_KEY") returns ""', async () => {
|
||||
jest.mocked(core.getBooleanInput).mockReturnValue(true);
|
||||
jest.mocked(core.getState).mockReturnValue('');
|
||||
|
||||
await run();
|
||||
|
||||
expect(jest.mocked(core.setFailed)).not.toHaveBeenCalled();
|
||||
expect(jest.mocked(core.getState)).toHaveBeenCalledTimes(2);
|
||||
expect(jest.mocked(fs.existsSync)).not.toHaveBeenCalled();
|
||||
expect(jest.mocked(cache.saveCache)).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('throws Error when cachePath not exists', async () => {
|
||||
jest.mocked(core.getBooleanInput).mockReturnValue(true);
|
||||
jest.mocked(core.getState).mockReturnValue('cache-key');
|
||||
jest.mocked(fs.existsSync).mockReturnValue(false);
|
||||
|
||||
await run();
|
||||
|
||||
expect(jest.mocked(core.setFailed)).toHaveBeenCalled();
|
||||
expect(jest.mocked(core.getState)).toHaveBeenCalledTimes(2);
|
||||
expect(jest.mocked(cache.saveCache)).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does not save cache when state.CACHE_KEY === state.CACHE_RESULT', async () => {
|
||||
jest.mocked(core.getBooleanInput).mockReturnValue(true);
|
||||
jest.mocked(core.getState).mockReturnValue('cache-key');
|
||||
jest.mocked(fs.existsSync).mockReturnValue(true);
|
||||
|
||||
await run();
|
||||
|
||||
expect(jest.mocked(core.setFailed)).not.toHaveBeenCalled();
|
||||
expect(jest.mocked(core.getState)).toHaveBeenCalledTimes(2);
|
||||
expect(jest.mocked(cache.saveCache)).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('saves cache when state.CACHE_KEY !== state.CACHE_RESULT', async () => {
|
||||
jest.mocked(core.getBooleanInput).mockReturnValue(true);
|
||||
jest.mocked(core.getState).mockImplementation(s => s);
|
||||
jest.mocked(fs.existsSync).mockReturnValue(true);
|
||||
|
||||
await run();
|
||||
|
||||
expect(jest.mocked(core.setFailed)).not.toHaveBeenCalled();
|
||||
expect(jest.mocked(core.getState)).toHaveBeenCalledTimes(2);
|
||||
expect(jest.mocked(cache.saveCache)).toHaveBeenCalled();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,122 @@
|
|||
import * as cache from '@actions/cache';
|
||||
import * as exec from '@actions/exec';
|
||||
|
||||
import {getNuGetFolderPath, isCacheFeatureAvailable} from '../src/cache-utils';
|
||||
|
||||
jest.mock('@actions/cache');
|
||||
jest.mock('@actions/core');
|
||||
jest.mock('@actions/exec');
|
||||
|
||||
describe('cache-utils tests', () => {
|
||||
describe('getNuGetFolderPath()', () => {
|
||||
it.each([
|
||||
[
|
||||
`
|
||||
http-cache: /home/codespace/.local/share/NuGet/v3-cache
|
||||
global-packages: /var/nuget
|
||||
temp: /tmp/NuGetScratch
|
||||
plugins-cache: /home/codespace/.local/share/NuGet/plugins-cache
|
||||
`,
|
||||
{
|
||||
'http-cache': '/home/codespace/.local/share/NuGet/v3-cache',
|
||||
'global-packages': '/var/nuget',
|
||||
temp: '/tmp/NuGetScratch',
|
||||
'plugins-cache': '/home/codespace/.local/share/NuGet/plugins-cache'
|
||||
}
|
||||
],
|
||||
[
|
||||
`
|
||||
http-cache: /home/codespace/.local/share/NuGet/v3-cache
|
||||
global-packages: /var/nuget
|
||||
temp: /tmp/NuGetScratch
|
||||
plugins-cache: /home/codespace/.local/share/NuGet/plugins-cache
|
||||
`,
|
||||
{
|
||||
'http-cache': '/home/codespace/.local/share/NuGet/v3-cache',
|
||||
'global-packages': '/var/nuget',
|
||||
temp: '/tmp/NuGetScratch',
|
||||
'plugins-cache': '/home/codespace/.local/share/NuGet/plugins-cache'
|
||||
}
|
||||
],
|
||||
[
|
||||
`
|
||||
http-cache: C:\\Users\\user\\AppData\\Local\\NuGet\\v3-cache
|
||||
global-packages: C:\\Users\\user\\.nuget\\packages\\
|
||||
temp: C:\\Users\\user\\AppData\\Local\\Temp\\NuGetScratch
|
||||
plugins-cache: C:\\Users\\user\\AppData\\Local\\NuGet\\plugins-cache
|
||||
`,
|
||||
{
|
||||
'http-cache': 'C:\\Users\\user\\AppData\\Local\\NuGet\\v3-cache',
|
||||
'global-packages': 'C:\\Users\\user\\.nuget\\packages\\',
|
||||
temp: 'C:\\Users\\user\\AppData\\Local\\Temp\\NuGetScratch',
|
||||
'plugins-cache':
|
||||
'C:\\Users\\user\\AppData\\Local\\NuGet\\plugins-cache'
|
||||
}
|
||||
],
|
||||
[
|
||||
`
|
||||
http-cache: C:\\Users\\user\\AppData\\Local\\NuGet\\v3-cache
|
||||
global-packages: C:\\Users\\user\\.nuget\\packages\\
|
||||
temp: C:\\Users\\user\\AppData\\Local\\Temp\\NuGetScratch
|
||||
plugins-cache: C:\\Users\\user\\AppData\\Local\\NuGet\\plugins-cache
|
||||
`,
|
||||
{
|
||||
'http-cache': 'C:\\Users\\user\\AppData\\Local\\NuGet\\v3-cache',
|
||||
'global-packages': 'C:\\Users\\user\\.nuget\\packages\\',
|
||||
temp: 'C:\\Users\\user\\AppData\\Local\\Temp\\NuGetScratch',
|
||||
'plugins-cache':
|
||||
'C:\\Users\\user\\AppData\\Local\\NuGet\\plugins-cache'
|
||||
}
|
||||
]
|
||||
])('(stdout: "%s") returns %p', async (stdout, expected) => {
|
||||
jest
|
||||
.mocked(exec.getExecOutput)
|
||||
.mockResolvedValue({stdout, stderr: '', exitCode: 0});
|
||||
const pathes = await getNuGetFolderPath();
|
||||
expect(pathes).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
it.each([
|
||||
`
|
||||
error: An invalid local resource name was provided. Provide one of the following values: http-cache, temp, global-packages, all.
|
||||
Usage: dotnet nuget locals [arguments] [options]
|
||||
Arguments:
|
||||
Cache Location(s) Specifies the cache location(s) to list or clear.
|
||||
<all | http-cache | global-packages | temp>
|
||||
Options:
|
||||
-h|--help Show help information
|
||||
--force-english-output Forces the application to run using an invariant, English-based culture.
|
||||
-c|--clear Clear the selected local resources or cache location(s).
|
||||
-l|--list List the selected local resources or cache location(s).
|
||||
`,
|
||||
'bash: dotnet: command not found',
|
||||
''
|
||||
])('(stderr: "%s", exitCode: 1) throws Error', async stderr => {
|
||||
jest
|
||||
.mocked(exec.getExecOutput)
|
||||
.mockResolvedValue({stdout: '', stderr, exitCode: 1});
|
||||
await expect(getNuGetFolderPath()).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe.each(['', 'https://github.com/', 'https://example.com/'])(
|
||||
'isCacheFeatureAvailable()',
|
||||
url => {
|
||||
// Save & Restore env
|
||||
let serverUrlEnv: string | undefined;
|
||||
beforeAll(() => (serverUrlEnv = process.env['GITHUB_SERVER_URL']));
|
||||
beforeEach(() => (process.env['GITHUB_SERVER_URL'] = url));
|
||||
afterEach(() => (process.env['GITHUB_SERVER_URL'] = serverUrlEnv));
|
||||
|
||||
it('returns true when cache.isFeatureAvailable() === true', () => {
|
||||
jest.mocked(cache.isFeatureAvailable).mockReturnValue(true);
|
||||
expect(isCacheFeatureAvailable()).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false when cache.isFeatureAvailable() === false', () => {
|
||||
jest.mocked(cache.isFeatureAvailable).mockReturnValue(false);
|
||||
expect(isCacheFeatureAvailable()).toBe(false);
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
|
@ -1,21 +1,45 @@
|
|||
import cscFile from '../.github/csc.json';
|
||||
describe('csc tests', () => {
|
||||
it('Valid regular expression', async () => {
|
||||
var cscFile = require('../.github/csc.json');
|
||||
var regex = cscFile['problemMatcher'][0]['pattern'][0]['regexp'];
|
||||
test('regular expression in csc.json is valid', async () => {
|
||||
const regexPattern = cscFile['problemMatcher'][0]['pattern'][0]['regexp'];
|
||||
const regexResultsMap = cscFile['problemMatcher'][0]['pattern'][0];
|
||||
|
||||
console.log(regex);
|
||||
var re = new RegExp(regex);
|
||||
const regex = new RegExp(regexPattern);
|
||||
|
||||
// Ideally we would verify that this
|
||||
var stringsToMatch = [
|
||||
const stringsToMatch = [
|
||||
'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]"
|
||||
];
|
||||
// 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 => {
|
||||
var matchStr = string.match(re);
|
||||
console.log(matchStr);
|
||||
expect(matchStr).toEqual(expect.anything());
|
||||
stringsToMatch.map((string, index) => {
|
||||
const matchedResultsArray = string.match(regex);
|
||||
for (const propName in expectedResults[index]) {
|
||||
const propertyIndex = regexResultsMap[propName];
|
||||
const expectedPropValue = expectedResults[index][propName];
|
||||
const matchedPropValue = matchedResultsArray![propertyIndex];
|
||||
expect(matchedPropValue).toEqual(expectedPropValue);
|
||||
}
|
||||
});
|
||||
}, 10000);
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,16 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>$(TEST_TARGET_FRAMEWORK)</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<DisableImplicitNuGetFallbackFolder>true</DisableImplicitNuGetFallbackFolder>
|
||||
</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>
|
|
@ -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,492 @@
|
|||
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 * as hc from '@actions/http-client';
|
||||
import semver from 'semver';
|
||||
import fs from 'fs';
|
||||
import fspromises from 'fs/promises';
|
||||
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 {QualityOptions} from '../src/setup-dotnet';
|
||||
|
||||
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) {
|
||||
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', 'temp');
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
process.env = {...env};
|
||||
});
|
||||
|
||||
process.env['RUNNER_TOOL_CACHE'] = toolDir;
|
||||
process.env['RUNNER_TEMP'] = tempDir;
|
||||
describe('DotnetCoreInstaller tests', () => {
|
||||
const getExecOutputSpy = jest.spyOn(exec, 'getExecOutput');
|
||||
const warningSpy = jest.spyOn(core, 'warning');
|
||||
const whichSpy = jest.spyOn(io, 'which');
|
||||
const maxSatisfyingSpy = jest.spyOn(semver, 'maxSatisfying');
|
||||
const chmodSyncSpy = jest.spyOn(fs, 'chmodSync');
|
||||
const readdirSpy = jest.spyOn(fspromises, 'readdir');
|
||||
|
||||
describe('DotnetCoreInstaller tests', () => {
|
||||
beforeAll(async () => {
|
||||
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);
|
||||
describe('installDotnet() tests', () => {
|
||||
beforeAll(() => {
|
||||
whichSpy.mockImplementation(() => Promise.resolve('PathToShell'));
|
||||
chmodSyncSpy.mockImplementation(() => {});
|
||||
readdirSpy.mockImplementation(() => Promise.resolve([]));
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
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);
|
||||
afterAll(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
it('Aquires multiple versions of dotnet', async () => {
|
||||
const versions = ['2.2.207', '3.1.120'];
|
||||
it('should throw the error in case of non-zero exit code of the installation script. The error message should contain logs.', async () => {
|
||||
const inputVersion = '3.1.100';
|
||||
const inputQuality = '' as QualityOptions;
|
||||
const errorMessage = 'fictitious error message!';
|
||||
|
||||
for (const version of versions) {
|
||||
await getDotnet(version);
|
||||
}
|
||||
expect(fs.existsSync(path.join(toolDir, 'sdk', '2.2.207'))).toBe(true);
|
||||
expect(fs.existsSync(path.join(toolDir, 'sdk', '3.1.120'))).toBe(true);
|
||||
getExecOutputSpy.mockImplementation(() => {
|
||||
return Promise.resolve({
|
||||
exitCode: 1,
|
||||
stdout: '',
|
||||
stderr: errorMessage
|
||||
});
|
||||
});
|
||||
|
||||
if (IS_WINDOWS) {
|
||||
expect(fs.existsSync(path.join(toolDir, 'dotnet.exe'))).toBe(true);
|
||||
} else {
|
||||
expect(fs.existsSync(path.join(toolDir, 'dotnet'))).toBe(true);
|
||||
}
|
||||
const dotnetInstaller = new installer.DotnetCoreInstaller(
|
||||
inputVersion,
|
||||
inputQuality
|
||||
);
|
||||
await expect(dotnetInstaller.installDotnet()).rejects.toThrow(
|
||||
`Failed to install dotnet, exit code: 1. ${errorMessage}`
|
||||
);
|
||||
});
|
||||
|
||||
expect(process.env.DOTNET_ROOT).toBeDefined;
|
||||
expect(process.env.PATH).toBeDefined;
|
||||
expect(process.env.DOTNET_ROOT).toBe(toolDir);
|
||||
expect(process.env.PATH?.startsWith(toolDir)).toBe(true);
|
||||
}, 600000);
|
||||
it('should return version of .NET SDK after installation complete', async () => {
|
||||
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);
|
||||
|
||||
it('Acquires version of dotnet if no matching version is installed', async () => {
|
||||
await getDotnet('3.1.201');
|
||||
expect(fs.existsSync(path.join(toolDir, 'sdk', '3.1.201'))).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);
|
||||
}
|
||||
const dotnetInstaller = new installer.DotnetCoreInstaller(
|
||||
inputVersion,
|
||||
inputQuality
|
||||
);
|
||||
const installedVersion = await dotnetInstaller.installDotnet();
|
||||
|
||||
expect(process.env.DOTNET_ROOT).toBeDefined;
|
||||
expect(process.env.PATH).toBeDefined;
|
||||
expect(process.env.DOTNET_ROOT).toBe(toolDir);
|
||||
expect(process.env.PATH?.startsWith(toolDir)).toBe(true);
|
||||
}, 600000); //This needs some time to download on "slower" internet connections
|
||||
expect(installedVersion).toBe(inputVersion);
|
||||
});
|
||||
|
||||
it('Acquires generic version of dotnet if no matching version is installed', async () => {
|
||||
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);
|
||||
}
|
||||
it(`should supply 'version' argument to the installation script if supplied version is in A.B.C syntax`, async () => {
|
||||
const inputVersion = '6.0.300';
|
||||
const inputQuality = '' as QualityOptions;
|
||||
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
||||
|
||||
expect(process.env.DOTNET_ROOT).toBeDefined;
|
||||
expect(process.env.PATH).toBeDefined;
|
||||
expect(process.env.DOTNET_ROOT).toBe(toolDir);
|
||||
expect(process.env.PATH?.startsWith(toolDir)).toBe(true);
|
||||
}, 600000); //This needs some time to download on "slower" internet connections
|
||||
getExecOutputSpy.mockImplementation(() => {
|
||||
return Promise.resolve({
|
||||
exitCode: 0,
|
||||
stdout: `${stdout}`,
|
||||
stderr: ''
|
||||
});
|
||||
});
|
||||
maxSatisfyingSpy.mockImplementation(() => inputVersion);
|
||||
|
||||
it('Returns string with installed SDK version', async () => {
|
||||
const version = '3.1.120';
|
||||
let installedVersion: string;
|
||||
const dotnetInstaller = new installer.DotnetCoreInstaller(
|
||||
inputVersion,
|
||||
inputQuality
|
||||
);
|
||||
|
||||
installedVersion = await getDotnet(version);
|
||||
await dotnetInstaller.installDotnet();
|
||||
|
||||
expect(installedVersion).toBe('3.1.120');
|
||||
}, 600000);
|
||||
/**
|
||||
* First time script would be called to
|
||||
* install runtime, here we checking only the
|
||||
* second one that installs actual SDK. i.e. 1
|
||||
*/
|
||||
const callIndex = 1;
|
||||
|
||||
it('Throws if no location contains correct dotnet version', async () => {
|
||||
await expect(async () => {
|
||||
await getDotnet('1000.0.0');
|
||||
}).rejects.toThrow();
|
||||
}, 30000);
|
||||
const scriptArguments = (
|
||||
getExecOutputSpy.mock.calls[callIndex][1] as string[]
|
||||
).join(' ');
|
||||
const expectedArgument = IS_WINDOWS
|
||||
? `-Version ${inputVersion}`
|
||||
: `--version ${inputVersion}`;
|
||||
|
||||
it('Uses an up to date bash download script', async () => {
|
||||
const httpCallbackClient = new hc.HttpClient('setup-dotnet-test', [], {
|
||||
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);
|
||||
expect(scriptArguments).toContain(expectedArgument);
|
||||
});
|
||||
|
||||
it('Uses an up to date powershell download script', async () => {
|
||||
var httpCallbackClient = new hc.HttpClient('setup-dotnet-test', [], {
|
||||
allowRetries: true,
|
||||
maxRetries: 3
|
||||
});
|
||||
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);
|
||||
});
|
||||
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);
|
||||
|
||||
describe('DotnetVersionResolver tests', () => {
|
||||
each([
|
||||
'3.1',
|
||||
'3.x',
|
||||
'3.1.x',
|
||||
'3.1.*',
|
||||
'3.1.X',
|
||||
'3.1.2',
|
||||
'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();
|
||||
const dotnetInstaller = new installer.DotnetCoreInstaller(
|
||||
inputVersion,
|
||||
inputQuality
|
||||
);
|
||||
|
||||
expect(!!versionObject.value).toBeTruthy;
|
||||
}
|
||||
);
|
||||
await dotnetInstaller.installDotnet();
|
||||
|
||||
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: '%s' is supplied, it should throw",
|
||||
async version => {
|
||||
const dotnetVersionResolver = new installer.DotnetVersionResolver(
|
||||
version
|
||||
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.`
|
||||
);
|
||||
});
|
||||
|
||||
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 () => {
|
||||
const inputVersion = '3.1';
|
||||
const inputQuality = 'ga' as QualityOptions;
|
||||
const stdout = `Fictitious dotnet version 3.1.100 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();
|
||||
|
||||
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`,
|
||||
async inputVersion => {
|
||||
const inputQuality = 'ga' 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);
|
||||
|
||||
const dotnetInstaller = new installer.DotnetCoreInstaller(
|
||||
inputVersion,
|
||||
inputQuality
|
||||
);
|
||||
|
||||
await dotnetInstaller.installDotnet();
|
||||
|
||||
/**
|
||||
* First time script would be called to
|
||||
* install runtime, here we checking only the
|
||||
* second one that installs actual SDK. i.e. 1
|
||||
*/
|
||||
const callIndex = 1;
|
||||
|
||||
const scriptArguments = (
|
||||
getExecOutputSpy.mock.calls[callIndex][1] as string[]
|
||||
).join(' ');
|
||||
const expectedArgument = IS_WINDOWS
|
||||
? `-Quality ${inputQuality}`
|
||||
: `--quality ${inputQuality}`;
|
||||
|
||||
expect(scriptArguments).toContain(expectedArgument);
|
||||
}
|
||||
);
|
||||
|
||||
await expect(
|
||||
async () => await dotnetVersionResolver.createDotNetVersion()
|
||||
).rejects.toThrow();
|
||||
}
|
||||
);
|
||||
each(['6', '6.0', '6.0.x', '6.0.*', '6.0.X']).test(
|
||||
`should supply 'channel' argument to the installation script if version (%s) isn't in A.B.C syntax`,
|
||||
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(
|
||||
"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",
|
||||
async version => {
|
||||
const dotnetVersionResolver = new installer.DotnetVersionResolver(
|
||||
version
|
||||
const dotnetInstaller = new installer.DotnetCoreInstaller(
|
||||
inputVersion,
|
||||
inputQuality
|
||||
);
|
||||
|
||||
await dotnetInstaller.installDotnet();
|
||||
|
||||
/**
|
||||
* First time script would be called to
|
||||
* install runtime, here we checking only the
|
||||
* second one that installs actual SDK. i.e. 1
|
||||
*/
|
||||
const callIndex = 1;
|
||||
|
||||
const scriptArguments = (
|
||||
getExecOutputSpy.mock.calls[callIndex][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) {
|
||||
expect(windowsRegEx.test(versionObject.type)).toBeTruthy;
|
||||
expect(nonWindowsRegEx.test(versionObject.type)).toBeFalsy;
|
||||
} else {
|
||||
expect(nonWindowsRegEx.test(versionObject.type)).toBeTruthy;
|
||||
expect(windowsRegEx.test(versionObject.type)).toBeFalsy;
|
||||
it(`should supply '-ProxyAddress' argument to the installation script if env.variable 'https_proxy' is set`, async () => {
|
||||
process.env['https_proxy'] = 'https://proxy.com';
|
||||
const inputVersion = '6.0.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);
|
||||
|
||||
const dotnetInstaller = new installer.DotnetCoreInstaller(
|
||||
inputVersion,
|
||||
inputQuality
|
||||
);
|
||||
|
||||
await dotnetInstaller.installDotnet();
|
||||
|
||||
/**
|
||||
* First time script would be called to
|
||||
* install runtime, here we checking only the
|
||||
* second one that installs actual SDK. i.e. 1
|
||||
*/
|
||||
const callIndex = 1;
|
||||
|
||||
const scriptArguments = (
|
||||
getExecOutputSpy.mock.calls[callIndex][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();
|
||||
|
||||
/**
|
||||
* First time script would be called to
|
||||
* install runtime, here we checking only the
|
||||
* second one that installs actual SDK. i.e. 1
|
||||
*/
|
||||
const callIndex = 1;
|
||||
|
||||
const scriptArguments = (
|
||||
getExecOutputSpy.mock.calls[callIndex][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.DotnetInstallDir.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.DotnetInstallDir.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,225 @@
|
|||
import * as io from '@actions/io';
|
||||
import * as core from '@actions/core';
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import semver from 'semver';
|
||||
import * as auth from '../src/authutil';
|
||||
|
||||
import * as setup from '../src/setup-dotnet';
|
||||
import {IS_WINDOWS} from '../src/utils';
|
||||
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');
|
||||
import {DotnetCoreInstaller, DotnetInstallDir} from '../src/installer';
|
||||
import * as cacheUtils from '../src/cache-utils';
|
||||
import * as cacheRestore from '../src/cache-restore';
|
||||
|
||||
describe('setup-dotnet tests', () => {
|
||||
let getInputSpy = jest.spyOn(core, 'getInput');
|
||||
let getMultilineInputSpy = jest.spyOn(core, 'getMultilineInput');
|
||||
let setOutputSpy = jest.spyOn(core, 'setOutput');
|
||||
const inputs = {} as any;
|
||||
|
||||
let inputs = {} as any;
|
||||
const getInputSpy = jest.spyOn(core, 'getInput');
|
||||
const getMultilineInputSpy = jest.spyOn(core, 'getMultilineInput');
|
||||
const getBooleanInputSpy = jest.spyOn(core, 'getBooleanInput');
|
||||
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 () => {
|
||||
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);
|
||||
const existsSyncSpy = jest.spyOn(fs, 'existsSync');
|
||||
|
||||
afterEach(async () => {
|
||||
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);
|
||||
const maxSatisfyingSpy = jest.spyOn(semver, 'maxSatisfying');
|
||||
|
||||
it('Acquires version of dotnet from global.json if no matching version is installed', async () => {
|
||||
const globalJsonPath = path.join(process.cwd(), 'global.json');
|
||||
const jsonContents = `{${os.EOL}"sdk": {${os.EOL}"version": "3.1.201"${os.EOL}}${os.EOL}}`;
|
||||
if (!fs.existsSync(globalJsonPath)) {
|
||||
fs.writeFileSync(globalJsonPath, jsonContents);
|
||||
}
|
||||
await setup.run();
|
||||
const installDotnetSpy = jest.spyOn(
|
||||
DotnetCoreInstaller.prototype,
|
||||
'installDotnet'
|
||||
);
|
||||
|
||||
expect(fs.existsSync(path.join(toolDir, 'sdk', '3.1.201'))).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);
|
||||
}
|
||||
}, 400000);
|
||||
const isCacheFeatureAvailableSpy = jest.spyOn(
|
||||
cacheUtils,
|
||||
'isCacheFeatureAvailable'
|
||||
);
|
||||
const restoreCacheSpy = jest.spyOn(cacheRestore, 'restoreCache');
|
||||
const configAuthenticationSpy = jest.spyOn(auth, 'configAuthentication');
|
||||
const addToPathOriginal = DotnetInstallDir.addToPath;
|
||||
|
||||
it("Sets output with the latest installed by action version if global.json file isn't specified", async () => {
|
||||
inputs['dotnet-version'] = ['3.1.201', '6.0.401'];
|
||||
describe('run() tests', () => {
|
||||
beforeEach(() => {
|
||||
DotnetInstallDir.addToPath = jest.fn();
|
||||
getMultilineInputSpy.mockImplementation(input => inputs[input as string]);
|
||||
getInputSpy.mockImplementation(input => inputs[input as string]);
|
||||
getBooleanInputSpy.mockImplementation(input => inputs[input as string]);
|
||||
});
|
||||
|
||||
getMultilineInputSpy.mockImplementation(input => inputs[input]);
|
||||
afterEach(() => {
|
||||
DotnetInstallDir.addToPath = addToPathOriginal;
|
||||
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');
|
||||
}, 400000);
|
||||
const expectedErrorMessage = `The specified global.json file '${inputs['global-json-file']}' does not exist`;
|
||||
|
||||
it("Sets output with the version specified in global.json, if it's present", async () => {
|
||||
const globalJsonPath = path.join(process.cwd(), 'global.json');
|
||||
const jsonContents = `{${os.EOL}"sdk": {${os.EOL}"version": "3.0.103"${os.EOL}}${os.EOL}}`;
|
||||
if (!fs.existsSync(globalJsonPath)) {
|
||||
fs.writeFileSync(globalJsonPath, jsonContents);
|
||||
}
|
||||
await setup.run();
|
||||
expect(setFailedSpy).toHaveBeenCalledWith(expectedErrorMessage);
|
||||
});
|
||||
|
||||
inputs['dotnet-version'] = ['3.1.201', '6.0.401'];
|
||||
inputs['global-json-file'] = './global.json';
|
||||
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'] = '';
|
||||
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');
|
||||
}, 400000);
|
||||
expect(debugSpy).toHaveBeenCalledWith(expectedDebugMessage);
|
||||
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(''));
|
||||
|
||||
await setup.run();
|
||||
expect(DotnetInstallDir.addToPath).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']}`)
|
||||
);
|
||||
|
||||
await setup.run();
|
||||
expect(DotnetInstallDir.addToPath).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));
|
||||
|
||||
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.`;
|
||||
|
||||
await setup.run();
|
||||
|
||||
expect(infoSpy).toHaveBeenCalledWith(warningMessage);
|
||||
expect(setOutputSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it(`should get 'cache-dependency-path' and call restoreCache() if input cache is set to true and cache feature is available`, async () => {
|
||||
inputs['dotnet-version'] = ['6.0.300'];
|
||||
inputs['dotnet-quality'] = '';
|
||||
inputs['cache'] = true;
|
||||
inputs['cache-dependency-path'] = 'fictitious.package.lock.json';
|
||||
|
||||
installDotnetSpy.mockImplementation(() => Promise.resolve(''));
|
||||
|
||||
isCacheFeatureAvailableSpy.mockImplementation(() => true);
|
||||
restoreCacheSpy.mockImplementation(() => Promise.resolve());
|
||||
|
||||
await setup.run();
|
||||
expect(isCacheFeatureAvailableSpy).toHaveBeenCalledTimes(1);
|
||||
expect(restoreCacheSpy).toHaveBeenCalledWith(
|
||||
inputs['cache-dependency-path']
|
||||
);
|
||||
});
|
||||
|
||||
it(`shouldn't call restoreCache() if input cache isn't set to true`, async () => {
|
||||
inputs['dotnet-version'] = ['6.0.300'];
|
||||
inputs['dotnet-quality'] = '';
|
||||
inputs['cache'] = false;
|
||||
|
||||
installDotnetSpy.mockImplementation(() => Promise.resolve(''));
|
||||
|
||||
isCacheFeatureAvailableSpy.mockImplementation(() => true);
|
||||
restoreCacheSpy.mockImplementation(() => Promise.resolve());
|
||||
|
||||
await setup.run();
|
||||
expect(restoreCacheSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it(`shouldn't call restoreCache() if cache feature isn't available`, async () => {
|
||||
inputs['dotnet-version'] = ['6.0.300'];
|
||||
inputs['dotnet-quality'] = '';
|
||||
inputs['cache'] = true;
|
||||
|
||||
installDotnetSpy.mockImplementation(() => Promise.resolve(''));
|
||||
|
||||
isCacheFeatureAvailableSpy.mockImplementation(() => false);
|
||||
restoreCacheSpy.mockImplementation(() => Promise.resolve());
|
||||
|
||||
await setup.run();
|
||||
expect(restoreCacheSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,73 +1,117 @@
|
|||
if (!$args[0])
|
||||
{
|
||||
throw "Must supply dotnet version argument"
|
||||
<#
|
||||
.DESCRIPTION
|
||||
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 }
|
||||
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() }
|
||||
Write-Host "Version $version"
|
||||
if (-not ($version.StartsWith($args[0].ToString())))
|
||||
foreach($pattern in $PatternsList)
|
||||
{
|
||||
Write-Host "PATH='$env:PATH'"
|
||||
throw "Unexpected version"
|
||||
}
|
||||
}
|
||||
|
||||
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 ($version -match $pattern)
|
||||
{
|
||||
$PatternsList.Remove($pattern)
|
||||
$InstalledVersionCount--
|
||||
break
|
||||
}
|
||||
}
|
||||
if ( $InstalledVersionCount -ne $args.Count)
|
||||
{
|
||||
Write-Host "PATH='$env:PATH'"
|
||||
throw "Unexpected version"
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Building sample csproj"
|
||||
& $dotnet build __tests__/sample-csproj/ --no-cache
|
||||
if ($LASTEXITCODE -ne 0)
|
||||
if ( $InstalledVersionCount -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"
|
||||
$sample_output = "$(dotnet test __tests__/sample-csproj/ --no-build)"
|
||||
Write-Host "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 ($args[1])
|
||||
$workingDir = Get-Location
|
||||
$testProjectDir = "./__tests__/e2e-test-csproj"
|
||||
Write-Host "Changing directory to the $testProjectDir"
|
||||
Set-Location $testProjectDir
|
||||
|
||||
$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"
|
||||
}
|
||||
}
|
||||
if ($args[2])
|
||||
{
|
||||
if ($sample_output -notlike "*Test Run Successful.*Test Run Successful.*Test Run Successful.*")
|
||||
Write-Host "The global.json file for the version $version is created. Currently used .NET version is: $(& $dotnet --version)."
|
||||
|
||||
# Environment variable TEST_TARGET_FRAMEWORK is used inside the test.csproj file to target required framework version
|
||||
$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."
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($sample_output -notlike "*Test Run Successful.*")
|
||||
Write-Host "Setting the TEST_TARGET_FRAMEWORK environment variable to $($targetFrameworkVersionMap[$Matches.key])"
|
||||
[Environment]::SetEnvironmentVariable('TEST_TARGET_FRAMEWORK', $($targetFrameworkVersionMap[$Matches.key]))
|
||||
|
||||
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
|
15
action.yml
15
action.yml
|
@ -6,7 +6,7 @@ branding:
|
|||
color: green
|
||||
inputs:
|
||||
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:
|
||||
description: 'Optional quality of the build. The possible values are: daily, signed, validated, preview, ga.'
|
||||
global-json-file:
|
||||
|
@ -17,9 +17,20 @@ inputs:
|
|||
description: 'Optional OWNER for using packages from GitHub Package Registry organizations/users other than the current repository''s owner. Only used if a GPR URL is also provided in source-url'
|
||||
config-file:
|
||||
description: 'Optional NuGet.config location, if your NuGet.config isn''t located in the root of the repo.'
|
||||
cache:
|
||||
description: 'Optional input to enable caching of the NuGet global-packages folder'
|
||||
required: false
|
||||
default: false
|
||||
cache-dependency-path:
|
||||
description: 'Used to specify the path to a dependency file: packages.lock.json. Supports wildcards or a list of file names for caching multiple dependencies.'
|
||||
required: false
|
||||
outputs:
|
||||
cache-hit:
|
||||
description: 'A boolean value to indicate if a cache was hit.'
|
||||
dotnet-version:
|
||||
description: 'Contains the installed by action .NET SDK version for reuse.'
|
||||
runs:
|
||||
using: 'node16'
|
||||
main: 'dist/index.js'
|
||||
main: 'dist/setup/index.js'
|
||||
post: 'dist/cache-save/index.js'
|
||||
post-if: success()
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -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 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
|
||||
|
||||
**Learn more about how to implement tests:**
|
||||
|
||||
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
|
||||
- Tests should cover a successful execution, as well as some edge cases and possible errors
|
||||
|
|
|
@ -9,6 +9,12 @@
|
|||
.DESCRIPTION
|
||||
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.
|
||||
|
||||
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
|
||||
Default: LTS
|
||||
Download from the Channel specified. Possible values:
|
||||
|
@ -164,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) {
|
||||
$command = $Invocation.MyCommand;
|
||||
$args = (($Invocation.BoundParameters.Keys | foreach { "-$_ `"$($Invocation.BoundParameters[$_])`"" }) -join " ")
|
||||
|
@ -1104,10 +1116,10 @@ function Prepare-Install-Directory {
|
|||
}
|
||||
}
|
||||
|
||||
Say "Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:"
|
||||
Say "- The SDK needs to be installed without user interaction and without admin rights."
|
||||
Say "- The SDK installation doesn't need to persist across multiple CI runs."
|
||||
Say "To set up a development environment or to run apps, use installers rather than this script. Visit https://dotnet.microsoft.com/download to get the installer.`r`n"
|
||||
Say-Verbose "Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:"
|
||||
Say-Verbose "- The SDK needs to be installed without user interaction and without admin rights."
|
||||
Say-Verbose "- The SDK installation doesn't need to persist across multiple CI runs."
|
||||
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)) {
|
||||
$Runtime = "dotnet"
|
||||
|
@ -1115,14 +1127,16 @@ if ($SharedRuntime -and (-not $Runtime)) {
|
|||
|
||||
$OverrideNonVersionedFiles = !$SkipNonVersionedFiles
|
||||
|
||||
$CLIArchitecture = Get-CLIArchitecture-From-Architecture $Architecture
|
||||
$NormalizedQuality = Get-NormalizedQuality $Quality
|
||||
Say-Verbose "Normalized quality: '$NormalizedQuality'"
|
||||
$NormalizedChannel = Get-NormalizedChannel $Channel
|
||||
Say-Verbose "Normalized channel: '$NormalizedChannel'"
|
||||
$NormalizedProduct = Get-NormalizedProduct $Runtime
|
||||
Say-Verbose "Normalized product: '$NormalizedProduct'"
|
||||
$FeedCredential = ValidateFeedCredential $FeedCredential
|
||||
Measure-Action "Product discovery" {
|
||||
$script:CLIArchitecture = Get-CLIArchitecture-From-Architecture $Architecture
|
||||
$script:NormalizedQuality = Get-NormalizedQuality $Quality
|
||||
Say-Verbose "Normalized quality: '$NormalizedQuality'"
|
||||
$script:NormalizedChannel = Get-NormalizedChannel $Channel
|
||||
Say-Verbose "Normalized channel: '$NormalizedChannel'"
|
||||
$script:NormalizedProduct = Get-NormalizedProduct $Runtime
|
||||
Say-Verbose "Normalized product: '$NormalizedProduct'"
|
||||
$script:FeedCredential = ValidateFeedCredential $FeedCredential
|
||||
}
|
||||
|
||||
$InstallRoot = Resolve-Installation-Path $InstallDir
|
||||
Say-Verbose "InstallRoot: $InstallRoot"
|
||||
|
@ -1200,7 +1214,7 @@ if ($DryRun) {
|
|||
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())
|
||||
Say-Verbose "Zip path: $ZipPath"
|
||||
|
@ -1214,7 +1228,7 @@ foreach ($link in $DownloadLinks)
|
|||
Say-Verbose "Downloading `"$($link.type)`" link $($link.downloadLink)"
|
||||
|
||||
try {
|
||||
DownloadFile -Source $link.downloadLink -OutPath $ZipPath
|
||||
Measure-Action "Package download" { DownloadFile -Source $link.downloadLink -OutPath $ZipPath }
|
||||
Say-Verbose "Download succeeded."
|
||||
$DownloadSucceeded = $true
|
||||
$DownloadedLink = $link
|
||||
|
@ -1251,7 +1265,7 @@ if (-not $DownloadSucceeded) {
|
|||
}
|
||||
|
||||
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.
|
||||
$isAssetInstalled = $false
|
||||
|
@ -1277,225 +1291,224 @@ if (!$isAssetInstalled) {
|
|||
|
||||
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 "To check the list of dependencies, go to https://learn.microsoft.com/dotnet/core/install/windows#dependencies"
|
||||
Say "Installed version is $($DownloadedLink.effectiveVersion)"
|
||||
Say "Installation finished"
|
||||
|
||||
# SIG # Begin signature block
|
||||
# MIInzgYJKoZIhvcNAQcCoIInvzCCJ7sCAQExDzANBglghkgBZQMEAgEFADB5Bgor
|
||||
# MIInvwYJKoZIhvcNAQcCoIInsDCCJ6wCAQExDzANBglghkgBZQMEAgEFADB5Bgor
|
||||
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
|
||||
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCB7pzZ0nuEMd30h
|
||||
# n1EcAYUQN+1clltqaLf9611TDrw/laCCDYUwggYDMIID66ADAgECAhMzAAACzfNk
|
||||
# v/jUTF1RAAAAAALNMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
|
||||
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBhfTi3SRn7+vyy
|
||||
# uCXKPjhiawegWZ493EcaOEycbgkZcKCCDXYwggX0MIID3KADAgECAhMzAAACy7d1
|
||||
# OfsCcUI2AAAAAALLMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
|
||||
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
|
||||
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
|
||||
# bmcgUENBIDIwMTEwHhcNMjIwNTEyMjA0NjAyWhcNMjMwNTExMjA0NjAyWjB0MQsw
|
||||
# bmcgUENBIDIwMTEwHhcNMjIwNTEyMjA0NTU5WhcNMjMwNTExMjA0NTU5WjB0MQsw
|
||||
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
|
||||
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
|
||||
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
|
||||
# AQDrIzsY62MmKrzergm7Ucnu+DuSHdgzRZVCIGi9CalFrhwtiK+3FIDzlOYbs/zz
|
||||
# HwuLC3hir55wVgHoaC4liQwQ60wVyR17EZPa4BQ28C5ARlxqftdp3H8RrXWbVyvQ
|
||||
# aUnBQVZM73XDyGV1oUPZGHGWtgdqtBUd60VjnFPICSf8pnFiit6hvSxH5IVWI0iO
|
||||
# nfqdXYoPWUtVUMmVqW1yBX0NtbQlSHIU6hlPvo9/uqKvkjFUFA2LbC9AWQbJmH+1
|
||||
# uM0l4nDSKfCqccvdI5l3zjEk9yUSUmh1IQhDFn+5SL2JmnCF0jZEZ4f5HE7ykDP+
|
||||
# oiA3Q+fhKCseg+0aEHi+DRPZAgMBAAGjggGCMIIBfjAfBgNVHSUEGDAWBgorBgEE
|
||||
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQU0WymH4CP7s1+yQktEwbcLQuR9Zww
|
||||
# VAYDVR0RBE0wS6RJMEcxLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh
|
||||
# dGlvbnMgTGltaXRlZDEWMBQGA1UEBRMNMjMwMDEyKzQ3MDUzMDAfBgNVHSMEGDAW
|
||||
# gBRIbmTlUAXTgqoXNzcitW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8v
|
||||
# d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIw
|
||||
# MTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDov
|
||||
# L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDEx
|
||||
# XzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIB
|
||||
# AE7LSuuNObCBWYuttxJAgilXJ92GpyV/fTiyXHZ/9LbzXs/MfKnPwRydlmA2ak0r
|
||||
# GWLDFh89zAWHFI8t9JLwpd/VRoVE3+WyzTIskdbBnHbf1yjo/+0tpHlnroFJdcDS
|
||||
# MIsH+T7z3ClY+6WnjSTetpg1Y/pLOLXZpZjYeXQiFwo9G5lzUcSd8YVQNPQAGICl
|
||||
# 2JRSaCNlzAdIFCF5PNKoXbJtEqDcPZ8oDrM9KdO7TqUE5VqeBe6DggY1sZYnQD+/
|
||||
# LWlz5D0wCriNgGQ/TWWexMwwnEqlIwfkIcNFxo0QND/6Ya9DTAUykk2SKGSPt0kL
|
||||
# tHxNEn2GJvcNtfohVY/b0tuyF05eXE3cdtYZbeGoU1xQixPZAlTdtLmeFNly82uB
|
||||
# VbybAZ4Ut18F//UrugVQ9UUdK1uYmc+2SdRQQCccKwXGOuYgZ1ULW2u5PyfWxzo4
|
||||
# BR++53OB/tZXQpz4OkgBZeqs9YaYLFfKRlQHVtmQghFHzB5v/WFonxDVlvPxy2go
|
||||
# a0u9Z+ZlIpvooZRvm6OtXxdAjMBcWBAsnBRr/Oj5s356EDdf2l/sLwLFYE61t+ME
|
||||
# iNYdy0pXL6gN3DxTVf2qjJxXFkFfjjTisndudHsguEMk8mEtnvwo9fOSKT6oRHhM
|
||||
# 9sZ4HTg/TTMjUljmN3mBYWAWI5ExdC1inuog0xrKmOWVMIIHejCCBWKgAwIBAgIK
|
||||
# YQ6Q0gAAAAAAAzANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV
|
||||
# AQC3sN0WcdGpGXPZIb5iNfFB0xZ8rnJvYnxD6Uf2BHXglpbTEfoe+mO//oLWkRxA
|
||||
# wppditsSVOD0oglKbtnh9Wp2DARLcxbGaW4YanOWSB1LyLRpHnnQ5POlh2U5trg4
|
||||
# 3gQjvlNZlQB3lL+zrPtbNvMA7E0Wkmo+Z6YFnsf7aek+KGzaGboAeFO4uKZjQXY5
|
||||
# RmMzE70Bwaz7hvA05jDURdRKH0i/1yK96TDuP7JyRFLOvA3UXNWz00R9w7ppMDcN
|
||||
# lXtrmbPigv3xE9FfpfmJRtiOZQKd73K72Wujmj6/Su3+DBTpOq7NgdntW2lJfX3X
|
||||
# a6oe4F9Pk9xRhkwHsk7Ju9E/AgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE
|
||||
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUrg/nt/gj+BBLd1jZWYhok7v5/w4w
|
||||
# RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW
|
||||
# MBQGA1UEBRMNMjMwMDEyKzQ3MDUyODAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci
|
||||
# tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j
|
||||
# b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG
|
||||
# CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu
|
||||
# Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0
|
||||
# MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBAJL5t6pVjIRlQ8j4dAFJ
|
||||
# ZnMke3rRHeQDOPFxswM47HRvgQa2E1jea2aYiMk1WmdqWnYw1bal4IzRlSVf4czf
|
||||
# zx2vjOIOiaGllW2ByHkfKApngOzJmAQ8F15xSHPRvNMmvpC3PFLvKMf3y5SyPJxh
|
||||
# 922TTq0q5epJv1SgZDWlUlHL/Ex1nX8kzBRhHvc6D6F5la+oAO4A3o/ZC05OOgm4
|
||||
# EJxZP9MqUi5iid2dw4Jg/HvtDpCcLj1GLIhCDaebKegajCJlMhhxnDXrGFLJfX8j
|
||||
# 7k7LUvrZDsQniJZ3D66K+3SZTLhvwK7dMGVFuUUJUfDifrlCTjKG9mxsPDllfyck
|
||||
# 4zGnRZv8Jw9RgE1zAghnU14L0vVUNOzi/4bE7wIsiRyIcCcVoXRneBA3n/frLXvd
|
||||
# jDsbb2lpGu78+s1zbO5N0bhHWq4j5WMutrspBxEhqG2PSBjC5Ypi+jhtfu3+x76N
|
||||
# mBvsyKuxx9+Hm/ALnlzKxr4KyMR3/z4IRMzA1QyppNk65Ui+jB14g+w4vole33M1
|
||||
# pVqVckrmSebUkmjnCshCiH12IFgHZF7gRwE4YZrJ7QjxZeoZqHaKsQLRMp653beB
|
||||
# fHfeva9zJPhBSdVcCW7x9q0c2HVPLJHX9YCUU714I+qtLpDGrdbZxD9mikPqL/To
|
||||
# /1lDZ0ch8FtePhME7houuoPcMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq
|
||||
# hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x
|
||||
# EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv
|
||||
# bjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5
|
||||
# IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEwOTA5WjB+MQswCQYDVQQG
|
||||
# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG
|
||||
# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQg
|
||||
# Q29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
|
||||
# CgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+laUKq4BjgaBEm6f8MMHt03
|
||||
# a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc6Whe0t+bU7IKLMOv2akr
|
||||
# rnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4Ddato88tt8zpcoRb0Rrrg
|
||||
# OGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+lD3v++MrWhAfTVYoonpy
|
||||
# 4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nkkDstrjNYxbc+/jLTswM9
|
||||
# sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6A4aN91/w0FK/jJSHvMAh
|
||||
# dCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmdX4jiJV3TIUs+UsS1Vz8k
|
||||
# A/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL5zmhD+kjSbwYuER8ReTB
|
||||
# w3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zdsGbiwZeBe+3W7UvnSSmn
|
||||
# Eyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3T8HhhUSJxAlMxdSlQy90
|
||||
# lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS4NaIjAsCAwEAAaOCAe0w
|
||||
# ggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRIbmTlUAXTgqoXNzcitW2o
|
||||
# ynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYD
|
||||
# VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBDuRQFTuHqp8cx0SOJNDBa
|
||||
# BgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny
|
||||
# bC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3JsMF4GCCsG
|
||||
# AQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3dy5taWNyb3NvZnQuY29t
|
||||
# L3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3J0MIGfBgNV
|
||||
# HSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEFBQcCARYzaHR0cDovL3d3
|
||||
# dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1hcnljcHMuaHRtMEAGCCsG
|
||||
# AQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkAYwB5AF8AcwB0AGEAdABl
|
||||
# AG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn8oalmOBUeRou09h0ZyKb
|
||||
# C5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7v0epo/Np22O/IjWll11l
|
||||
# hJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0bpdS1HXeUOeLpZMlEPXh6
|
||||
# I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/KmtYSWMfCWluWpiW5IP0
|
||||
# wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvyCInWH8MyGOLwxS3OW560
|
||||
# STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBpmLJZiWhub6e3dMNABQam
|
||||
# ASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJihsMdYzaXht/a8/jyFqGa
|
||||
# J+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYbBL7fQccOKO7eZS/sl/ah
|
||||
# XJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbSoqKfenoi+kiVH6v7RyOA
|
||||
# 9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sLgOppO6/8MO0ETI7f33Vt
|
||||
# Y5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtXcVZOSEXAQsmbdlsKgEhr
|
||||
# /Xmfwb1tbWrJUnMTDXpQzTGCGZ8wghmbAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw
|
||||
# EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN
|
||||
# aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp
|
||||
# Z25pbmcgUENBIDIwMTECEzMAAALLt3U5+wJxQjYAAAAAAsswDQYJYIZIAWUDBAIB
|
||||
# BQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO
|
||||
# MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIFmuaTXYQ37AFvsEol24fdW+
|
||||
# nRqHcc1fr+VQVdqhXc/vMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8A
|
||||
# cwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEB
|
||||
# BQAEggEAjY5XW5Ly7TJ1OTbeIR98xU+2dmtw7L71ws+ICnQCGhj2xJDUK+5yrTfO
|
||||
# 8C98l/P4ynFi33Dl8z2YElqUCuqEXbiCzz06lIL4NuibC5DV/X80ZmICR/NYd2v1
|
||||
# ww7IH+7dpsHAowBBindCYpVwQ3Ea3kDWgsjPAinAysFFushSOnNWFvrF6vi2smrs
|
||||
# smbrAAhEhSfLd1Pxxdw73hQ0YjM/D3F3opaybMQ0blpHhOaqtbiyYzvk0doIzBEc
|
||||
# trSH4NDIc3yLNj5VbjSczpexE+hyQNY4xCtwco4bVtXhONUihv08AIKR8+sIaI7A
|
||||
# mM/SWrrwGYSSSxydKqDei7biKG4jDqGCFykwghclBgorBgEEAYI3AwMBMYIXFTCC
|
||||
# FxEGCSqGSIb3DQEHAqCCFwIwghb+AgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFZBgsq
|
||||
# hkiG9w0BCRABBKCCAUgEggFEMIIBQAIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFl
|
||||
# AwQCAQUABCB6Hzt2gUb/WZK8fvVnOocriE4rYr6mscZi3gZnBCpiigIGZBr2iMZU
|
||||
# GBMyMDIzMDMzMTE1MjEwNi41MTZaMASAAgH0oIHYpIHVMIHSMQswCQYDVQQGEwJV
|
||||
# UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE
|
||||
# ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJl
|
||||
# bGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNO
|
||||
# OjA4NDItNEJFNi1DMjlBMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBT
|
||||
# ZXJ2aWNloIIReDCCBycwggUPoAMCAQICEzMAAAGybkADf26plJIAAQAAAbIwDQYJ
|
||||
# KoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x
|
||||
# EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv
|
||||
# bjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcNMjIw
|
||||
# OTIwMjAyMjAxWhcNMjMxMjE0MjAyMjAxWjCB0jELMAkGA1UEBhMCVVMxEzARBgNV
|
||||
# BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv
|
||||
# c29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlm
|
||||
# aWNhdGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEw
|
||||
# OTA5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE
|
||||
# BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYD
|
||||
# VQQDEx9NaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG
|
||||
# 9w0BAQEFAAOCAg8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+la
|
||||
# UKq4BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc
|
||||
# 6Whe0t+bU7IKLMOv2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4D
|
||||
# dato88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+
|
||||
# lD3v++MrWhAfTVYoonpy4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nk
|
||||
# kDstrjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6
|
||||
# A4aN91/w0FK/jJSHvMAhdCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmd
|
||||
# X4jiJV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL
|
||||
# 5zmhD+kjSbwYuER8ReTBw3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zd
|
||||
# sGbiwZeBe+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3
|
||||
# T8HhhUSJxAlMxdSlQy90lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS
|
||||
# 4NaIjAsCAwEAAaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRI
|
||||
# bmTlUAXTgqoXNzcitW2oynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAL
|
||||
# BgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBD
|
||||
# uRQFTuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jv
|
||||
# c29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf
|
||||
# MDNfMjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3
|
||||
# dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf
|
||||
# MDNfMjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEF
|
||||
# BQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1h
|
||||
# cnljcHMuaHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkA
|
||||
# YwB5AF8AcwB0AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn
|
||||
# 8oalmOBUeRou09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7
|
||||
# v0epo/Np22O/IjWll11lhJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0b
|
||||
# pdS1HXeUOeLpZMlEPXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/
|
||||
# KmtYSWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvy
|
||||
# CInWH8MyGOLwxS3OW560STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBp
|
||||
# mLJZiWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJi
|
||||
# hsMdYzaXht/a8/jyFqGaJ+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYb
|
||||
# BL7fQccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbS
|
||||
# oqKfenoi+kiVH6v7RyOA9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sL
|
||||
# gOppO6/8MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtX
|
||||
# cVZOSEXAQsmbdlsKgEhr/Xmfwb1tbWrJUnMTDXpQzTGCGZ8wghmbAgEBMIGVMH4x
|
||||
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
|
||||
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01p
|
||||
# Y3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTECEzMAAALN82S/+NRMXVEAAAAA
|
||||
# As0wDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQw
|
||||
# HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEINK7
|
||||
# cJe0KVfbcXchjID30U/cUg7pWAQUa3+n8JuhjLCLMEIGCisGAQQBgjcCAQwxNDAy
|
||||
# oBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5j
|
||||
# b20wDQYJKoZIhvcNAQEBBQAEggEAODLxcflOtjpIXXIhbYyQ0wFeBx0NrmoMU/Ri
|
||||
# e7CRrAieAbG4iLJzs4DhUov5iuMHY6AAbLWAH54QlSkd4XNp6POsE7lSzN9yjlVw
|
||||
# V/e0XCaYeXIbtd75hGd5P7wAhM4m2ViDI4IRHyQtjysW0U0F6YiqNlFm7Fzo5Si6
|
||||
# l2XxvuEDSdyJcEN70wHQajx6bKfnI/oMY59iGjDXvDP/6cQV9NI0gPHFTwPKA7vg
|
||||
# PySyVFEG7dQMoEwAWy9GHbcS//RulgUwBhWcrtUP411XLSO6is2VTknwbdglc9HZ
|
||||
# zViuS4C1ujHlPrlMzm8Y5iGVIQCna5w2NU/kGsSK5+dMkovomKGCFykwghclBgor
|
||||
# BgEEAYI3AwMBMYIXFTCCFxEGCSqGSIb3DQEHAqCCFwIwghb+AgEDMQ8wDQYJYIZI
|
||||
# AWUDBAIBBQAwggFZBgsqhkiG9w0BCRABBKCCAUgEggFEMIIBQAIBAQYKKwYBBAGE
|
||||
# WQoDATAxMA0GCWCGSAFlAwQCAQUABCDRz6ce9oWlH6+o0BtjmAjtvEMN1hfhIA5v
|
||||
# +wTZHvB4XgIGY2PeyIloGBMyMDIyMTExMDE1MDUxNi43MzRaMASAAgH0oIHYpIHV
|
||||
# MIHSMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
|
||||
# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQL
|
||||
# EyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJjAkBgNVBAsT
|
||||
# HVRoYWxlcyBUU1MgRVNOOkEyNDAtNEI4Mi0xMzBFMSUwIwYDVQQDExxNaWNyb3Nv
|
||||
# ZnQgVGltZS1TdGFtcCBTZXJ2aWNloIIReDCCBycwggUPoAMCAQICEzMAAAG4CNTB
|
||||
# uHngUUkAAQAAAbgwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNV
|
||||
# BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv
|
||||
# c29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAg
|
||||
# UENBIDIwMTAwHhcNMjIwOTIwMjAyMjE2WhcNMjMxMjE0MjAyMjE2WjCB0jELMAkG
|
||||
# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
|
||||
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9z
|
||||
# b2Z0IElyZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMg
|
||||
# VFNTIEVTTjpBMjQwLTRCODItMTMwRTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUt
|
||||
# U3RhbXAgU2VydmljZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJwb
|
||||
# sfwRHERn5C95QPGn37tJ5vOiY9aWjeIDxpgaXaYGiqsw0G0cvCK3YulrqemEf2Ck
|
||||
# GSdcOJAF++EqhOSqrO13nGcjqw6hFNnsGwKANyzddwnOO0jz1lfBIIu77TbfNvna
|
||||
# WbwSRu0DTGHA7n7PR0MYJ9bC/HopStpbFf606LKcTWnwaUuEdAhx6FAqg1rkgugi
|
||||
# uuaaxKyxRkdjFZLKFXEXL9p01PtwS0fG6vZiRVnEKgeal2TeLvdAIqapBwltPYif
|
||||
# gqnp7Z4VJMcPo0TWmRNVFOcHRNwWHehN9xg6ugIGXPo7hMpWrPgg4moHO2epc0T3
|
||||
# 6rgm9hlDrl28bG5TakmV7NJ98kbF5lgtlrowT6ecwEVtuLd4a0gzYqhanW7zaFZn
|
||||
# Dft5yMexy59ifETdzpwArj2nJAyIsiq1PY3XPm2mUMLlACksqelHKfWihK/Fehw/
|
||||
# mziovBVwkkr/G0F19OWgR+MBUKifwpOyQiLAxrqvVnfCY4QjJCZiHIuS15HCQ/TI
|
||||
# t/Qj4x1WvRa1UqjnmpLu4/yBYWZsdvZoq8SXI7iOs7muecAJeEkYlM6iOkMighzE
|
||||
# hjQK9ThPpoAtluXbL7qIHGrfFlHmX/4soc7jj1j8uB31U34gJlB2XphjMaT+E+O9
|
||||
# SImk/6GRV9Sm8C88Fnmm2VdwMluCNAUzPFjfvHx3AgMBAAGjggFJMIIBRTAdBgNV
|
||||
# HQ4EFgQUxP1HJTeFwzNYo1njfucXuUfQaW4wHwYDVR0jBBgwFoAUn6cVXQBeYl2D
|
||||
# 9OXSZacbUzUZ6XIwXwYDVR0fBFgwVjBUoFKgUIZOaHR0cDovL3d3dy5taWNyb3Nv
|
||||
# ZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUy
|
||||
# MDIwMTAoMSkuY3JsMGwGCCsGAQUFBwEBBGAwXjBcBggrBgEFBQcwAoZQaHR0cDov
|
||||
# L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBUaW1l
|
||||
# LVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcnQwDAYDVR0TAQH/BAIwADAWBgNVHSUB
|
||||
# Af8EDDAKBggrBgEFBQcDCDAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQAD
|
||||
# ggIBAJ9uk8miwpMoKw3D996piEzbegAGxkABHYn2vP2hbqnkS9U97s/6QlyZOhGF
|
||||
# sVudaiLeRZZTsaG5hR0oCuBINZ/lelo5xzHc+mBOpBXpxSaW1hqoxaCLsVH1EBtz
|
||||
# 7in25Hjy+ejuBcilH6EZ0ZtNxmWGIQz8R0AuS0Tj4VgJXHIlXP9dVOiyGo9Velrk
|
||||
# +FGx/BC+iEuCaKd/IsypHPiCUCh52DGc91s2S7ldQx1H4CljOAtanDfbvSejASWL
|
||||
# o/s3w0XMAbDurWNns0XidAF2RnL1PaxoOyz9VYakNGK4F3/uJRZnVgbsCYuwNX1B
|
||||
# mSwM1ZbPSnggNSGTZx/FQ20Jj/ulrK0ryAbvNbNb4kkaS4a767ifCqvUOFLlUT8P
|
||||
# N43hhldxI6yHPMOWItJpEHIZBiTNKblBsYbIrghb1Ym9tfSsLa5ZJDzVZNndRfhU
|
||||
# qJOyXF+CVm9OtVmFDG9kIwM6QAX8Q0if721z4VOzZNvD8ktg1lI+XjXgXDJVs3h4
|
||||
# 7sMu9GXSYzky+7dtgmc3iRPkda3YVRdmPJtNFN0NLybcssE7vhFCij75eDGQBFq0
|
||||
# A4KVG6uBdr6UTWwE0VKHxBz2BpGvn7BCs+5yxnF+HV6CUickDqqPi/II7Zssd9Eb
|
||||
# P9uzj4luldXDAPrWGtdGq+wK0odlGNVuCMxsL3hn8+KiO9UiMIIHcTCCBVmgAwIB
|
||||
# AgITMwAAABXF52ueAptJmQAAAAAAFTANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UE
|
||||
# BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc
|
||||
# BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0
|
||||
# IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMjEwOTMwMTgyMjI1
|
||||
# WhcNMzAwOTMwMTgzMjI1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu
|
||||
# Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv
|
||||
# cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCC
|
||||
# AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOThpkzntHIhC3miy9ckeb0O
|
||||
# 1YLT/e6cBwfSqWxOdcjKNVf2AX9sSuDivbk+F2Az/1xPx2b3lVNxWuJ+Slr+uDZn
|
||||
# hUYjDLWNE893MsAQGOhgfWpSg0S3po5GawcU88V29YZQ3MFEyHFcUTE3oAo4bo3t
|
||||
# 1w/YJlN8OWECesSq/XJprx2rrPY2vjUmZNqYO7oaezOtgFt+jBAcnVL+tuhiJdxq
|
||||
# D89d9P6OU8/W7IVWTe/dvI2k45GPsjksUZzpcGkNyjYtcI4xyDUoveO0hyTD4MmP
|
||||
# frVUj9z6BVWYbWg7mka97aSueik3rMvrg0XnRm7KMtXAhjBcTyziYrLNueKNiOSW
|
||||
# rAFKu75xqRdbZ2De+JKRHh09/SDPc31BmkZ1zcRfNN0Sidb9pSB9fvzZnkXftnIv
|
||||
# 231fgLrbqn427DZM9ituqBJR6L8FA6PRc6ZNN3SUHDSCD/AQ8rdHGO2n6Jl8P0zb
|
||||
# r17C89XYcz1DTsEzOUyOArxCaC4Q6oRRRuLRvWoYWmEBc8pnol7XKHYC4jMYcten
|
||||
# IPDC+hIK12NvDMk2ZItboKaDIV1fMHSRlJTYuVD5C4lh8zYGNRiER9vcG9H9stQc
|
||||
# xWv2XFJRXRLbJbqvUAV6bMURHXLvjflSxIUXk8A8FdsaN8cIFRg/eKtFtvUeh17a
|
||||
# j54WcmnGrnu3tz5q4i6tAgMBAAGjggHdMIIB2TASBgkrBgEEAYI3FQEEBQIDAQAB
|
||||
# MCMGCSsGAQQBgjcVAgQWBBQqp1L+ZMSavoKRPEY1Kc8Q/y8E7jAdBgNVHQ4EFgQU
|
||||
# n6cVXQBeYl2D9OXSZacbUzUZ6XIwXAYDVR0gBFUwUzBRBgwrBgEEAYI3TIN9AQEw
|
||||
# QTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9E
|
||||
# b2NzL1JlcG9zaXRvcnkuaHRtMBMGA1UdJQQMMAoGCCsGAQUFBwMIMBkGCSsGAQQB
|
||||
# gjcUAgQMHgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/
|
||||
# MB8GA1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQW9fOmhjEMFYGA1UdHwRPME0wS6BJ
|
||||
# oEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01p
|
||||
# Y1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYB
|
||||
# BQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9v
|
||||
# Q2VyQXV0XzIwMTAtMDYtMjMuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQCdVX38Kq3h
|
||||
# LB9nATEkW+Geckv8qW/qXBS2Pk5HZHixBpOXPTEztTnXwnE2P9pkbHzQdTltuw8x
|
||||
# 5MKP+2zRoZQYIu7pZmc6U03dmLq2HnjYNi6cqYJWAAOwBb6J6Gngugnue99qb74p
|
||||
# y27YP0h1AdkY3m2CDPVtI1TkeFN1JFe53Z/zjj3G82jfZfakVqr3lbYoVSfQJL1A
|
||||
# oL8ZthISEV09J+BAljis9/kpicO8F7BUhUKz/AyeixmJ5/ALaoHCgRlCGVJ1ijbC
|
||||
# HcNhcy4sa3tuPywJeBTpkbKpW99Jo3QMvOyRgNI95ko+ZjtPu4b6MhrZlvSP9pEB
|
||||
# 9s7GdP32THJvEKt1MMU0sHrYUP4KWN1APMdUbZ1jdEgssU5HLcEUBHG/ZPkkvnNt
|
||||
# yo4JvbMBV0lUZNlz138eW0QBjloZkWsNn6Qo3GcZKCS6OEuabvshVGtqRRFHqfG3
|
||||
# rsjoiV5PndLQTHa1V1QJsWkBRH58oWFsc/4Ku+xBZj1p/cvBQUl+fpO+y/g75LcV
|
||||
# v7TOPqUxUYS8vwLBgqJ7Fx0ViY1w/ue10CgaiQuPNtq6TPmb/wrpNPgkNWcr4A24
|
||||
# 5oyZ1uEi6vAnQj0llOZ0dFtq0Z4+7X6gMTN9vMvpe784cETRkPHIqzqKOghif9lw
|
||||
# Y1NNje6CbaUFEMFxBmoQtB1VM1izoXBm8qGCAtQwggI9AgEBMIIBAKGB2KSB1TCB
|
||||
# 0jELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1Jl
|
||||
# ZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMk
|
||||
# TWljcm9zb2Z0IElyZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1U
|
||||
# aGFsZXMgVFNTIEVTTjpBMjQwLTRCODItMTMwRTElMCMGA1UEAxMcTWljcm9zb2Z0
|
||||
# IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsOAwIaAxUAcGteVqFx/IbTKXHL
|
||||
# euXCPRPMD7uggYMwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu
|
||||
# Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv
|
||||
# cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDAN
|
||||
# BgkqhkiG9w0BAQUFAAIFAOcW7qowIhgPMjAyMjExMTAxMTI5NDZaGA8yMDIyMTEx
|
||||
# MTExMjk0NlowdDA6BgorBgEEAYRZCgQBMSwwKjAKAgUA5xbuqgIBADAHAgEAAgIE
|
||||
# qTAHAgEAAgIRVjAKAgUA5xhAKgIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEE
|
||||
# AYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GB
|
||||
# AGsU2HTQg158bHX+QngoY7NVfCbGRaLjQOi8geKi26qQWAxll9QLFg4+epiG2nZB
|
||||
# eQvhxeNmIzounhWfJ+gfhFMi8aBT5z4dLK9iBtmpG1Y14RmSS4andiUlS6bVNVNe
|
||||
# WGObqHijMVeMOphiTaAfzR6zSASDaG0CfVm9bNBOnZZsMYIEDTCCBAkCAQEwgZMw
|
||||
# fDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1Jl
|
||||
# ZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMd
|
||||
# TWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAG4CNTBuHngUUkAAQAA
|
||||
# AbgwDQYJYIZIAWUDBAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRAB
|
||||
# BDAvBgkqhkiG9w0BCQQxIgQg578XwPrBwneU95xu1sHFncHeCC0UPQ7QK7PvSSby
|
||||
# VpwwgfoGCyqGSIb3DQEJEAIvMYHqMIHnMIHkMIG9BCAo69Y4oHA7Q4pS+Y1NsBfr
|
||||
# pIYTeWsPeGTami0X0PD7HzCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQI
|
||||
# EwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv
|
||||
# ZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBD
|
||||
# QSAyMDEwAhMzAAABuAjUwbh54FFJAAEAAAG4MCIEIJVlMK4mQfdJaAZx7Unfka/I
|
||||
# D4Wbw5edh/SR7TTptzRqMA0GCSqGSIb3DQEBCwUABIICAA1QlR3ywR7e+jqZ++NC
|
||||
# xsIwREiwVS70CEkbH8XpPRS0mFS0SHcCfpwymGfdep3D0CWk0PIfMhXq0SD97iBI
|
||||
# rOLdHglVBkMYTjGEBHyBzv/LevAZUuzoc5aqyIF4Ywa5KS4PGbMSuRK5CKAojOzH
|
||||
# A/vp2/KYuADmf9kOOgOfDVicyfoqZ+3W+QaUI/k0KKV4dPLF55+y18C+Td6sR60Y
|
||||
# AkcvGZObuj/OkREhdTJ1qJ2E/4RKG8gtGY1DfluLon7+UvS/ciWDWrJnHMmkxM11
|
||||
# cYuRIvLArIdq/YS2bcSnY6AVO2zYjj7gCqDN9GuCurstUKC5uxVl3VNxntC0u3Le
|
||||
# BoI/R5uMYlTXodW8ukLNL6zHrQ4wI4udgW77KJref+3E1PEpZBRMxwose7Vt8lDc
|
||||
# sW1vdM+eZzUXRLhDR8a0Nai7+PaNoukoGf4pvwsu8Mkeji5a0hWtU9lUVRv6nzue
|
||||
# 3L2olhsbiHhAET7N6Rj0kzEhbUgfVUJrGvNlWOfN7MDr+OpArGXMPLtovbKTLtXF
|
||||
# v/GrJo9wQuyqUmY6KQSRDZgOw1CcoZpJcy40HG/aOlJwk03N13OZD5H3KfHwEphR
|
||||
# YnbGwGq9zUId5druSr5s40Yyl3idAkqmI5SXAm9v/gRq2X9vMU0a7KqXet9wO62F
|
||||
# TqxV+7Qp48Vw6hW1g+Q7oWoc
|
||||
# c29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0IElyZWxhbmQgT3Bl
|
||||
# cmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjowODQyLTRC
|
||||
# RTYtQzI5QTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZTCC
|
||||
# AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMqiZTIde/lQ4rC+Bml5f/Wu
|
||||
# q/xKTxrfbG23HofmQ+qZAN4GyO73PF3y9OAfpt7Qf2jcldWOGUB+HzBuwllYyP3f
|
||||
# x4MY8zvuAuB37FvoytnNC2DKnVrVlHOVcGUL9CnmhDNMA2/nskjIf2IoiG9J0qLY
|
||||
# r8duvHdQJ9Li2Pq9guySb9mvUL60ogslCO9gkh6FiEDwMrwUr8Wja6jFpUTny8tg
|
||||
# 0N0cnCN2w4fKkp5qZcbUYFYicLSb/6A7pHCtX6xnjqwhmJoib3vkKJyVxbuFLRhV
|
||||
# XxH95b0LHeNhifn3jvo2j+/4QV10jEpXVW+iC9BsTtR69xvTjU51ZgP7BR4YDEWq
|
||||
# 7JsylSOv5B5THTDXRf184URzFhTyb8OZQKY7mqMh7c8J8w1sEM4XDUF2UZNy829N
|
||||
# VCzG2tfdEXZaHxF8RmxpQYBxyhZwY1rotuIS+gfN2eq+hkAT3ipGn8/KmDwDtzAb
|
||||
# nfuXjApgeZqwgcYJ8pDJ+y/xU6ouzJz1Bve5TTihkiA7wQsQe6R60Zk9dPdNzw0M
|
||||
# K5niRzuQZAt4GI96FhjhlUWcUZOCkv/JXM/OGu/rgSplYwdmPLzzfDtXyuy/GCU5
|
||||
# I4l08g6iifXypMgoYkkceOAAz4vx1x0BOnZWfI3fSwqNUvoN7ncTT+MB4Vpvf1QB
|
||||
# ppjBAQUuvui6eCG0MCVNAgMBAAGjggFJMIIBRTAdBgNVHQ4EFgQUmfIngFzZEZlP
|
||||
# kjDOVluBSDDaanEwHwYDVR0jBBgwFoAUn6cVXQBeYl2D9OXSZacbUzUZ6XIwXwYD
|
||||
# VR0fBFgwVjBUoFKgUIZOaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9j
|
||||
# cmwvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3JsMGwG
|
||||
# CCsGAQUFBwEBBGAwXjBcBggrBgEFBQcwAoZQaHR0cDovL3d3dy5taWNyb3NvZnQu
|
||||
# Y29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIw
|
||||
# MjAxMCgxKS5jcnQwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcD
|
||||
# CDAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggIBANxHtu3FzIabaDbW
|
||||
# qswdKBlAhKXRCN+5CSMiv2TYa4i2QuWIm+99piwAhDhADfbqor1zyLi95Y6GQnvI
|
||||
# WUgdeC7oL1ZtZye92zYK+EIfwYZmhS+CH4infAzUvscHZF3wlrJUfPUIDGVP0lCY
|
||||
# Vse9mguvG0dqkY4ayQPEHOvJubgZZaOdg/N8dInd6fGeOc+0DoGzB+LieObJ2Q0A
|
||||
# tEt3XN3iX8Cp6+dZTX8xwE/LvhRwPpb/+nKshO7TVuvenwdTwqB/LT6CNPaElwFe
|
||||
# KxKrqRTPMbHeg+i+KnBLfwmhEXsMg2s1QX7JIxfvT96md0eiMjiMEO22LbOzmLMN
|
||||
# d3LINowAnRBAJtX+3/e390B9sMGMHp+a1V+hgs62AopBl0p/00li30DN5wEQ5If3
|
||||
# 5Zk7b/T6pEx6rJUDYCti7zCbikjKTanBnOc99zGMlej5X+fC/k5ExUCrOs3/VzGR
|
||||
# CZt5LvVQSdWqq/QMzTEmim4sbzASK9imEkjNtZZyvC1CsUcD1voFktld4mKMjE+u
|
||||
# DEV3IddD+DrRk94nVzNPSuZXewfVOnXHSeqG7xM3V7fl2aL4v1OhL2+JwO1Tx3B0
|
||||
# irO1O9qbNdJk355bntd1RSVKgM22KFBHnoL7Js7pRhBiaKmVTQGoOb+j1Qa7q+ci
|
||||
# xGo48Vh9k35BDsJS/DLoXFSPDl4mMIIHcTCCBVmgAwIBAgITMwAAABXF52ueAptJ
|
||||
# mQAAAAAAFTANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT
|
||||
# Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m
|
||||
# dCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNh
|
||||
# dGUgQXV0aG9yaXR5IDIwMTAwHhcNMjEwOTMwMTgyMjI1WhcNMzAwOTMwMTgzMjI1
|
||||
# WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
|
||||
# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD
|
||||
# Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCCAiIwDQYJKoZIhvcNAQEB
|
||||
# BQADggIPADCCAgoCggIBAOThpkzntHIhC3miy9ckeb0O1YLT/e6cBwfSqWxOdcjK
|
||||
# NVf2AX9sSuDivbk+F2Az/1xPx2b3lVNxWuJ+Slr+uDZnhUYjDLWNE893MsAQGOhg
|
||||
# fWpSg0S3po5GawcU88V29YZQ3MFEyHFcUTE3oAo4bo3t1w/YJlN8OWECesSq/XJp
|
||||
# rx2rrPY2vjUmZNqYO7oaezOtgFt+jBAcnVL+tuhiJdxqD89d9P6OU8/W7IVWTe/d
|
||||
# vI2k45GPsjksUZzpcGkNyjYtcI4xyDUoveO0hyTD4MmPfrVUj9z6BVWYbWg7mka9
|
||||
# 7aSueik3rMvrg0XnRm7KMtXAhjBcTyziYrLNueKNiOSWrAFKu75xqRdbZ2De+JKR
|
||||
# Hh09/SDPc31BmkZ1zcRfNN0Sidb9pSB9fvzZnkXftnIv231fgLrbqn427DZM9itu
|
||||
# qBJR6L8FA6PRc6ZNN3SUHDSCD/AQ8rdHGO2n6Jl8P0zbr17C89XYcz1DTsEzOUyO
|
||||
# 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
|
||||
|
|
|
@ -310,6 +310,10 @@ get_machine_architecture() {
|
|||
echo "s390x"
|
||||
return 0
|
||||
;;
|
||||
ppc64le)
|
||||
echo "ppc64le"
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
|
@ -347,6 +351,10 @@ get_normalized_architecture_from_architecture() {
|
|||
echo "s390x"
|
||||
return 0
|
||||
;;
|
||||
ppc64le)
|
||||
echo "ppc64le"
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
|
||||
say_err "Architecture \`$architecture\` not supported. If you think this is a bug, report it at https://github.com/dotnet/install-scripts/issues"
|
||||
|
@ -1617,6 +1625,10 @@ do
|
|||
echo " $script_name -h|-?|--help"
|
||||
echo ""
|
||||
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 "Options:"
|
||||
echo " -c,--channel <CHANNEL> Download from the channel specified, Defaults to \`$channel\`."
|
||||
|
@ -1651,7 +1663,7 @@ do
|
|||
echo " -InstallDir"
|
||||
echo " --architecture <ARCHITECTURE> Architecture of dotnet binaries to be installed, Defaults to \`$architecture\`."
|
||||
echo " --arch,-Architecture,-Arch"
|
||||
echo " Possible values: x64, arm, arm64 and s390x"
|
||||
echo " Possible values: x64, arm, arm64, s390x and ppc64le"
|
||||
echo " --os <system> Specifies operating system to be used when selecting the installer."
|
||||
echo " Overrides the OS determination approach used by the script. Supported values: osx, linux, linux-musl, freebsd, rhel.6."
|
||||
echo " In case any other value is provided, the platform will be determined by the script based on machine configuration."
|
||||
|
@ -1694,10 +1706,10 @@ do
|
|||
shift
|
||||
done
|
||||
|
||||
say "Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:"
|
||||
say "- The SDK needs to be installed without user interaction and without admin rights."
|
||||
say "- The SDK installation doesn't need to persist across multiple CI runs."
|
||||
say "To set up a development environment or to run apps, use installers rather than this script. Visit https://dotnet.microsoft.com/download to get the installer.\n"
|
||||
say_verbose "Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:"
|
||||
say_verbose "- The SDK needs to be installed without user interaction and without admin rights."
|
||||
say_verbose "- The SDK installation doesn't need to persist across multiple CI runs."
|
||||
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
|
||||
message="Provide credentials via --feed-credential parameter."
|
||||
|
|
File diff suppressed because it is too large
Load Diff
37
package.json
37
package.json
|
@ -3,12 +3,13 @@
|
|||
"version": "3.0.2",
|
||||
"private": true,
|
||||
"description": "setup dotnet action",
|
||||
"main": "lib/setup-dotnet.js",
|
||||
"main": "dist/setup/index.js",
|
||||
"scripts": {
|
||||
"build": "tsc && ncc build",
|
||||
"format": "prettier --write **/*.ts",
|
||||
"format-check": "prettier --check **/*.ts",
|
||||
"lint": "echo \"Fake command that does nothing. It is used in reusable workflows\"",
|
||||
"build": "ncc build -o dist/setup src/setup-dotnet.ts && ncc build -o dist/cache-save src/cache-save.ts",
|
||||
"format": "prettier --no-error-on-unmatched-pattern --config ./.prettierrc.js --write \"**/*.{ts,yml,yaml}\"",
|
||||
"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",
|
||||
"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"
|
||||
|
@ -25,23 +26,33 @@
|
|||
"author": "GitHub",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/cache": "^3.0.0",
|
||||
"@actions/core": "^1.10.0",
|
||||
"@actions/exec": "^1.0.4",
|
||||
"@actions/exec": "^1.1.1",
|
||||
"@actions/github": "^1.1.0",
|
||||
"@actions/glob": "^0.3.0",
|
||||
"@actions/http-client": "^2.0.1",
|
||||
"@actions/io": "^1.0.2",
|
||||
"fast-xml-parser": "^4.0.10",
|
||||
"semver": "^6.3.0"
|
||||
"fast-xml-parser": "^4.2.4",
|
||||
"json5": "^2.2.3",
|
||||
"semver": "^6.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^27.0.2",
|
||||
"@types/jest": "^27.5.2",
|
||||
"@types/node": "^16.11.25",
|
||||
"@types/semver": "^6.2.2",
|
||||
"@vercel/ncc": "^0.33.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||
"@typescript-eslint/parser": "^5.54.0",
|
||||
"@vercel/ncc": "^0.34.0",
|
||||
"eslint": "^8.35.0",
|
||||
"eslint-config-prettier": "^8.6.0",
|
||||
"eslint-plugin-jest": "^27.2.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"husky": "^8.0.1",
|
||||
"jest": "^27.2.5",
|
||||
"jest-circus": "^27.2.5",
|
||||
"prettier": "^2.7.1",
|
||||
"jest": "^27.5.1",
|
||||
"jest-circus": "^27.5.1",
|
||||
"jest-each": "^27.5.1",
|
||||
"prettier": "^2.8.4",
|
||||
"ts-jest": "^27.0.5",
|
||||
"typescript": "^4.8.4",
|
||||
"wget-improved": "^3.2.1"
|
||||
|
|
392
src/authutil.ts
392
src/authutil.ts
|
@ -1,196 +1,196 @@
|
|||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as core from '@actions/core';
|
||||
import * as github from '@actions/github';
|
||||
import {XMLParser, XMLBuilder} from 'fast-xml-parser';
|
||||
|
||||
export function configAuthentication(
|
||||
feedUrl: string,
|
||||
existingFileLocation: string = '',
|
||||
processRoot: string = process.cwd()
|
||||
) {
|
||||
const existingNuGetConfig: string = path.resolve(
|
||||
processRoot,
|
||||
existingFileLocation === ''
|
||||
? getExistingNugetConfig(processRoot)
|
||||
: existingFileLocation
|
||||
);
|
||||
|
||||
const tempNuGetConfig: string = path.resolve(
|
||||
processRoot,
|
||||
'../',
|
||||
'nuget.config'
|
||||
);
|
||||
|
||||
writeFeedToFile(feedUrl, existingNuGetConfig, tempNuGetConfig);
|
||||
}
|
||||
|
||||
function isValidKey(key: string): boolean {
|
||||
return /^[\w\-\.]+$/i.test(key);
|
||||
}
|
||||
|
||||
function getExistingNugetConfig(processRoot: string) {
|
||||
const defaultConfigName = 'nuget.config';
|
||||
const configFileNames = fs
|
||||
.readdirSync(processRoot)
|
||||
.filter(filename => filename.toLowerCase() === defaultConfigName);
|
||||
if (configFileNames.length) {
|
||||
return configFileNames[0];
|
||||
}
|
||||
return defaultConfigName;
|
||||
}
|
||||
|
||||
function writeFeedToFile(
|
||||
feedUrl: string,
|
||||
existingFileLocation: string,
|
||||
tempFileLocation: string
|
||||
) {
|
||||
core.info(
|
||||
`dotnet-auth: Finding any source references in ${existingFileLocation}, writing a new temporary configuration file with credentials to ${tempFileLocation}`
|
||||
);
|
||||
let sourceKeys: string[] = [];
|
||||
let owner: string = core.getInput('owner');
|
||||
let sourceUrl: string = feedUrl;
|
||||
if (!owner) {
|
||||
owner = github.context.repo.owner;
|
||||
}
|
||||
|
||||
if (!process.env.NUGET_AUTH_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
|
||||
const curContents: string = fs.readFileSync(existingFileLocation, 'utf8');
|
||||
|
||||
const parserOptions = {
|
||||
ignoreAttributes: false
|
||||
};
|
||||
const parser = new XMLParser(parserOptions);
|
||||
const json = parser.parse(curContents);
|
||||
|
||||
if (typeof json.configuration === 'undefined') {
|
||||
throw new Error(`The provided NuGet.config seems invalid.`);
|
||||
}
|
||||
if (json.configuration?.packageSources?.add) {
|
||||
const packageSources = json.configuration.packageSources.add;
|
||||
|
||||
if (Array.isArray(packageSources)) {
|
||||
packageSources.forEach(source => {
|
||||
const value = source['@_value'];
|
||||
core.debug(`source '${value}'`);
|
||||
if (value.toLowerCase().includes(feedUrl.toLowerCase())) {
|
||||
const key = source['@_key'];
|
||||
sourceKeys.push(key);
|
||||
core.debug(`Found a URL with key ${key}`);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (
|
||||
packageSources['@_value']
|
||||
.toLowerCase()
|
||||
.includes(feedUrl.toLowerCase())
|
||||
) {
|
||||
const key = packageSources['@_key'];
|
||||
sourceKeys.push(key);
|
||||
core.debug(`Found a URL with key ${key}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const xmlSource: any[] = [
|
||||
{
|
||||
'?xml': [
|
||||
{
|
||||
'#text': ''
|
||||
}
|
||||
],
|
||||
':@': {
|
||||
'@_version': '1.0'
|
||||
}
|
||||
},
|
||||
{
|
||||
configuration: [
|
||||
{
|
||||
config: [
|
||||
{
|
||||
add: [],
|
||||
':@': {
|
||||
'@_key': 'defaultPushSource',
|
||||
'@_value': sourceUrl
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
if (!sourceKeys.length) {
|
||||
let keystring = 'Source';
|
||||
|
||||
xmlSource[1].configuration.push({
|
||||
packageSources: [
|
||||
{
|
||||
add: [],
|
||||
':@': {
|
||||
'@_key': keystring,
|
||||
'@_value': sourceUrl
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
sourceKeys.push(keystring);
|
||||
}
|
||||
|
||||
const packageSourceCredentials: any[] = [];
|
||||
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."
|
||||
);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as core from '@actions/core';
|
||||
import * as github from '@actions/github';
|
||||
import {XMLParser, XMLBuilder} from 'fast-xml-parser';
|
||||
|
||||
export function configAuthentication(
|
||||
feedUrl: string,
|
||||
existingFileLocation = '',
|
||||
processRoot: string = process.cwd()
|
||||
) {
|
||||
const existingNuGetConfig: string = path.resolve(
|
||||
processRoot,
|
||||
existingFileLocation === ''
|
||||
? getExistingNugetConfig(processRoot)
|
||||
: existingFileLocation
|
||||
);
|
||||
|
||||
const tempNuGetConfig: string = path.resolve(
|
||||
processRoot,
|
||||
'../',
|
||||
'nuget.config'
|
||||
);
|
||||
|
||||
writeFeedToFile(feedUrl, existingNuGetConfig, tempNuGetConfig);
|
||||
}
|
||||
|
||||
function isValidKey(key: string): boolean {
|
||||
return /^[\w\-.]+$/i.test(key);
|
||||
}
|
||||
|
||||
function getExistingNugetConfig(processRoot: string) {
|
||||
const defaultConfigName = 'nuget.config';
|
||||
const configFileNames = fs
|
||||
.readdirSync(processRoot)
|
||||
.filter(filename => filename.toLowerCase() === defaultConfigName);
|
||||
if (configFileNames.length) {
|
||||
return configFileNames[0];
|
||||
}
|
||||
return defaultConfigName;
|
||||
}
|
||||
|
||||
function writeFeedToFile(
|
||||
feedUrl: string,
|
||||
existingFileLocation: string,
|
||||
tempFileLocation: string
|
||||
) {
|
||||
core.info(
|
||||
`dotnet-auth: Finding any source references in ${existingFileLocation}, writing a new temporary configuration file with credentials to ${tempFileLocation}`
|
||||
);
|
||||
const sourceKeys: string[] = [];
|
||||
let owner: string = core.getInput('owner');
|
||||
const sourceUrl: string = feedUrl;
|
||||
if (!owner) {
|
||||
owner = github.context.repo.owner;
|
||||
}
|
||||
|
||||
if (!process.env.NUGET_AUTH_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
|
||||
const curContents: string = fs.readFileSync(existingFileLocation, 'utf8');
|
||||
|
||||
const parserOptions = {
|
||||
ignoreAttributes: false
|
||||
};
|
||||
const parser = new XMLParser(parserOptions);
|
||||
const json = parser.parse(curContents);
|
||||
|
||||
if (typeof json.configuration === 'undefined') {
|
||||
throw new Error(`The provided NuGet.config seems invalid.`);
|
||||
}
|
||||
if (json.configuration?.packageSources?.add) {
|
||||
const packageSources = json.configuration.packageSources.add;
|
||||
|
||||
if (Array.isArray(packageSources)) {
|
||||
packageSources.forEach(source => {
|
||||
const value = source['@_value'];
|
||||
core.debug(`source '${value}'`);
|
||||
if (value.toLowerCase().includes(feedUrl.toLowerCase())) {
|
||||
const key = source['@_key'];
|
||||
sourceKeys.push(key);
|
||||
core.debug(`Found a URL with key ${key}`);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (
|
||||
packageSources['@_value']
|
||||
.toLowerCase()
|
||||
.includes(feedUrl.toLowerCase())
|
||||
) {
|
||||
const key = packageSources['@_key'];
|
||||
sourceKeys.push(key);
|
||||
core.debug(`Found a URL with key ${key}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const xmlSource: any[] = [
|
||||
{
|
||||
'?xml': [
|
||||
{
|
||||
'#text': ''
|
||||
}
|
||||
],
|
||||
':@': {
|
||||
'@_version': '1.0'
|
||||
}
|
||||
},
|
||||
{
|
||||
configuration: [
|
||||
{
|
||||
config: [
|
||||
{
|
||||
add: [],
|
||||
':@': {
|
||||
'@_key': 'defaultPushSource',
|
||||
'@_value': sourceUrl
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
if (!sourceKeys.length) {
|
||||
const keystring = 'Source';
|
||||
|
||||
xmlSource[1].configuration.push({
|
||||
packageSources: [
|
||||
{
|
||||
add: [],
|
||||
':@': {
|
||||
'@_key': keystring,
|
||||
'@_value': sourceUrl
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
sourceKeys.push(keystring);
|
||||
}
|
||||
|
||||
const packageSourceCredentials: any[] = [];
|
||||
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."
|
||||
);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
import {readdir} from 'node:fs/promises';
|
||||
import {join} from 'node:path';
|
||||
import * as cache from '@actions/cache';
|
||||
import * as core from '@actions/core';
|
||||
import * as glob from '@actions/glob';
|
||||
|
||||
import {getNuGetFolderPath} from './cache-utils';
|
||||
import {lockFilePatterns, State, Outputs} from './constants';
|
||||
|
||||
export const restoreCache = async (cacheDependencyPath?: string) => {
|
||||
const lockFilePath = cacheDependencyPath || (await findLockFile());
|
||||
const fileHash = await glob.hashFiles(lockFilePath);
|
||||
if (!fileHash) {
|
||||
throw new Error(
|
||||
'Some specified paths were not resolved, unable to cache dependencies.'
|
||||
);
|
||||
}
|
||||
|
||||
const platform = process.env.RUNNER_OS;
|
||||
const primaryKey = `dotnet-cache-${platform}-${fileHash}`;
|
||||
core.debug(`primary key is ${primaryKey}`);
|
||||
|
||||
core.saveState(State.CachePrimaryKey, primaryKey);
|
||||
|
||||
const {'global-packages': cachePath} = await getNuGetFolderPath();
|
||||
const cacheKey = await cache.restoreCache([cachePath], primaryKey);
|
||||
core.setOutput(Outputs.CacheHit, Boolean(cacheKey));
|
||||
|
||||
if (!cacheKey) {
|
||||
core.info('Dotnet cache is not found');
|
||||
return;
|
||||
}
|
||||
|
||||
core.saveState(State.CacheMatchedKey, cacheKey);
|
||||
core.info(`Cache restored from key: ${cacheKey}`);
|
||||
};
|
||||
|
||||
const findLockFile = async () => {
|
||||
const workspace = process.env.GITHUB_WORKSPACE!;
|
||||
const rootContent = await readdir(workspace);
|
||||
|
||||
const lockFile = lockFilePatterns.find(item => rootContent.includes(item));
|
||||
if (!lockFile) {
|
||||
throw new Error(
|
||||
`Dependencies lock file is not found in ${workspace}. Supported file patterns: ${lockFilePatterns.toString()}`
|
||||
);
|
||||
}
|
||||
|
||||
return join(workspace, lockFile);
|
||||
};
|
|
@ -0,0 +1,57 @@
|
|||
import * as core from '@actions/core';
|
||||
import * as cache from '@actions/cache';
|
||||
import fs from 'node:fs';
|
||||
import {getNuGetFolderPath} from './cache-utils';
|
||||
import {State} from './constants';
|
||||
|
||||
// Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in
|
||||
// @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to
|
||||
// throw an uncaught exception. Instead of failing this action, just warn.
|
||||
process.on('uncaughtException', e => {
|
||||
const warningPrefix = '[warning]';
|
||||
core.info(`${warningPrefix}${e.message}`);
|
||||
});
|
||||
|
||||
export async function run() {
|
||||
try {
|
||||
if (core.getBooleanInput('cache')) {
|
||||
await cachePackages();
|
||||
}
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
const cachePackages = async () => {
|
||||
const state = core.getState(State.CacheMatchedKey);
|
||||
const primaryKey = core.getState(State.CachePrimaryKey);
|
||||
|
||||
if (!primaryKey) {
|
||||
core.info('Primary key was not generated, not saving cache.');
|
||||
return;
|
||||
}
|
||||
|
||||
const {'global-packages': cachePath} = await getNuGetFolderPath();
|
||||
|
||||
if (!fs.existsSync(cachePath)) {
|
||||
throw new Error(
|
||||
`Cache folder path is retrieved for .NET CLI but doesn't exist on disk: ${cachePath}`
|
||||
);
|
||||
}
|
||||
|
||||
if (primaryKey === state) {
|
||||
core.info(
|
||||
`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const cacheId = await cache.saveCache([cachePath], primaryKey);
|
||||
if (cacheId == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
core.info(`Cache saved with the key: ${primaryKey}`);
|
||||
};
|
||||
|
||||
run();
|
|
@ -0,0 +1,98 @@
|
|||
import * as cache from '@actions/cache';
|
||||
import * as core from '@actions/core';
|
||||
import * as exec from '@actions/exec';
|
||||
|
||||
import {cliCommand} from './constants';
|
||||
|
||||
type NuGetFolderName =
|
||||
| 'http-cache'
|
||||
| 'global-packages'
|
||||
| 'temp'
|
||||
| 'plugins-cache';
|
||||
|
||||
/**
|
||||
* Get NuGet global packages, cache, and temp folders from .NET CLI.
|
||||
* @returns (Folder Name)-(Path) mappings
|
||||
* @see https://docs.microsoft.com/nuget/consume-packages/managing-the-global-packages-and-cache-folders
|
||||
* @example
|
||||
* Windows
|
||||
* ```json
|
||||
* {
|
||||
* "http-cache": "C:\\Users\\user1\\AppData\\Local\\NuGet\\v3-cache",
|
||||
* "global-packages": "C:\\Users\\user1\\.nuget\\packages\\",
|
||||
* "temp": "C:\\Users\\user1\\AppData\\Local\\Temp\\NuGetScratch",
|
||||
* "plugins-cache": "C:\\Users\\user1\\AppData\\Local\\NuGet\\plugins-cache"
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Mac/Linux
|
||||
* ```json
|
||||
* {
|
||||
* "http-cache": "/home/user1/.local/share/NuGet/v3-cache",
|
||||
* "global-packages": "/home/user1/.nuget/packages/",
|
||||
* "temp": "/tmp/NuGetScratch",
|
||||
* "plugins-cache": "/home/user1/.local/share/NuGet/plugins-cache"
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export const getNuGetFolderPath = async () => {
|
||||
const {stdout, stderr, exitCode} = await exec.getExecOutput(
|
||||
cliCommand,
|
||||
undefined,
|
||||
{ignoreReturnCode: true, silent: true}
|
||||
);
|
||||
|
||||
if (exitCode) {
|
||||
throw new Error(
|
||||
!stderr.trim()
|
||||
? `The '${cliCommand}' command failed with exit code: ${exitCode}`
|
||||
: stderr
|
||||
);
|
||||
}
|
||||
|
||||
const result: Record<NuGetFolderName, string> = {
|
||||
'http-cache': '',
|
||||
'global-packages': '',
|
||||
temp: '',
|
||||
'plugins-cache': ''
|
||||
};
|
||||
|
||||
const regex = /(?:^|\s)(?<key>[a-z-]+): (?<path>.+[/\\].+)$/gm;
|
||||
|
||||
let match: RegExpExecArray | null;
|
||||
while ((match = regex.exec(stdout)) !== null) {
|
||||
const key = match.groups!.key;
|
||||
if ((key as NuGetFolderName) in result) {
|
||||
result[key] = match.groups!.path;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
export function isCacheFeatureAvailable(): boolean {
|
||||
if (cache.isFeatureAvailable()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isGhes()) {
|
||||
core.warning(
|
||||
'Cache action is only supported on GHES version >= 3.5. If you are on version >=3.5 Please check with GHES admin if Actions cache service is enabled or not.'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
core.warning(
|
||||
'The runner was not able to contact the cache service. Caching will be skipped'
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this action runs on GitHub Enterprise Server or not.
|
||||
* (port from https://github.com/actions/toolkit/blob/457303960f03375db6f033e214b9f90d79c3fe5c/packages/cache/src/internal/cacheUtils.ts#L134)
|
||||
*/
|
||||
function isGhes(): boolean {
|
||||
const url = process.env['GITHUB_SERVER_URL'] || 'https://github.com';
|
||||
return new URL(url).hostname.toUpperCase() !== 'GITHUB.COM';
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
/** NuGet lock file patterns */
|
||||
export const lockFilePatterns = ['packages.lock.json'];
|
||||
|
||||
/**
|
||||
* .NET CLI command to list local NuGet resources.
|
||||
* @see https://docs.microsoft.com/dotnet/core/tools/dotnet-nuget-locals
|
||||
*/
|
||||
export const cliCommand =
|
||||
'dotnet nuget locals all --list --force-english-output';
|
||||
|
||||
export enum State {
|
||||
CachePrimaryKey = 'CACHE_KEY',
|
||||
CacheMatchedKey = 'CACHE_RESULT'
|
||||
}
|
||||
|
||||
export enum Outputs {
|
||||
CacheHit = 'cache-hit',
|
||||
DotnetVersion = 'dotnet-version'
|
||||
}
|
582
src/installer.ts
582
src/installer.ts
|
@ -1,263 +1,319 @@
|
|||
// Load tempDirectory before it gets wiped by tool-cache
|
||||
import * as core from '@actions/core';
|
||||
import * as exec from '@actions/exec';
|
||||
import * as io from '@actions/io';
|
||||
import * as hc from '@actions/http-client';
|
||||
import {chmodSync} from 'fs';
|
||||
import {readdir} from 'fs/promises';
|
||||
import path from 'path';
|
||||
import os from 'os';
|
||||
import semver from 'semver';
|
||||
import {IS_LINUX, IS_WINDOWS} from './utils';
|
||||
import {QualityOptions} from './setup-dotnet';
|
||||
|
||||
export interface DotnetVersion {
|
||||
type: string;
|
||||
value: string;
|
||||
qualityFlag: boolean;
|
||||
}
|
||||
|
||||
export class DotnetVersionResolver {
|
||||
private inputVersion: string;
|
||||
private resolvedArgument: DotnetVersion;
|
||||
|
||||
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(
|
||||
`'dotnet-version' was supplied in invalid format: ${this.inputVersion}! Supported syntax: A.B.C, A.B, A.B.x, A, A.x`
|
||||
);
|
||||
}
|
||||
if (semver.valid(this.inputVersion)) {
|
||||
this.resolvedArgument.type = 'version';
|
||||
this.resolvedArgument.value = this.inputVersion;
|
||||
} else {
|
||||
const [major, minor] = this.inputVersion.split('.');
|
||||
|
||||
if (this.isNumericTag(major)) {
|
||||
this.resolvedArgument.type = 'channel';
|
||||
if (this.isNumericTag(minor)) {
|
||||
this.resolvedArgument.value = `${major}.${minor}`;
|
||||
} else {
|
||||
const httpClient = new hc.HttpClient('actions/setup-dotnet', [], {
|
||||
allowRetries: true,
|
||||
maxRetries: 3
|
||||
});
|
||||
this.resolvedArgument.value = await this.getLatestVersion(
|
||||
httpClient,
|
||||
[major, minor]
|
||||
);
|
||||
}
|
||||
}
|
||||
this.resolvedArgument.qualityFlag = +major >= 6 ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
private isNumericTag(versionTag): boolean {
|
||||
return /^\d+$/.test(versionTag);
|
||||
}
|
||||
|
||||
public async createDotNetVersion(): Promise<{
|
||||
type: string;
|
||||
value: string;
|
||||
qualityFlag: boolean;
|
||||
}> {
|
||||
await this.resolveVersionInput();
|
||||
if (!this.resolvedArgument.type) {
|
||||
return this.resolvedArgument;
|
||||
}
|
||||
if (IS_WINDOWS) {
|
||||
this.resolvedArgument.type =
|
||||
this.resolvedArgument.type === 'channel' ? '-Channel' : '-Version';
|
||||
} else {
|
||||
this.resolvedArgument.type =
|
||||
this.resolvedArgument.type === 'channel' ? '--channel' : '--version';
|
||||
}
|
||||
return this.resolvedArgument;
|
||||
}
|
||||
|
||||
private async getLatestVersion(
|
||||
httpClient: hc.HttpClient,
|
||||
versionParts: string[]
|
||||
): Promise<string> {
|
||||
const response = await httpClient.getJson<any>(
|
||||
DotnetVersionResolver.DotNetCoreIndexUrl
|
||||
);
|
||||
const result = response.result || {};
|
||||
let releasesInfo: any[] = result['releases-index'];
|
||||
|
||||
let releaseInfo = releasesInfo.find(info => {
|
||||
let sdkParts: string[] = info['channel-version'].split('.');
|
||||
return sdkParts[0] === versionParts[0];
|
||||
});
|
||||
|
||||
if (!releaseInfo) {
|
||||
throw new Error(
|
||||
`Could not find info for version ${versionParts.join('.')} at ${
|
||||
DotnetVersionResolver.DotNetCoreIndexUrl
|
||||
}`
|
||||
);
|
||||
}
|
||||
|
||||
return releaseInfo['channel-version'];
|
||||
}
|
||||
|
||||
static DotNetCoreIndexUrl: string =
|
||||
'https://dotnetcli.azureedge.net/dotnet/release-metadata/releases-index.json';
|
||||
}
|
||||
|
||||
export class DotnetCoreInstaller {
|
||||
private version: string;
|
||||
private quality: QualityOptions;
|
||||
|
||||
static {
|
||||
const installationDirectoryWindows = path.join(
|
||||
process.env['PROGRAMFILES'] + '',
|
||||
'dotnet'
|
||||
);
|
||||
const installationDirectoryLinux = '/usr/share/dotnet';
|
||||
const installationDirectoryMac = path.join(
|
||||
process.env['HOME'] + '',
|
||||
'.dotnet'
|
||||
);
|
||||
const dotnetInstallDir: string | undefined =
|
||||
process.env['DOTNET_INSTALL_DIR'];
|
||||
if (dotnetInstallDir) {
|
||||
process.env['DOTNET_INSTALL_DIR'] =
|
||||
this.convertInstallPathToAbsolute(dotnetInstallDir);
|
||||
} else {
|
||||
if (IS_WINDOWS) {
|
||||
process.env['DOTNET_INSTALL_DIR'] = installationDirectoryWindows;
|
||||
} else {
|
||||
process.env['DOTNET_INSTALL_DIR'] = IS_LINUX
|
||||
? installationDirectoryLinux
|
||||
: installationDirectoryMac;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constructor(version: string, quality: QualityOptions) {
|
||||
this.version = version;
|
||||
this.quality = quality;
|
||||
}
|
||||
|
||||
private static convertInstallPathToAbsolute(installDir: string): string {
|
||||
let transformedPath;
|
||||
if (path.isAbsolute(installDir)) {
|
||||
transformedPath = installDir;
|
||||
} else {
|
||||
transformedPath = installDir.startsWith('~')
|
||||
? path.join(os.homedir(), installDir.slice(1))
|
||||
: (transformedPath = path.join(process.cwd(), installDir));
|
||||
}
|
||||
return path.normalize(transformedPath);
|
||||
}
|
||||
|
||||
static addToPath() {
|
||||
core.addPath(process.env['DOTNET_INSTALL_DIR']!);
|
||||
core.exportVariable('DOTNET_ROOT', process.env['DOTNET_INSTALL_DIR']);
|
||||
}
|
||||
|
||||
private setQuality(
|
||||
dotnetVersion: DotnetVersion,
|
||||
scriptArguments: string[]
|
||||
): void {
|
||||
const option = IS_WINDOWS ? '-Quality' : '--quality';
|
||||
if (dotnetVersion.qualityFlag) {
|
||||
scriptArguments.push(option, this.quality);
|
||||
} else {
|
||||
core.warning(
|
||||
`'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.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public async installDotnet(): Promise<string> {
|
||||
const windowsDefaultOptions = [
|
||||
'-NoLogo',
|
||||
'-Sta',
|
||||
'-NoProfile',
|
||||
'-NonInteractive',
|
||||
'-ExecutionPolicy',
|
||||
'Unrestricted',
|
||||
'-Command'
|
||||
];
|
||||
const scriptName = IS_WINDOWS ? 'install-dotnet.ps1' : 'install-dotnet.sh';
|
||||
const escapedScript = path
|
||||
.join(__dirname, '..', 'externals', scriptName)
|
||||
.replace(/'/g, "''");
|
||||
let scriptArguments: string[];
|
||||
let scriptPath = '';
|
||||
|
||||
const versionResolver = new DotnetVersionResolver(this.version);
|
||||
const dotnetVersion = await versionResolver.createDotNetVersion();
|
||||
|
||||
if (IS_WINDOWS) {
|
||||
scriptArguments = ['&', `'${escapedScript}'`];
|
||||
|
||||
if (dotnetVersion.type) {
|
||||
scriptArguments.push(dotnetVersion.type, dotnetVersion.value);
|
||||
}
|
||||
|
||||
if (this.quality) {
|
||||
this.setQuality(dotnetVersion, scriptArguments);
|
||||
}
|
||||
|
||||
if (process.env['https_proxy'] != null) {
|
||||
scriptArguments.push(`-ProxyAddress ${process.env['https_proxy']}`);
|
||||
}
|
||||
// This is not currently an option
|
||||
if (process.env['no_proxy'] != null) {
|
||||
scriptArguments.push(`-ProxyBypassList ${process.env['no_proxy']}`);
|
||||
}
|
||||
|
||||
scriptPath =
|
||||
(await io.which('pwsh', false)) || (await io.which('powershell', true));
|
||||
scriptArguments = windowsDefaultOptions.concat(scriptArguments);
|
||||
} else {
|
||||
chmodSync(escapedScript, '777');
|
||||
scriptPath = await io.which(escapedScript, true);
|
||||
scriptArguments = [];
|
||||
|
||||
if (dotnetVersion.type) {
|
||||
scriptArguments.push(dotnetVersion.type, dotnetVersion.value);
|
||||
}
|
||||
|
||||
if (this.quality) {
|
||||
this.setQuality(dotnetVersion, scriptArguments);
|
||||
}
|
||||
}
|
||||
// process.env must be explicitly passed in for DOTNET_INSTALL_DIR to be used
|
||||
const getExecOutputOptions = {
|
||||
ignoreReturnCode: true,
|
||||
env: process.env as {string: string}
|
||||
};
|
||||
const {exitCode, stdout} = await exec.getExecOutput(
|
||||
`"${scriptPath}"`,
|
||||
scriptArguments,
|
||||
getExecOutputOptions
|
||||
);
|
||||
if (exitCode) {
|
||||
throw new Error(`Failed to install dotnet ${exitCode}. ${stdout}`);
|
||||
}
|
||||
|
||||
return this.outputDotnetVersion(dotnetVersion.value);
|
||||
}
|
||||
|
||||
private async outputDotnetVersion(version): Promise<string> {
|
||||
const installationPath = process.env['DOTNET_INSTALL_DIR']!;
|
||||
let versionsOnRunner: string[] = await readdir(
|
||||
path.join(installationPath.replace(/'/g, ''), 'sdk')
|
||||
);
|
||||
|
||||
let installedVersion = semver.maxSatisfying(versionsOnRunner, version, {
|
||||
includePrerelease: true
|
||||
})!;
|
||||
|
||||
return installedVersion;
|
||||
}
|
||||
}
|
||||
// Load tempDirectory before it gets wiped by tool-cache
|
||||
import * as core from '@actions/core';
|
||||
import * as exec from '@actions/exec';
|
||||
import * as io from '@actions/io';
|
||||
import * as hc from '@actions/http-client';
|
||||
import {chmodSync} from 'fs';
|
||||
import path from 'path';
|
||||
import os from 'os';
|
||||
import semver from 'semver';
|
||||
import {IS_WINDOWS, PLATFORM} from './utils';
|
||||
import {QualityOptions} from './setup-dotnet';
|
||||
|
||||
export interface DotnetVersion {
|
||||
type: string;
|
||||
value: string;
|
||||
qualityFlag: boolean;
|
||||
}
|
||||
|
||||
const QUALITY_INPUT_MINIMAL_MAJOR_TAG = 6;
|
||||
const LATEST_PATCH_SYNTAX_MINIMAL_MAJOR_TAG = 5;
|
||||
export class DotnetVersionResolver {
|
||||
private inputVersion: string;
|
||||
private resolvedArgument: DotnetVersion;
|
||||
|
||||
constructor(version: string) {
|
||||
this.inputVersion = version.trim();
|
||||
this.resolvedArgument = {type: '', value: '', qualityFlag: false};
|
||||
}
|
||||
|
||||
private async resolveVersionInput(): Promise<void> {
|
||||
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.createVersionArgument();
|
||||
} else {
|
||||
await this.createChannelArgument();
|
||||
}
|
||||
}
|
||||
|
||||
private isNumericTag(versionTag): boolean {
|
||||
return /^\d+$/.test(versionTag);
|
||||
}
|
||||
|
||||
private isLatestPatchSyntax() {
|
||||
const majorTag = this.inputVersion.match(
|
||||
/^(?<majorTag>\d+)\.\d+\.\d{1}x{2}$/
|
||||
)?.groups?.majorTag;
|
||||
if (
|
||||
majorTag &&
|
||||
parseInt(majorTag) < LATEST_PATCH_SYNTAX_MINIMAL_MAJOR_TAG
|
||||
) {
|
||||
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.`
|
||||
);
|
||||
}
|
||||
return majorTag ? true : false;
|
||||
}
|
||||
|
||||
private createVersionArgument() {
|
||||
this.resolvedArgument.type = 'version';
|
||||
this.resolvedArgument.value = this.inputVersion;
|
||||
}
|
||||
|
||||
private async createChannelArgument() {
|
||||
this.resolvedArgument.type = 'channel';
|
||||
const [major, minor] = this.inputVersion.split('.');
|
||||
if (this.isLatestPatchSyntax()) {
|
||||
this.resolvedArgument.value = this.inputVersion;
|
||||
} else if (this.isNumericTag(major) && this.isNumericTag(minor)) {
|
||||
this.resolvedArgument.value = `${major}.${minor}`;
|
||||
} else if (this.isNumericTag(major)) {
|
||||
this.resolvedArgument.value = await this.getLatestByMajorTag(major);
|
||||
} else {
|
||||
// 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';
|
||||
}
|
||||
this.resolvedArgument.qualityFlag =
|
||||
parseInt(major) >= QUALITY_INPUT_MINIMAL_MAJOR_TAG ? true : false;
|
||||
}
|
||||
|
||||
public async createDotnetVersion(): Promise<DotnetVersion> {
|
||||
await this.resolveVersionInput();
|
||||
if (!this.resolvedArgument.type) {
|
||||
return this.resolvedArgument;
|
||||
}
|
||||
if (IS_WINDOWS) {
|
||||
this.resolvedArgument.type =
|
||||
this.resolvedArgument.type === 'channel' ? '-Channel' : '-Version';
|
||||
} else {
|
||||
this.resolvedArgument.type =
|
||||
this.resolvedArgument.type === 'channel' ? '--channel' : '--version';
|
||||
}
|
||||
return this.resolvedArgument;
|
||||
}
|
||||
|
||||
private async getLatestByMajorTag(majorTag: string): Promise<string> {
|
||||
const httpClient = new hc.HttpClient('actions/setup-dotnet', [], {
|
||||
allowRetries: true,
|
||||
maxRetries: 3
|
||||
});
|
||||
const response = await httpClient.getJson<any>(
|
||||
DotnetVersionResolver.DotnetCoreIndexUrl
|
||||
);
|
||||
const result = response.result || {};
|
||||
const releasesInfo: any[] = result['releases-index'];
|
||||
|
||||
const releaseInfo = releasesInfo.find(info => {
|
||||
const sdkParts: string[] = info['channel-version'].split('.');
|
||||
return sdkParts[0] === majorTag;
|
||||
});
|
||||
|
||||
if (!releaseInfo) {
|
||||
throw new Error(
|
||||
`Could not find info for version with major tag: "${majorTag}" at ${DotnetVersionResolver.DotnetCoreIndexUrl}`
|
||||
);
|
||||
}
|
||||
|
||||
return releaseInfo['channel-version'];
|
||||
}
|
||||
|
||||
static DotnetCoreIndexUrl =
|
||||
'https://dotnetcli.azureedge.net/dotnet/release-metadata/releases-index.json';
|
||||
}
|
||||
|
||||
export class DotnetInstallScript {
|
||||
private scriptName = IS_WINDOWS ? 'install-dotnet.ps1' : 'install-dotnet.sh';
|
||||
private escapedScript: string;
|
||||
private scriptArguments: string[] = [];
|
||||
|
||||
constructor() {
|
||||
this.escapedScript = path
|
||||
.join(__dirname, '..', '..', 'externals', this.scriptName)
|
||||
.replace(/'/g, "''");
|
||||
|
||||
if (IS_WINDOWS) {
|
||||
this.setupScriptPowershell();
|
||||
return;
|
||||
}
|
||||
|
||||
this.setupScriptBash();
|
||||
}
|
||||
|
||||
private setupScriptPowershell() {
|
||||
this.scriptArguments = [
|
||||
'-NoLogo',
|
||||
'-Sta',
|
||||
'-NoProfile',
|
||||
'-NonInteractive',
|
||||
'-ExecutionPolicy',
|
||||
'Unrestricted',
|
||||
'-Command'
|
||||
];
|
||||
|
||||
this.scriptArguments.push('&', `'${this.escapedScript}'`);
|
||||
|
||||
if (process.env['https_proxy'] != null) {
|
||||
this.scriptArguments.push(`-ProxyAddress ${process.env['https_proxy']}`);
|
||||
}
|
||||
// This is not currently an option
|
||||
if (process.env['no_proxy'] != null) {
|
||||
this.scriptArguments.push(`-ProxyBypassList ${process.env['no_proxy']}`);
|
||||
}
|
||||
}
|
||||
|
||||
private setupScriptBash() {
|
||||
chmodSync(this.escapedScript, '777');
|
||||
}
|
||||
|
||||
private async getScriptPath() {
|
||||
if (IS_WINDOWS) {
|
||||
return (await io.which('pwsh', false)) || io.which('powershell', true);
|
||||
}
|
||||
|
||||
return io.which(this.escapedScript, true);
|
||||
}
|
||||
|
||||
public useArguments(...args: string[]) {
|
||||
this.scriptArguments.push(...args);
|
||||
return this;
|
||||
}
|
||||
|
||||
public useVersion(dotnetVersion: DotnetVersion, quality?: QualityOptions) {
|
||||
if (dotnetVersion.type) {
|
||||
this.useArguments(dotnetVersion.type, dotnetVersion.value);
|
||||
}
|
||||
|
||||
if (quality && !dotnetVersion.qualityFlag) {
|
||||
core.warning(
|
||||
`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: ${dotnetVersion.value}. 'dotnet-quality' input is ignored.`
|
||||
);
|
||||
return this;
|
||||
}
|
||||
|
||||
if (quality) {
|
||||
this.useArguments(IS_WINDOWS ? '-Quality' : '--quality', quality);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public async execute() {
|
||||
const getExecOutputOptions = {
|
||||
ignoreReturnCode: true,
|
||||
env: process.env as {string: string}
|
||||
};
|
||||
|
||||
return exec.getExecOutput(
|
||||
`"${await this.getScriptPath()}"`,
|
||||
this.scriptArguments,
|
||||
getExecOutputOptions
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class DotnetInstallDir {
|
||||
private static readonly default = {
|
||||
linux: '/usr/share/dotnet',
|
||||
mac: path.join(process.env['HOME'] + '', '.dotnet'),
|
||||
windows: path.join(process.env['PROGRAMFILES'] + '', 'dotnet')
|
||||
};
|
||||
|
||||
public static readonly dirPath = process.env['DOTNET_INSTALL_DIR']
|
||||
? DotnetInstallDir.convertInstallPathToAbsolute(
|
||||
process.env['DOTNET_INSTALL_DIR']
|
||||
)
|
||||
: DotnetInstallDir.default[PLATFORM];
|
||||
|
||||
private static convertInstallPathToAbsolute(installDir: string): string {
|
||||
if (path.isAbsolute(installDir)) return path.normalize(installDir);
|
||||
|
||||
const transformedPath = installDir.startsWith('~')
|
||||
? path.join(os.homedir(), installDir.slice(1))
|
||||
: path.join(process.cwd(), installDir);
|
||||
|
||||
return path.normalize(transformedPath);
|
||||
}
|
||||
|
||||
public static addToPath() {
|
||||
core.addPath(process.env['DOTNET_INSTALL_DIR']!);
|
||||
core.exportVariable('DOTNET_ROOT', process.env['DOTNET_INSTALL_DIR']);
|
||||
}
|
||||
|
||||
public static setEnvironmentVariable() {
|
||||
process.env['DOTNET_INSTALL_DIR'] = DotnetInstallDir.dirPath;
|
||||
}
|
||||
}
|
||||
|
||||
export class DotnetCoreInstaller {
|
||||
static {
|
||||
DotnetInstallDir.setEnvironmentVariable();
|
||||
}
|
||||
|
||||
constructor(private version: string, private quality: QualityOptions) {}
|
||||
|
||||
public async installDotnet(): Promise<string | null> {
|
||||
const versionResolver = new DotnetVersionResolver(this.version);
|
||||
const dotnetVersion = await versionResolver.createDotnetVersion();
|
||||
|
||||
/**
|
||||
* Install dotnet runitme first in order to get
|
||||
* the latest stable version of dotnet CLI
|
||||
*/
|
||||
const runtimeInstallOutput = await new DotnetInstallScript()
|
||||
// If dotnet CLI is already installed - avoid overwriting it
|
||||
.useArguments(
|
||||
IS_WINDOWS ? '-SkipNonVersionedFiles' : '--skip-non-versioned-files'
|
||||
)
|
||||
// Install only runtime + CLI
|
||||
.useArguments(IS_WINDOWS ? '-Runtime' : '--runtime', 'dotnet')
|
||||
// Use latest stable version
|
||||
.useArguments(IS_WINDOWS ? '-Channel' : '--channel', 'LTS')
|
||||
.execute();
|
||||
|
||||
if (runtimeInstallOutput.exitCode) {
|
||||
/**
|
||||
* dotnetInstallScript will install CLI and runtime even if previous script haven't succeded,
|
||||
* so at this point it's too early to throw an error
|
||||
*/
|
||||
core.warning(
|
||||
`Failed to install dotnet runtime + cli, exit code: ${runtimeInstallOutput.exitCode}. ${runtimeInstallOutput.stderr}`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Install dotnet over the latest version of
|
||||
* dotnet CLI
|
||||
*/
|
||||
const dotnetInstallOutput = await new DotnetInstallScript()
|
||||
// Don't overwrite CLI because it should be already installed
|
||||
.useArguments(
|
||||
IS_WINDOWS ? '-SkipNonVersionedFiles' : '--skip-non-versioned-files'
|
||||
)
|
||||
// Use version provided by user
|
||||
.useVersion(dotnetVersion, this.quality)
|
||||
.execute();
|
||||
|
||||
if (dotnetInstallOutput.exitCode) {
|
||||
throw new Error(
|
||||
`Failed to install dotnet, exit code: ${dotnetInstallOutput.exitCode}. ${dotnetInstallOutput.stderr}`
|
||||
);
|
||||
}
|
||||
|
||||
return this.parseInstalledVersion(dotnetInstallOutput.stdout);
|
||||
}
|
||||
|
||||
private parseInstalledVersion(stdout: string): string | null {
|
||||
const regex = /(?<version>\d+\.\d+\.\d+[a-z0-9._-]*)/gm;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
import * as core from '@actions/core';
|
||||
import {DotnetCoreInstaller} from './installer';
|
||||
import {DotnetCoreInstaller, DotnetInstallDir} from './installer';
|
||||
import * as fs from 'fs';
|
||||
import path from 'path';
|
||||
import semver from 'semver';
|
||||
import * as auth from './authutil';
|
||||
import {isCacheFeatureAvailable} from './cache-utils';
|
||||
import {restoreCache} from './cache-restore';
|
||||
import {Outputs} from './constants';
|
||||
import JSON5 from 'json5';
|
||||
|
||||
const qualityOptions = [
|
||||
'daily',
|
||||
|
@ -13,7 +17,7 @@ const qualityOptions = [
|
|||
'ga'
|
||||
] as const;
|
||||
|
||||
export type QualityOptions = typeof qualityOptions[number];
|
||||
export type QualityOptions = (typeof qualityOptions)[number];
|
||||
|
||||
export async function run() {
|
||||
try {
|
||||
|
@ -27,11 +31,11 @@ export async function run() {
|
|||
// Proxy, auth, (etc) are still set up, even if no version is identified
|
||||
//
|
||||
const versions = core.getMultilineInput('dotnet-version');
|
||||
const installedDotnetVersions: string[] = [];
|
||||
const installedDotnetVersions: (string | null)[] = [];
|
||||
|
||||
const globalJsonFileInput = core.getInput('global-json-file');
|
||||
if (globalJsonFileInput) {
|
||||
const globalJsonPath = path.join(process.cwd(), globalJsonFileInput);
|
||||
const globalJsonPath = path.resolve(process.cwd(), globalJsonFileInput);
|
||||
if (!fs.existsSync(globalJsonPath)) {
|
||||
throw new Error(
|
||||
`The specified global.json file '${globalJsonFileInput}' does not exist`
|
||||
|
@ -48,7 +52,7 @@ export async function run() {
|
|||
versions.push(getVersionFromGlobalJson(globalJsonPath));
|
||||
} else {
|
||||
core.info(
|
||||
`global.json wasn't found in the root directory. No .NET version will be installed.`
|
||||
`The global.json wasn't found in the root directory. No .NET version will be installed.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +62,7 @@ export async function run() {
|
|||
|
||||
if (quality && !qualityOptions.includes(quality)) {
|
||||
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.`
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -69,7 +73,7 @@ export async function run() {
|
|||
const installedVersion = await dotnetInstaller.installDotnet();
|
||||
installedDotnetVersions.push(installedVersion);
|
||||
}
|
||||
DotnetCoreInstaller.addToPath();
|
||||
DotnetInstallDir.addToPath();
|
||||
}
|
||||
|
||||
const sourceUrl: string = core.getInput('source-url');
|
||||
|
@ -78,21 +82,14 @@ export async function run() {
|
|||
auth.configAuthentication(sourceUrl, configFile);
|
||||
}
|
||||
|
||||
const comparisonRange: string = globalJsonFileInput
|
||||
? versions[versions.length - 1]!
|
||||
: '*';
|
||||
outputInstalledVersion(installedDotnetVersions, globalJsonFileInput);
|
||||
|
||||
const versionToOutput = semver.maxSatisfying(
|
||||
installedDotnetVersions,
|
||||
comparisonRange,
|
||||
{
|
||||
includePrerelease: true
|
||||
}
|
||||
);
|
||||
if (core.getBooleanInput('cache') && isCacheFeatureAvailable()) {
|
||||
const cacheDependencyPath = core.getInput('cache-dependency-path');
|
||||
await restoreCache(cacheDependencyPath);
|
||||
}
|
||||
|
||||
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')}`);
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
|
@ -100,10 +97,15 @@ export async function run() {
|
|||
}
|
||||
|
||||
function getVersionFromGlobalJson(globalJsonPath: string): string {
|
||||
let version: string = '';
|
||||
const globalJson = JSON.parse(
|
||||
let version = '';
|
||||
const globalJson = JSON5.parse(
|
||||
// .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(),
|
||||
// is necessary as JSON5 supports wider variety of options for numbers: https://www.npmjs.com/package/json5#numbers
|
||||
(key, value) => {
|
||||
if (key === 'version' || key === 'rollForward') return String(value);
|
||||
return value;
|
||||
}
|
||||
);
|
||||
if (globalJson.sdk && globalJson.sdk.version) {
|
||||
version = globalJson.sdk.version;
|
||||
|
@ -116,4 +118,37 @@ function getVersionFromGlobalJson(globalJsonPath: string): string {
|
|||
return version;
|
||||
}
|
||||
|
||||
function outputInstalledVersion(
|
||||
installedVersions: (string | null)[],
|
||||
globalJsonFileInput: string
|
||||
): void {
|
||||
if (!installedVersions.length) {
|
||||
core.info(`The '${Outputs.DotnetVersion}' output will not be set.`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (installedVersions.includes(null)) {
|
||||
core.warning(
|
||||
`Failed to output the installed version of .NET. The '${Outputs.DotnetVersion}' 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(Outputs.DotnetVersion, versionToOutput);
|
||||
return;
|
||||
}
|
||||
|
||||
const versionToOutput = semver.maxSatisfying(
|
||||
installedVersions as string[],
|
||||
'*',
|
||||
{
|
||||
includePrerelease: true
|
||||
}
|
||||
);
|
||||
|
||||
core.setOutput(Outputs.DotnetVersion, versionToOutput);
|
||||
}
|
||||
|
||||
run();
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue