You've already forked setup-dotnet
mirror of
https://github.com/actions/setup-dotnet.git
synced 2025-07-10 00:50:33 +07:00
Compare commits
109 Commits
Author | SHA1 | Date | |
---|---|---|---|
aa983c550d | |||
b891376106 | |||
b05a3f26b3 | |||
5fdecd2063 | |||
38b49fb717 | |||
3cf3e230c1 | |||
83a1653fa3 | |||
898aa0ce4d | |||
2f028bc044 | |||
21cf89aa73 | |||
fefaa59d2e | |||
e8501859aa | |||
426d75d071 | |||
0f534f5829 | |||
fbdbede901 | |||
0bc43909e0 | |||
c5a57b219c | |||
6adeb768ce | |||
f425be78f5 | |||
fc8786b149 | |||
7d08dc7593 | |||
e0a32d6459 | |||
255362be61 | |||
50b46b3b1d | |||
e8ac21d503 | |||
a79ce57e6b | |||
180a15970f | |||
b72f430d36 | |||
559e47b01b | |||
7358a44590 | |||
34c30d0e81 | |||
5f570676c2 | |||
aa34a3ceaa | |||
12f70884d7 | |||
0318091611 | |||
f199d27aa1 | |||
660c25a321 | |||
4f6b2f576a | |||
920b830bd1 | |||
abdd14ee80 | |||
1d9f0dad5b | |||
2699274f6e | |||
ca579e0fb2 | |||
c82240598b | |||
926f442022 | |||
c41fd15071 | |||
0c8652569e | |||
3cf27f13bb | |||
ae8edb8fff | |||
82b2b40816 | |||
fe74f1cb7d | |||
e94d154672 | |||
fe67d2f8db | |||
023f7252a0 | |||
3f3ad54c0c | |||
e1d35446fe | |||
11aaa65761 | |||
13abe4777e | |||
aefe5b483f | |||
047f06d086 | |||
014f8c8384 | |||
80c862dc38 | |||
e21107efbd | |||
d8f1ab14a7 | |||
f05a62b1cc | |||
338d4e3bbf | |||
228eec3014 | |||
c483e03222 | |||
a35f420124 | |||
4214866121 | |||
0681939502 | |||
ba8a1f9c02 | |||
09d024bd02 | |||
8ae4c080ce | |||
c5d2f92cae | |||
069c35efca | |||
6a2cd88ae8 | |||
9984a6fa87 | |||
607fce577a | |||
501b34e8f6 | |||
b827fcce4d | |||
239baf3c5b | |||
4d4a70f4a5 | |||
70c3f4d098 | |||
9260643816 | |||
45c9f236cf | |||
6d6c7c9313 | |||
e753bbf2ff | |||
629365b26e | |||
942a0bea39 | |||
26db2473e9 | |||
467621733d | |||
bdd38d13dc | |||
1d2f8f9eaf | |||
354d280fa3 | |||
0ff311b0d0 | |||
bc65ba63d3 | |||
90642fa8c5 | |||
c7e7147fd3 | |||
cf081e76a2 | |||
4ca3c96b49 | |||
0705ef0281 | |||
cc76dfab99 | |||
1f2c90bb99 | |||
251997c37d | |||
5d7bc0454b | |||
792e988dae | |||
e5034212c9 | |||
0997db20d4 |
6
.eslintignore
Normal file
6
.eslintignore
Normal file
@ -0,0 +1,6 @@
|
||||
# Ignore list
|
||||
/*
|
||||
|
||||
# Do not ignore these folders:
|
||||
!__tests__/
|
||||
!src/
|
50
.eslintrc.js
Normal file
50
.eslintrc.js
Normal file
@ -0,0 +1,50 @@
|
||||
// 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-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}]
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['**/*{test,spec}.ts'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-unused-vars': 'off',
|
||||
'jest/no-standalone-expect': 'off',
|
||||
'jest/no-conditional-expect': 'off',
|
||||
'no-console': 'off',
|
||||
|
||||
}
|
||||
}
|
||||
],
|
||||
env: {
|
||||
node: true,
|
||||
es6: true,
|
||||
'jest/globals': true
|
||||
}
|
||||
};
|
3
.gitattributes
vendored
3
.gitattributes
vendored
@ -1 +1,2 @@
|
||||
.licenses/** -diff linguist-generated=true
|
||||
* text=auto eol=lf
|
||||
.licenses/** -diff linguist-generated=true
|
||||
|
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@ -1 +1 @@
|
||||
* @actions/virtual-environments-owners
|
||||
* @actions/setup-actions-team
|
||||
|
17
.github/workflows/basic-validation.yml
vendored
Normal file
17
.github/workflows/basic-validation.yml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
name: Basic validation
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- releases/*
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
|
||||
jobs:
|
||||
call-basic-validation:
|
||||
name: Basic validation
|
||||
uses: actions/reusable-workflows/.github/workflows/basic-validation.yml@main
|
41
.github/workflows/check-dist.yml
vendored
41
.github/workflows/check-dist.yml
vendored
@ -1,8 +1,3 @@
|
||||
# `dist/index.js` is a special file in Actions.
|
||||
# When you reference an action with `uses:` in a workflow,
|
||||
# `index.js` is the code that will run.
|
||||
# For our project, we generate this file through a build process from other source files.
|
||||
# We need to make sure the checked-in `index.js` actually matches what we expect it to be.
|
||||
name: Check dist/
|
||||
|
||||
on:
|
||||
@ -17,36 +12,6 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
check-dist:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set Node.js 16
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
cache: npm
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci --ignore-scripts
|
||||
|
||||
- name: Rebuild the dist/ directory
|
||||
run: npm run build
|
||||
|
||||
- name: Compare the expected and actual dist/ directories
|
||||
run: |
|
||||
if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then
|
||||
echo "Detected uncommitted changes after build. See status below:"
|
||||
git diff
|
||||
exit 1
|
||||
fi
|
||||
id: diff
|
||||
|
||||
# If index.js was different than expected, upload the expected version as an artifact
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: ${{ failure() && steps.diff.conclusion == 'failure' }}
|
||||
with:
|
||||
name: dist
|
||||
path: dist/
|
||||
call-check-dist:
|
||||
name: Check dist/
|
||||
uses: actions/reusable-workflows/.github/workflows/check-dist.yml@main
|
||||
|
70
.github/workflows/codeql-analysis.yml
vendored
70
.github/workflows/codeql-analysis.yml
vendored
@ -1,70 +1,14 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
name: CodeQL analysis
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
branches: [main]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ main ]
|
||||
branches: [main]
|
||||
schedule:
|
||||
- cron: '23 19 * * 0'
|
||||
- cron: '0 3 * * 0'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'javascript' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
call-codeQL-analysis:
|
||||
name: CodeQL analysis
|
||||
uses: actions/reusable-workflows/.github/workflows/codeql-analysis.yml@main
|
||||
|
368
.github/workflows/e2e-tests.yml
vendored
Normal file
368
.github/workflows/e2e-tests.yml
vendored
Normal file
@ -0,0 +1,368 @@
|
||||
name: e2e tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- releases/*
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
|
||||
jobs:
|
||||
test-setup-multiple-versions:
|
||||
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 2.2.402, 3.1.404 and 3.0.x
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: |
|
||||
2.2.402
|
||||
3.1.404
|
||||
3.0.x
|
||||
- name: Verify dotnet
|
||||
shell: pwsh
|
||||
run: __tests__/verify-dotnet.ps1 -Patterns "^2.2.402$", "^3.1.404$", "^3.0"
|
||||
|
||||
test-setup-full-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 }}
|
||||
# Side-by-side install of 2.2 and 3.1 used for the test project
|
||||
- name: Setup dotnet 2.2.402
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: 2.2.402
|
||||
- name: Setup dotnet 3.1.201
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: 3.1.201
|
||||
# We are including this variable to force the generation of the nuget config file to verify that it is created in the correct place
|
||||
source-url: https://api.nuget.org/v3/index.json
|
||||
env:
|
||||
NUGET_AUTH_TOKEN: NOTATOKEN
|
||||
- name: Verify dotnet
|
||||
shell: pwsh
|
||||
run: __tests__/verify-dotnet.ps1 -Patterns "^3.1.201$", "^2.2.402$" -CheckNugetConfig
|
||||
|
||||
test-setup-without-patch-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 }}
|
||||
# 2.0, 3.0, 5.0 needs to be in single quotes to interpret as a string instead of as an integer
|
||||
- name: Setup dotnet '3.1'
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: '3.1'
|
||||
- name: Setup dotnet '2.2'
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: '2.2'
|
||||
- name: Verify dotnet
|
||||
shell: pwsh
|
||||
run: __tests__/verify-dotnet.ps1 -Patterns "^3.1", "^2.2"
|
||||
|
||||
test-setup-prerelease-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 '3.1.100-preview1-014459'
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: '3.1.100-preview1-014459'
|
||||
- name: Verify dotnet
|
||||
shell: pwsh
|
||||
run: __tests__/verify-dotnet.ps1 -Patterns "3.1.100-preview1-014459"
|
||||
|
||||
test-setup-latest-patch-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 3.1.x
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: 3.1.x
|
||||
- name: Setup dotnet 2.2.X
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: 2.2.X
|
||||
- name: Verify dotnet
|
||||
shell: pwsh
|
||||
run: __tests__/verify-dotnet.ps1 -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 }}
|
||||
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 3.1.*
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: 3.1.*
|
||||
- name: Setup dotnet 2.2.*
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: 2.2.*
|
||||
- name: Verify dotnet
|
||||
shell: pwsh
|
||||
run: __tests__/verify-dotnet.ps1 -Patterns "^3.1", "^2.2"
|
||||
|
||||
test-setup-global-json-specified-and-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: Write global.json
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir subdirectory
|
||||
echo '{"sdk":{"version": "2.2.207","rollForward": "latestFeature"}}' > ./subdirectory/global.json
|
||||
- name: Setup dotnet
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: 3.1
|
||||
global-json-file: ./subdirectory/global.json
|
||||
- name: Verify dotnet
|
||||
shell: pwsh
|
||||
run: __tests__/verify-dotnet.ps1 -Patterns "^2.2", "^3.1"
|
||||
|
||||
test-setup-global-json-only:
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
operating-system: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Clear toolcache
|
||||
shell: pwsh
|
||||
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
||||
- name: Write global.json
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir subdirectory
|
||||
echo '{"sdk":{"version": "2.2.207","rollForward": "latestFeature"}}' > ./subdirectory/global.json
|
||||
- name: Setup dotnet
|
||||
uses: ./
|
||||
with:
|
||||
global-json-file: ./subdirectory/global.json
|
||||
- name: Verify dotnet
|
||||
shell: pwsh
|
||||
run: __tests__/verify-dotnet.ps1 -Patterns "^2.2"
|
||||
|
||||
test-setup-with-dotnet-quality:
|
||||
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-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'
|
||||
|
||||
- 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
|
||||
|
||||
- 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: ubuntu:latest
|
||||
options: --dns 127.0.0.1
|
||||
services:
|
||||
squid-proxy:
|
||||
image: ubuntu/squid:latest
|
||||
ports:
|
||||
- 3128:3128
|
||||
env:
|
||||
https_proxy: http://squid-proxy:3128
|
||||
http_proxy: http://squid-proxy:3128
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Install Powershell
|
||||
run: |
|
||||
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: 6.0
|
||||
source-url: https://api.nuget.org/v3/index.json
|
||||
env:
|
||||
NUGET_AUTH_TOKEN: NOTATOKEN
|
||||
- name: Verify dotnet
|
||||
shell: pwsh
|
||||
run: |
|
||||
__tests__/verify-dotnet.ps1 -Patterns "^6.0" -CheckNugetConfig
|
||||
|
||||
test-bypass-proxy:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
https_proxy: http://no-such-proxy:3128
|
||||
no_proxy: github.com,dotnetcli.blob.core.windows.net,download.visualstudio.microsoft.com,api.nuget.org,dotnetcli.azureedge.net
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Clear toolcache
|
||||
shell: pwsh
|
||||
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
||||
- name: Setup dotnet 3.1.201
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: 3.1.201
|
||||
source-url: https://api.nuget.org/v3/index.json
|
||||
env:
|
||||
NUGET_AUTH_TOKEN: NOTATOKEN
|
||||
- name: Verify dotnet
|
||||
shell: pwsh
|
||||
run: __tests__/verify-dotnet.ps1 -Patterns "^3.1.201$" -CheckNugetConfig
|
16
.github/workflows/licensed.yml
vendored
16
.github/workflows/licensed.yml
vendored
@ -10,16 +10,6 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
name: Check licenses
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- run: npm ci --ignore-scripts
|
||||
- name: Install licensed
|
||||
run: |
|
||||
cd $RUNNER_TEMP
|
||||
curl -Lfs -o licensed.tar.gz https://github.com/github/licensed/releases/download/3.4.4/licensed-3.4.4-linux-x64.tar.gz
|
||||
sudo tar -xzf licensed.tar.gz
|
||||
sudo mv licensed /usr/local/bin/licensed
|
||||
- run: licensed status
|
||||
call-licensed:
|
||||
name: Licensed
|
||||
uses: actions/reusable-workflows/.github/workflows/licensed.yml@main
|
||||
|
13
.github/workflows/release-new-action-version.yml
vendored
13
.github/workflows/release-new-action-version.yml
vendored
@ -1,4 +1,5 @@
|
||||
name: Release new action version
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [released]
|
||||
@ -20,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.1.0
|
||||
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 }}
|
||||
|
10
.github/workflows/test-dotnet.yml
vendored
10
.github/workflows/test-dotnet.yml
vendored
@ -17,8 +17,8 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
operating-system: [ubuntu-22.04, windows-latest, macOS-latest]
|
||||
dotnet-version: ['2.1', '2.2', '3.0', '3.1', '5.0']
|
||||
operating-system: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
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 }}"
|
||||
|
11
.github/workflows/update-config-files.yml
vendored
Normal file
11
.github/workflows/update-config-files.yml
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
name: Update configuration files
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 3 * * 0'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
call-update-configuration-files:
|
||||
name: Update configuration files
|
||||
uses: actions/reusable-workflows/.github/workflows/update-config-files.yml@main
|
244
.github/workflows/workflow.yml
vendored
244
.github/workflows/workflow.yml
vendored
@ -1,244 +0,0 @@
|
||||
name: Main workflow
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- releases/*
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
operating-system: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Set Node.js 16
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
cache: npm
|
||||
- run: npm ci --ignore-scripts
|
||||
- run: npm run build
|
||||
- run: npm run format-check
|
||||
- run: npm test
|
||||
- name: Verify no unstaged changes
|
||||
if: runner.os != 'windows'
|
||||
run: __tests__/verify-no-unstaged-changes.sh
|
||||
|
||||
test-setup-multiple-versions:
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
operating-system: [ubuntu-22.04, 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 2.2.402 and 3.1.404
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: |
|
||||
2.2.402
|
||||
3.1.404
|
||||
3.0.x
|
||||
- name: Verify dotnet
|
||||
shell: pwsh
|
||||
run: __tests__/verify-dotnet.ps1 2.2.402 3.1.404 '3.0'
|
||||
|
||||
test-setup-full-version:
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
operating-system: [ubuntu-22.04, windows-latest, macos-13]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Clear toolcache
|
||||
shell: pwsh
|
||||
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
||||
# Side-by-side install of 2.2 and 3.1 used for the test project
|
||||
- name: Setup dotnet 2.2.402
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: 2.2.402
|
||||
- name: Setup dotnet 3.1.201
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: 3.1.201
|
||||
# We are including this veriable to force the generation of the nuget config file to verify that it is created in the correct place
|
||||
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
|
||||
|
||||
test-setup-without-patch-version:
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
operating-system: [ubuntu-22.04, windows-latest, macOS-latest]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Clear toolcache
|
||||
shell: pwsh
|
||||
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
||||
# 2.0, 3.0, 5.0 needs to be in single quotes to interpret as a string instead of as an integer
|
||||
- name: Setup dotnet '3.1'
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: '3.1'
|
||||
- name: Setup dotnet '2.2'
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: '2.2'
|
||||
- name: Verify dotnet
|
||||
shell: pwsh
|
||||
run: __tests__/verify-dotnet.ps1 3.1 2.2
|
||||
|
||||
test-setup-latest-patch-version:
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
operating-system: [ubuntu-22.04, 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 3.1.x
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: 3.1.x
|
||||
- name: Setup dotnet 2.2.x
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: 2.2.x
|
||||
- name: Verify dotnet
|
||||
shell: pwsh
|
||||
run: __tests__/verify-dotnet.ps1 3.1 2.2
|
||||
|
||||
test-setup-with-wildcard:
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
operating-system: [ubuntu-22.04, 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 3.1.*
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: 3.1.*
|
||||
- name: Setup dotnet 2.2.*
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: 2.2.*
|
||||
- name: Verify dotnet
|
||||
shell: pwsh
|
||||
run: __tests__/verify-dotnet.ps1 3.1 2.2
|
||||
|
||||
test-setup-global-json-specified-and-version:
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
operating-system: [ubuntu-22.04, 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","rollForward": "latestFeature"}}' > ./subdirectory/global.json
|
||||
- name: Setup dotnet
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: 3.1
|
||||
global-json-file: ./subdirectory/global.json
|
||||
- name: Verify dotnet
|
||||
shell: pwsh
|
||||
run: __tests__/verify-dotnet.ps1 2.2 3.1
|
||||
|
||||
test-proxy:
|
||||
runs-on: ubuntu-20.04
|
||||
container:
|
||||
image: ubuntu:20.04
|
||||
options: --dns 127.0.0.1
|
||||
services:
|
||||
squid-proxy:
|
||||
image: ubuntu/squid:latest
|
||||
ports:
|
||||
- 3128:3128
|
||||
env:
|
||||
https_proxy: http://squid-proxy:3128
|
||||
http_proxy: http://squid-proxy:3128
|
||||
DOTNET_SYSTEM_GLOBALIZATION_INVARIANT: true
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Clear tool cache
|
||||
run: rm -rf "/usr/share/dotnet"
|
||||
- name: Install curl
|
||||
run: |
|
||||
apt update
|
||||
apt -y install curl libssl1.1 libssl-dev
|
||||
- name: Setup dotnet 3.1.201
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: 3.1.201
|
||||
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
|
||||
|
||||
test-bypass-proxy:
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
https_proxy: http://no-such-proxy:3128
|
||||
no_proxy: github.com,download.visualstudio.microsoft.com,api.nuget.org,builds.dotnet.microsoft.com,ci.dot.net
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Clear tool cache
|
||||
run: rm -rf "/usr/share/dotnet"
|
||||
- name: Setup dotnet 3.1.201
|
||||
uses: ./
|
||||
with:
|
||||
dotnet-version: 3.1.201
|
||||
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
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -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
|
||||
|
2
.licenses/npm/@actions/core.dep.yml
generated
2
.licenses/npm/@actions/core.dep.yml
generated
@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "@actions/core"
|
||||
version: 1.6.0
|
||||
version: 1.10.0
|
||||
type: npm
|
||||
summary: Actions core lib
|
||||
homepage: https://github.com/actions/toolkit/tree/main/packages/core
|
||||
|
30
.licenses/npm/@actions/exec.dep.yml
generated
30
.licenses/npm/@actions/exec.dep.yml
generated
@ -1,30 +1,20 @@
|
||||
---
|
||||
name: "@actions/exec"
|
||||
version: 1.0.4
|
||||
version: 1.1.1
|
||||
type: npm
|
||||
summary: Actions exec lib
|
||||
homepage: https://github.com/actions/toolkit/tree/master/packages/exec
|
||||
homepage: https://github.com/actions/toolkit/tree/main/packages/exec
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: Auto-generated MIT license text
|
||||
text: |
|
||||
MIT License
|
||||
- sources: LICENSE.md
|
||||
text: |-
|
||||
The MIT License (MIT)
|
||||
|
||||
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:
|
||||
Copyright 2019 GitHub
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
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 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.
|
||||
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: []
|
||||
|
32
.licenses/npm/@actions/http-client-1.0.8.dep.yml
generated
32
.licenses/npm/@actions/http-client-1.0.8.dep.yml
generated
@ -1,32 +0,0 @@
|
||||
---
|
||||
name: "@actions/http-client"
|
||||
version: 1.0.8
|
||||
type: npm
|
||||
summary: Actions Http Client
|
||||
homepage: https://github.com/actions/http-client#readme
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
Actions Http Client for Node.js
|
||||
|
||||
Copyright (c) GitHub, Inc.
|
||||
|
||||
All rights reserved.
|
||||
|
||||
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.
|
||||
notices: []
|
@ -1,9 +1,9 @@
|
||||
---
|
||||
name: "@actions/http-client"
|
||||
version: 1.0.11
|
||||
version: 2.0.1
|
||||
type: npm
|
||||
summary: Actions Http Client
|
||||
homepage: https://github.com/actions/http-client#readme
|
||||
homepage: https://github.com/actions/toolkit/tree/main/packages/http-client
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
30
.licenses/npm/@actions/io.dep.yml
generated
30
.licenses/npm/@actions/io.dep.yml
generated
@ -1,30 +1,20 @@
|
||||
---
|
||||
name: "@actions/io"
|
||||
version: 1.0.2
|
||||
version: 1.1.2
|
||||
type: npm
|
||||
summary: Actions io lib
|
||||
homepage: https://github.com/actions/toolkit/tree/master/packages/io
|
||||
homepage: https://github.com/actions/toolkit/tree/main/packages/io
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: Auto-generated MIT license text
|
||||
text: |
|
||||
MIT License
|
||||
- sources: LICENSE.md
|
||||
text: |-
|
||||
The MIT License (MIT)
|
||||
|
||||
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:
|
||||
Copyright 2019 GitHub
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
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 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.
|
||||
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: []
|
||||
|
22
.licenses/npm/fast-xml-parser.dep.yml
generated
22
.licenses/npm/fast-xml-parser.dep.yml
generated
@ -1,27 +1,11 @@
|
||||
---
|
||||
name: fast-xml-parser
|
||||
version: 3.17.4
|
||||
version: 4.0.10
|
||||
type: npm
|
||||
summary: Validate XML or Parse XML to JS/JSON very fast without C/C++ based libraries
|
||||
summary: Validate XML, Parse XML to JS Object, or Build XML from JS Object without C/C++ based libraries and no callback.
|
||||
homepage: https://github.com/NaturalIntelligence/fast-xml-parser#readme
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: "MIT License\n\nCopyright (c) 2017 Amit Kumar Gupta\n\nPermission is hereby
|
||||
granted, free of charge, to any person obtaining a copy\nof this software and
|
||||
associated documentation files (the \"Software\"), to deal\nin the Software without
|
||||
restriction, including without limitation the rights\nto use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit
|
||||
persons to whom the Software is\nfurnished to do so, subject to the following
|
||||
conditions:\n\nIf you use this library in a public repository then you give us
|
||||
the right to mention your company name and logo in user's list without further
|
||||
permission required, but you can request them to be taken down within 30 days.
|
||||
\n\nThe above copyright notice and this permission notice shall be included in
|
||||
all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED
|
||||
\"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT
|
||||
LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE
|
||||
AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR
|
||||
THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
|
||||
text: "MIT License\n\nCopyright (c) 2017 Amit Kumar Gupta\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
|
||||
notices: []
|
||||
|
11
.licenses/npm/strnum.dep.yml
generated
Normal file
11
.licenses/npm/strnum.dep.yml
generated
Normal file
@ -0,0 +1,11 @@
|
||||
---
|
||||
name: strnum
|
||||
version: 1.0.5
|
||||
type: npm
|
||||
summary: Parse string into Number based on configuration
|
||||
homepage: https://github.com/NaturalIntelligence/strnum
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: "MIT License\n\nCopyright (c) 2021 Natural Intelligence\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
|
||||
notices: []
|
20
.licenses/npm/uuid.dep.yml
generated
Normal file
20
.licenses/npm/uuid.dep.yml
generated
Normal file
@ -0,0 +1,20 @@
|
||||
---
|
||||
name: uuid
|
||||
version: 8.3.2
|
||||
type: npm
|
||||
summary: RFC4122 (v1, v4, and v5) UUIDs
|
||||
homepage:
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE.md
|
||||
text: |
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2010-2020 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: []
|
24
.licenses/npm/xmlbuilder.dep.yml
generated
24
.licenses/npm/xmlbuilder.dep.yml
generated
@ -1,24 +0,0 @@
|
||||
---
|
||||
name: xmlbuilder
|
||||
version: 13.0.2
|
||||
type: npm
|
||||
summary: An XML builder for node.js
|
||||
homepage: http://github.com/oozcitak/xmlbuilder-js
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: "The MIT License (MIT)\r\n\r\nCopyright (c) 2013 Ozgur Ozcitak\r\n\r\nPermission
|
||||
is hereby granted, free of charge, to any person obtaining a copy\r\nof this software
|
||||
and associated documentation files (the \"Software\"), to deal\r\nin the Software
|
||||
without restriction, including without limitation the rights\r\nto use, copy,
|
||||
modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software,
|
||||
and to permit persons to whom the Software is\r\nfurnished to do so, subject to
|
||||
the following conditions:\r\n\r\nThe above copyright notice and this permission
|
||||
notice shall be included in\r\nall copies or substantial portions of the Software.\r\n\r\nTHE
|
||||
SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR
|
||||
A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\nTHE SOFTWARE.\r\n"
|
||||
notices: []
|
7
.prettierignore
Normal file
7
.prettierignore
Normal file
@ -0,0 +1,7 @@
|
||||
# Ignore list
|
||||
/*
|
||||
|
||||
# Do not ignore these folders:
|
||||
!__tests__/
|
||||
!.github/
|
||||
!src/
|
11
.prettierrc.js
Normal file
11
.prettierrc.js
Normal file
@ -0,0 +1,11 @@
|
||||
// This is a reusable configuration file copied from https://github.com/actions/reusable-workflows/tree/main/reusable-configurations. Please don't make changes to this file as it's the subject of an automatic update.
|
||||
module.exports = {
|
||||
printWidth: 80,
|
||||
tabWidth: 2,
|
||||
useTabs: false,
|
||||
semi: true,
|
||||
singleQuote: true,
|
||||
trailingComma: 'none',
|
||||
bracketSpacing: false,
|
||||
arrowParens: 'avoid'
|
||||
};
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"printWidth": 80,
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"bracketSpacing": false,
|
||||
"arrowParens": "avoid",
|
||||
"parser": "typescript"
|
||||
}
|
191
README.md
191
README.md
@ -1,6 +1,7 @@
|
||||
# setup-dotnet
|
||||
|
||||
[](https://github.com/actions/setup-dotnet)
|
||||
[](https://github.com/actions/setup-dotnet/actions/workflows/basic-validation.yml)
|
||||
[](https://github.com/actions/setup-dotnet/actions/workflows/e2e-tests.yml)
|
||||
|
||||
This action sets up a [.NET CLI](https://github.com/dotnet/sdk) environment for use in actions by:
|
||||
|
||||
@ -8,62 +9,82 @@ This action sets up a [.NET CLI](https://github.com/dotnet/sdk) environment for
|
||||
- registering problem matchers for error output
|
||||
- setting up authentication to private package sources like GitHub Packages
|
||||
|
||||
Please Note: GitHub hosted runners have some versions of the .NET SDK
|
||||
> **Note**: GitHub hosted runners have some versions of the .NET SDK
|
||||
preinstalled. Installed versions are subject to change. Please refer to the
|
||||
documentation
|
||||
[software installed on github hosted runners](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-software)
|
||||
documentation:
|
||||
[Software installed on github hosted runners](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-software)
|
||||
for .NET SDK versions that are currently available.
|
||||
|
||||
# Usage
|
||||
## Usage
|
||||
|
||||
See [action.yml](action.yml)
|
||||
|
||||
Basic:
|
||||
**Basic**:
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-dotnet@v2
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '3.1.x' # SDK Version to use; x will use the latest version of the 3.1 channel
|
||||
dotnet-version: '3.1.x'
|
||||
- run: dotnet build <my project>
|
||||
```
|
||||
Multiple versions:
|
||||
> Note: In case multiple versions are installed, the latest .NET version will be used by default unless another version is specified in the `global.json` file.
|
||||
> **Warning**: Unless a concrete version is specified in the [`global.json`](https://learn.microsoft.com/en-us/dotnet/core/tools/global-json) file, **_the latest .NET version installed on the runner (including preinstalled versions) will be used [by default](https://learn.microsoft.com/en-us/dotnet/core/versions/selection#the-sdk-uses-the-latest-installed-version)_**. Please refer to the [documentation](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-software) for the currently preinstalled .NET SDK versions.
|
||||
|
||||
**Multiple version installation**:
|
||||
```yml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup dotnet
|
||||
uses: actions/setup-dotnet@v2
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: |
|
||||
3.1.x
|
||||
5.0.x
|
||||
- run: dotnet build <my project>
|
||||
```
|
||||
Preview version:
|
||||
## Supported version syntax
|
||||
|
||||
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', '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:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-dotnet@v2
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '6.0.x'
|
||||
include-prerelease: true
|
||||
dotnet-quality: 'preview'
|
||||
- run: dotnet build <my project>
|
||||
```
|
||||
global.json in a subdirectory:
|
||||
|
||||
## Using the `global-json-file` input
|
||||
`setup-dotnet` action can read .NET SDK version from a `global.json` file. Input `global-json-file` is used for specifying the path to the `global.json`. If the file that was supplied to `global-json-file` input doesn't exist, the action will fail with error.
|
||||
|
||||
>**Note**: In case both `dotnet-version` and `global-json-file` inputs are used, versions from both inputs will be installed.
|
||||
|
||||
```yml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-dotnet@v2
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
global-json-file: csharp/global.json
|
||||
- run: dotnet build <my project>
|
||||
working-directory: csharp
|
||||
```
|
||||
|
||||
Matrix Testing:
|
||||
```yaml
|
||||
## 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
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
@ -74,38 +95,44 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup dotnet
|
||||
uses: actions/setup-dotnet@v2
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: ${{ matrix.dotnet }}
|
||||
- run: dotnet build <my project>
|
||||
- name: Execute dotnet
|
||||
run: dotnet build <my project>
|
||||
```
|
||||
>**Note**: Unless a concrete version is specified in the [`global.json`](https://learn.microsoft.com/en-us/dotnet/core/tools/global-json) file, the latest .NET version installed on the runner (including preinstalled versions) will be used [by default](https://learn.microsoft.com/en-us/dotnet/core/versions/selection#the-sdk-uses-the-latest-installed-version). To control this behavior you may want to use temporary `global.json` files:
|
||||
|
||||
Side by Side Testing:
|
||||
```yaml
|
||||
**Matrix testing with temporary global.json creation**
|
||||
```yml
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
name: Dotnet Side by Side testing sample
|
||||
strategy:
|
||||
matrix:
|
||||
dotnet: [ '2.1.x', '3.1.x', '5.0.x' ]
|
||||
name: Dotnet ${{ matrix.dotnet }} sample
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup dotnet
|
||||
uses: actions/setup-dotnet@v2
|
||||
uses: actions/setup-dotnet@v3
|
||||
id: stepid
|
||||
with:
|
||||
dotnet-version: |
|
||||
2.1.x
|
||||
3.1.x
|
||||
- run: dotnet build <my project>
|
||||
- run: dotnet test <my project>
|
||||
dotnet-version: ${{ matrix.dotnet }}
|
||||
- name: Create temporary global.json
|
||||
run: echo '{"sdk":{"version": "${{ steps.stepid.outputs.dotnet-version }}"}}' > ./global.json
|
||||
- name: Execute dotnet
|
||||
run: dotnet build <my project>
|
||||
```
|
||||
## Setting up authentication for nuget feeds
|
||||
|
||||
Authentication for nuget feeds:
|
||||
```yaml
|
||||
### Github Package Registry (GPR)
|
||||
```yml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
# Authenticates packages to push to GPR
|
||||
- uses: actions/setup-dotnet@v2
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '3.1.x' # SDK Version to use.
|
||||
dotnet-version: '3.1.x'
|
||||
source-url: https://nuget.pkg.github.com/<owner>/index.json
|
||||
env:
|
||||
NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||
@ -114,19 +141,22 @@ steps:
|
||||
run: dotnet pack --configuration Release <my project>
|
||||
- name: Publish the package to GPR
|
||||
run: dotnet nuget push <my project>/bin/Release/*.nupkg
|
||||
```
|
||||
|
||||
# Authenticates packages to push to Azure Artifacts
|
||||
- uses: actions/setup-dotnet@v2
|
||||
### Azure Artifacts
|
||||
```yml
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
source-url: https://pkgs.dev.azure.com/<your-organization>/_packaging/<your-feed-name>/nuget/v3/index.json
|
||||
env:
|
||||
NUGET_AUTH_TOKEN: ${{secrets.AZURE_DEVOPS_PAT}} # Note, create a secret with this name in Settings
|
||||
- name: Publish the package to Azure Artifacts
|
||||
run: dotnet nuget push <my project>/bin/Release/*.nupkg
|
||||
```
|
||||
|
||||
# Authenticates packages to push to nuget.org.
|
||||
# It's only the way to push a package to nuget.org feed for macOS/Linux machines due to API key config store limitations.
|
||||
- uses: actions/setup-dotnet@v2
|
||||
### nuget.org
|
||||
```yml
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: 3.1.x
|
||||
- name: Publish the package to nuget.org
|
||||
@ -134,32 +164,91 @@ steps:
|
||||
env:
|
||||
NUGET_AUTH_TOKEN: ${{ secrets.NUGET_TOKEN }}
|
||||
```
|
||||
> **Note**: It's the only way to push a package to nuget.org feed for macOS/Linux machines due to API key config store limitations.
|
||||
|
||||
## Environment Variables to use with dotnet
|
||||
# Outputs and environment variables
|
||||
|
||||
## Outputs
|
||||
|
||||
### `dotnet-version`
|
||||
|
||||
Using the **dotnet-version** output it's possible to get the installed by the action .NET SDK version.
|
||||
|
||||
**Single version installation**
|
||||
|
||||
In case of a single version installation, the `dotnet-version` output contains the version that is installed by the action.
|
||||
|
||||
```yaml
|
||||
- uses: actions/setup-dotnet@v3
|
||||
id: stepid
|
||||
with:
|
||||
dotnet-version: 3.1.422
|
||||
- run: echo '${{ steps.stepid.outputs.dotnet-version }}' # outputs 3.1.422
|
||||
```
|
||||
|
||||
**Multiple version installation**
|
||||
|
||||
In case of a multiple version installation, the `dotnet-version` output contains the latest version that is installed by the action.
|
||||
|
||||
```yaml
|
||||
- uses: actions/setup-dotnet@v3
|
||||
id: stepid
|
||||
with:
|
||||
dotnet-version: |
|
||||
3.1.422
|
||||
5.0.408
|
||||
- run: echo '${{ steps.stepid.outputs.dotnet-version }}' # outputs 5.0.408
|
||||
```
|
||||
**Installation from global.json**
|
||||
|
||||
When the `dotnet-version` input is used along with the `global-json-file` input, the `dotnet-version` output contains the version resolved from the `global.json`.
|
||||
|
||||
```yaml
|
||||
- uses: actions/setup-dotnet@v3
|
||||
id: stepid
|
||||
with:
|
||||
dotnet-version: |
|
||||
3.1.422
|
||||
5.0.408
|
||||
global-json-file: "./global.json" # contains version 2.2.207
|
||||
- run: echo '${{ steps.stepid.outputs.dotnet-version }}' # outputs 2.2.207
|
||||
```
|
||||
|
||||
## 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
|
||||
|
||||
- DOTNET_NOLOGO - removes logo and telemetry message from first run of dotnet cli (default: false)
|
||||
- DOTNET_CLI_TELEMETRY_OPTOUT - opt-out of telemetry being sent to Microsoft (default: false)
|
||||
- DOTNET_MULTILEVEL_LOOKUP - configures whether the global install location is used as a fall-back (default: true)
|
||||
| **Env.variable** | **Description** | **Default value** |
|
||||
| ----------- | ----------- | ----------- |
|
||||
| DOTNET_INSTALL_DIR |Specifies a directory where .NET SDKs should be installed by the action.|*default value for each OS* |
|
||||
| DOTNET_NOLOGO |Removes logo and telemetry message from first run of dotnet cli|*false*|
|
||||
| DOTNET_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*|
|
||||
|
||||
Example usage:
|
||||
```yaml
|
||||
The default value of the `DOTNET_INSTALL_DIR` environment variable depends on the operation system which is used on a runner:
|
||||
| **Operation system** | **Default value** |
|
||||
| ----------- | ----------- |
|
||||
| **Windows** | `C:\Program Files\dotnet` |
|
||||
| **Ubuntu** | `/usr/share/dotnet` |
|
||||
| **macOS** | `/Users/runner/.dotnet` |
|
||||
|
||||
**Example usage**:
|
||||
```yml
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOTNET_NOLOGO: true
|
||||
DOTNET_INSTALL_DIR: "path/to/directory"
|
||||
steps:
|
||||
- uses: actions/checkout@main
|
||||
- uses: actions/setup-dotnet@v2
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '3.1.x' # SDK Version to use.
|
||||
dotnet-version: '3.1.x'
|
||||
```
|
||||
|
||||
# License
|
||||
## License
|
||||
|
||||
The scripts and documentation in this project are released under the [MIT License](LICENSE)
|
||||
|
||||
# Contributions
|
||||
## Contributions
|
||||
|
||||
Contributions are welcome! See [Contributor's Guide](docs/contributors.md)
|
||||
Contributions are welcome! See [Contributor's Guide](docs/contributors.md)
|
||||
|
@ -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,340 +1,336 @@
|
||||
import io = require('@actions/io');
|
||||
import fs = require('fs');
|
||||
import path = require('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();
|
||||
});
|
||||
});
|
||||
|
@ -1,23 +1,45 @@
|
||||
import fs = require('fs');
|
||||
|
||||
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);
|
||||
});
|
||||
|
18
__tests__/e2e-test-csproj/Test.cs
Normal file
18
__tests__/e2e-test-csproj/Test.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
|
||||
namespace test_csproj
|
||||
{
|
||||
[TestClass]
|
||||
public class Test
|
||||
{
|
||||
[TestMethod]
|
||||
public void TestMethod()
|
||||
{
|
||||
Console.WriteLine("TestMethod");
|
||||
int calculatedResult = 1000 / 25;
|
||||
int expectedResult = 40;
|
||||
Assert.AreEqual(calculatedResult, expectedResult);
|
||||
}
|
||||
}
|
||||
}
|
15
__tests__/e2e-test-csproj/test.csproj
Normal file
15
__tests__/e2e-test-csproj/test.csproj
Normal file
@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>$(TEST_TARGET_FRAMEWORK)</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- These packages will be downloaded over the network for testing proxy settings -->
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0-preview-20170810-02" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="1.1.18" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="1.1.18" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
65
__tests__/installation-scripts.test.ts
Normal file
65
__tests__/installation-scripts.test.ts
Normal file
@ -0,0 +1,65 @@
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import * as hc from '@actions/http-client';
|
||||
|
||||
const HTTP_CLIENT_OPTIONS = {allowRetries: true, maxRetries: 10} as const;
|
||||
const TEST_TIMEOUT = 30000;
|
||||
|
||||
describe('Dotnet installation scripts tests', () => {
|
||||
it(
|
||||
'Uses an up to date bash download script',
|
||||
async () => {
|
||||
const httpCallbackClient = new hc.HttpClient(
|
||||
'setup-dotnet-test',
|
||||
[],
|
||||
HTTP_CLIENT_OPTIONS
|
||||
);
|
||||
const response: hc.HttpClientResponse = await httpCallbackClient.get(
|
||||
'https://dot.net/v1/dotnet-install.sh'
|
||||
);
|
||||
expect(response.message.statusCode).toBe(200);
|
||||
const upToDateContents: string = await response.readBody();
|
||||
const currentContents: string = fs
|
||||
.readFileSync(
|
||||
path.join(__dirname, '..', 'externals', 'install-dotnet.sh')
|
||||
)
|
||||
.toString();
|
||||
expect(normalizeFileContents(currentContents)).toBe(
|
||||
normalizeFileContents(upToDateContents)
|
||||
);
|
||||
},
|
||||
TEST_TIMEOUT
|
||||
);
|
||||
|
||||
it(
|
||||
'Uses an up to date powershell download script',
|
||||
async () => {
|
||||
const httpCallbackClient = new hc.HttpClient(
|
||||
'setup-dotnet-test',
|
||||
[],
|
||||
HTTP_CLIENT_OPTIONS
|
||||
);
|
||||
const response: hc.HttpClientResponse = await httpCallbackClient.get(
|
||||
'https://dot.net/v1/dotnet-install.ps1'
|
||||
);
|
||||
expect(response.message.statusCode).toBe(200);
|
||||
const upToDateContents: string = await response.readBody();
|
||||
const currentContents: string = fs
|
||||
.readFileSync(
|
||||
path.join(__dirname, '..', 'externals', 'install-dotnet.ps1')
|
||||
)
|
||||
.toString();
|
||||
expect(normalizeFileContents(currentContents)).toBe(
|
||||
normalizeFileContents(upToDateContents)
|
||||
);
|
||||
},
|
||||
TEST_TIMEOUT
|
||||
);
|
||||
});
|
||||
|
||||
function normalizeFileContents(contents: string): string {
|
||||
return contents
|
||||
.trim()
|
||||
.replace(new RegExp('\r\n', 'g'), '\n')
|
||||
.replace(new RegExp('\r', 'g'), '\n');
|
||||
}
|
@ -1,151 +1,443 @@
|
||||
import io = require('@actions/io');
|
||||
import fs = require('fs');
|
||||
import os = require('os');
|
||||
import path = require('path');
|
||||
import hc = require('@actions/http-client');
|
||||
|
||||
const toolDir = path.join(__dirname, 'runner', 'tools');
|
||||
const tempDir = path.join(__dirname, 'runner', 'temp');
|
||||
|
||||
process.env['RUNNER_TOOL_CACHE'] = toolDir;
|
||||
process.env['RUNNER_TEMP'] = tempDir;
|
||||
import each from 'jest-each';
|
||||
import semver from 'semver';
|
||||
import * as exec from '@actions/exec';
|
||||
import * as core from '@actions/core';
|
||||
import * as io from '@actions/io';
|
||||
import * as installer from '../src/installer';
|
||||
|
||||
const IS_WINDOWS = process.platform === 'win32';
|
||||
import {IS_WINDOWS} from '../src/utils';
|
||||
import {QualityOptions} from '../src/setup-dotnet';
|
||||
|
||||
describe('installer tests', () => {
|
||||
beforeAll(async () => {
|
||||
process.env.RUNNER_TOOL_CACHE = toolDir;
|
||||
process.env.DOTNET_INSTALL_DIR = toolDir;
|
||||
process.env.RUNNER_TEMP = tempDir;
|
||||
process.env.DOTNET_ROOT = '';
|
||||
await io.rmRF(toolDir);
|
||||
await io.rmRF(tempDir);
|
||||
const env = process.env;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
process.env = {...env};
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
try {
|
||||
await io.rmRF(toolDir);
|
||||
await io.rmRF(tempDir);
|
||||
} catch {
|
||||
console.log('Failed to remove test directories');
|
||||
}
|
||||
}, 30000);
|
||||
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');
|
||||
|
||||
it('Aquires multiple versions of dotnet', async () => {
|
||||
const versions = ['2.2.207', '3.1.120'];
|
||||
describe('installDotnet() tests', () => {
|
||||
whichSpy.mockImplementation(() => Promise.resolve('PathToShell'));
|
||||
|
||||
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);
|
||||
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!';
|
||||
getExecOutputSpy.mockImplementation(() => {
|
||||
return Promise.resolve({
|
||||
exitCode: 1,
|
||||
stdout: '',
|
||||
stderr: errorMessage
|
||||
});
|
||||
});
|
||||
const dotnetInstaller = new installer.DotnetCoreInstaller(
|
||||
inputVersion,
|
||||
inputQuality
|
||||
);
|
||||
await expect(dotnetInstaller.installDotnet()).rejects.toThrow(
|
||||
`Failed to install dotnet, exit code: 1. ${errorMessage}`
|
||||
);
|
||||
});
|
||||
|
||||
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 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);
|
||||
|
||||
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);
|
||||
const dotnetInstaller = new installer.DotnetCoreInstaller(
|
||||
inputVersion,
|
||||
inputQuality
|
||||
);
|
||||
const installedVersion = await dotnetInstaller.installDotnet();
|
||||
|
||||
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);
|
||||
}
|
||||
expect(installedVersion).toBe(inputVersion);
|
||||
});
|
||||
|
||||
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
|
||||
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`;
|
||||
|
||||
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);
|
||||
}
|
||||
getExecOutputSpy.mockImplementation(() => {
|
||||
return Promise.resolve({
|
||||
exitCode: 0,
|
||||
stdout: `${stdout}`,
|
||||
stderr: ''
|
||||
});
|
||||
});
|
||||
maxSatisfyingSpy.mockImplementation(() => inputVersion);
|
||||
|
||||
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
|
||||
const dotnetInstaller = new installer.DotnetCoreInstaller(
|
||||
inputVersion,
|
||||
inputQuality
|
||||
);
|
||||
|
||||
it('Throws if no location contains correct dotnet version', async () => {
|
||||
let thrown = false;
|
||||
try {
|
||||
await getDotnet('1000.0.0');
|
||||
} catch {
|
||||
thrown = true;
|
||||
}
|
||||
expect(thrown).toBe(true);
|
||||
}, 30000);
|
||||
await dotnetInstaller.installDotnet();
|
||||
|
||||
it('Uses an up to date bash download script', async () => {
|
||||
const httpCallbackClient = new hc.HttpClient('setup-dotnet-test', [], {
|
||||
allowRetries: true,
|
||||
maxRetries: 3
|
||||
const scriptArguments = (
|
||||
getExecOutputSpy.mock.calls[0][1] as string[]
|
||||
).join(' ');
|
||||
const expectedArgument = IS_WINDOWS
|
||||
? `-Version ${inputVersion}`
|
||||
: `--version ${inputVersion}`;
|
||||
|
||||
expect(scriptArguments).toContain(expectedArgument);
|
||||
});
|
||||
|
||||
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);
|
||||
|
||||
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.`
|
||||
);
|
||||
});
|
||||
|
||||
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();
|
||||
|
||||
const scriptArguments = (
|
||||
getExecOutputSpy.mock.calls[0][1] as string[]
|
||||
).join(' ');
|
||||
const expectedArgument = IS_WINDOWS
|
||||
? `-Quality ${inputQuality}`
|
||||
: `--quality ${inputQuality}`;
|
||||
|
||||
expect(scriptArguments).toContain(expectedArgument);
|
||||
}
|
||||
);
|
||||
|
||||
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);
|
||||
|
||||
const dotnetInstaller = new installer.DotnetCoreInstaller(
|
||||
inputVersion,
|
||||
inputQuality
|
||||
);
|
||||
|
||||
await dotnetInstaller.installDotnet();
|
||||
|
||||
const scriptArguments = (
|
||||
getExecOutputSpy.mock.calls[0][1] as string[]
|
||||
).join(' ');
|
||||
const expectedArgument = IS_WINDOWS
|
||||
? `-Channel 6.0`
|
||||
: `--channel 6.0`;
|
||||
|
||||
expect(scriptArguments).toContain(expectedArgument);
|
||||
}
|
||||
);
|
||||
|
||||
if (IS_WINDOWS) {
|
||||
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();
|
||||
|
||||
const scriptArguments = (
|
||||
getExecOutputSpy.mock.calls[0][1] as string[]
|
||||
).join(' ');
|
||||
|
||||
expect(scriptArguments).toContain(
|
||||
`-ProxyAddress ${process.env['https_proxy']}`
|
||||
);
|
||||
});
|
||||
|
||||
it(`should supply '-ProxyBypassList' argument to the installation script if env.variable 'no_proxy' is set`, async () => {
|
||||
process.env['no_proxy'] = 'first.url,second.url';
|
||||
const inputVersion = '6.0.100';
|
||||
const inputQuality = '' as QualityOptions;
|
||||
const stdout = `Fictitious dotnet version 6.0.0 is installed`;
|
||||
|
||||
getExecOutputSpy.mockImplementation(() => {
|
||||
return Promise.resolve({
|
||||
exitCode: 0,
|
||||
stdout: `${stdout}`,
|
||||
stderr: ''
|
||||
});
|
||||
});
|
||||
maxSatisfyingSpy.mockImplementation(() => inputVersion);
|
||||
|
||||
const dotnetInstaller = new installer.DotnetCoreInstaller(
|
||||
inputVersion,
|
||||
inputQuality
|
||||
);
|
||||
|
||||
await dotnetInstaller.installDotnet();
|
||||
|
||||
const scriptArguments = (
|
||||
getExecOutputSpy.mock.calls[0][1] as string[]
|
||||
).join(' ');
|
||||
|
||||
expect(scriptArguments).toContain(
|
||||
`-ProxyBypassList ${process.env['no_proxy']}`
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
const response: hc.HttpClientResponse = await httpCallbackClient.get(
|
||||
'https://dot.net/v1/dotnet-install.sh'
|
||||
);
|
||||
expect(response.message.statusCode).toBe(200);
|
||||
const upToDateContents: string = await response.readBody();
|
||||
const currentContents: string = fs
|
||||
.readFileSync(
|
||||
path.join(__dirname, '..', 'externals', 'install-dotnet.sh')
|
||||
)
|
||||
.toString();
|
||||
expect(normalizeFileContents(currentContents)).toBe(
|
||||
normalizeFileContents(upToDateContents)
|
||||
);
|
||||
}, 30000);
|
||||
|
||||
it('Uses an up to date powershell download script', async () => {
|
||||
var httpCallbackClient = new hc.HttpClient('setup-dotnet-test', [], {
|
||||
allowRetries: true,
|
||||
maxRetries: 3
|
||||
describe('addToPath() tests', () => {
|
||||
it(`should export DOTNET_ROOT env.var with value from DOTNET_INSTALL_DIR env.var`, async () => {
|
||||
process.env['DOTNET_INSTALL_DIR'] = 'fictitious/dotnet/install/dir';
|
||||
installer.DotnetCoreInstaller.addToPath();
|
||||
const dotnet_root = process.env['DOTNET_ROOT'];
|
||||
expect(dotnet_root).toBe(process.env['DOTNET_INSTALL_DIR']);
|
||||
});
|
||||
|
||||
it(`should export value from DOTNET_INSTALL_DIR env.var to the PATH`, async () => {
|
||||
process.env['DOTNET_INSTALL_DIR'] = 'fictitious/dotnet/install/dir';
|
||||
installer.DotnetCoreInstaller.addToPath();
|
||||
const path = process.env['PATH'];
|
||||
expect(path).toContain(process.env['DOTNET_INSTALL_DIR']);
|
||||
});
|
||||
});
|
||||
const response: hc.HttpClientResponse = await httpCallbackClient.get(
|
||||
'https://dot.net/v1/dotnet-install.ps1'
|
||||
);
|
||||
expect(response.message.statusCode).toBe(200);
|
||||
const upToDateContents: string = await response.readBody();
|
||||
const currentContents: string = fs
|
||||
.readFileSync(
|
||||
path.join(__dirname, '..', 'externals', 'install-dotnet.ps1')
|
||||
)
|
||||
.toString();
|
||||
expect(normalizeFileContents(currentContents)).toBe(
|
||||
normalizeFileContents(upToDateContents)
|
||||
);
|
||||
}, 30000);
|
||||
});
|
||||
|
||||
describe('DotnetVersionResolver tests', () => {
|
||||
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): Promise<void> {
|
||||
const dotnetInstaller = new installer.DotnetCoreInstaller(version);
|
||||
await dotnetInstaller.installDotnet();
|
||||
installer.DotnetCoreInstaller.addToPath();
|
||||
}
|
||||
|
@ -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,71 +1,173 @@
|
||||
import io = require('@actions/io');
|
||||
import fs = require('fs');
|
||||
import os = require('os');
|
||||
import path = require('path');
|
||||
|
||||
const toolDir = path.join(__dirname, 'runner', 'tools2');
|
||||
const tempDir = path.join(__dirname, 'runner', 'temp2');
|
||||
import * as core from '@actions/core';
|
||||
import fs from 'fs';
|
||||
import semver from 'semver';
|
||||
import * as auth from '../src/authutil';
|
||||
|
||||
import * as setup from '../src/setup-dotnet';
|
||||
import * as dotnetInstaller from '../src/installer';
|
||||
|
||||
const IS_WINDOWS = process.platform === 'win32';
|
||||
import {DotnetCoreInstaller} from '../src/installer';
|
||||
|
||||
describe('setup-dotnet tests', () => {
|
||||
beforeAll(async () => {
|
||||
process.env.RUNNER_TOOL_CACHE = toolDir;
|
||||
process.env.DOTNET_INSTALL_DIR = toolDir;
|
||||
process.env.RUNNER_TEMP = tempDir;
|
||||
process.env['INPUT_INCLUDE-PRERELEASE'] = 'false';
|
||||
await io.rmRF(toolDir);
|
||||
await io.rmRF(tempDir);
|
||||
const inputs = {} as any;
|
||||
|
||||
const getInputSpy = jest.spyOn(core, 'getInput');
|
||||
const getMultilineInputSpy = jest.spyOn(core, 'getMultilineInput');
|
||||
const setFailedSpy = jest.spyOn(core, 'setFailed');
|
||||
const warningSpy = jest.spyOn(core, 'warning');
|
||||
const debugSpy = jest.spyOn(core, 'debug');
|
||||
const infoSpy = jest.spyOn(core, 'info');
|
||||
const setOutputSpy = jest.spyOn(core, 'setOutput');
|
||||
|
||||
const existsSyncSpy = jest.spyOn(fs, 'existsSync');
|
||||
|
||||
const maxSatisfyingSpy = jest.spyOn(semver, 'maxSatisfying');
|
||||
|
||||
const installDotnetSpy = jest.spyOn(
|
||||
DotnetCoreInstaller.prototype,
|
||||
'installDotnet'
|
||||
);
|
||||
const addToPathSpy = jest.spyOn(DotnetCoreInstaller, 'addToPath');
|
||||
|
||||
const configAuthenticationSpy = jest.spyOn(auth, 'configAuthentication');
|
||||
|
||||
describe('run() tests', () => {
|
||||
beforeEach(() => {
|
||||
getMultilineInputSpy.mockImplementation(input => inputs[input as string]);
|
||||
getInputSpy.mockImplementation(input => inputs[input as string]);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
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'] = [];
|
||||
|
||||
const expectedErrorMessage = `The specified global.json file '${inputs['global-json-file']}' does not exist`;
|
||||
|
||||
await setup.run();
|
||||
expect(setFailedSpy).toHaveBeenCalledWith(expectedErrorMessage);
|
||||
});
|
||||
|
||||
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'] = [];
|
||||
|
||||
maxSatisfyingSpy.mockImplementation(() => null);
|
||||
setOutputSpy.mockImplementation(() => {});
|
||||
|
||||
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();
|
||||
|
||||
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(''));
|
||||
addToPathSpy.mockImplementation(() => {});
|
||||
|
||||
await setup.run();
|
||||
expect(addToPathSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should call auth.configAuthentication() if source-url input is provided', async () => {
|
||||
inputs['global-json-file'] = '';
|
||||
inputs['dotnet-version'] = [];
|
||||
inputs['dotnet-quality'] = '';
|
||||
inputs['source-url'] = 'fictitious.source.url';
|
||||
|
||||
configAuthenticationSpy.mockImplementation(() => {});
|
||||
|
||||
await setup.run();
|
||||
expect(configAuthenticationSpy).toHaveBeenCalledWith(
|
||||
inputs['source-url'],
|
||||
undefined
|
||||
);
|
||||
});
|
||||
|
||||
it('should call auth.configAuthentication() with proper parameters if source-url and config-file inputs are provided', async () => {
|
||||
inputs['global-json-file'] = '';
|
||||
inputs['dotnet-version'] = [];
|
||||
inputs['dotnet-quality'] = '';
|
||||
inputs['source-url'] = 'fictitious.source.url';
|
||||
inputs['config-file'] = 'fictitious.path';
|
||||
|
||||
configAuthenticationSpy.mockImplementation(() => {});
|
||||
setOutputSpy.mockImplementation(() => {});
|
||||
|
||||
await setup.run();
|
||||
expect(configAuthenticationSpy).toHaveBeenCalledWith(
|
||||
inputs['source-url'],
|
||||
inputs['config-file']
|
||||
);
|
||||
});
|
||||
|
||||
it('should call setOutput() after installation complete successfully', async () => {
|
||||
inputs['dotnet-version'] = ['6.0.300'];
|
||||
|
||||
installDotnetSpy.mockImplementation(() =>
|
||||
Promise.resolve(`${inputs['dotnet-version']}`)
|
||||
);
|
||||
addToPathSpy.mockImplementation(() => {});
|
||||
|
||||
await setup.run();
|
||||
expect(setOutputSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it(`shouldn't call setOutput() if parsing dotnet-installer logs failed`, async () => {
|
||||
inputs['dotnet-version'] = ['6.0.300'];
|
||||
const warningMessage = `Failed to output the installed version of .NET. The 'dotnet-version' output will not be set.`;
|
||||
|
||||
installDotnetSpy.mockImplementation(() => Promise.resolve(null));
|
||||
addToPathSpy.mockImplementation(() => {});
|
||||
|
||||
await setup.run();
|
||||
expect(warningSpy).toHaveBeenCalledWith(warningMessage);
|
||||
expect(setOutputSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it(`shouldn't call setOutput() if actions didn't install .NET`, async () => {
|
||||
inputs['dotnet-version'] = [];
|
||||
const warningMessage = `The 'dotnet-version' output will not be set.`;
|
||||
|
||||
addToPathSpy.mockImplementation(() => {});
|
||||
|
||||
await setup.run();
|
||||
|
||||
expect(infoSpy).toHaveBeenCalledWith(warningMessage);
|
||||
expect(setOutputSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
try {
|
||||
await io.rmRF(path.join(process.cwd(), 'global.json'));
|
||||
await io.rmRF(toolDir);
|
||||
await io.rmRF(tempDir);
|
||||
} catch {
|
||||
console.log('Failed to remove test directories');
|
||||
}
|
||||
}, 30000);
|
||||
|
||||
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();
|
||||
|
||||
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);
|
||||
|
||||
it('Acquires version of dotnet from global.json with rollForward option, install the latest patch', async () => {
|
||||
const globalJsonPath = path.join(process.cwd(), 'global.json');
|
||||
const jsonContents = `{${os.EOL}"sdk": {${os.EOL}"version":"3.1.201",${os.EOL}"rollForward":"latestFeature"${os.EOL}}${os.EOL}}`;
|
||||
if (!fs.existsSync(globalJsonPath)) {
|
||||
fs.writeFileSync(globalJsonPath, jsonContents);
|
||||
}
|
||||
|
||||
const version = '3.1';
|
||||
const installer = new dotnetInstaller.DotnetCoreInstaller(version);
|
||||
const patchVersion = await installer.resolveVersion(
|
||||
new dotnetInstaller.DotNetVersionInfo(version)
|
||||
);
|
||||
await setup.run();
|
||||
|
||||
expect(fs.existsSync(path.join(toolDir, 'sdk', patchVersion))).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);
|
||||
});
|
||||
|
@ -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
|
@ -1,17 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ "$(git status --porcelain)" != "" ]]; then
|
||||
echo ----------------------------------------
|
||||
echo git status
|
||||
echo ----------------------------------------
|
||||
git status
|
||||
echo ----------------------------------------
|
||||
echo git diff
|
||||
echo ----------------------------------------
|
||||
git diff
|
||||
echo ----------------------------------------
|
||||
echo Troubleshooting
|
||||
echo ----------------------------------------
|
||||
echo "::error::Unstaged changes detected. Locally try running: git clean -ffdx && npm ci && npm run pre-checkin"
|
||||
exit 1
|
||||
fi
|
@ -1,91 +0,0 @@
|
||||
import each from 'jest-each';
|
||||
import * as installer from '../src/installer';
|
||||
|
||||
describe('version tests', () => {
|
||||
each(['3.1.999', '3.1.101-preview.3']).test(
|
||||
"Exact version '%s' should be the same",
|
||||
vers => {
|
||||
let versInfo = new installer.DotNetVersionInfo(vers);
|
||||
|
||||
expect(versInfo.isExactVersion()).toBe(true);
|
||||
expect(versInfo.version()).toBe(vers);
|
||||
}
|
||||
);
|
||||
|
||||
each([
|
||||
['3.x', '3.x'],
|
||||
['3.*', '3.*'],
|
||||
['3.1.x', '3.1'],
|
||||
['1.1.*', '1.1'],
|
||||
['2.0', '2.0']
|
||||
]).test("Generic version '%s' should be '%s'", (vers, resVers) => {
|
||||
let versInfo = new installer.DotNetVersionInfo(vers);
|
||||
|
||||
expect(versInfo.isExactVersion()).toBe(false);
|
||||
expect(versInfo.version()).toBe(resVers);
|
||||
});
|
||||
|
||||
each([
|
||||
'',
|
||||
'.',
|
||||
'..',
|
||||
' . ',
|
||||
'. ',
|
||||
' .',
|
||||
' . . ',
|
||||
' .. ',
|
||||
' . ',
|
||||
'-1.-1',
|
||||
'-1',
|
||||
'-1.-1.-1',
|
||||
'..3',
|
||||
'1..3',
|
||||
'1..',
|
||||
'.2.3',
|
||||
'.2.x',
|
||||
'1',
|
||||
'*.*.1',
|
||||
'*.1',
|
||||
'*.',
|
||||
'1.2.',
|
||||
'1.2.-abc',
|
||||
'a.b',
|
||||
'a.b.c',
|
||||
'a.b.c-preview',
|
||||
' 0 . 1 . 2 '
|
||||
]).test("Malformed version '%s' should throw", vers => {
|
||||
expect(() => new installer.DotNetVersionInfo(vers)).toThrow();
|
||||
});
|
||||
|
||||
each([
|
||||
['3.1.x', '3.1.'],
|
||||
['3.1.*', '3.1.'],
|
||||
['3.1', '3.1.'],
|
||||
['5.0.0-preview.6', '5.0.0-preview.6'],
|
||||
['3.1.201', '3.1.201']
|
||||
]).test(
|
||||
"Resolving version '%s' as '%s'",
|
||||
async (input, expectedVersion) => {
|
||||
const dotnetInstaller = new installer.DotnetCoreInstaller(input);
|
||||
let versInfo = await dotnetInstaller.resolveVersion(
|
||||
new installer.DotNetVersionInfo(input)
|
||||
);
|
||||
console.log(versInfo);
|
||||
|
||||
expect(versInfo.startsWith(expectedVersion));
|
||||
},
|
||||
100000
|
||||
);
|
||||
|
||||
it('Resolving a nonexistent generic version fails', async () => {
|
||||
const dotnetInstaller = new installer.DotnetCoreInstaller('999.1.x');
|
||||
try {
|
||||
await dotnetInstaller.resolveVersion(
|
||||
new installer.DotNetVersionInfo('999.1.x')
|
||||
);
|
||||
fail();
|
||||
} catch {
|
||||
expect(true);
|
||||
}
|
||||
}, 100000);
|
||||
});
|
11
action.yml
11
action.yml
@ -6,7 +6,9 @@ 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'
|
||||
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:
|
||||
description: 'Optional global.json location, if your global.json isn''t located in the root of the repo.'
|
||||
source-url:
|
||||
@ -15,10 +17,9 @@ 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.'
|
||||
include-prerelease:
|
||||
description: 'Whether prerelease versions should be matched with non-exact versions (for example 5.0.0-preview.6 being matched by 5, 5.0, 5.x or 5.0.x). Defaults to false if not provided.'
|
||||
required: False
|
||||
default: 'false'
|
||||
outputs:
|
||||
dotnet-version:
|
||||
description: 'Contains the installed by action .NET SDK version for reuse.'
|
||||
runs:
|
||||
using: 'node16'
|
||||
main: 'dist/index.js'
|
||||
|
11646
dist/index.js
vendored
11646
dist/index.js
vendored
File diff suppressed because it is too large
Load Diff
@ -61,12 +61,13 @@ Pull requests are the easiest way to contribute changes to git repos at GitHub.
|
||||
|
||||
- To implement new features or fix bugs, you need to make changes to the `.ts` files, which are located in the `src` folder
|
||||
- To 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
|
||||
|
3119
externals/install-dotnet.ps1
vendored
3119
externals/install-dotnet.ps1
vendored
File diff suppressed because it is too large
Load Diff
298
externals/install-dotnet.sh
vendored
298
externals/install-dotnet.sh
vendored
@ -298,20 +298,11 @@ get_machine_architecture() {
|
||||
if command -v uname > /dev/null; then
|
||||
CPUName=$(uname -m)
|
||||
case $CPUName in
|
||||
armv1*|armv2*|armv3*|armv4*|armv5*|armv6*)
|
||||
echo "armv6-or-below"
|
||||
return 0
|
||||
;;
|
||||
armv*l)
|
||||
echo "arm"
|
||||
return 0
|
||||
;;
|
||||
aarch64|arm64)
|
||||
if [ "$(getconf LONG_BIT)" -lt 64 ]; then
|
||||
# This is 32-bit OS running on 64-bit CPU (for example Raspberry Pi OS)
|
||||
echo "arm"
|
||||
return 0
|
||||
fi
|
||||
echo "arm64"
|
||||
return 0
|
||||
;;
|
||||
@ -319,22 +310,6 @@ get_machine_architecture() {
|
||||
echo "s390x"
|
||||
return 0
|
||||
;;
|
||||
ppc64le)
|
||||
echo "ppc64le"
|
||||
return 0
|
||||
;;
|
||||
loongarch64)
|
||||
echo "loongarch64"
|
||||
return 0
|
||||
;;
|
||||
riscv64)
|
||||
echo "riscv64"
|
||||
return 0
|
||||
;;
|
||||
powerpc|ppc)
|
||||
echo "ppc"
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
@ -351,13 +326,7 @@ get_normalized_architecture_from_architecture() {
|
||||
local architecture="$(to_lowercase "$1")"
|
||||
|
||||
if [[ $architecture == \<auto\> ]]; then
|
||||
machine_architecture="$(get_machine_architecture)"
|
||||
if [[ "$machine_architecture" == "armv6-or-below" ]]; then
|
||||
say_err "Architecture \`$machine_architecture\` not supported. If you think this is a bug, report it at https://github.com/dotnet/install-scripts/issues"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo $machine_architecture
|
||||
echo "$(get_machine_architecture)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
@ -378,14 +347,6 @@ get_normalized_architecture_from_architecture() {
|
||||
echo "s390x"
|
||||
return 0
|
||||
;;
|
||||
ppc64le)
|
||||
echo "ppc64le"
|
||||
return 0
|
||||
;;
|
||||
loongarch64)
|
||||
echo "loongarch64"
|
||||
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"
|
||||
@ -423,17 +384,11 @@ get_normalized_architecture_for_specific_sdk_version() {
|
||||
# args:
|
||||
# version or channel - $1
|
||||
is_arm64_supported() {
|
||||
# Extract the major version by splitting on the dot
|
||||
major_version="${1%%.*}"
|
||||
|
||||
# Check if the major version is a valid number and less than 6
|
||||
case "$major_version" in
|
||||
[0-9]*)
|
||||
if [ "$major_version" -lt 6 ]; then
|
||||
echo false
|
||||
return 0
|
||||
fi
|
||||
;;
|
||||
#any channel or version that starts with the specified versions
|
||||
case "$1" in
|
||||
( "1"* | "2"* | "3"* | "4"* | "5"*)
|
||||
echo false
|
||||
return 0
|
||||
esac
|
||||
|
||||
echo true
|
||||
@ -452,13 +407,8 @@ get_normalized_os() {
|
||||
echo "$osname"
|
||||
return 0
|
||||
;;
|
||||
macos)
|
||||
osname='osx'
|
||||
echo "$osname"
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
say_err "'$user_defined_os' is not a supported value for --os option, supported values are: osx, macos, linux, linux-musl, freebsd, rhel.6. If you think this is a bug, report it at https://github.com/dotnet/install-scripts/issues."
|
||||
say_err "'$user_defined_os' is not a supported value for --os option, supported values are: osx, linux, linux-musl, freebsd, rhel.6. If you think this is a bug, report it at https://github.com/dotnet/install-scripts/issues."
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
@ -588,40 +538,6 @@ is_dotnet_package_installed() {
|
||||
fi
|
||||
}
|
||||
|
||||
# args:
|
||||
# downloaded file - $1
|
||||
# remote_file_size - $2
|
||||
validate_remote_local_file_sizes()
|
||||
{
|
||||
eval $invocation
|
||||
|
||||
local downloaded_file="$1"
|
||||
local remote_file_size="$2"
|
||||
local file_size=''
|
||||
|
||||
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
||||
file_size="$(stat -c '%s' "$downloaded_file")"
|
||||
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
# hardcode in order to avoid conflicts with GNU stat
|
||||
file_size="$(/usr/bin/stat -f '%z' "$downloaded_file")"
|
||||
fi
|
||||
|
||||
if [ -n "$file_size" ]; then
|
||||
say "Downloaded file size is $file_size bytes."
|
||||
|
||||
if [ -n "$remote_file_size" ] && [ -n "$file_size" ]; then
|
||||
if [ "$remote_file_size" -ne "$file_size" ]; then
|
||||
say "The remote and local file sizes are not equal. The remote file size is $remote_file_size bytes and the local size is $file_size bytes. The local package may be corrupted."
|
||||
else
|
||||
say "The remote and local file sizes are equal."
|
||||
fi
|
||||
fi
|
||||
|
||||
else
|
||||
say "Either downloaded or local package size can not be measured. One of them may be corrupted."
|
||||
fi
|
||||
}
|
||||
|
||||
# args:
|
||||
# azure_feed - $1
|
||||
# channel - $2
|
||||
@ -956,37 +872,6 @@ get_absolute_path() {
|
||||
return 0
|
||||
}
|
||||
|
||||
# args:
|
||||
# override - $1 (boolean, true or false)
|
||||
get_cp_options() {
|
||||
eval $invocation
|
||||
|
||||
local override="$1"
|
||||
local override_switch=""
|
||||
|
||||
if [ "$override" = false ]; then
|
||||
override_switch="-n"
|
||||
|
||||
# create temporary files to check if 'cp -u' is supported
|
||||
tmp_dir="$(mktemp -d)"
|
||||
tmp_file="$tmp_dir/testfile"
|
||||
tmp_file2="$tmp_dir/testfile2"
|
||||
|
||||
touch "$tmp_file"
|
||||
|
||||
# use -u instead of -n if it's available
|
||||
if cp -u "$tmp_file" "$tmp_file2" 2>/dev/null; then
|
||||
override_switch="-u"
|
||||
fi
|
||||
|
||||
# clean up
|
||||
rm -f "$tmp_file" "$tmp_file2"
|
||||
rm -rf "$tmp_dir"
|
||||
fi
|
||||
|
||||
echo "$override_switch"
|
||||
}
|
||||
|
||||
# args:
|
||||
# input_files - stdin
|
||||
# root_path - $1
|
||||
@ -998,7 +883,15 @@ copy_files_or_dirs_from_list() {
|
||||
local root_path="$(remove_trailing_slash "$1")"
|
||||
local out_path="$(remove_trailing_slash "$2")"
|
||||
local override="$3"
|
||||
local override_switch="$(get_cp_options "$override")"
|
||||
local osname="$(get_current_os_name)"
|
||||
local override_switch=$(
|
||||
if [ "$override" = false ]; then
|
||||
if [ "$osname" = "linux-musl" ]; then
|
||||
printf -- "-u";
|
||||
else
|
||||
printf -- "-n";
|
||||
fi
|
||||
fi)
|
||||
|
||||
cat | uniq | while read -r file_path; do
|
||||
local path="$(remove_beginning_slash "${file_path#$root_path}")"
|
||||
@ -1013,39 +906,14 @@ copy_files_or_dirs_from_list() {
|
||||
done
|
||||
}
|
||||
|
||||
# args:
|
||||
# zip_uri - $1
|
||||
get_remote_file_size() {
|
||||
local zip_uri="$1"
|
||||
|
||||
if machine_has "curl"; then
|
||||
file_size=$(curl -sI "$zip_uri" | grep -i content-length | awk '{ num = $2 + 0; print num }')
|
||||
elif machine_has "wget"; then
|
||||
file_size=$(wget --spider --server-response -O /dev/null "$zip_uri" 2>&1 | grep -i 'Content-Length:' | awk '{ num = $2 + 0; print num }')
|
||||
else
|
||||
say "Neither curl nor wget is available on this system."
|
||||
return
|
||||
fi
|
||||
|
||||
if [ -n "$file_size" ]; then
|
||||
say "Remote file $zip_uri size is $file_size bytes."
|
||||
echo "$file_size"
|
||||
else
|
||||
say_verbose "Content-Length header was not extracted for $zip_uri."
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
|
||||
# args:
|
||||
# zip_path - $1
|
||||
# out_path - $2
|
||||
# remote_file_size - $3
|
||||
extract_dotnet_package() {
|
||||
eval $invocation
|
||||
|
||||
local zip_path="$1"
|
||||
local out_path="$2"
|
||||
local remote_file_size="$3"
|
||||
|
||||
local temp_out_path="$(mktemp -d "$temporary_file_template")"
|
||||
|
||||
@ -1055,13 +923,9 @@ extract_dotnet_package() {
|
||||
local folders_with_version_regex='^.*/[0-9]+\.[0-9]+[^/]+/'
|
||||
find "$temp_out_path" -type f | grep -Eo "$folders_with_version_regex" | sort | copy_files_or_dirs_from_list "$temp_out_path" "$out_path" false
|
||||
find "$temp_out_path" -type f | grep -Ev "$folders_with_version_regex" | copy_files_or_dirs_from_list "$temp_out_path" "$out_path" "$override_non_versioned_files"
|
||||
|
||||
validate_remote_local_file_sizes "$zip_path" "$remote_file_size"
|
||||
|
||||
|
||||
rm -rf "$temp_out_path"
|
||||
if [ -z ${keep_zip+x} ]; then
|
||||
rm -f "$zip_path" && say_verbose "Temporary archive file $zip_path was removed"
|
||||
fi
|
||||
rm -f "$zip_path" && say_verbose "Temporary zip file $zip_path was removed"
|
||||
|
||||
if [ "$failed" = true ]; then
|
||||
say_err "Extraction failed"
|
||||
@ -1272,61 +1136,6 @@ downloadwget() {
|
||||
return 0
|
||||
}
|
||||
|
||||
extract_stem() {
|
||||
local url="$1"
|
||||
# extract the protocol
|
||||
proto="$(echo $1 | grep :// | sed -e's,^\(.*://\).*,\1,g')"
|
||||
# remove the protocol
|
||||
url="${1/$proto/}"
|
||||
# extract the path (if any) - since we know all of our feeds have a first path segment, we can skip the first one. otherwise we'd use -f2- to get the full path
|
||||
full_path="$(echo $url | grep / | cut -d/ -f2-)"
|
||||
path="$(echo $full_path | cut -d/ -f2-)"
|
||||
echo $path
|
||||
}
|
||||
|
||||
check_url_exists() {
|
||||
eval $invocation
|
||||
local url="$1"
|
||||
|
||||
local code=""
|
||||
if machine_has "curl"
|
||||
then
|
||||
code=$(curl --head -o /dev/null -w "%{http_code}" -s --fail "$url");
|
||||
elif machine_has "wget"
|
||||
then
|
||||
# get the http response, grab the status code
|
||||
server_response=$(wget -qO- --method=HEAD --server-response "$url" 2>&1)
|
||||
code=$(echo "$server_response" | grep "HTTP/" | awk '{print $2}')
|
||||
fi
|
||||
if [ $code = "200" ]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
sanitize_redirect_url() {
|
||||
eval $invocation
|
||||
|
||||
local url_stem
|
||||
url_stem=$(extract_stem "$1")
|
||||
say_verbose "Checking configured feeds for the asset at ${yellow:-}$url_stem${normal:-}"
|
||||
|
||||
for feed in "${feeds[@]}"
|
||||
do
|
||||
local trial_url="$feed/$url_stem"
|
||||
say_verbose "Checking ${yellow:-}$trial_url${normal:-}"
|
||||
if check_url_exists "$trial_url"; then
|
||||
say_verbose "Found a match at ${yellow:-}$trial_url${normal:-}"
|
||||
echo "$trial_url"
|
||||
return 0
|
||||
else
|
||||
say_verbose "No match at ${yellow:-}$trial_url${normal:-}"
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
get_download_link_from_aka_ms() {
|
||||
eval $invocation
|
||||
|
||||
@ -1363,12 +1172,6 @@ get_download_link_from_aka_ms() {
|
||||
http_codes=$( echo "$response" | awk '$1 ~ /^HTTP/ {print $2}' )
|
||||
# They all need to be 301, otherwise some links are broken (except for the last, which is not a redirect but 200 or 404).
|
||||
broken_redirects=$( echo "$http_codes" | sed '$d' | grep -v '301' )
|
||||
# The response may end without final code 2xx/4xx/5xx somehow, e.g. network restrictions on www.bing.com causes redirecting to bing.com fails with connection refused.
|
||||
# In this case it should not exclude the last.
|
||||
last_http_code=$( echo "$http_codes" | tail -n 1 )
|
||||
if ! [[ $last_http_code =~ ^(2|4|5)[0-9][0-9]$ ]]; then
|
||||
broken_redirects=$( echo "$http_codes" | grep -v '301' )
|
||||
fi
|
||||
|
||||
# All HTTP codes are 301 (Moved Permanently), the redirect link exists.
|
||||
if [[ -z "$broken_redirects" ]]; then
|
||||
@ -1379,11 +1182,6 @@ get_download_link_from_aka_ms() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
sanitized_redirect_url=$(sanitize_redirect_url "$aka_ms_download_link")
|
||||
if [[ -n "$sanitized_redirect_url" ]]; then
|
||||
aka_ms_download_link="$sanitized_redirect_url"
|
||||
fi
|
||||
|
||||
say_verbose "The redirect location retrieved: '$aka_ms_download_link'."
|
||||
return 0
|
||||
else
|
||||
@ -1395,16 +1193,23 @@ get_download_link_from_aka_ms() {
|
||||
get_feeds_to_use()
|
||||
{
|
||||
feeds=(
|
||||
"https://builds.dotnet.microsoft.com/dotnet"
|
||||
"https://ci.dot.net/public"
|
||||
"https://dotnetcli.azureedge.net/dotnet"
|
||||
"https://dotnetbuilds.azureedge.net/public"
|
||||
)
|
||||
|
||||
if [[ -n "$azure_feed" ]]; then
|
||||
feeds=("$azure_feed")
|
||||
fi
|
||||
|
||||
if [[ -n "$uncached_feed" ]]; then
|
||||
feeds=("$uncached_feed")
|
||||
if [[ "$no_cdn" == "true" ]]; then
|
||||
feeds=(
|
||||
"https://dotnetcli.blob.core.windows.net/dotnet"
|
||||
"https://dotnetbuilds.blob.core.windows.net/public"
|
||||
)
|
||||
|
||||
if [[ -n "$uncached_feed" ]]; then
|
||||
feeds=("$uncached_feed")
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
@ -1536,7 +1341,7 @@ generate_regular_links() {
|
||||
link_types+=("legacy")
|
||||
else
|
||||
legacy_download_link=""
|
||||
say_verbose "Could not construct a legacy_download_link; omitting..."
|
||||
say_verbose "Cound not construct a legacy_download_link; omitting..."
|
||||
fi
|
||||
|
||||
# Check if the SDK version is already installed.
|
||||
@ -1614,11 +1419,10 @@ install_dotnet() {
|
||||
eval $invocation
|
||||
local download_failed=false
|
||||
local download_completed=false
|
||||
local remote_file_size=0
|
||||
|
||||
mkdir -p "$install_root"
|
||||
zip_path="${zip_path:-$(mktemp "$temporary_file_template")}"
|
||||
say_verbose "Archive path: $zip_path"
|
||||
zip_path="$(mktemp "$temporary_file_template")"
|
||||
say_verbose "Zip path: $zip_path"
|
||||
|
||||
for link_index in "${!download_links[@]}"
|
||||
do
|
||||
@ -1639,10 +1443,10 @@ install_dotnet() {
|
||||
say "The resource at $link_type link '$download_link' is not available."
|
||||
;;
|
||||
*)
|
||||
say "Failed to download $link_type link '$download_link': $http_code $download_error_msg"
|
||||
say "Failed to download $link_type link '$download_link': $download_error_msg"
|
||||
;;
|
||||
esac
|
||||
rm -f "$zip_path" 2>&1 && say_verbose "Temporary archive file $zip_path was removed"
|
||||
rm -f "$zip_path" 2>&1 && say_verbose "Temporary zip file $zip_path was removed"
|
||||
else
|
||||
download_completed=true
|
||||
break
|
||||
@ -1655,10 +1459,8 @@ install_dotnet() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
remote_file_size="$(get_remote_file_size "$download_link")"
|
||||
|
||||
say "Extracting archive from $download_link"
|
||||
extract_dotnet_package "$zip_path" "$install_root" "$remote_file_size" || return 1
|
||||
say "Extracting zip from $download_link"
|
||||
extract_dotnet_package "$zip_path" "$install_root" || return 1
|
||||
|
||||
# Check if the SDK version is installed; if not, fail the installation.
|
||||
# if the version contains "RTM" or "servicing"; check if a 'release-type' SDK version is installed.
|
||||
@ -1700,6 +1502,7 @@ install_dir="<auto>"
|
||||
architecture="<auto>"
|
||||
dry_run=false
|
||||
no_path=false
|
||||
no_cdn=false
|
||||
azure_feed=""
|
||||
uncached_feed=""
|
||||
feed_credential=""
|
||||
@ -1772,6 +1575,10 @@ do
|
||||
verbose=true
|
||||
non_dynamic_parameters+=" $name"
|
||||
;;
|
||||
--no-cdn|-[Nn]o[Cc]dn)
|
||||
no_cdn=true
|
||||
non_dynamic_parameters+=" $name"
|
||||
;;
|
||||
--azure-feed|-[Aa]zure[Ff]eed)
|
||||
shift
|
||||
azure_feed="$1"
|
||||
@ -1803,22 +1610,10 @@ do
|
||||
override_non_versioned_files=false
|
||||
non_dynamic_parameters+=" $name"
|
||||
;;
|
||||
--keep-zip|-[Kk]eep[Zz]ip)
|
||||
keep_zip=true
|
||||
non_dynamic_parameters+=" $name"
|
||||
;;
|
||||
--zip-path|-[Zz]ip[Pp]ath)
|
||||
shift
|
||||
zip_path="$1"
|
||||
;;
|
||||
-?|--?|-h|--help|-[Hh]elp)
|
||||
script_name="dotnet-install.sh"
|
||||
script_name="$(basename "$0")"
|
||||
echo ".NET Tools Installer"
|
||||
echo "Usage:"
|
||||
echo " # Install a .NET SDK of a given Quality from a given Channel"
|
||||
echo " $script_name [-c|--channel <CHANNEL>] [-q|--quality <QUALITY>]"
|
||||
echo " # Install a .NET SDK of a specific public version"
|
||||
echo " $script_name [-v|--version <VERSION>]"
|
||||
echo "Usage: $script_name [-c|--channel <CHANNEL>] [-v|--version <VERSION>] [-p|--prefix <DESTINATION>]"
|
||||
echo " $script_name -h|-?|--help"
|
||||
echo ""
|
||||
echo "$script_name is a simple command line interface for obtaining dotnet cli."
|
||||
@ -1860,7 +1655,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, s390x, ppc64le and loongarch64"
|
||||
echo " Possible values: x64, arm, arm64 and s390x"
|
||||
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."
|
||||
@ -1876,14 +1671,15 @@ do
|
||||
echo " --verbose,-Verbose Display diagnostics information."
|
||||
echo " --azure-feed,-AzureFeed For internal use only."
|
||||
echo " Allows using a different storage to download SDK archives from."
|
||||
echo " This parameter is only used if --no-cdn is false."
|
||||
echo " --uncached-feed,-UncachedFeed For internal use only."
|
||||
echo " Allows using a different storage to download SDK archives from."
|
||||
echo " This parameter is only used if --no-cdn is true."
|
||||
echo " --skip-non-versioned-files Skips non-versioned files if they already exist, such as the dotnet executable."
|
||||
echo " -SkipNonVersionedFiles"
|
||||
echo " --no-cdn,-NoCdn Disable downloading from the Azure CDN, and use the uncached feed directly."
|
||||
echo " --jsonfile <JSONFILE> Determines the SDK version from a user specified global.json file."
|
||||
echo " Note: global.json must have a value for 'SDK:Version'"
|
||||
echo " --keep-zip,-KeepZip If set, downloaded file is kept."
|
||||
echo " --zip-path, -ZipPath If set, downloaded file is stored at the specified path."
|
||||
echo " -?,--?,-h,--help,-Help Shows this help message"
|
||||
echo ""
|
||||
echo "Install Location:"
|
||||
|
2549
package-lock.json
generated
2549
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
28
package.json
28
package.json
@ -1,15 +1,17 @@
|
||||
{
|
||||
"name": "setup-dotnet",
|
||||
"version": "2.1.0",
|
||||
"version": "3.0.2",
|
||||
"private": true,
|
||||
"description": "setup dotnet action",
|
||||
"main": "lib/setup-dotnet.js",
|
||||
"scripts": {
|
||||
"build": "tsc && ncc build",
|
||||
"format": "prettier --write **/*.ts",
|
||||
"format-check": "prettier --check **/*.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",
|
||||
"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"
|
||||
},
|
||||
"repository": {
|
||||
@ -24,26 +26,30 @@
|
||||
"author": "GitHub",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.6.0",
|
||||
"@actions/core": "^1.10.0",
|
||||
"@actions/exec": "^1.0.4",
|
||||
"@actions/github": "^1.1.0",
|
||||
"@actions/http-client": "^1.0.8",
|
||||
"@actions/http-client": "^2.0.1",
|
||||
"@actions/io": "^1.0.2",
|
||||
"fast-xml-parser": "^3.15.1",
|
||||
"semver": "^6.3.0",
|
||||
"xmlbuilder": "^13.0.2"
|
||||
"fast-xml-parser": "^4.0.10",
|
||||
"semver": "^6.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^27.0.2",
|
||||
"@types/node": "^16.11.25",
|
||||
"@types/semver": "^6.2.2",
|
||||
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||
"@typescript-eslint/parser": "^5.54.0",
|
||||
"@vercel/ncc": "^0.33.4",
|
||||
"eslint": "^8.35.0",
|
||||
"eslint-config-prettier": "^8.6.0",
|
||||
"eslint-plugin-jest": "^27.2.1",
|
||||
"husky": "^8.0.1",
|
||||
"jest": "^27.2.5",
|
||||
"jest-circus": "^27.2.5",
|
||||
"prettier": "^1.19.1",
|
||||
"prettier": "^2.8.4",
|
||||
"ts-jest": "^27.0.5",
|
||||
"typescript": "^3.9.7",
|
||||
"typescript": "^4.8.4",
|
||||
"wget-improved": "^3.2.1"
|
||||
},
|
||||
"jest": {
|
||||
|
351
src/authutil.ts
351
src/authutil.ts
@ -1,155 +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 * as xmlbuilder from 'xmlbuilder';
|
||||
import * as xmlParser from 'fast-xml-parser';
|
||||
import {ProcessEnvOptions} from 'child_process';
|
||||
|
||||
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
|
||||
) {
|
||||
console.log(
|
||||
`dotnet-auth: Finding any source references in ${existingFileLocation}, writing a new temporary configuration file with credentials to ${tempFileLocation}`
|
||||
);
|
||||
let xml: xmlbuilder.XMLElement;
|
||||
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 || 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');
|
||||
var json = xmlParser.parse(curContents, {ignoreAttributes: false});
|
||||
|
||||
if (typeof json.configuration == 'undefined') {
|
||||
throw new Error(`The provided NuGet.config seems invalid.`);
|
||||
}
|
||||
if (typeof json.configuration.packageSources != 'undefined') {
|
||||
if (typeof json.configuration.packageSources.add != 'undefined') {
|
||||
// file has at least one <add>
|
||||
if (typeof json.configuration.packageSources.add[0] == 'undefined') {
|
||||
// file has only one <add>
|
||||
if (
|
||||
json.configuration.packageSources.add['@_value']
|
||||
.toLowerCase()
|
||||
.includes(feedUrl.toLowerCase())
|
||||
) {
|
||||
let key = json.configuration.packageSources.add['@_key'];
|
||||
sourceKeys.push(key);
|
||||
core.debug(`Found a URL with key ${key}`);
|
||||
}
|
||||
} else {
|
||||
// file has 2+ <add>
|
||||
for (
|
||||
let i = 0;
|
||||
i < json.configuration.packageSources.add.length;
|
||||
i++
|
||||
) {
|
||||
const source = json.configuration.packageSources.add[i];
|
||||
const value = source['@_value'];
|
||||
core.debug(`source '${value}'`);
|
||||
if (value.toLowerCase().includes(feedUrl.toLowerCase())) {
|
||||
let key = source['@_key'];
|
||||
sourceKeys.push(key);
|
||||
core.debug(`Found a URL with key ${key}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xml = xmlbuilder
|
||||
.create('configuration')
|
||||
.ele('config')
|
||||
.ele('add', {key: 'defaultPushSource', value: sourceUrl})
|
||||
.up()
|
||||
.up();
|
||||
|
||||
if (sourceKeys.length == 0) {
|
||||
let keystring = 'Source';
|
||||
xml = xml
|
||||
.ele('packageSources')
|
||||
.ele('add', {key: keystring, value: sourceUrl})
|
||||
.up()
|
||||
.up();
|
||||
sourceKeys.push(keystring);
|
||||
}
|
||||
xml = xml.ele('packageSourceCredentials');
|
||||
|
||||
sourceKeys.forEach(key => {
|
||||
if (!isValidKey(key)) {
|
||||
throw new Error(
|
||||
"Source name can contain letters, numbers, and '-', '_', '.' symbols only. Please, fix source name in NuGet.config and try again."
|
||||
);
|
||||
}
|
||||
|
||||
xml = xml
|
||||
.ele(key)
|
||||
.ele('add', {key: 'Username', value: owner})
|
||||
.up()
|
||||
.ele('add', {
|
||||
key: 'ClearTextPassword',
|
||||
value: process.env.NUGET_AUTH_TOKEN
|
||||
})
|
||||
.up()
|
||||
.up();
|
||||
});
|
||||
|
||||
// If NuGet fixes itself such that on Linux it can look for environment variables in the config file (it doesn't seem to work today),
|
||||
// use this for the value above
|
||||
// process.platform == 'win32'
|
||||
// ? '%NUGET_AUTH_TOKEN%'
|
||||
// : '$NUGET_AUTH_TOKEN'
|
||||
|
||||
var output = xml.end({pretty: true});
|
||||
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);
|
||||
}
|
||||
|
582
src/installer.ts
582
src/installer.ts
@ -1,304 +1,278 @@
|
||||
// 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 hc = require('@actions/http-client');
|
||||
import {chmodSync} from 'fs';
|
||||
import * as path from 'path';
|
||||
import {ExecOptions} from '@actions/exec/lib/interfaces';
|
||||
import * as semver from 'semver';
|
||||
|
||||
const IS_WINDOWS = process.platform === 'win32';
|
||||
|
||||
/**
|
||||
* Represents the inputted version information
|
||||
*/
|
||||
export class DotNetVersionInfo {
|
||||
public inputVersion: string;
|
||||
private fullversion: string;
|
||||
private isExactVersionSet: boolean = false;
|
||||
|
||||
constructor(version: string) {
|
||||
this.inputVersion = version;
|
||||
|
||||
// Check for exact match
|
||||
if (semver.valid(semver.clean(version) || '') != null) {
|
||||
this.fullversion = semver.clean(version) as string;
|
||||
this.isExactVersionSet = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const parts: string[] = version.split('.');
|
||||
|
||||
if (parts.length < 2 || parts.length > 3) this.throwInvalidVersionFormat();
|
||||
|
||||
if (parts.length == 3 && parts[2] !== 'x' && parts[2] !== '*') {
|
||||
this.throwInvalidVersionFormat();
|
||||
}
|
||||
|
||||
const major = this.getVersionNumberOrThrow(parts[0]);
|
||||
const minor = ['x', '*'].includes(parts[1])
|
||||
? parts[1]
|
||||
: this.getVersionNumberOrThrow(parts[1]);
|
||||
|
||||
this.fullversion = major + '.' + minor;
|
||||
}
|
||||
|
||||
private getVersionNumberOrThrow(input: string): number {
|
||||
try {
|
||||
if (!input || input.trim() === '') this.throwInvalidVersionFormat();
|
||||
|
||||
let number = Number(input);
|
||||
|
||||
if (Number.isNaN(number) || number < 0) this.throwInvalidVersionFormat();
|
||||
|
||||
return number;
|
||||
} catch {
|
||||
this.throwInvalidVersionFormat();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private throwInvalidVersionFormat() {
|
||||
throw new Error(
|
||||
'Invalid version format! Supported: 1.2.3, 1.2, 1.2.x, 1.2.*'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* If true exacatly one version should be resolved
|
||||
*/
|
||||
public isExactVersion(): boolean {
|
||||
return this.isExactVersionSet;
|
||||
}
|
||||
|
||||
public version(): string {
|
||||
return this.fullversion;
|
||||
}
|
||||
}
|
||||
|
||||
export class DotnetCoreInstaller {
|
||||
constructor(version: string, includePrerelease: boolean = false) {
|
||||
this.version = version;
|
||||
this.includePrerelease = includePrerelease;
|
||||
}
|
||||
|
||||
public async installDotnet() {
|
||||
let output = '';
|
||||
let resultCode = 0;
|
||||
|
||||
let calculatedVersion = await this.resolveVersion(
|
||||
new DotNetVersionInfo(this.version)
|
||||
);
|
||||
|
||||
var envVariables: {[key: string]: string} = {};
|
||||
for (let key in process.env) {
|
||||
if (process.env[key]) {
|
||||
let value: any = process.env[key];
|
||||
envVariables[key] = value;
|
||||
}
|
||||
}
|
||||
if (IS_WINDOWS) {
|
||||
let escapedScript = path
|
||||
.join(__dirname, '..', 'externals', 'install-dotnet.ps1')
|
||||
.replace(/'/g, "''");
|
||||
let command = `& '${escapedScript}'`;
|
||||
if (calculatedVersion) {
|
||||
command += ` -Version ${calculatedVersion}`;
|
||||
}
|
||||
if (process.env['https_proxy'] != null) {
|
||||
command += ` -ProxyAddress ${process.env['https_proxy']}`;
|
||||
}
|
||||
// This is not currently an option
|
||||
if (process.env['no_proxy'] != null) {
|
||||
command += ` -ProxyBypassList ${process.env['no_proxy']}`;
|
||||
}
|
||||
|
||||
// process.env must be explicitly passed in for DOTNET_INSTALL_DIR to be used
|
||||
const powershellPath =
|
||||
(await io.which('pwsh', false)) || (await io.which('powershell', true));
|
||||
|
||||
var options: ExecOptions = {
|
||||
listeners: {
|
||||
stdout: (data: Buffer) => {
|
||||
output += data.toString();
|
||||
}
|
||||
},
|
||||
env: envVariables
|
||||
};
|
||||
|
||||
resultCode = await exec.exec(
|
||||
`"${powershellPath}"`,
|
||||
[
|
||||
'-NoLogo',
|
||||
'-Sta',
|
||||
'-NoProfile',
|
||||
'-NonInteractive',
|
||||
'-ExecutionPolicy',
|
||||
'Unrestricted',
|
||||
'-Command',
|
||||
command
|
||||
],
|
||||
options
|
||||
);
|
||||
} else {
|
||||
let escapedScript = path
|
||||
.join(__dirname, '..', 'externals', 'install-dotnet.sh')
|
||||
.replace(/'/g, "''");
|
||||
chmodSync(escapedScript, '777');
|
||||
|
||||
const scriptPath = await io.which(escapedScript, true);
|
||||
|
||||
let scriptArguments: string[] = [];
|
||||
if (calculatedVersion) {
|
||||
scriptArguments.push('--version', calculatedVersion);
|
||||
}
|
||||
|
||||
// process.env must be explicitly passed in for DOTNET_INSTALL_DIR to be used
|
||||
resultCode = await exec.exec(`"${scriptPath}"`, scriptArguments, {
|
||||
listeners: {
|
||||
stdout: (data: Buffer) => {
|
||||
output += data.toString();
|
||||
}
|
||||
},
|
||||
env: envVariables
|
||||
});
|
||||
}
|
||||
|
||||
if (resultCode != 0) {
|
||||
throw new Error(`Failed to install dotnet ${resultCode}. ${output}`);
|
||||
}
|
||||
}
|
||||
|
||||
static addToPath() {
|
||||
if (process.env['DOTNET_INSTALL_DIR']) {
|
||||
core.addPath(process.env['DOTNET_INSTALL_DIR']);
|
||||
core.exportVariable('DOTNET_ROOT', process.env['DOTNET_INSTALL_DIR']);
|
||||
} else {
|
||||
if (IS_WINDOWS) {
|
||||
// This is the default set in install-dotnet.ps1
|
||||
core.addPath(
|
||||
path.join(process.env['LocalAppData'] + '', 'Microsoft', 'dotnet')
|
||||
);
|
||||
core.exportVariable(
|
||||
'DOTNET_ROOT',
|
||||
path.join(process.env['LocalAppData'] + '', 'Microsoft', 'dotnet')
|
||||
);
|
||||
} else {
|
||||
// This is the default set in install-dotnet.sh
|
||||
core.addPath(path.join(process.env['HOME'] + '', '.dotnet'));
|
||||
core.exportVariable(
|
||||
'DOTNET_ROOT',
|
||||
path.join(process.env['HOME'] + '', '.dotnet')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(process.env['PATH']);
|
||||
}
|
||||
|
||||
// versionInfo - versionInfo of the SDK/Runtime
|
||||
async resolveVersion(versionInfo: DotNetVersionInfo): Promise<string> {
|
||||
if (versionInfo.isExactVersion()) {
|
||||
return versionInfo.version();
|
||||
}
|
||||
|
||||
const httpClient = new hc.HttpClient('actions/setup-dotnet', [], {
|
||||
allowRetries: true,
|
||||
maxRetries: 3
|
||||
});
|
||||
|
||||
const releasesJsonUrl: string = await this.getReleasesJsonUrl(
|
||||
httpClient,
|
||||
versionInfo.version().split('.')
|
||||
);
|
||||
|
||||
const releasesResponse = await httpClient.getJson<any>(releasesJsonUrl);
|
||||
const releasesResult = releasesResponse.result || {};
|
||||
let releasesInfo: any[] = releasesResult['releases'];
|
||||
releasesInfo = releasesInfo.filter((releaseInfo: any) => {
|
||||
return (
|
||||
semver.satisfies(releaseInfo['sdk']['version'], versionInfo.version(), {
|
||||
includePrerelease: this.includePrerelease
|
||||
}) ||
|
||||
semver.satisfies(
|
||||
releaseInfo['sdk']['version-display'],
|
||||
versionInfo.version(),
|
||||
{
|
||||
includePrerelease: this.includePrerelease
|
||||
}
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
// Exclude versions that are newer than the latest if using not exact
|
||||
let latestSdk: string = releasesResult['latest-sdk'];
|
||||
|
||||
releasesInfo = releasesInfo.filter((releaseInfo: any) =>
|
||||
semver.lte(releaseInfo['sdk']['version'], latestSdk, {
|
||||
includePrerelease: this.includePrerelease
|
||||
})
|
||||
);
|
||||
|
||||
// Sort for latest version
|
||||
releasesInfo = releasesInfo.sort((a, b) =>
|
||||
semver.rcompare(a['sdk']['version'], b['sdk']['version'], {
|
||||
includePrerelease: this.includePrerelease
|
||||
})
|
||||
);
|
||||
|
||||
if (releasesInfo.length == 0) {
|
||||
throw new Error(
|
||||
`Could not find dotnet core version. Please ensure that specified version ${versionInfo.inputVersion} is valid.`
|
||||
);
|
||||
}
|
||||
|
||||
let release = releasesInfo[0];
|
||||
return release['sdk']['version'];
|
||||
}
|
||||
|
||||
private async getReleasesJsonUrl(
|
||||
httpClient: hc.HttpClient,
|
||||
versionParts: string[]
|
||||
): Promise<string> {
|
||||
const response = await httpClient.getJson<any>(DotNetCoreIndexUrl);
|
||||
const result = response.result || {};
|
||||
let releasesInfo: any[] = result['releases-index'];
|
||||
|
||||
releasesInfo = releasesInfo.filter((info: any) => {
|
||||
// channel-version is the first 2 elements of the version (e.g. 2.1), filter out versions that don't match 2.1.x.
|
||||
const sdkParts: string[] = info['channel-version'].split('.');
|
||||
if (
|
||||
versionParts.length >= 2 &&
|
||||
!(versionParts[1] == 'x' || versionParts[1] == '*')
|
||||
) {
|
||||
return versionParts[0] == sdkParts[0] && versionParts[1] == sdkParts[1];
|
||||
}
|
||||
return versionParts[0] == sdkParts[0];
|
||||
});
|
||||
|
||||
if (releasesInfo.length === 0) {
|
||||
throw new Error(
|
||||
`Could not find info for version ${versionParts.join(
|
||||
'.'
|
||||
)} at ${DotNetCoreIndexUrl}`
|
||||
);
|
||||
}
|
||||
|
||||
const releaseInfo = releasesInfo[0];
|
||||
if (releaseInfo['support-phase'] === 'eol') {
|
||||
core.warning(
|
||||
`${releaseInfo['product']} ${releaseInfo['channel-version']} is no longer supported and will not receive security updates in the future. Please refer to https://aka.ms/dotnet-core-support for more information about the .NET support policy.`
|
||||
);
|
||||
}
|
||||
|
||||
return releaseInfo['releases.json'];
|
||||
}
|
||||
|
||||
private version: string;
|
||||
private includePrerelease: boolean;
|
||||
}
|
||||
|
||||
const DotNetCoreIndexUrl: string =
|
||||
'https://builds.dotnet.microsoft.com/dotnet/release-metadata/releases-index.json';
|
||||
// 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_LINUX, IS_WINDOWS} 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 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(
|
||||
`The 'dotnet-quality' input can be used only with .NET SDK version in A.B, A.B.x, A, A.x and A.B.Cxx formats where the major tag is higher than 5. You specified: ${this.version}. 'dotnet-quality' input is ignored.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public async installDotnet(): Promise<string | null> {
|
||||
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, stderr} = await exec.getExecOutput(
|
||||
`"${scriptPath}"`,
|
||||
scriptArguments,
|
||||
getExecOutputOptions
|
||||
);
|
||||
if (exitCode) {
|
||||
throw new Error(
|
||||
`Failed to install dotnet, exit code: ${exitCode}. ${stderr}`
|
||||
);
|
||||
}
|
||||
|
||||
return this.parseInstalledVersion(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,20 @@
|
||||
import * as core from '@actions/core';
|
||||
import * as installer from './installer';
|
||||
import {DotnetCoreInstaller} from './installer';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import path from 'path';
|
||||
import semver from 'semver';
|
||||
import * as auth from './authutil';
|
||||
|
||||
const qualityOptions = [
|
||||
'daily',
|
||||
'signed',
|
||||
'validated',
|
||||
'preview',
|
||||
'ga'
|
||||
] as const;
|
||||
|
||||
export type QualityOptions = (typeof qualityOptions)[number];
|
||||
|
||||
export async function run() {
|
||||
try {
|
||||
//
|
||||
@ -15,11 +26,12 @@ export async function run() {
|
||||
// If a valid version still can't be identified, nothing will be installed.
|
||||
// Proxy, auth, (etc) are still set up, even if no version is identified
|
||||
//
|
||||
let versions = core.getMultilineInput('dotnet-version');
|
||||
const versions = core.getMultilineInput('dotnet-version');
|
||||
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`
|
||||
@ -34,22 +46,30 @@ export async function run() {
|
||||
const globalJsonPath = path.join(process.cwd(), 'global.json');
|
||||
if (fs.existsSync(globalJsonPath)) {
|
||||
versions.push(getVersionFromGlobalJson(globalJsonPath));
|
||||
} else {
|
||||
core.info(
|
||||
`The global.json wasn't found in the root directory. No .NET version will be installed.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (versions.length) {
|
||||
const includePrerelease: boolean = core.getBooleanInput(
|
||||
'include-prerelease'
|
||||
);
|
||||
let dotnetInstaller!: installer.DotnetCoreInstaller;
|
||||
for (const version of new Set<string>(versions)) {
|
||||
dotnetInstaller = new installer.DotnetCoreInstaller(
|
||||
version,
|
||||
includePrerelease
|
||||
const quality = core.getInput('dotnet-quality') as QualityOptions;
|
||||
|
||||
if (quality && !qualityOptions.includes(quality)) {
|
||||
throw new Error(
|
||||
`Value '${quality}' is not supported for the 'dotnet-quality' option. Supported values are: daily, signed, validated, preview, ga.`
|
||||
);
|
||||
await dotnetInstaller.installDotnet();
|
||||
}
|
||||
installer.DotnetCoreInstaller.addToPath();
|
||||
|
||||
let dotnetInstaller: DotnetCoreInstaller;
|
||||
const uniqueVersions = new Set<string>(versions);
|
||||
for (const version of uniqueVersions) {
|
||||
dotnetInstaller = new DotnetCoreInstaller(version, quality);
|
||||
const installedVersion = await dotnetInstaller.installDotnet();
|
||||
installedDotnetVersions.push(installedVersion);
|
||||
}
|
||||
DotnetCoreInstaller.addToPath();
|
||||
}
|
||||
|
||||
const sourceUrl: string = core.getInput('source-url');
|
||||
@ -58,15 +78,17 @@ export async function run() {
|
||||
auth.configAuthentication(sourceUrl, configFile);
|
||||
}
|
||||
|
||||
outputInstalledVersion(installedDotnetVersions, globalJsonFileInput);
|
||||
|
||||
const matchersPath = path.join(__dirname, '..', '.github');
|
||||
console.log(`##[add-matcher]${path.join(matchersPath, 'csc.json')}`);
|
||||
core.info(`##[add-matcher]${path.join(matchersPath, 'csc.json')}`);
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
function getVersionFromGlobalJson(globalJsonPath: string): string {
|
||||
let version: string = '';
|
||||
let version = '';
|
||||
const globalJson = JSON.parse(
|
||||
// .trim() is necessary to strip BOM https://github.com/nodejs/node/issues/20649
|
||||
fs.readFileSync(globalJsonPath, {encoding: 'utf8'}).trim()
|
||||
@ -82,4 +104,37 @@ function getVersionFromGlobalJson(globalJsonPath: string): string {
|
||||
return version;
|
||||
}
|
||||
|
||||
function outputInstalledVersion(
|
||||
installedVersions: (string | null)[],
|
||||
globalJsonFileInput: string
|
||||
): void {
|
||||
if (!installedVersions.length) {
|
||||
core.info(`The 'dotnet-version' output will not be set.`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (installedVersions.includes(null)) {
|
||||
core.warning(
|
||||
`Failed to output the installed version of .NET. The 'dotnet-version' output will not be set.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (globalJsonFileInput) {
|
||||
const versionToOutput = installedVersions.at(-1); // .NET SDK version parsed from the global.json file is installed last
|
||||
core.setOutput('dotnet-version', versionToOutput);
|
||||
return;
|
||||
}
|
||||
|
||||
const versionToOutput = semver.maxSatisfying(
|
||||
installedVersions as string[],
|
||||
'*',
|
||||
{
|
||||
includePrerelease: true
|
||||
}
|
||||
);
|
||||
|
||||
core.setOutput('dotnet-version', versionToOutput);
|
||||
}
|
||||
|
||||
run();
|
||||
|
2
src/utils.ts
Normal file
2
src/utils.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export const IS_WINDOWS = process.platform === 'win32';
|
||||
export const IS_LINUX = process.platform === 'linux';
|
@ -35,6 +35,7 @@
|
||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||
|
||||
/* Additional Checks */
|
||||
"useUnknownInCatchVariables": false, /* Type catch clause variables as 'unknown' instead of 'any'. */
|
||||
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||
@ -48,7 +49,8 @@
|
||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||
// "types": [], /* Type declaration files to be included in compilation. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
"resolveJsonModule": true, /* Allows importing modules with a '.json' extension, which is a common practice in node projects. */
|
||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
|
||||
|
Reference in New Issue
Block a user