Compare commits

..

119 Commits

Author SHA1 Message Date
fe67d2f8db update team 2022-12-22 23:59:20 +01:00
023f7252a0 Update CODEOWNERS 2022-12-22 23:56:54 +01:00
3f3ad54c0c Merge pull request #358 from akv-platform/apply-reusable-workflows
Update action to use reusable workflows
2022-12-22 10:50:01 +02:00
e1d35446fe Merge pull request #359 from akv-platform/documentation-clarification
Update README.md to clarify installation process
2022-12-21 16:17:31 +02:00
11aaa65761 Fix review points 2022-12-20 16:24:40 +01:00
13abe4777e Update step id naming 2022-12-20 15:31:56 +01:00
aefe5b483f Update README.md 2022-12-20 15:03:30 +01:00
047f06d086 Update README.md 2022-12-20 14:58:50 +01:00
014f8c8384 Add part about temporary global.json files 2022-12-20 12:30:05 +01:00
80c862dc38 Update README.md 2022-12-20 11:45:22 +01:00
e21107efbd Update README.md 2022-12-20 11:41:39 +01:00
d8f1ab14a7 Add link to global.json documentation ti README.md 2022-12-20 11:38:26 +01:00
f05a62b1cc Update README.md to clarify installation process 2022-12-20 11:36:11 +01:00
338d4e3bbf Update workflows to use reusable-workflows repo 2022-12-19 12:38:18 +01:00
228eec3014 Add links to reusable workflows 2022-12-15 16:24:18 +01:00
c483e03222 Update workflows 2022-12-15 16:16:00 +01:00
a35f420124 Update to use public version of reusable workflows 2022-12-14 13:20:26 +01:00
4214866121 Update workflows 2022-12-14 12:24:48 +01:00
0681939502 Update workflow.yml 2022-12-14 11:56:17 +01:00
ba8a1f9c02 Update action to use reusable workflows 2022-12-14 11:41:18 +01:00
09d024bd02 Merge pull request #348 from JamesMGreene/patch-1
Update to latest `actions/publish-action`
2022-11-23 11:20:14 +02:00
8ae4c080ce Update to latest actions/publish-action
To avoid Actions core deprecation messages.

https://github.com/actions/publish-action/releases/tag/v0.2.1
2022-11-22 10:50:00 -06:00
c5d2f92cae Bump minimatch from 3.0.4 to 3.1.2 (#347) 2022-11-18 15:49:29 +01:00
069c35efca Merge pull request #344 from teo-tsirpanis/patch-1
Notify if `global.json` was not found in the root directory.
2022-11-17 10:03:58 +01:00
6a2cd88ae8 Address PR feedback; update the installers and the Squid image. 2022-11-15 18:00:14 +02:00
9984a6fa87 Warn if the action ends up not installing any .NET version. 2022-11-14 19:58:22 +02:00
607fce577a Update the link to the .Net Core releases index file (#337) 2022-10-24 14:21:32 +02:00
501b34e8f6 Merge pull request #336 from e-korolevskii/refactor-nuget-cfg-parse
Refactor nuget cfg parse
2022-10-24 09:42:37 +02:00
b827fcce4d build 2022-10-13 16:35:12 +02:00
239baf3c5b Merge branch 'main' into refactor-nuget-cfg-parse 2022-10-13 16:34:35 +02:00
4d4a70f4a5 Add logic for processing DOTNET_INSTALL_DIR environment variable (#332) 2022-10-10 14:27:29 +02:00
70c3f4d098 Merge pull request #331 from rentziass/rentziass/update-actions-core
Update @actions/core to 1.10.0
2022-10-07 13:50:06 +02:00
9260643816 Update @actions/core to 1.10.0 2022-10-06 12:05:06 +01:00
45c9f236cf Enable ability to change .NET SDK installation directory by DOTNET_INSTALL_DIR environment variable (#329) 2022-10-04 10:22:05 +02:00
6d6c7c9313 build 2022-09-30 09:33:54 +02:00
e753bbf2ff remove build 2022-09-30 09:33:03 +02:00
629365b26e Merge branch 'main' into refactor-nuget-cfg-parse 2022-09-30 09:28:48 +02:00
942a0bea39 format 2022-09-30 02:37:51 +02:00
26db2473e9 fix empty first line 2022-09-30 02:23:20 +02:00
467621733d add packageSourceCredentials 2022-09-30 02:19:09 +02:00
bdd38d13dc build 2022-09-30 02:05:09 +02:00
1d2f8f9eaf add debug log 2022-09-30 02:04:34 +02:00
354d280fa3 refactor using of XMLBuilder 2022-09-30 01:54:05 +02:00
0ff311b0d0 add nested dep license 2022-09-29 18:43:45 +02:00
bc65ba63d3 update license 2022-09-29 18:30:09 +02:00
90642fa8c5 update parser to v4 2022-09-29 18:23:42 +02:00
c7e7147fd3 Add ability to write resolved version of SDK into the output variable (#324) 2022-09-29 17:45:25 +02:00
cf081e76a2 merge main & build 2022-09-28 15:30:56 +02:00
4ca3c96b49 Merge branch 'main' into refactor-nuget-cfg-parse 2022-09-28 09:30:07 +02:00
0705ef0281 Implement proposal stated in ADR for setup-dotnet v3 and functionality from feature request #219 (#315) 2022-09-27 14:47:12 +02:00
a351d9ea84 Add support for Windows-arm (#320)
* update to use pwsh if it is available

* fix spacing

* update install script

* Update src/installer.ts

Co-authored-by: Ivan <98037481+IvanZosimov@users.noreply.github.com>

* update index.js

* fix format

Co-authored-by: Ivan <98037481+IvanZosimov@users.noreply.github.com>
2022-09-26 10:12:13 +02:00
cc76dfab99 format 2022-09-21 15:14:01 +03:00
857c316a9d Merge pull request #313 from panticmilos/vmpantic/update-version-package-json
Update package lock version
2022-09-20 11:36:22 +02:00
1f2c90bb99 Merge branch 'main' into refactor-nuget-cfg-parse 2022-09-19 20:18:40 +02:00
251997c37d updated installers 2022-09-19 20:18:24 +02:00
bba8299c35 npm run update-installers 2022-09-14 16:08:36 +02:00
fd4e15fa44 Merge pull request #291 from vsafonkin/v-vsafonkin/v3-adr
V3 setup-dotnet ADR
2022-09-14 09:52:09 +02:00
95e7de77d1 Set status accepted 2022-09-13 16:19:35 +02:00
52c3199a78 ADR change (#1)
* Update ADR proposal

ADR proposal was updated in order to reflect cahnges that will be done
more thoroughly.

* Fix formatting
2022-09-13 12:41:55 +02:00
2d9def7067 Rework 2022-09-11 13:42:07 +02:00
df51eabf53 Update package lock version 2022-09-05 13:18:26 +02:00
e4b2fcaa19 Merge pull request #312 from panticmilos/vmpantic/update-version-package-json
Update actions version in package json
2022-09-01 09:44:52 +02:00
d45c10e6f7 Run update installers 2022-08-31 17:40:05 +02:00
4d1b6c2c63 Update actions version in package json 2022-08-31 16:21:24 +02:00
5d7bc0454b update installers 2022-08-31 16:01:51 +02:00
792e988dae build 2022-08-31 15:43:30 +02:00
e5034212c9 refactoring 2022-08-31 15:41:59 +02:00
0997db20d4 refactoring 2022-08-31 15:41:46 +02:00
4cb4764ae2 Update ADR date 2022-08-29 11:23:22 +02:00
d33e605efe Grammar fixes 2022-08-24 12:32:58 +02:00
f7747565a1 Merge pull request #305 from e-korolevskii/update-contributors-guide
Update contributors guide
2022-08-10 16:45:38 +02:00
2f75d1de25 Merge branch 'actions:main' into update-contributors-guide 2022-08-10 16:42:02 +02:00
e6a9a96293 Update docs/contributors.md
Co-authored-by: Ivan <98037481+IvanZosimov@users.noreply.github.com>
2022-08-09 23:54:52 +02:00
025aba53b2 rephased docs 2022-08-03 19:15:44 +02:00
37b00c4fc5 Merge pull request #250 from nogic1008/refactor/boolean-input
Use `core.getBooleanInput()` to resolve `include-prerelease` option
2022-08-02 15:24:04 +02:00
c2dac7f367 test: add include-prerelease env on test 2022-07-31 23:27:05 +00:00
c5267f5e54 chore: set include-prerelease to false on default 2022-07-31 23:27:05 +00:00
ba5e53c61d refactor: use core.getBooleanInput() 2022-07-31 23:27:05 +00:00
043fb8900f advice on updating installers 2022-08-01 01:10:29 +02:00
cb04ff8cb3 Merge pull request #301 from nogic1008/migrate/husky4-8
Fix husky config to resolve git hook error
2022-07-29 15:19:36 +02:00
bac4044d91 ci: add --ignore-scripts argument 2022-07-29 07:17:54 +00:00
d26ead4cf0 chore(deps-dev): migrate husky config to v8
Follow: https://github.com/typicode/husky-4-to-8
- npm install husky --save-dev
- npx husky-init
- npm exec -- github:typicode/husky-4-to-8 --remove-v4-config
2022-07-29 07:17:54 +00:00
e81cd4d454 Merge pull request #302 from e-korolevskii/scripts-update
Updated local installation scripts
2022-07-29 08:52:45 +02:00
ee11c4faa4 updated guide 2022-07-29 02:02:42 +02:00
8bf1fb6084 updated local installation scripts 2022-07-29 01:22:35 +02:00
c0d4ad69d8 Don't need C# analysis for CodeQL 2022-04-29 13:54:18 -04:00
afe2daba1f Create codeql-analysis.yml 2022-04-29 13:48:41 -04:00
fb09b12527 v3 adr 2022-04-29 11:22:26 +02:00
5cc895510b Update @zeit/ncc to @vercel/ncc (#290)
* update @zeit/ncc to @vercel/ncc

* rebuild project
2022-04-28 11:37:53 +02:00
158737d5b1 Merge pull request #289 from vsafonkin/v-vsafonkin/update-wget-package
Update vulnerable packages
2022-04-21 13:10:39 +03:00
fcf565ec50 Update vulnerable packages 2022-04-21 11:17:56 +02:00
f078482971 add global-json-file input (#276)
* support specifying global.json location with global-json-file input

* add test workflow jobs for global.json usage

* fix typo in global-json-file description

Co-authored-by: Brian Cristante <33549821+brcrista@users.noreply.github.com>

Co-authored-by: Brian Cristante <33549821+brcrista@users.noreply.github.com>
2022-04-18 08:25:56 -04:00
0fb87b12d2 Merge pull request #285 from vsafonkin/v-vsafonkin/add-code-of-conduct
Add code of conduct
2022-04-15 11:03:29 +03:00
4fe7a196b5 Add code of conduct 2022-04-13 16:58:12 +02:00
9283a8cf7a switch side by side testing example to single setup step (#283) 2022-04-11 11:50:34 -04:00
53d632b5c0 Update docs to v2 (#278)
* Update docs to v2

* Bump checkout action to v3

* Update installer scripts

* Replace v2 to vX on the docs, minor fixes

* Remove extra whitespace
2022-04-01 09:48:47 -04:00
9211491ffb Merge pull request #273 from actions/v-vlsafo/update-deps
Update npm dependencies
2022-02-24 18:33:48 +03:00
edfd7b3266 Update licenses 2022-02-24 18:12:33 +03:00
9744af7b74 Update dependencies 2022-02-24 18:04:55 +03:00
7016f85f93 Merge pull request #271 from vsafonkin/v-vlsafo/update-node-version
Update default runtime to node16
2022-02-24 17:29:31 +03:00
d292011f5d Update node version to v16 2022-02-24 11:16:01 +03:00
608ee757cf Merge pull request #270 from snickler/main
Updated dotnet-install scripts to latest version
2022-02-22 16:38:32 +03:00
e54e706650 Updated dotnet-install scripts to latest version 2022-02-19 17:07:00 -05:00
c20f59e04a Avoiding installing the same version multiple times (#252) 2021-12-29 14:07:42 +03:00
13b852df87 Moved checkout above setup step to align with the other samples (#256) 2021-12-28 15:37:44 +03:00
f85bcda870 Fix the Licensed workflow (#258) 2021-12-23 14:35:09 +03:00
499789684c Warn users when installing EOL .NET versions (#245) 2021-11-23 16:58:49 +03:00
76ddd67c90 Fix a space in the documentation (#248) 2021-11-23 16:56:22 +03:00
550702114f Support multiple versions in single invocation (#240) 2021-11-23 13:03:56 +03:00
e3ce4164b3 Merge pull request #238 from vsafonkin/v-vlsafo/fix-dependencies
Update dependencies and installer scripts
2021-10-13 17:24:51 +03:00
463326422f Update jest 2021-10-13 16:35:23 +03:00
547d075822 Revert jest version 2021-10-13 14:58:41 +03:00
fc9265379f Update deps with force 2021-10-13 14:50:32 +03:00
32c76e2669 Update installer scripts 2021-10-13 14:27:43 +03:00
8ca0cf75a1 Update dependencies 2021-10-13 14:20:02 +03:00
7f88dbf08f Merge pull request #231 from actions/dependabot/npm_and_yarn/tmpl-1.0.5
Bump tmpl from 1.0.4 to 1.0.5
2021-10-13 11:12:15 +03:00
af0ed6536b Bump tmpl from 1.0.4 to 1.0.5
Bumps [tmpl](https://github.com/daaku/nodejs-tmpl) from 1.0.4 to 1.0.5.
- [Release notes](https://github.com/daaku/nodejs-tmpl/releases)
- [Commits](https://github.com/daaku/nodejs-tmpl/commits/v1.0.5)

---
updated-dependencies:
- dependency-name: tmpl
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-13 07:14:28 +00:00
9dd9d27e57 Merge pull request #234 from IEvangelist/patch-1
Update README.md
2021-10-12 17:27:43 +03:00
44530e8569 Update README.md
Fix the README.md file to avoid the .NET CLI repo link that is now the .NET SDK repo.
2021-10-05 10:05:48 -05:00
48 changed files with 24336 additions and 21283 deletions

2
.gitattributes vendored
View File

@ -1 +1 @@
.licenses/** -diff linguist-generated=true
.licenses/** -diff linguist-generated=true

2
.github/CODEOWNERS vendored
View File

@ -1 +1 @@
* @actions/virtual-environments-owners
* @actions/runner-images-team

17
.github/workflows/basic-validation.yml vendored Normal file
View 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

View File

@ -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,35 +12,6 @@ on:
workflow_dispatch:
jobs:
check-dist:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set Node.js 12.x
uses: actions/setup-node@v1
with:
node-version: 12.x
- name: Install dependencies
run: npm ci
- 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@v2
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

14
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@ -0,0 +1,14 @@
name: CodeQL analysis
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
schedule:
- cron: '0 3 * * 0'
jobs:
call-codeQL-analysis:
name: CodeQL analysis
uses: actions/reusable-workflows/.github/workflows/codeql-analysis.yml@main

323
.github/workflows/e2e-tests.yml vendored Normal file
View File

@ -0,0 +1,323 @@
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 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-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 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-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 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 '2.2'
uses: ./
with:
dotnet-version: '2.2'
- name: Setup dotnet '3.1.100-preview1-014459'
uses: ./
with:
dotnet-version: '3.1.100-preview1-014459'
- name: Verify dotnet
shell: pwsh
run: __tests__/verify-dotnet.ps1 3.1.100-preview1-014459
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 '2.2' '3.1'
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 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","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-setup-with-dotnet-quality:
runs-on: ${{ matrix.operating-system }}
strategy:
fail-fast: false
matrix:
operating-system: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Clear toolcache
shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
- name: Setup dotnet 7.0 with preview quality
uses: ./
with:
dotnet-version: "7.0"
dotnet-quality: "preview"
- name: Verify preview version
shell: pwsh
run: |
$version = & dotnet --version
Write-Host "Installed version: $version"
if (-not ($version.Contains("preview") -or $version.Contains("rc"))) { throw "Unexpected version" }
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: mcr.microsoft.com/dotnet/core/runtime-deps:3.0-bionic
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: Clear tool cache
run: rm -rf "/usr/share/dotnet"
- name: Install curl
run: |
apt update
apt -y install curl
- 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-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 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

View File

@ -7,18 +7,9 @@ on:
pull_request:
branches:
- main
workflow_dispatch:
jobs:
test:
runs-on: ubuntu-latest
name: Check licenses
steps:
- uses: actions/checkout@v2
- run: npm ci
- name: Install licensed
run: |
cd $RUNNER_TEMP
curl -Lfs -o licensed.tar.gz https://github.com/github/licensed/releases/download/2.12.2/licensed-2.12.2-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

View File

@ -1,4 +1,5 @@
name: Release new action version
on:
release:
types: [released]
@ -22,7 +23,7 @@ jobs:
steps:
- name: Update the ${{ env.TAG_NAME }} tag
id: update-major-tag
uses: actions/publish-action@v0.1.0
uses: actions/publish-action@v0.2.1
with:
source-tag: ${{ env.TAG_NAME }}
slack-webhook: ${{ secrets.SLACK_WEBHOOK }}

View File

@ -21,7 +21,7 @@ jobs:
dotnet-version: ['2.1', '2.2', '3.0', '3.1', '5.0']
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Clear toolcache
shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}

View File

@ -1,192 +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@v2
- name: Set Node.js 12
uses: actions/setup-node@v1
with:
node-version: 12.x
- run: npm ci
- 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-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@v2
- 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-latest, windows-latest, macOS-latest]
steps:
- name: Checkout
uses: actions/checkout@v2
- 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-latest, windows-latest, macOS-latest]
steps:
- name: Checkout
uses: actions/checkout@v2
- 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-latest, windows-latest, macOS-latest]
steps:
- name: Checkout
uses: actions/checkout@v2
- 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-proxy:
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/dotnet/core/runtime-deps:3.0-bionic
options: --dns 127.0.0.1
services:
squid-proxy:
image: datadog/squid:latest
ports:
- 3128:3128
env:
https_proxy: http://squid-proxy:3128
http_proxy: http://squid-proxy:3128
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Clear tool cache
run: rm -rf "/usr/share/dotnet"
- name: Install curl
run: |
apt update
apt -y install curl
- 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-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@v2
- 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
.husky/pre-commit Executable file
View File

@ -0,0 +1,4 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm run format

5
.husky/pre-push Executable file
View File

@ -0,0 +1,5 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
# Tests are not run at push time since they can take 2-4 minutes to complete
npm run format-check

View File

@ -1,6 +1,6 @@
---
name: "@actions/core"
version: 1.2.6
version: 1.10.0
type: npm
summary: Actions core lib
homepage: https://github.com/actions/toolkit/tree/main/packages/core

View File

@ -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: []

View File

@ -1,9 +1,9 @@
---
name: "@actions/http-client"
version: 1.0.8
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

View File

@ -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: []

View File

@ -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: []

View File

@ -1,6 +1,6 @@
---
name: node-fetch
version: 2.6.1
version: 2.6.7
type: npm
summary: A light-weight module that brings window.fetch to node.js
homepage: https://github.com/bitinn/node-fetch

11
.licenses/npm/strnum.dep.yml generated Normal file
View 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: []

30
.licenses/npm/tr46.dep.yml generated Normal file
View File

@ -0,0 +1,30 @@
---
name: tr46
version: 0.0.3
type: npm
summary: An implementation of the Unicode TR46 spec
homepage: https://github.com/Sebmaster/tr46.js#readme
license: mit
licenses:
- sources: Auto-generated MIT license text
text: |
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: []

20
.licenses/npm/uuid.dep.yml generated Normal file
View 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: []

23
.licenses/npm/webidl-conversions.dep.yml generated Normal file
View File

@ -0,0 +1,23 @@
---
name: webidl-conversions
version: 3.0.1
type: npm
summary: Implements the WebIDL algorithms for converting to and from JavaScript values
homepage:
license: bsd-2-clause
licenses:
- sources: LICENSE.md
text: |
# The BSD 2-Clause License
Copyright (c) 2014, Domenic Denicola
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
notices: []

32
.licenses/npm/whatwg-url.dep.yml generated Normal file
View File

@ -0,0 +1,32 @@
---
name: whatwg-url
version: 5.0.0
type: npm
summary: An implementation of the WHATWG URL Standard's URL API and parsing machinery
homepage:
license: mit
licenses:
- sources: LICENSE.txt
text: |
The MIT License (MIT)
Copyright (c) 20152016 Sebastian Mayr
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: []

View File

@ -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: []

View File

@ -7,5 +7,6 @@
"trailingComma": "none",
"bracketSpacing": false,
"arrowParens": "avoid",
"parser": "typescript"
"parser": "typescript",
"endOfLine": "auto"
}

76
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,76 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to make participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies within all project spaces, and it also applies when
an individual is representing the project or its community in public spaces.
Examples of representing a project or community include using an official
project e-mail address, posting via an official social media account, or acting
as an appointed representative at an online or offline event. Representation of
a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at opensource+actions/setup-dotnet@github.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

220
README.md
View File

@ -1,48 +1,88 @@
# setup-dotnet
<p align="left">
<a href="https://github.com/actions/setup-dotnet"><img alt="GitHub Actions status" src="https://github.com/actions/setup-dotnet/workflows/Main%20workflow/badge.svg"></a>
</p>
[![GitHub Actions Status](https://github.com/actions/setup-dotnet/workflows/Main%20workflow/badge.svg)](https://github.com/actions/setup-dotnet)
This action sets up a [dotnet core cli](https://github.com/dotnet/cli) environment for use in actions by:
This action sets up a [.NET CLI](https://github.com/dotnet/sdk) environment for use in actions by:
- optionally downloading and caching a version of dotnet by SDK version and adding to PATH
- optionally downloading and caching a version(s) of dotnet by SDK version(s) and adding to PATH
- 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@v2
- uses: actions/setup-dotnet@v1
- uses: actions/checkout@v3
- 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>
```
> **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.
Preview version:
**Multiple version installation**:
```yml
steps:
- uses: actions/checkout@v2
- uses: actions/setup-dotnet@v1
- uses: actions/checkout@v3
- name: Setup dotnet
uses: actions/setup-dotnet@v3
with:
dotnet-version: |
3.1.x
5.0.x
- run: dotnet build <my project>
```
## 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)
## Using the `dotnet-quality` input
This input sets up the action to install the latest build of the specified quality in the channel. The possible values of `dotnet-quality` are: **daily**, **signed**, **validated**, **preview**, **ga**.
> **Note**: `dotnet-quality` input can be used only with .NET SDK version in 'A.B', 'A.B.x', 'A' and 'A.x' formats where the major version is higher than 5. In other cases, `dotnet-quality` input will be ignored.
```yml
steps:
- uses: actions/checkout@v3
- uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.0.x'
include-prerelease: true
dotnet-quality: 'preview'
- run: dotnet build <my project>
```
Matrix Testing:
```yaml
## 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@v3
with:
global-json-file: csharp/global.json
- run: dotnet build <my project>
working-directory: csharp
```
## 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
@ -51,42 +91,46 @@ jobs:
dotnet: [ '2.1.x', '3.1.x', '5.0.x' ]
name: Dotnet ${{ matrix.dotnet }} sample
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Setup dotnet
uses: actions/setup-dotnet@v1
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@v2
- uses: actions/checkout@v3
- name: Setup dotnet
uses: actions/setup-dotnet@v1
uses: actions/setup-dotnet@v3
id: stepid
with:
dotnet-version: '2.1.x'
- name: Setup dotnet
uses: actions/setup-dotnet@v1
with:
dotnet-version: '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@v2
# Authenticates packages to push to GPR
- uses: actions/setup-dotnet@v1
- uses: actions/checkout@v3
- 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}}
@ -95,19 +139,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@v1
### 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@v1
### nuget.org
```yml
- uses: actions/setup-dotnet@v3
with:
dotnet-version: 3.1.x
- name: Publish the package to nuget.org
@ -115,32 +162,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@v1
- 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)

View File

@ -1,15 +1,11 @@
import io = require('@actions/io');
import fs = require('fs');
import path = require('path');
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)
),
path.join(Math.random().toString(36).substring(7)),
's'
);

View File

@ -1,5 +1,3 @@
import fs = require('fs');
describe('csc tests', () => {
it('Valid regular expression', async () => {
var cscFile = require('../.github/csc.json');

View File

@ -1,37 +1,79 @@
import io = require('@actions/io');
import fs = require('fs');
import os = require('os');
import path = require('path');
import hc = require('@actions/http-client');
import * as io from '@actions/io';
import * as os from 'os';
import fs from 'fs';
import path from 'path';
import each from 'jest-each';
import * as hc from '@actions/http-client';
import * as installer from '../src/installer';
import {QualityOptions} from '../src/setup-dotnet';
const toolDir = path.join(__dirname, 'runner', 'tools');
import {IS_WINDOWS} from '../src/utils';
import {IS_LINUX} from '../src/utils';
let toolDir: string;
if (IS_WINDOWS) {
toolDir = path.join(process.env['PROGRAMFILES'] + '', 'dotnet');
} else if (IS_LINUX) {
toolDir = '/usr/share/dotnet';
} else {
toolDir = path.join(process.env['HOME'] + '', '.dotnet');
}
const tempDir = path.join(__dirname, 'runner', 'temp');
process.env['RUNNER_TOOL_CACHE'] = toolDir;
process.env['RUNNER_TEMP'] = tempDir;
import * as installer from '../src/installer';
const IS_WINDOWS = process.platform === 'win32';
describe('installer tests', () => {
describe('DotnetCoreInstaller tests', () => {
beforeAll(async () => {
process.env.RUNNER_TOOL_CACHE = toolDir;
process.env.DOTNET_INSTALL_DIR = toolDir;
process.env.RUNNER_TEMP = tempDir;
process.env.DOTNET_ROOT = '';
await io.rmRF(toolDir);
await io.rmRF(tempDir);
});
afterAll(async () => {
try {
await io.rmRF(toolDir);
await io.rmRF(tempDir);
} catch {
console.log('Failed to remove test directories');
await io.rmRF(`${toolDir}/*`);
await io.rmRF(`${tempDir}/*`);
} catch (err) {
console.log(
`Failed to remove test directories, check the error message:${os.EOL}`,
err.message
);
}
}, 30000);
afterEach(async () => {
try {
await io.rmRF(`${toolDir}/*`);
await io.rmRF(`${tempDir}/*`);
} catch (err) {
console.log(
`Failed to remove test directories, check the error message:${os.EOL}`,
err.message
);
}
}, 30000);
it('Aquires multiple versions of dotnet', async () => {
const versions = ['2.2.207', '3.1.120'];
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);
if (IS_WINDOWS) {
expect(fs.existsSync(path.join(toolDir, 'dotnet.exe'))).toBe(true);
} else {
expect(fs.existsSync(path.join(toolDir, 'dotnet'))).toBe(true);
}
expect(process.env.DOTNET_ROOT).toBeDefined;
expect(process.env.PATH).toBeDefined;
expect(process.env.DOTNET_ROOT).toBe(toolDir);
expect(process.env.PATH?.startsWith(toolDir)).toBe(true);
}, 600000);
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);
@ -65,14 +107,19 @@ describe('installer tests', () => {
expect(process.env.PATH?.startsWith(toolDir)).toBe(true);
}, 600000); //This needs some time to download on "slower" internet connections
it('Returns string with installed SDK version', async () => {
const version = '3.1.120';
let installedVersion: string;
installedVersion = await getDotnet(version);
expect(installedVersion).toBe('3.1.120');
}, 600000);
it('Throws if no location contains correct dotnet version', async () => {
let thrown = false;
try {
await expect(async () => {
await getDotnet('1000.0.0');
} catch {
thrown = true;
}
expect(thrown).toBe(true);
}).rejects.toThrow();
}, 30000);
it('Uses an up to date bash download script', async () => {
@ -116,6 +163,112 @@ describe('installer tests', () => {
}, 30000);
});
describe('DotnetVersionResolver tests', () => {
each([
'3.1',
'3.x',
'3.1.x',
'3.1.*',
'3.1.X',
'3.1.2',
'3.1.0-preview1'
]).test(
"if valid version: '%s' is supplied, it should return version object with some value",
async version => {
const dotnetVersionResolver = new installer.DotnetVersionResolver(
version
);
const versionObject = await dotnetVersionResolver.createDotNetVersion();
expect(!!versionObject.value).toBeTruthy;
}
);
each([
'.',
'..',
' . ',
'. ',
' .',
' . . ',
' .. ',
' . ',
'-1.-1',
'-1',
'-1.-1.-1',
'..3',
'1..3',
'1..',
'.2.3',
'.2.x',
'*.',
'1.2.',
'1.2.-abc',
'a.b',
'a.b.c',
'a.b.c-preview',
' 0 . 1 . 2 ',
'invalid'
]).test(
"if invalid version: '%s' is supplied, it should throw",
async version => {
const dotnetVersionResolver = new installer.DotnetVersionResolver(
version
);
await expect(
async () => await dotnetVersionResolver.createDotNetVersion()
).rejects.toThrow();
}
);
each(['3.1', '3.1.x', '3.1.*', '3.1.X']).test(
"if version: '%s' that can be resolved to 'channel' option is supplied, it should set quality flag to 'true' and type to 'channel' in version object",
async version => {
const dotnetVersionResolver = new installer.DotnetVersionResolver(
version
);
const versionObject = await dotnetVersionResolver.createDotNetVersion();
expect(versionObject.type.toLowerCase().includes('channel')).toBeTruthy;
expect(versionObject.qualityFlag).toBeTruthy;
}
);
each(['3.1.2', '3.1.0-preview1']).test(
"if version: '%s' that can be resolved to 'version' option is supplied, it should set quality flag to 'false' and type to 'version' in version object",
async version => {
const dotnetVersionResolver = new installer.DotnetVersionResolver(
version
);
const versionObject = await dotnetVersionResolver.createDotNetVersion();
expect(versionObject.type.toLowerCase().includes('version')).toBeTruthy;
expect(versionObject.qualityFlag).toBeFalsy;
}
);
each(['3.1.2', '3.1']).test(
'it should create proper line arguments for powershell/bash installation scripts',
async version => {
const dotnetVersionResolver = new installer.DotnetVersionResolver(
version
);
const versionObject = await dotnetVersionResolver.createDotNetVersion();
const windowsRegEx = new RegExp(/^-[VC]/);
const nonWindowsRegEx = new RegExp(/^--[vc]/);
if (IS_WINDOWS) {
expect(windowsRegEx.test(versionObject.type)).toBeTruthy;
expect(nonWindowsRegEx.test(versionObject.type)).toBeFalsy;
} else {
expect(nonWindowsRegEx.test(versionObject.type)).toBeTruthy;
expect(windowsRegEx.test(versionObject.type)).toBeFalsy;
}
}
);
});
function normalizeFileContents(contents: string): string {
return contents
.trim()
@ -123,7 +276,15 @@ function normalizeFileContents(contents: string): string {
.replace(new RegExp('\r', 'g'), '\n');
}
async function getDotnet(version: string): Promise<void> {
const dotnetInstaller = new installer.DotnetCoreInstaller(version);
await dotnetInstaller.installDotnet();
async function getDotnet(
version: string,
quality: string = ''
): Promise<string> {
const dotnetInstaller = new installer.DotnetCoreInstaller(
version,
quality as QualityOptions
);
const installedVersion = await dotnetInstaller.installDotnet();
installer.DotnetCoreInstaller.addToPath();
return installedVersion;
}

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp3.1;netcoreapp2.2</TargetFrameworks>
<TargetFrameworks>netcoreapp3.1;netcoreapp3.0;netcoreapp2.2</TargetFrameworks>
<RootNamespace>sample_csproj</RootNamespace>
<IsPackable>false</IsPackable>

View File

@ -1,31 +1,52 @@
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 io from '@actions/io';
import * as core from '@actions/core';
import fs from 'fs';
import os from 'os';
import path from 'path';
import * as setup from '../src/setup-dotnet';
import * as dotnetInstaller from '../src/installer';
import {IS_WINDOWS} from '../src/utils';
import {IS_LINUX} from '../src/utils';
const IS_WINDOWS = process.platform === 'win32';
let toolDir: string;
if (IS_WINDOWS) {
toolDir = path.join(process.env['PROGRAMFILES'] + '', 'dotnet');
} else if (IS_LINUX) {
toolDir = '/usr/share/dotnet';
} else {
toolDir = path.join(process.env['HOME'] + '', '.dotnet');
}
const tempDir = path.join(__dirname, 'runner', 'temp2');
describe('setup-dotnet tests', () => {
let getInputSpy = jest.spyOn(core, 'getInput');
let getMultilineInputSpy = jest.spyOn(core, 'getMultilineInput');
let setOutputSpy = jest.spyOn(core, 'setOutput');
let inputs = {} as any;
beforeAll(async () => {
process.env.RUNNER_TOOL_CACHE = toolDir;
process.env.DOTNET_INSTALL_DIR = toolDir;
process.env.RUNNER_TEMP = tempDir;
await io.rmRF(toolDir);
await io.rmRF(tempDir);
});
try {
await io.rmRF(`${toolDir}/*`);
await io.rmRF(`${tempDir}/*`);
} catch (err) {
console.log(err.message);
console.log('Failed to remove test directories');
}
}, 30000);
afterEach(async () => {
try {
await io.rmRF(path.join(process.cwd(), 'global.json'));
await io.rmRF(toolDir);
await io.rmRF(tempDir);
} catch {
await io.rmRF(`${toolDir}/*`);
await io.rmRF(`${tempDir}/*`);
} catch (err) {
console.log(err.message);
console.log('Failed to remove test directories');
}
}, 30000);
@ -46,25 +67,32 @@ describe('setup-dotnet tests', () => {
}
}, 400000);
it('Acquires version of dotnet from global.json with rollForward option, install the latest patch', async () => {
it("Sets output with the latest installed by action version if global.json file isn't specified", async () => {
inputs['dotnet-version'] = ['3.1.201', '6.0.401'];
getMultilineInputSpy.mockImplementation(input => inputs[input]);
await setup.run();
expect(setOutputSpy).toBeCalledWith('dotnet-version', '6.0.401');
}, 400000);
it("Sets output with the version specified in global.json, if it's present", async () => {
const globalJsonPath = path.join(process.cwd(), 'global.json');
const jsonContents = `{${os.EOL}"sdk": {${os.EOL}"version":"3.1.201",${os.EOL}"rollForward":"latestFeature"${os.EOL}}${os.EOL}}`;
const jsonContents = `{${os.EOL}"sdk": {${os.EOL}"version": "3.0.103"${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)
);
inputs['dotnet-version'] = ['3.1.201', '6.0.401'];
inputs['global-json-file'] = './global.json';
getMultilineInputSpy.mockImplementation(input => inputs[input]);
getInputSpy.mockImplementation(input => inputs[input]);
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);
}
expect(setOutputSpy).toBeCalledWith('dotnet-version', '3.0.103');
}, 400000);
});

View File

@ -6,12 +6,15 @@ if (!$args[0])
$dotnet = Get-Command dotnet | Select-Object -First 1 | ForEach-Object { $_.Path }
Write-Host "Found '$dotnet'"
$version = & $dotnet --version | Out-String | ForEach-Object { $_.Trim() }
Write-Host "Version $version"
if (-not ($version.StartsWith($args[0].ToString())))
if($args.count -eq 1)
{
Write-Host "PATH='$env:PATH'"
throw "Unexpected version"
$version = & $dotnet --version | Out-String | ForEach-Object { $_.Trim() }
Write-Host "Version $version"
if (-not ($version.StartsWith($args[0].ToString())))
{
Write-Host "PATH='$env:PATH'"
throw "Unexpected version"
}
}
if ($args[1])
@ -19,16 +22,17 @@ 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"
$isInstalledVersion = $false
foreach ($version in $versions)
{
if ($version.StartsWith($args[1].ToString()))
$InstalledVersionCount = 0
foreach($arg in $args){
foreach ($version in $versions)
{
$isInstalledVersion = $true
break
if ($version.StartsWith($arg.ToString()))
{
$InstalledVersionCount++
}
}
}
if (-not $isInstalledVersion)
}
if ( $InstalledVersionCount -ne $args.Count)
{
Write-Host "PATH='$env:PATH'"
throw "Unexpected version"
@ -53,6 +57,13 @@ if ($args[1])
throw "Unexpected output"
}
}
if ($args[2])
{
if ($sample_output -notlike "*Test Run Successful.*Test Run Successful.*Test Run Successful.*")
{
throw "Unexpected output"
}
}
else
{
if ($sample_output -notlike "*Test Run Successful.*")

View File

@ -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

View File

@ -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);
});

View File

@ -6,16 +6,20 @@ branding:
color: green
inputs:
dotnet-version:
description: 'Optional SDK version to use. If not provided, will install global.json version when available. Examples: 2.2.104, 3.1, 3.1.x'
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'
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:
description: 'Optional package source for which to set up authentication. Will consult any existing NuGet.config in the root of the repo and provide a temporary NuGet.config using the NUGET_AUTH_TOKEN environment variable as a ClearTextPassword'
owner:
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
outputs:
dotnet-version:
description: 'Contains the installed by action .NET SDK version for reuse.'
runs:
using: 'node12'
using: 'node16'
main: 'dist/index.js'

32599
dist/index.js vendored

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,57 @@
# v3 setup-dotnet
Date: 2022-08-25
Status: Accepted
# Context
- GitHub-hosted Ubuntu and Windows runners have .NET versions pre-installed in system directories
- Ubuntu:`/usr/share/dotnet`
- Windows:`C:\Program Files\dotnet`
- V1 version of Action installs .NET to the user's directory
- Ubuntu:`/home/runner/.dotnet`
- Windows: `C:\Users\runneradmin\AppData\Local\Microsoft\dotnet`
- It means that action always downloads and installs .NET version even if it is pre-installed. Also after using the action all pre-installed .NET versions are unavailable because `DOTNET_ROOT` is overridden to the user's directory.
The behavior is different for macOS runners because the pre-installation directory matches the one that is used by action. It means action can use pre-installed versions if they exist, which speeds up the customer's workflow.
- The different behavior of the setup task on Ubuntu, Windows and macOS runners is unclear and confusing for customers.
- .NET supports installing and using multiple versions of .NET SDK and .NET runtime side-by-side. .NET CLI will use the latest installed .NET SDK and .NET runtime versions if there is no global.json file containing a different version. This behavior is defined by .NET design (https://docs.microsoft.com/en-us/dotnet/core/versions/selection).
- The action contains logic to handle inputs with wildcards, for example `5.0.x`, `5.0.*`, `5.x` or `5.*`. This logic uses metadata from `https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/releases-index.json` to retrieve the list of available releases and get the latest release version for the specified major and/or minor version from the input. After that, installer script (`dotnet-install.ps1` for Windows or `dotnet-install.sh` for Linux and macOS) installs the required SDK using exact version as a parameter.
# Proposal
- Change .NET installation path for Windows and Ubuntu images to match the location of pre-installed versions by using `-InstallDir` (Windows) and `--install-dir` (Ubuntu) properties for installer scripts:
https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script
- Simplify and in some cases fully get rid of logic for resolving wildcard versions and start relying on [official installer scripts provided by .NET Core team](https://github.com/dotnet/install-scripts).
The execution `dotnet-install.ps1 -Channel 5.0` installs the latest patch version for 5.0 SDK. If SDK is in the prerelease phase, the latest prerelease version (preview or rc) will be installed.
Inputs with wildcards in the patch tag (`5.0.x` or `5.0.*`) can be handled by passing major and minor versions to the installer script directly as a `channel` parameter. This parameter supports two-part version in `X.Y` format as input value ([see installer scripts documentation](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script)).
Inputs with wildcards in the minor tag (`3.x` or `3.*`) can be handled like that:
1. The request is sent to MS dist and the `releases.json` file is got
2. The action gets the latest possible channel version out of retrieved `releases.json` that satisfies input major tag (e.g. for `3.x` nowadays it's `3.1`)
3. Retrieved channel version is passed to installer script directly as `channel` parameter.
> **Note:** Using the `channel` parameter of the MS .NET installer scripts will allow us to use the `quality` parameter as well. This functionality is also asked for by our customers.
# Breaking changes
- The presence of pre-installed .NET versions that are higher than the version that the users specify in the setup task can be breaking for some customers, who expect only one installed .NET version on the runner after using the setup task. If a user doesn't have .NET version specified in project file, the `dotnet` will use the latest installed version instead of provided in the setup task.
> **Note:** It is the biggest deal in this ADR.
Previously, when a user would specify a .NET version, this exact version was used by the `dotnet` command by default (because it was installed in a separate folder and there were no other.NET versions in that folder)
In the proposal, the specified version will be installed on the machine but the latest version will be used by the `dotnet` command by default (because specified version will be installed alongside with pre-installed .NET versions).
Based on [official .NET documentation](https://docs.microsoft.com/en-us/dotnet/core/versions/selection), it is expected behavior and how it works on user's local machine with multiple installed .NET versions but some customer's workflows could be broken because they already rely on current behavior.
To avoid breaking customers, we will need to release a new major task version (v3).
# v3-preview
There will be a v3-preview branch that will be created for development and testing. Any changes will first be merged into the v3-preview branch. After a period of testing & verification, the v3-preview branch will be merged into the main branch and a v3 tag will be created. Any GitHub public documentation and starter workflows that mention setup-dotnet will then be updated to use v3 instead of v2:
- [README.md](https://github.com/actions/setup-dotnet/blob/main/README.md)
- [action.yml](https://github.com/actions/setup-dotnet/blob/main/action.yml)
- [GitHub docs](https://docs.github.com/en/actions/guides/building-and-testing-net#using-a-specific-net-version)
- Starter-workflow yamls: [#1](https://github.com/actions/starter-workflows/blob/main/ci/dotnet.yml#L17), [#2](https://github.com/actions/starter-workflows/blob/main/ci/dotnet-desktop.yml#L72)
# Consequences
- Customers will be able to use pre-installed .NET versions with setup-dotnet action on Windows and Ubuntu

View File

@ -1,34 +1,113 @@
# Contributors
Thank you for contributing! This action is targetted around setting up the dotnet cli and related sdks for GitHub actions. As part of that we use proxy settings (for self-hosted runners) and set-up nuget authentication for private feeds.
Thank you for contributing!
If you would like to contribute there are a few things to consider:
We have prepared a short guide so that the process of making your contribution is as simple and clear as possible. Please check it out before you contribute!
## Commands to use
## How can I contribute...
- npm run build - Compiles the action into a single js file at dist/index.js (Please check in the changes made by this command)
- npm run test - Runs all tests under __tests__
- npm run format - Runs formatting required to pass the lint test (Please check in the changes made by this command)
- npm run update-installers - Updates the install-dotnet scripts in externals (Please check in the changes made by this command)
* [Contribute Documentation:green_book:](#contribute-documentation)
## To check in or not to check in
* [Contribute Code :computer:](#contribute-code)
- Do check in source (src)
- Do check in index file (dist)
- Do check in updates to install-dotnet scripts (externals)
- Do not check in build output (lib)
- Do not check in runtime (node_modules)
* [Provide Support on Issues:pencil:](#provide-support-on-issues)
## Writing tests
* [Review Pull Requests:mag:](#review-pull-requests)
With any contribution please take time to consider how this can be tested to maintain high quality. Current tests can be found in the folder __tests__ for examples.
## Contribute documentation
## Creating new version
Documentation is a super important, critical part of this project. Docs are how we keep track of what we're doing, how, and why. It's how we stay on the same page about our policies and how we tell others everything they need to be able to use this project or contribute to it.
Details on versioning can be found here: https://github.com/actions/toolkit/blob/main/docs/action-versioning.md
Create a new release using the UI. Version format should be `v1.x.x`. Creating a new major version requires reaction from users and should be done only with breaking changes.
Once the new release is created, the v1 tag needs to be updated as well.
```
git tag -fa v1 -m "Update v1 tag"
git push origin v1 --force
```
Documentation contributions of any size are welcome! Feel free to contribute even if you're just rewording a sentence to be more clear, or fixing a spelling mistake!
**How to contribute:**
Pull requests are the easiest way to contribute changes to git repos at GitHub. They are the preferred contribution method, as they offer a convenient way of commenting and amending the proposed changes.
- Please check that no one else has already created a pull request with these or similar changes
- Use a "feature branch" for your changes. That separates the changes in the pull request from your other changes and makes it easy to edit/amend commits in the pull request
- Make sure your changes are formatted properly and consistently with the rest of the documentation
- Re-read what you wrote, and run a spellchecker on it to make sure you didn't miss anything
- If your pull request is connected to an open issue, please, leave a link to this issue in the `Related issue:` section
- If you later need to add new commits to the pull request, you can simply commit the changes to the local branch and then push them. The pull request gets automatically updated
**Once you've filed the pull request:**
- Maintainers will review your pull request
- If a maintainer requests changes, first of all, try to think about this request critically and only after that implement and request another review
- If your PR gets accepted, it will soon be merged into the main branch. But your contribution will take effect only after the release of a new version of the action and updating the major tag
> Sometimes maintainers reject pull requests and that's ok! Usually, along with rejection, we supply the reason for it. Nonetheless, we still really appreciate you taking the time to do it, and we don't take that lightly :heart:
## Contribute code
We like code commits a lot! They're super handy, and they keep the project going and doing the work it needs to do to be useful to others.
Code contributions of just about any size are acceptable!
The main difference between code contributions and documentation contributions is that contributing code requires the inclusion of relevant tests for the code being added or changed. Contributions without accompanying tests will be held off until a test is added unless the maintainers consider the specific tests to be either impossible or way too much of a burden for such a contribution.
**How to contribute:**
Pull requests are the easiest way to contribute changes to git repos at GitHub. They are the preferred contribution method, as they offer a convenient way of commenting and amending the proposed changes.
- Please check that no one else has already created a pull request with these or similar changes
- Use a "feature branch" for your changes. That separates the changes in the pull request from your other changes and makes it easy to edit/amend commits in the pull request
- Format, build and test changes
- Make sure your changes are well formatted and that all tests are passing
- If your pull request is connected to an open issue, please, leave a link to this issue in the `Related issue:` section
- If you later need to add new commits to the pull request, you can simply commit the changes to the local branch and then push them. The pull request gets automatically updated
**Learn more about how to work with the repository:**
- 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 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).
- 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
- As already mentioned, pull requests without tests will be considered more carefully by maintainers. If you are sure that in this situation the tests are not needed or cannot be implemented with a commensurate effort - please add this clarification message to your pull request
**Once you've filed the pull request:**
- CI will start automatically with some checks. Wait until the end of the execution and make sure that all checks passed successfully. If some checks fail, you can open them one by one, try to find the reason for failing and make changes to your code to resolve the problem
> Sometimes you may need to update the installers you can do this with the `npm run update-installers` command
- Maintainers will review your pull request
- If a maintainer requests changes, first of all, try to think about his request critically and only after that implement and request another review
- If your PR gets accepted, it will soon be merged into the main branch. But your contribution will take effect only after the release of a new version of the action and updating the major tag
> Sometimes maintainers reject pull requests and that's ok! Usually, along with rejection, we supply the reason for it. Nonetheless, we still really appreciate you taking the time to do it, and we don't take that lightly :heart:
## Provide support on issues
Helping out other users with their questions is an awesome way of contributing to any community. It's not uncommon for most of the issues on open source projects to be support-related questions by users trying to understand something they ran into or find their way around a known bug.
**To help other folks out with their questions:**
- Go to the [issue tracker](https://github.com/actions/setup-dotnet/issues)
- Read through the list until you find something that you're familiar enough with to answer to
- Respond to the issue with whatever details are needed to clarify the question, or get more details about what's going on
- Once the discussion wraps up and things are clarified, ask the original issue filer (or a maintainer) to close it for you
*Some notes on picking up support issues:*
- Avoid responding to issues you don't know you can answer accurately
- Try to refer to past issues with accepted answers as much as possible. Link to them from your replies
- Be kind and patient with users. Often, folks who have run into confusing things might be upset or impatient. This is natural. If you feel uncomfortable in conversation with them, it's better to stay away or withdraw from the issue.
> If some user is violating our code of conduct [standards](https://github.com/actions/setup-dotnet/blob/main/CODE_OF_CONDUCT.md#our-standards), refer to the [Enforcement](https://github.com/actions/setup-dotnet/blob/main/CODE_OF_CONDUCT.md#enforcement) section of the Code of Conduct to resolve the conflict
## Review pull requests
Another great way to contribute is to review pull request. Please, be extra kind: people who submit code/doc contributions are putting themselves in a pretty vulnerable position, and have put time and care into what they've done (even if that's not obvious to you!) Please, always respond with respect, and be understanding, but don't feel like you need to sacrifice your standards for their sake, either.
**How to review:**
- Go to the [pull requests](https://github.com/actions/setup-dotnet/pulls)
- Make sure you're familiar with the code or documentation is updated, unless it's a minor change (spellchecking, minor formatting, etc.)
- Review changes using the GitHub functionality. You can ask a clarifying question, point out an error or suggest an alternative.
> Note: You may ask for minor changes - "nitpicks", but consider whether they are real blockers to merging or not
- Submit your review, which may include comments, an approval, or a changes request

File diff suppressed because it is too large Load Diff

View File

@ -135,6 +135,31 @@ get_legacy_os_name_from_platform() {
return 1
}
get_legacy_os_name() {
eval $invocation
local uname=$(uname)
if [ "$uname" = "Darwin" ]; then
echo "osx"
return 0
elif [ -n "$runtime_id" ]; then
echo $(get_legacy_os_name_from_platform "${runtime_id%-*}" || echo "${runtime_id%-*}")
return 0
else
if [ -e /etc/os-release ]; then
. /etc/os-release
os=$(get_legacy_os_name_from_platform "$ID${VERSION_ID:+.${VERSION_ID}}" || echo "")
if [ -n "$os" ]; then
echo "$os"
return 0
fi
fi
fi
say_verbose "Distribution specific OS name and version could not be detected: UName = $uname"
return 1
}
get_linux_platform_name() {
eval $invocation
@ -174,8 +199,8 @@ get_current_os_name() {
echo "freebsd"
return 0
elif [ "$uname" = "Linux" ]; then
local linux_platform_name
linux_platform_name="$(get_linux_platform_name)" || { echo "linux" && return 0 ; }
local linux_platform_name=""
linux_platform_name="$(get_linux_platform_name)" || true
if [ "$linux_platform_name" = "rhel.6" ]; then
echo $linux_platform_name
@ -196,39 +221,13 @@ get_current_os_name() {
return 1
}
get_legacy_os_name() {
eval $invocation
local uname=$(uname)
if [ "$uname" = "Darwin" ]; then
echo "osx"
return 0
elif [ -n "$runtime_id" ]; then
echo $(get_legacy_os_name_from_platform "${runtime_id%-*}" || echo "${runtime_id%-*}")
return 0
else
if [ -e /etc/os-release ]; then
. /etc/os-release
os=$(get_legacy_os_name_from_platform "$ID${VERSION_ID:+.${VERSION_ID}}" || echo "")
if [ -n "$os" ]; then
echo "$os"
return 0
fi
fi
fi
say_verbose "Distribution specific OS name and version could not be detected: UName = $uname"
return 1
}
machine_has() {
eval $invocation
hash "$1" > /dev/null 2>&1
command -v "$1" > /dev/null 2>&1
return $?
}
check_min_reqs() {
local hasMinimum=false
if machine_has "curl"; then
@ -307,6 +306,10 @@ get_machine_architecture() {
echo "arm64"
return 0
;;
s390x)
echo "s390x"
return 0
;;
esac
fi
@ -321,11 +324,13 @@ get_normalized_architecture_from_architecture() {
eval $invocation
local architecture="$(to_lowercase "$1")"
if [[ $architecture == \<auto\> ]]; then
echo "$(get_machine_architecture)"
return 0
fi
case "$architecture" in
\<auto\>)
echo "$(get_normalized_architecture_from_architecture "$(get_machine_architecture)")"
return 0
;;
amd64|x64)
echo "x64"
return 0
@ -338,12 +343,58 @@ get_normalized_architecture_from_architecture() {
echo "arm64"
return 0
;;
s390x)
echo "s390x"
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"
return 1
}
# args:
# version - $1
# channel - $2
# architecture - $3
get_normalized_architecture_for_specific_sdk_version() {
eval $invocation
local is_version_support_arm64="$(is_arm64_supported "$1")"
local is_channel_support_arm64="$(is_arm64_supported "$2")"
local architecture="$3";
local osname="$(get_current_os_name)"
if [ "$osname" == "osx" ] && [ "$architecture" == "arm64" ] && { [ "$is_version_support_arm64" = false ] || [ "$is_channel_support_arm64" = false ]; }; then
#check if rosetta is installed
if [ "$(/usr/bin/pgrep oahd >/dev/null 2>&1;echo $?)" -eq 0 ]; then
say_verbose "Changing user architecture from '$architecture' to 'x64' because .NET SDKs prior to version 6.0 do not support arm64."
echo "x64"
return 0;
else
say_err "Architecture \`$architecture\` is not supported for .NET SDK version \`$version\`. Please install Rosetta to allow emulation of the \`$architecture\` .NET SDK on this platform"
return 1
fi
fi
echo "$architecture"
return 0
}
# args:
# version or channel - $1
is_arm64_supported() {
#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
return 0
}
# args:
# user_defined_os - $1
get_normalized_os() {
@ -400,6 +451,10 @@ get_normalized_channel() {
local channel="$(to_lowercase "$1")"
if [[ $channel == current ]]; then
say_warning 'Value "Current" is deprecated for -Channel option. Use "STS" instead.'
fi
if [[ $channel == release/* ]]; then
say_warning 'Using branch name with -Channel option is no longer supported with newer releases. Use -Quality option with a channel in X.Y format instead.';
fi
@ -410,6 +465,14 @@ get_normalized_channel() {
echo "LTS"
return 0
;;
sts)
echo "STS"
return 0
;;
current)
echo "STS"
return 0
;;
*)
echo "$channel"
return 0
@ -425,6 +488,7 @@ get_normalized_channel() {
get_normalized_product() {
eval $invocation
local product=""
local runtime="$(to_lowercase "$1")"
if [[ "$runtime" == "dotnet" ]]; then
product="dotnet-runtime"
@ -446,7 +510,7 @@ get_normalized_product() {
# args:
# version_text - stdin
get_version_from_version_info() {
get_version_from_latestversion_file_content() {
eval $invocation
cat | tail -n 1 | sed 's/\r$//'
@ -478,7 +542,7 @@ is_dotnet_package_installed() {
# azure_feed - $1
# channel - $2
# normalized_architecture - $3
get_latest_version_info() {
get_version_from_latestversion_file() {
eval $invocation
local azure_feed="$1"
@ -487,24 +551,24 @@ get_latest_version_info() {
local version_file_url=null
if [[ "$runtime" == "dotnet" ]]; then
version_file_url="$uncached_feed/Runtime/$channel/latest.version"
version_file_url="$azure_feed/Runtime/$channel/latest.version"
elif [[ "$runtime" == "aspnetcore" ]]; then
version_file_url="$uncached_feed/aspnetcore/Runtime/$channel/latest.version"
version_file_url="$azure_feed/aspnetcore/Runtime/$channel/latest.version"
elif [ -z "$runtime" ]; then
version_file_url="$uncached_feed/Sdk/$channel/latest.version"
version_file_url="$azure_feed/Sdk/$channel/latest.version"
else
say_err "Invalid value for \$runtime"
return 1
fi
say_verbose "get_latest_version_info: latest url: $version_file_url"
say_verbose "get_version_from_latestversion_file: latest url: $version_file_url"
download "$version_file_url"
return $?
download "$version_file_url" || return $?
return 0
}
# args:
# json_file - $1
parse_jsonfile_for_version() {
parse_globaljson_file_for_version() {
eval $invocation
local json_file="$1"
@ -513,7 +577,7 @@ parse_jsonfile_for_version() {
return 1
fi
sdk_section=$(cat $json_file | awk '/"sdk"/,/}/')
sdk_section=$(cat $json_file | tr -d "\r" | awk '/"sdk"/,/}/')
if [ -z "$sdk_section" ]; then
say_err "Unable to parse the SDK node in \`$json_file\`"
return 1
@ -560,9 +624,9 @@ get_specific_version_from_version() {
if [ -z "$json_file" ]; then
if [[ "$version" == "latest" ]]; then
local version_info
version_info="$(get_latest_version_info "$azure_feed" "$channel" "$normalized_architecture" false)" || return 1
version_info="$(get_version_from_latestversion_file "$azure_feed" "$channel" "$normalized_architecture" false)" || return 1
say_verbose "get_specific_version_from_version: version_info=$version_info"
echo "$version_info" | get_version_from_version_info
echo "$version_info" | get_version_from_latestversion_file_content
return 0
else
echo "$version"
@ -570,7 +634,7 @@ get_specific_version_from_version() {
fi
else
local version_info
version_info="$(parse_jsonfile_for_version "$json_file")" || return 1
version_info="$(parse_globaljson_file_for_version "$json_file")" || return 1
echo "$version_info"
return 0
fi
@ -635,14 +699,16 @@ get_specific_product_version() {
if machine_has "curl"
then
specific_product_version=$(curl -s --fail "${download_link}${feed_credential}")
if [ $? = 0 ]; then
if ! specific_product_version=$(curl -s --fail "${download_link}${feed_credential}" 2>&1); then
continue
else
echo "${specific_product_version//[$'\t\r\n']}"
return 0
fi
elif machine_has "wget"
then
specific_product_version=$(wget -qO- "${download_link}${feed_credential}")
specific_product_version=$(wget -qO- "${download_link}${feed_credential}" 2>&1)
if [ $? = 0 ]; then
echo "${specific_product_version//[$'\t\r\n']}"
return 0
@ -907,7 +973,7 @@ get_http_header_curl() {
fi
curl_options="-I -sSL --retry 5 --retry-delay 2 --connect-timeout 15 "
curl $curl_options "$remote_path_with_credential" || return 1
curl $curl_options "$remote_path_with_credential" 2>&1 || return 1
return 0
}
@ -918,15 +984,25 @@ get_http_header_wget() {
eval $invocation
local remote_path="$1"
local disable_feed_credential="$2"
local wget_options="-q -S --spider --tries 5 "
local wget_options_extra=''
# Test for options that aren't supported on all wget implementations.
if [[ $(wget -h 2>&1 | grep -E 'waitretry|connect-timeout') ]]; then
wget_options_extra="--waitretry 2 --connect-timeout 15 "
else
say "wget extra options are unavailable for this environment"
fi
remote_path_with_credential="$remote_path"
if [ "$disable_feed_credential" = false ]; then
remote_path_with_credential+="$feed_credential"
fi
wget_options="-q -S --spider --tries 5 --waitretry 2 --connect-timeout 15 "
wget $wget_options "$remote_path_with_credential" 2>&1 || return 1
return 0
wget $wget_options $wget_options_extra "$remote_path_with_credential" 2>&1
return $?
}
# args:
@ -966,8 +1042,6 @@ download() {
sleep $((attempts*10))
done
if [ "$failed" = true ]; then
say_verbose "Download failed: $remote_path"
return 1
@ -986,19 +1060,27 @@ downloadcurl() {
# Avoid passing URI with credentials to functions: note, most of them echoing parameters of invocation in verbose output.
local remote_path_with_credential="${remote_path}${feed_credential}"
local curl_options="--retry 20 --retry-delay 2 --connect-timeout 15 -sSL -f --create-dirs "
local failed=false
local curl_exit_code=0;
if [ -z "$out_path" ]; then
curl $curl_options "$remote_path_with_credential" || failed=true
curl $curl_options "$remote_path_with_credential" 2>&1
curl_exit_code=$?
else
curl $curl_options -o "$out_path" "$remote_path_with_credential" || failed=true
curl $curl_options -o "$out_path" "$remote_path_with_credential" 2>&1
curl_exit_code=$?
fi
if [ "$failed" = true ]; then
local disable_feed_credential=false
local response=$(get_http_header_curl $remote_path $disable_feed_credential)
http_code=$( echo "$response" | awk '/^HTTP/{print $2}' | tail -1 )
if [ $curl_exit_code -gt 0 ]; then
download_error_msg="Unable to download $remote_path."
if [[ $http_code != 2* ]]; then
download_error_msg+=" Returned HTTP status code: $http_code."
# Check for curl timeout codes
if [[ $curl_exit_code == 7 || $curl_exit_code == 28 ]]; then
download_error_msg+=" Failed to reach the server: connection timeout."
else
local disable_feed_credential=false
local response=$(get_http_header_curl $remote_path $disable_feed_credential)
http_code=$( echo "$response" | awk '/^HTTP/{print $2}' | tail -1 )
if [[ ! -z $http_code && $http_code != 2* ]]; then
download_error_msg+=" Returned HTTP status code: $http_code."
fi
fi
say_verbose "$download_error_msg"
return 1
@ -1016,34 +1098,52 @@ downloadwget() {
local out_path="${2:-}"
# Append feed_credential as late as possible before calling wget to avoid logging feed_credential
local remote_path_with_credential="${remote_path}${feed_credential}"
local wget_options="--tries 20 --waitretry 2 --connect-timeout 15 "
local failed=false
if [ -z "$out_path" ]; then
wget -q $wget_options -O - "$remote_path_with_credential" || failed=true
local wget_options="--tries 20 "
local wget_options_extra=''
local wget_result=''
# Test for options that aren't supported on all wget implementations.
if [[ $(wget -h 2>&1 | grep -E 'waitretry|connect-timeout') ]]; then
wget_options_extra="--waitretry 2 --connect-timeout 15 "
else
wget $wget_options -O "$out_path" "$remote_path_with_credential" || failed=true
say "wget extra options are unavailable for this environment"
fi
if [ "$failed" = true ]; then
if [ -z "$out_path" ]; then
wget -q $wget_options $wget_options_extra -O - "$remote_path_with_credential" 2>&1
wget_result=$?
else
wget $wget_options $wget_options_extra -O "$out_path" "$remote_path_with_credential" 2>&1
wget_result=$?
fi
if [[ $wget_result != 0 ]]; then
local disable_feed_credential=false
local response=$(get_http_header_wget $remote_path $disable_feed_credential)
http_code=$( echo "$response" | awk '/^ HTTP/{print $2}' | tail -1 )
download_error_msg="Unable to download $remote_path."
if [[ $http_code != 2* ]]; then
if [[ ! -z $http_code && $http_code != 2* ]]; then
download_error_msg+=" Returned HTTP status code: $http_code."
# wget exit code 4 stands for network-issue
elif [[ $wget_result == 4 ]]; then
download_error_msg+=" Failed to reach the server: connection timeout."
fi
say_verbose "$download_error_msg"
return 1
fi
return 0
}
get_download_link_from_aka_ms() {
get_download_link_from_aka_ms() {
eval $invocation
#quality is not supported for LTS or current channel
if [[ ! -z "$normalized_quality" && ("$normalized_channel" == "LTS" || "$normalized_channel" == "current") ]]; then
#quality is not supported for LTS or STS channel
#STS maps to current
if [[ ! -z "$normalized_quality" && ("$normalized_channel" == "LTS" || "$normalized_channel" == "STS") ]]; then
normalized_quality=""
say_warning "Specifying quality for current or LTS channel is not supported, the quality will be ignored."
say_warning "Specifying quality for STS or LTS channel is not supported, the quality will be ignored."
fi
say_verbose "Retrieving primary payload URL from aka.ms for channel: '$normalized_channel', quality: '$normalized_quality', product: '$normalized_product', os: '$normalized_os', architecture: '$normalized_architecture'."
@ -1090,11 +1190,202 @@ get_download_link_from_aka_ms() {
fi
}
get_feeds_to_use()
{
feeds=(
"https://dotnetcli.azureedge.net/dotnet"
"https://dotnetbuilds.azureedge.net/public"
)
if [[ -n "$azure_feed" ]]; then
feeds=("$azure_feed")
fi
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
}
# THIS FUNCTION MAY EXIT (if the determined version is already installed).
generate_download_links() {
download_links=()
specific_versions=()
effective_versions=()
link_types=()
# If generate_akams_links returns false, no fallback to old links. Just terminate.
# This function may also 'exit' (if the determined version is already installed).
generate_akams_links || return
# Check other feeds only if we haven't been able to find an aka.ms link.
if [[ "${#download_links[@]}" -lt 1 ]]; then
for feed in ${feeds[@]}
do
# generate_regular_links may also 'exit' (if the determined version is already installed).
generate_regular_links $feed || return
done
fi
if [[ "${#download_links[@]}" -eq 0 ]]; then
say_err "Failed to resolve the exact version number."
return 1
fi
say_verbose "Generated ${#download_links[@]} links."
for link_index in ${!download_links[@]}
do
say_verbose "Link $link_index: ${link_types[$link_index]}, ${effective_versions[$link_index]}, ${download_links[$link_index]}"
done
}
# THIS FUNCTION MAY EXIT (if the determined version is already installed).
generate_akams_links() {
local valid_aka_ms_link=true;
normalized_version="$(to_lowercase "$version")"
if [[ "$normalized_version" != "latest" ]] && [ -n "$normalized_quality" ]; then
say_err "Quality and Version options are not allowed to be specified simultaneously. See https://learn.microsoft.com/dotnet/core/tools/dotnet-install-script#options for details."
return 1
fi
if [[ -n "$json_file" || "$normalized_version" != "latest" ]]; then
# aka.ms links are not needed when exact version is specified via command or json file
return
fi
get_download_link_from_aka_ms || valid_aka_ms_link=false
if [[ "$valid_aka_ms_link" == true ]]; then
say_verbose "Retrieved primary payload URL from aka.ms link: '$aka_ms_download_link'."
say_verbose "Downloading using legacy url will not be attempted."
download_link=$aka_ms_download_link
#get version from the path
IFS='/'
read -ra pathElems <<< "$download_link"
count=${#pathElems[@]}
specific_version="${pathElems[count-2]}"
unset IFS;
say_verbose "Version: '$specific_version'."
#Retrieve effective version
effective_version="$(get_specific_product_version "$azure_feed" "$specific_version" "$download_link")"
# Add link info to arrays
download_links+=($download_link)
specific_versions+=($specific_version)
effective_versions+=($effective_version)
link_types+=("aka.ms")
# Check if the SDK version is already installed.
if [[ "$dry_run" != true ]] && is_dotnet_package_installed "$install_root" "$asset_relative_path" "$effective_version"; then
say "$asset_name with version '$effective_version' is already installed."
exit 0
fi
return 0
fi
# if quality is specified - exit with error - there is no fallback approach
if [ ! -z "$normalized_quality" ]; then
say_err "Failed to locate the latest version in the channel '$normalized_channel' with '$normalized_quality' quality for '$normalized_product', os: '$normalized_os', architecture: '$normalized_architecture'."
say_err "Refer to: https://aka.ms/dotnet-os-lifecycle for information on .NET Core support."
return 1
fi
say_verbose "Falling back to latest.version file approach."
}
# THIS FUNCTION MAY EXIT (if the determined version is already installed)
# args:
# feed - $1
generate_regular_links() {
local feed="$1"
local valid_legacy_download_link=true
specific_version=$(get_specific_version_from_version "$feed" "$channel" "$normalized_architecture" "$version" "$json_file") || specific_version='0'
if [[ "$specific_version" == '0' ]]; then
say_verbose "Failed to resolve the specific version number using feed '$feed'"
return
fi
effective_version="$(get_specific_product_version "$feed" "$specific_version")"
say_verbose "specific_version=$specific_version"
download_link="$(construct_download_link "$feed" "$channel" "$normalized_architecture" "$specific_version" "$normalized_os")"
say_verbose "Constructed primary named payload URL: $download_link"
# Add link info to arrays
download_links+=($download_link)
specific_versions+=($specific_version)
effective_versions+=($effective_version)
link_types+=("primary")
legacy_download_link="$(construct_legacy_download_link "$feed" "$channel" "$normalized_architecture" "$specific_version")" || valid_legacy_download_link=false
if [ "$valid_legacy_download_link" = true ]; then
say_verbose "Constructed legacy named payload URL: $legacy_download_link"
download_links+=($legacy_download_link)
specific_versions+=($specific_version)
effective_versions+=($effective_version)
link_types+=("legacy")
else
legacy_download_link=""
say_verbose "Cound not construct a legacy_download_link; omitting..."
fi
# Check if the SDK version is already installed.
if [[ "$dry_run" != true ]] && is_dotnet_package_installed "$install_root" "$asset_relative_path" "$effective_version"; then
say "$asset_name with version '$effective_version' is already installed."
exit 0
fi
}
print_dry_run() {
say "Payload URLs:"
for link_index in "${!download_links[@]}"
do
say "URL #$link_index - ${link_types[$link_index]}: ${download_links[$link_index]}"
done
resolved_version=${specific_versions[0]}
repeatable_command="./$script_name --version "\""$resolved_version"\"" --install-dir "\""$install_root"\"" --architecture "\""$normalized_architecture"\"" --os "\""$normalized_os"\"""
if [ ! -z "$normalized_quality" ]; then
repeatable_command+=" --quality "\""$normalized_quality"\"""
fi
if [[ "$runtime" == "dotnet" ]]; then
repeatable_command+=" --runtime "\""dotnet"\"""
elif [[ "$runtime" == "aspnetcore" ]]; then
repeatable_command+=" --runtime "\""aspnetcore"\"""
fi
repeatable_command+="$non_dynamic_parameters"
if [ -n "$feed_credential" ]; then
repeatable_command+=" --feed-credential "\""<feed_credential>"\"""
fi
say "Repeatable invocation: $repeatable_command"
}
calculate_vars() {
eval $invocation
valid_legacy_download_link=true
#normalize input variables
script_name=$(basename "$0")
normalized_architecture="$(get_normalized_architecture_from_architecture "$architecture")"
say_verbose "Normalized architecture: '$normalized_architecture'."
normalized_os="$(get_normalized_os "$user_defined_os")"
@ -1105,76 +1396,10 @@ calculate_vars() {
say_verbose "Normalized channel: '$normalized_channel'."
normalized_product="$(get_normalized_product "$runtime")"
say_verbose "Normalized product: '$normalized_product'."
#try to get download location from aka.ms link
#not applicable when exact version is specified via command or json file
normalized_version="$(to_lowercase "$version")"
if [[ -z "$json_file" && "$normalized_version" == "latest" ]]; then
valid_aka_ms_link=true;
get_download_link_from_aka_ms || valid_aka_ms_link=false
if [ "$valid_aka_ms_link" == false ]; then
# if quality is specified - exit with error - there is no fallback approach
if [ ! -z "$normalized_quality" ]; then
say_err "Failed to locate the latest version in the channel '$normalized_channel' with '$normalized_quality' quality for '$normalized_product', os: '$normalized_os', architecture: '$normalized_architecture'."
say_err "Refer to: https://aka.ms/dotnet-os-lifecycle for information on .NET Core support."
return 1
fi
say_verbose "Falling back to latest.version file approach."
else
say_verbose "Retrieved primary payload URL from aka.ms link: '$aka_ms_download_link'."
download_link=$aka_ms_download_link
say_verbose "Downloading using legacy url will not be attempted."
valid_legacy_download_link=false
#get version from the path
IFS='/'
read -ra pathElems <<< "$download_link"
count=${#pathElems[@]}
specific_version="${pathElems[count-2]}"
unset IFS;
say_verbose "Version: '$specific_version'."
#Retrieve product specific version
specific_product_version="$(get_specific_product_version "$azure_feed" "$specific_version" "$download_link")"
say_verbose "Product specific version: '$specific_product_version'."
install_root="$(resolve_installation_path "$install_dir")"
say_verbose "InstallRoot: '$install_root'."
return
fi
fi
specific_version="$(get_specific_version_from_version "$azure_feed" "$channel" "$normalized_architecture" "$version" "$json_file")"
specific_product_version="$(get_specific_product_version "$azure_feed" "$specific_version")"
say_verbose "specific_version=$specific_version"
if [ -z "$specific_version" ]; then
say_err "Could not resolve version information."
return 1
fi
download_link="$(construct_download_link "$azure_feed" "$channel" "$normalized_architecture" "$specific_version" "$normalized_os")"
say_verbose "Constructed primary named payload URL: $download_link"
legacy_download_link="$(construct_legacy_download_link "$azure_feed" "$channel" "$normalized_architecture" "$specific_version")" || valid_legacy_download_link=false
if [ "$valid_legacy_download_link" = true ]; then
say_verbose "Constructed legacy named payload URL: $legacy_download_link"
else
say_verbose "Cound not construct a legacy_download_link; omitting..."
fi
install_root="$(resolve_installation_path "$install_dir")"
say_verbose "InstallRoot: $install_root"
}
say_verbose "InstallRoot: '$install_root'."
install_dotnet() {
eval $invocation
local download_failed=false
local asset_name=''
local asset_relative_path=''
normalized_architecture="$(get_normalized_architecture_for_specific_sdk_version "$version" "$normalized_channel" "$normalized_architecture")"
if [[ "$runtime" == "dotnet" ]]; then
asset_relative_path="shared/Microsoft.NETCore.App"
@ -1185,84 +1410,52 @@ install_dotnet() {
elif [ -z "$runtime" ]; then
asset_relative_path="sdk"
asset_name=".NET Core SDK"
else
say_err "Invalid value for \$runtime"
return 1
fi
# Check if the SDK version is already installed.
if is_dotnet_package_installed "$install_root" "$asset_relative_path" "$specific_version"; then
say "$asset_name version $specific_version is already installed."
return 0
fi
get_feeds_to_use
}
install_dotnet() {
eval $invocation
local download_failed=false
local download_completed=false
mkdir -p "$install_root"
zip_path="$(mktemp "$temporary_file_template")"
say_verbose "Zip path: $zip_path"
for link_index in "${!download_links[@]}"
do
download_link="${download_links[$link_index]}"
specific_version="${specific_versions[$link_index]}"
effective_version="${effective_versions[$link_index]}"
link_type="${link_types[$link_index]}"
# Failures are normal in the non-legacy case for ultimately legacy downloads.
# Do not output to stderr, since output to stderr is considered an error.
say "Downloading primary link $download_link"
say "Attempting to download using $link_type link $download_link"
# The download function will set variables $http_code and $download_error_msg in case of failure.
download "$download_link" "$zip_path" 2>&1 || download_failed=true
# The download function will set variables $http_code and $download_error_msg in case of failure.
download_failed=false
download "$download_link" "$zip_path" 2>&1 || download_failed=true
# if the download fails, download the legacy_download_link
if [ "$download_failed" = true ]; then
primary_path_http_code="$http_code"; primary_path_download_error_msg="$download_error_msg"
case $primary_path_http_code in
404)
say "The resource at $download_link is not available."
;;
*)
say "$primary_path_download_error_msg"
;;
esac
rm -f "$zip_path" 2>&1 && say_verbose "Temporary zip file $zip_path was removed"
if [ "$valid_legacy_download_link" = true ]; then
download_failed=false
download_link="$legacy_download_link"
zip_path="$(mktemp "$temporary_file_template")"
say_verbose "Legacy zip path: $zip_path"
say "Downloading legacy link $download_link"
# The download function will set variables $http_code and $download_error_msg in case of failure.
download "$download_link" "$zip_path" 2>&1 || download_failed=true
if [ "$download_failed" = true ]; then
legacy_path_http_code="$http_code"; legacy_path_download_error_msg="$download_error_msg"
case $legacy_path_http_code in
404)
say "The resource at $download_link is not available."
;;
*)
say "$legacy_path_download_error_msg"
;;
esac
rm -f "$zip_path" 2>&1 && say_verbose "Temporary zip file $zip_path was removed"
fi
fi
fi
if [ "$download_failed" = true ]; then
if [[ "$primary_path_http_code" = "404" && ( "$valid_legacy_download_link" = false || "$legacy_path_http_code" = "404") ]]; then
say_err "Could not find \`$asset_name\` with version = $specific_version"
say_err "Refer to: https://aka.ms/dotnet-os-lifecycle for information on .NET Core support"
if [ "$download_failed" = true ]; then
case $http_code in
404)
say "The resource at $link_type link '$download_link' is not available."
;;
*)
say "Failed to download $link_type link '$download_link': $download_error_msg"
;;
esac
rm -f "$zip_path" 2>&1 && say_verbose "Temporary zip file $zip_path was removed"
else
say_err "Could not download: \`$asset_name\` with version = $specific_version"
# 404-NotFound is an expected response if it goes from only one of the links, do not show that error.
# If primary path is available (not 404-NotFound) then show the primary error else show the legacy error.
if [ "$primary_path_http_code" != "404" ]; then
say_err "$primary_path_download_error_msg"
return 1
fi
if [[ "$valid_legacy_download_link" = true && "$legacy_path_http_code" != "404" ]]; then
say_err "$legacy_path_download_error_msg"
return 1
fi
download_completed=true
break
fi
done
if [[ "$download_completed" == false ]]; then
say_err "Could not find \`$asset_name\` with version = $specific_version"
say_err "Refer to: https://aka.ms/dotnet-os-lifecycle for information on .NET Core support"
return 1
fi
@ -1278,19 +1471,21 @@ install_dotnet() {
unset IFS;
say_verbose "Checking installation: version = $release_version"
if is_dotnet_package_installed "$install_root" "$asset_relative_path" "$release_version"; then
say "Installed version is $effective_version"
return 0
fi
fi
# Check if the standard SDK version is installed.
say_verbose "Checking installation: version = $specific_product_version"
if is_dotnet_package_installed "$install_root" "$asset_relative_path" "$specific_product_version"; then
say_verbose "Checking installation: version = $effective_version"
if is_dotnet_package_installed "$install_root" "$asset_relative_path" "$effective_version"; then
say "Installed version is $effective_version"
return 0
fi
# Version verification failed. More likely something is wrong either with the downloaded content or with the verification algorithm.
say_err "Failed to verify the version of installed \`$asset_name\`.\nInstallation source: $download_link.\nInstallation location: $install_root.\nReport the bug at https://github.com/dotnet/install-scripts/issues."
say_err "\`$asset_name\` with version = $specific_product_version failed to install with an unknown error."
say_err "\`$asset_name\` with version = $effective_version failed to install with an error."
return 1
}
@ -1308,8 +1503,8 @@ architecture="<auto>"
dry_run=false
no_path=false
no_cdn=false
azure_feed="https://dotnetcli.azureedge.net/dotnet"
uncached_feed="https://dotnetcli.blob.core.windows.net/dotnet"
azure_feed=""
uncached_feed=""
feed_credential=""
verbose=false
runtime=""
@ -1427,27 +1622,28 @@ do
echo " -c,--channel <CHANNEL> Download from the channel specified, Defaults to \`$channel\`."
echo " -Channel"
echo " Possible values:"
echo " - Current - most current release"
echo " - LTS - most current supported release"
echo " - STS - the most recent Standard Term Support release"
echo " - LTS - the most recent Long Term Support release"
echo " - 2-part version in a format A.B - represents a specific release"
echo " examples: 2.0; 1.0"
echo " - 3-part version in a format A.B.Cxx - represents a specific SDK release"
echo " examples: 5.0.1xx, 5.0.2xx."
echo " Supported since 5.0 release"
echo " Note: The version parameter overrides the channel parameter when any version other than `latest` is used."
echo " Warning: Value 'Current' is deprecated for the Channel parameter. Use 'STS' instead."
echo " Note: The version parameter overrides the channel parameter when any version other than 'latest' is used."
echo " -v,--version <VERSION> Use specific VERSION, Defaults to \`$version\`."
echo " -Version"
echo " Possible values:"
echo " - latest - most latest build on specific channel"
echo " - latest - the latest build on specific channel"
echo " - 3-part version in a format A.B.C - represents specific version of build"
echo " examples: 2.0.0-preview2-006120; 1.1.0"
echo " -q,--quality <quality> Download the latest build of specified quality in the channel."
echo " -Quality"
echo " The possible values are: daily, signed, validated, preview, GA."
echo " Works only in combination with channel. Not applicable for current and LTS channels and will be ignored if those channels are used."
echo " Works only in combination with channel. Not applicable for STS and LTS channels and will be ignored if those channels are used."
echo " For SDK use channel in A.B.Cxx format. Using quality for SDK together with channel in A.B format is not supported."
echo " Supported since 5.0 release."
echo " Note: The version parameter overrides the channel parameter when any version other than `latest` is used, and therefore overrides the quality."
echo " Note: The version parameter overrides the channel parameter when any version other than 'latest' is used, and therefore overrides the quality."
echo " --internal,-Internal Download internal builds. Requires providing credentials via --feed-credential parameter."
echo " --feed-credential <FEEDCREDENTIAL> Token to access Azure feed. Used as a query string to append to the Azure feed."
echo " -FeedCredential This parameter typically is not specified."
@ -1455,7 +1651,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, and arm64"
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."
@ -1469,8 +1665,12 @@ do
echo " --dry-run,-DryRun Do not perform installation. Display download link."
echo " --no-path, -NoPath Do not set PATH for the current process."
echo " --verbose,-Verbose Display diagnostics information."
echo " --azure-feed,-AzureFeed Azure feed location. Defaults to $azure_feed, This parameter typically is not changed by the user."
echo " --uncached-feed,-UncachedFeed Uncached feed location. This parameter typically is not changed by the user."
echo " --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."
@ -1478,14 +1678,6 @@ do
echo " Note: global.json must have a value for 'SDK:Version'"
echo " -?,--?,-h,--help,-Help Shows this help message"
echo ""
echo "Obsolete parameters:"
echo " --shared-runtime The recommended alternative is '--runtime dotnet'."
echo " This parameter is obsolete and may be removed in a future version of this script."
echo " Installs just the shared runtime bits, not the entire SDK."
echo " --runtime-id Installs the .NET Tools for the given platform (use linux-x64 for portable linux)."
echo " -RuntimeId" The parameter is obsolete and may be removed in a future version of this script. Should be used only for versions below 2.1.
echo " For primary links to override OS or/and architecture, use --os and --architecture option instead."
echo ""
echo "Install Location:"
echo " Location is chosen in following order:"
echo " - --install-dir option"
@ -1502,10 +1694,6 @@ do
shift
done
if [ "$no_cdn" = true ]; then
azure_feed="$uncached_feed"
fi
say "Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:"
say "- The SDK needs to be installed without user interaction and without admin rights."
say "- The SDK installation doesn't need to persist across multiple CI runs."
@ -1523,33 +1711,11 @@ fi
check_min_reqs
calculate_vars
script_name=$(basename "$0")
# generate_regular_links call below will 'exit' if the determined version is already installed.
generate_download_links
if [ "$dry_run" = true ]; then
say "Payload URLs:"
say "Primary named payload URL: ${download_link}"
if [ "$valid_legacy_download_link" = true ]; then
say "Legacy named payload URL: ${legacy_download_link}"
fi
repeatable_command="./$script_name --version "\""$specific_version"\"" --install-dir "\""$install_root"\"" --architecture "\""$normalized_architecture"\"" --os "\""$normalized_os"\"""
if [ ! -z "$normalized_quality" ]; then
repeatable_command+=" --quality "\""$normalized_quality"\"""
fi
if [[ "$runtime" == "dotnet" ]]; then
repeatable_command+=" --runtime "\""dotnet"\"""
elif [[ "$runtime" == "aspnetcore" ]]; then
repeatable_command+=" --runtime "\""aspnetcore"\"""
fi
repeatable_command+="$non_dynamic_parameters"
if [ -n "$feed_credential" ]; then
repeatable_command+=" --feed-credential "\""<feed_credential>"\"""
fi
say "Repeatable invocation: $repeatable_command"
if [[ "$dry_run" = true ]]; then
print_dry_run
exit 0
fi
@ -1564,5 +1730,5 @@ else
fi
say "Note that the script does not resolve dependencies during installation."
say "To check the list of dependencies, go to https://docs.microsoft.com/dotnet/core/install, select your operating system and check the \"Dependencies\" section."
say "Installation finished successfully."
say "To check the list of dependencies, go to https://learn.microsoft.com/dotnet/core/install, select your operating system and check the \"Dependencies\" section."
say "Installation finished successfully."

8755
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "setup-dotnet",
"version": "1.0.0",
"version": "3.0.2",
"private": true,
"description": "setup dotnet action",
"main": "lib/setup-dotnet.js",
@ -8,16 +8,11 @@
"build": "tsc && ncc build",
"format": "prettier --write **/*.ts",
"format-check": "prettier --check **/*.ts",
"test": "jest",
"lint": "echo \"Fake command that does nothing. It is used in reusable workflows\"",
"prepare": "husky install",
"test": "jest --coverage --config ./jest.config.js",
"update-installers": "nwget https://dot.net/v1/dotnet-install.ps1 -O externals/install-dotnet.ps1 && nwget https://dot.net/v1/dotnet-install.sh -O externals/install-dotnet.sh"
},
"husky": {
"hooks": {
"//": "Tests are not run at push time since they can take 2-4 minutes to complete",
"pre-commit": "npm run format",
"pre-push": "npm run format-check"
}
},
"repository": {
"type": "git",
"url": "git+https://github.com/actions/setup-dotnet.git"
@ -30,26 +25,25 @@
"author": "GitHub",
"license": "MIT",
"dependencies": {
"@actions/core": "^1.2.6",
"@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": "^25.2.3",
"@types/node": "^12.12.62",
"@types/jest": "^27.0.2",
"@types/node": "^16.11.25",
"@types/semver": "^6.2.2",
"@zeit/ncc": "^0.21.1",
"husky": "^4.3.0",
"jest": "^26.4.2",
"jest-circus": "^26.4.2",
"prettier": "^1.19.1",
"ts-jest": "^26.4.0",
"typescript": "^3.9.7",
"@vercel/ncc": "^0.33.4",
"husky": "^8.0.1",
"jest": "^27.2.5",
"jest-circus": "^27.2.5",
"prettier": "^2.7.1",
"ts-jest": "^27.0.5",
"typescript": "^4.8.4",
"wget-improved": "^3.2.1"
},
"jest": {

View File

@ -2,9 +2,7 @@ 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';
import {XMLParser, XMLBuilder} from 'fast-xml-parser';
export function configAuthentication(
feedUrl: string,
@ -47,10 +45,9 @@ function writeFeedToFile(
existingFileLocation: string,
tempFileLocation: string
) {
console.log(
core.info(
`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;
@ -58,7 +55,7 @@ function writeFeedToFile(
owner = github.context.repo.owner;
}
if (!process.env.NUGET_AUTH_TOKEN || process.env.NUGET_AUTH_TOKEN == '') {
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}}'
);
@ -67,64 +64,90 @@ function writeFeedToFile(
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') {
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 (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'];
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 {
// 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}`);
}
}
});
} else {
if (
packageSources['@_value']
.toLowerCase()
.includes(feedUrl.toLowerCase())
) {
const key = packageSources['@_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();
const xmlSource: any[] = [
{
'?xml': [
{
'#text': ''
}
],
':@': {
'@_version': '1.0'
}
},
{
configuration: [
{
config: [
{
add: [],
':@': {
'@_key': 'defaultPushSource',
'@_value': sourceUrl
}
}
]
}
]
}
];
if (sourceKeys.length == 0) {
if (!sourceKeys.length) {
let keystring = 'Source';
xml = xml
.ele('packageSources')
.ele('add', {key: keystring, value: sourceUrl})
.up()
.up();
xmlSource[1].configuration.push({
packageSources: [
{
add: [],
':@': {
'@_key': keystring,
'@_value': sourceUrl
}
}
]
});
sourceKeys.push(keystring);
}
xml = xml.ele('packageSourceCredentials');
const packageSourceCredentials: any[] = [];
sourceKeys.forEach(key => {
if (!isValidKey(key)) {
throw new Error(
@ -132,24 +155,42 @@ function writeFeedToFile(
);
}
xml = xml
.ele(key)
.ele('add', {key: 'Username', value: owner})
.up()
.ele('add', {
key: 'ClearTextPassword',
value: process.env.NUGET_AUTH_TOKEN
})
.up()
.up();
packageSourceCredentials.push({
[key]: [
{
add: [],
':@': {
'@_key': 'Username',
'@_value': owner
}
},
{
add: [],
':@': {
'@_key': 'ClearTextPassword',
'@_value': process.env.NUGET_AUTH_TOKEN
}
}
]
});
});
// 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'
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();
var output = xml.end({pretty: true});
fs.writeFileSync(tempFileLocation, output);
}

View File

@ -2,293 +2,262 @@
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 * as hc from '@actions/http-client';
import {chmodSync} from 'fs';
import * as path from 'path';
import {ExecOptions} from '@actions/exec/lib/interfaces';
import * as semver from 'semver';
import {readdir} from 'fs/promises';
import path from 'path';
import os from 'os';
import semver from 'semver';
import {IS_LINUX, IS_WINDOWS} from './utils';
import {QualityOptions} from './setup-dotnet';
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 interface DotnetVersion {
type: string;
value: string;
qualityFlag: boolean;
}
export class DotnetCoreInstaller {
constructor(version: string, includePrerelease: boolean = false) {
this.version = version;
this.includePrerelease = includePrerelease;
export class DotnetVersionResolver {
private inputVersion: string;
private resolvedArgument: DotnetVersion;
constructor(version: string) {
this.inputVersion = version.trim();
this.resolvedArgument = {type: '', value: '', qualityFlag: false};
}
public async installDotnet() {
let output = '';
let resultCode = 0;
private async resolveVersionInput(): Promise<void> {
if (!semver.validRange(this.inputVersion)) {
throw new Error(
`'dotnet-version' was supplied in invalid format: ${this.inputVersion}! Supported syntax: A.B.C, A.B, A.B.x, A, A.x`
);
}
if (semver.valid(this.inputVersion)) {
this.resolvedArgument.type = 'version';
this.resolvedArgument.value = this.inputVersion;
} else {
const [major, minor] = this.inputVersion.split('.');
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 (this.isNumericTag(major)) {
this.resolvedArgument.type = 'channel';
if (this.isNumericTag(minor)) {
this.resolvedArgument.value = `${major}.${minor}`;
} else {
const httpClient = new hc.HttpClient('actions/setup-dotnet', [], {
allowRetries: true,
maxRetries: 3
});
this.resolvedArgument.value = await this.getLatestVersion(
httpClient,
[major, minor]
);
}
}
this.resolvedArgument.qualityFlag = +major >= 6 ? true : false;
}
}
private isNumericTag(versionTag): boolean {
return /^\d+$/.test(versionTag);
}
public async createDotNetVersion(): Promise<{
type: string;
value: string;
qualityFlag: boolean;
}> {
await this.resolveVersionInput();
if (!this.resolvedArgument.type) {
return this.resolvedArgument;
}
if (IS_WINDOWS) {
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('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
);
this.resolvedArgument.type =
this.resolvedArgument.type === 'channel' ? '-Channel' : '-Version';
} 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 (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']);
if (resultCode != 0) {
throw new Error(`Failed to install dotnet ${resultCode}. ${output}`);
this.resolvedArgument.type =
this.resolvedArgument.type === 'channel' ? '--channel' : '--version';
}
return this.resolvedArgument;
}
// 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(
private async getLatestVersion(
httpClient: hc.HttpClient,
versionParts: string[]
): Promise<string> {
const response = await httpClient.getJson<any>(DotNetCoreIndexUrl);
const response = await httpClient.getJson<any>(
DotnetVersionResolver.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];
let releaseInfo = releasesInfo.find(info => {
let sdkParts: string[] = info['channel-version'].split('.');
return sdkParts[0] === versionParts[0];
});
if (releasesInfo.length === 0) {
if (!releaseInfo) {
throw new Error(
`Could not find info for version ${versionParts.join(
'.'
)} at ${DotNetCoreIndexUrl}`
`Could not find info for version ${versionParts.join('.')} at ${
DotnetVersionResolver.DotNetCoreIndexUrl
}`
);
}
return releasesInfo[0]['releases.json'];
return releaseInfo['channel-version'];
}
private version: string;
private includePrerelease: boolean;
static DotNetCoreIndexUrl: string =
'https://dotnetcli.azureedge.net/dotnet/release-metadata/releases-index.json';
}
const DotNetCoreIndexUrl: string =
'https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/releases-index.json';
export class DotnetCoreInstaller {
private version: string;
private quality: QualityOptions;
static {
const installationDirectoryWindows = path.join(
process.env['PROGRAMFILES'] + '',
'dotnet'
);
const installationDirectoryLinux = '/usr/share/dotnet';
const installationDirectoryMac = path.join(
process.env['HOME'] + '',
'.dotnet'
);
const dotnetInstallDir: string | undefined =
process.env['DOTNET_INSTALL_DIR'];
if (dotnetInstallDir) {
process.env['DOTNET_INSTALL_DIR'] =
this.convertInstallPathToAbsolute(dotnetInstallDir);
} else {
if (IS_WINDOWS) {
process.env['DOTNET_INSTALL_DIR'] = installationDirectoryWindows;
} else {
process.env['DOTNET_INSTALL_DIR'] = IS_LINUX
? installationDirectoryLinux
: installationDirectoryMac;
}
}
}
constructor(version: string, quality: QualityOptions) {
this.version = version;
this.quality = quality;
}
private static convertInstallPathToAbsolute(installDir: string): string {
let transformedPath;
if (path.isAbsolute(installDir)) {
transformedPath = installDir;
} else {
transformedPath = installDir.startsWith('~')
? path.join(os.homedir(), installDir.slice(1))
: (transformedPath = path.join(process.cwd(), installDir));
}
return path.normalize(transformedPath);
}
static addToPath() {
core.addPath(process.env['DOTNET_INSTALL_DIR']!);
core.exportVariable('DOTNET_ROOT', process.env['DOTNET_INSTALL_DIR']);
}
private setQuality(
dotnetVersion: DotnetVersion,
scriptArguments: string[]
): void {
const option = IS_WINDOWS ? '-Quality' : '--quality';
if (dotnetVersion.qualityFlag) {
scriptArguments.push(option, this.quality);
} else {
core.warning(
`'dotnet-quality' input can be used only with .NET SDK version in A.B, A.B.x, A and A.x formats where the major tag is higher than 5. You specified: ${this.version}. 'dotnet-quality' input is ignored.`
);
}
}
public async installDotnet(): Promise<string> {
const windowsDefaultOptions = [
'-NoLogo',
'-Sta',
'-NoProfile',
'-NonInteractive',
'-ExecutionPolicy',
'Unrestricted',
'-Command'
];
const scriptName = IS_WINDOWS ? 'install-dotnet.ps1' : 'install-dotnet.sh';
const escapedScript = path
.join(__dirname, '..', 'externals', scriptName)
.replace(/'/g, "''");
let scriptArguments: string[];
let scriptPath = '';
const versionResolver = new DotnetVersionResolver(this.version);
const dotnetVersion = await versionResolver.createDotNetVersion();
if (IS_WINDOWS) {
scriptArguments = ['&', `'${escapedScript}'`];
if (dotnetVersion.type) {
scriptArguments.push(dotnetVersion.type, dotnetVersion.value);
}
if (this.quality) {
this.setQuality(dotnetVersion, scriptArguments);
}
if (process.env['https_proxy'] != null) {
scriptArguments.push(`-ProxyAddress ${process.env['https_proxy']}`);
}
// This is not currently an option
if (process.env['no_proxy'] != null) {
scriptArguments.push(`-ProxyBypassList ${process.env['no_proxy']}`);
}
scriptPath =
(await io.which('pwsh', false)) || (await io.which('powershell', true));
scriptArguments = windowsDefaultOptions.concat(scriptArguments);
} else {
chmodSync(escapedScript, '777');
scriptPath = await io.which(escapedScript, true);
scriptArguments = [];
if (dotnetVersion.type) {
scriptArguments.push(dotnetVersion.type, dotnetVersion.value);
}
if (this.quality) {
this.setQuality(dotnetVersion, scriptArguments);
}
}
// process.env must be explicitly passed in for DOTNET_INSTALL_DIR to be used
const getExecOutputOptions = {
ignoreReturnCode: true,
env: process.env as {string: string}
};
const {exitCode, stdout} = await exec.getExecOutput(
`"${scriptPath}"`,
scriptArguments,
getExecOutputOptions
);
if (exitCode) {
throw new Error(`Failed to install dotnet ${exitCode}. ${stdout}`);
}
return this.outputDotnetVersion(dotnetVersion.value);
}
private async outputDotnetVersion(version): Promise<string> {
const installationPath = process.env['DOTNET_INSTALL_DIR']!;
let versionsOnRunner: string[] = await readdir(
path.join(installationPath.replace(/'/g, ''), 'sdk')
);
let installedVersion = semver.maxSatisfying(versionsOnRunner, version, {
includePrerelease: true
})!;
return installedVersion;
}
}

View File

@ -1,38 +1,75 @@
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 {
//
// dotnet-version is optional, but needs to be provided for most use cases.
// If supplied, install / use from the tool cache.
// global-version-file may be specified to point to a specific global.json
// and will be used to install an additional version.
// If not supplied, look for version in ./global.json.
// 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 version = core.getInput('dotnet-version');
if (!version) {
const versions = core.getMultilineInput('dotnet-version');
const installedDotnetVersions: string[] = [];
const globalJsonFileInput = core.getInput('global-json-file');
if (globalJsonFileInput) {
const globalJsonPath = path.join(process.cwd(), globalJsonFileInput);
if (!fs.existsSync(globalJsonPath)) {
throw new Error(
`The specified global.json file '${globalJsonFileInput}' does not exist`
);
}
versions.push(getVersionFromGlobalJson(globalJsonPath));
}
if (!versions.length) {
// Try to fall back to global.json
core.debug('No version found, trying to find version from global.json');
const globalJsonPath = path.join(process.cwd(), 'global.json');
if (fs.existsSync(globalJsonPath)) {
version = getVersionFromGlobalJson(globalJsonPath);
versions.push(getVersionFromGlobalJson(globalJsonPath));
} else {
core.info(
`global.json wasn't found in the root directory. No .NET version will be installed.`
);
}
}
if (version) {
const includePrerelease: boolean =
(core.getInput('include-prerelease') || 'false').toLowerCase() ===
'true';
if (versions.length) {
const quality = core.getInput('dotnet-quality') as QualityOptions;
const dotnetInstaller = new installer.DotnetCoreInstaller(
version,
includePrerelease
);
await dotnetInstaller.installDotnet();
if (quality && !qualityOptions.includes(quality)) {
throw new Error(
`${quality} is not a supported value for 'dotnet-quality' option. Supported values are: daily, signed, validated, preview, ga.`
);
}
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');
@ -41,8 +78,22 @@ export async function run() {
auth.configAuthentication(sourceUrl, configFile);
}
const comparisonRange: string = globalJsonFileInput
? versions[versions.length - 1]!
: '*';
const versionToOutput = semver.maxSatisfying(
installedDotnetVersions,
comparisonRange,
{
includePrerelease: true
}
);
core.setOutput('dotnet-version', versionToOutput);
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);
}

2
src/utils.ts Normal file
View File

@ -0,0 +1,2 @@
export const IS_WINDOWS = process.platform === 'win32';
export const IS_LINUX = process.platform === 'linux';

View File

@ -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. */