Compare commits

..

1 Commits

Author SHA1 Message Date
github-actions[bot]
2432953e24 Update configuration files 2026-07-12 04:14:09 +00:00
90 changed files with 102992 additions and 121009 deletions

6
.eslintignore Normal file
View File

@@ -0,0 +1,6 @@
# Ignore list
/*
# Do not ignore these folders:
!__tests__/
!src/

51
.eslintrc.js Normal file
View File

@@ -0,0 +1,51 @@
// This is a reusable configuration file copied from https://github.com/actions/reusable-workflows/tree/main/reusable-configurations. Please don't make changes to this file as it's the subject of an automatic update.
module.exports = {
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:eslint-plugin-jest/recommended',
'eslint-config-prettier'
],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint', 'eslint-plugin-node', 'eslint-plugin-jest'],
rules: {
'@typescript-eslint/no-require-imports': 'error',
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/ban-ts-comment': [
'error',
{
'ts-ignore': 'allow-with-description'
}
],
'no-console': 'error',
'yoda': 'error',
'prefer-const': [
'error',
{
destructuring: 'all'
}
],
'no-control-regex': 'off',
'no-constant-condition': ['error', {checkLoops: false}],
'node/no-extraneous-import': 'error'
},
overrides: [
{
files: ['**/*{test,spec}.ts'],
rules: {
'@typescript-eslint/no-unused-vars': 'off',
'jest/no-standalone-expect': 'off',
'jest/no-conditional-expect': 'off',
'no-console': 'off',
}
}
],
env: {
node: true,
es6: true,
'jest/globals': true
}
};

View File

@@ -14,7 +14,6 @@ on:
jobs: jobs:
call-basic-validation: call-basic-validation:
name: Basic validation name: Basic validation
cache-mode: read
uses: actions/reusable-workflows/.github/workflows/basic-validation.yml@main uses: actions/reusable-workflows/.github/workflows/basic-validation.yml@main
with: with:
node-version: '24' node-version: '24'

View File

@@ -14,7 +14,6 @@ on:
jobs: jobs:
call-check-dist: call-check-dist:
name: Check dist/ name: Check dist/
cache-mode: read
uses: actions/reusable-workflows/.github/workflows/check-dist.yml@main uses: actions/reusable-workflows/.github/workflows/check-dist.yml@main
with: with:
node-version: '24' node-version: '24'

View File

@@ -27,7 +27,7 @@ jobs:
] ]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clear toolcache - name: Clear toolcache
shell: pwsh shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }} run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
@@ -57,7 +57,7 @@ jobs:
] ]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clear toolcache - name: Clear toolcache
shell: pwsh shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }} run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
@@ -92,7 +92,7 @@ jobs:
] ]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clear toolcache - name: Clear toolcache
shell: pwsh shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }} run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
@@ -123,7 +123,7 @@ jobs:
] ]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clear toolcache - name: Clear toolcache
shell: pwsh shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }} run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
@@ -149,7 +149,7 @@ jobs:
] ]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clear toolcache - name: Clear toolcache
shell: pwsh shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }} run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
@@ -180,7 +180,7 @@ jobs:
] ]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clear toolcache - name: Clear toolcache
shell: pwsh shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }} run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
@@ -208,7 +208,7 @@ jobs:
] ]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clear toolcache - name: Clear toolcache
shell: pwsh shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }} run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
@@ -239,7 +239,7 @@ jobs:
] ]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clear toolcache - name: Clear toolcache
shell: pwsh shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }} run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
@@ -265,7 +265,7 @@ jobs:
operating-system: [ubuntu-latest, windows-latest, macos-latest] operating-system: [ubuntu-latest, windows-latest, macos-latest]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clear toolcache - name: Clear toolcache
shell: pwsh shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }} run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
@@ -290,7 +290,7 @@ jobs:
operating-system: [ubuntu-latest, windows-latest, macos-latest] operating-system: [ubuntu-latest, windows-latest, macos-latest]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clear toolcache - name: Clear toolcache
shell: pwsh shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }} run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
@@ -315,7 +315,7 @@ jobs:
operating-system: [ubuntu-latest, windows-latest, macos-latest] operating-system: [ubuntu-latest, windows-latest, macos-latest]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clear toolcache - name: Clear toolcache
shell: pwsh shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }} run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
@@ -347,7 +347,7 @@ jobs:
] ]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clear toolcache - name: Clear toolcache
shell: pwsh shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }} run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
@@ -379,7 +379,7 @@ jobs:
] ]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clear toolcache - name: Clear toolcache
shell: pwsh shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }} run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
@@ -410,7 +410,7 @@ jobs:
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clear toolcache - name: Clear toolcache
shell: pwsh shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }} run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
@@ -448,7 +448,7 @@ jobs:
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clear toolcache - name: Clear toolcache
shell: pwsh shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }} run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
@@ -482,7 +482,7 @@ jobs:
] ]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clear toolcache - name: Clear toolcache
shell: pwsh shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }} run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
@@ -515,7 +515,7 @@ jobs:
] ]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clear toolcache - name: Clear toolcache
shell: pwsh shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }} run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
@@ -555,7 +555,7 @@ jobs:
http_proxy: http://squid-proxy:3128 http_proxy: http://squid-proxy:3128
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clear toolcache - name: Clear toolcache
shell: pwsh shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }} run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
@@ -578,7 +578,7 @@ jobs:
no_proxy: github.com,download.visualstudio.microsoft.com,api.nuget.org,builds.dotnet.microsoft.com,ci.dot.net no_proxy: github.com,download.visualstudio.microsoft.com,api.nuget.org,builds.dotnet.microsoft.com,ci.dot.net
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clear toolcache - name: Clear toolcache
shell: pwsh shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }} run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
@@ -610,7 +610,7 @@ jobs:
higher-version: ['10.0.101'] higher-version: ['10.0.101']
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clear toolcache - name: Clear toolcache
shell: pwsh shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }} run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
@@ -639,7 +639,7 @@ jobs:
[ubuntu-latest, windows-latest, macos-15-intel, macos-latest] [ubuntu-latest, windows-latest, macos-15-intel, macos-latest]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clear toolcache - name: Clear toolcache
shell: pwsh shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }} run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
@@ -678,7 +678,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clear toolcache - name: Clear toolcache
shell: pwsh shell: pwsh
@@ -706,7 +706,7 @@ jobs:
operating-system: [ubuntu-latest] operating-system: [ubuntu-latest]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clear toolcache - name: Clear toolcache
shell: pwsh shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }} run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
@@ -726,7 +726,7 @@ jobs:
operating-system: [macos-latest] operating-system: [macos-latest]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clear toolcache - name: Clear toolcache
shell: pwsh shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }} run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
@@ -738,34 +738,3 @@ jobs:
- name: Verify dotnet - name: Verify dotnet
shell: pwsh shell: pwsh
run: __tests__/verify-dotnet.ps1 -Patterns "^9\.0\.1\d{2}" run: __tests__/verify-dotnet.ps1 -Patterns "^9\.0\.1\d{2}"
test-check-latest-false:
runs-on: ${{ matrix.operating-system }}
strategy:
fail-fast: false
matrix:
operating-system: [ubuntu-latest, windows-latest, macos-latest]
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Clear toolcache
shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
# Oldest 9.0.1xx SDK: resolving '9.0.1xx' online would return a newer patch.
- name: Setup dotnet 9.0.100
uses: ./
with:
dotnet-version: '9.0.100'
- name: Setup dotnet 9.0.1xx with check-latest false
id: reuse
uses: ./
with:
dotnet-version: '9.0.1xx'
check-latest: false
- name: Verify dotnet
shell: pwsh
run: |
if ('${{ steps.reuse.outputs.dotnet-version }}' -ne '9.0.100') {
throw "Expected 9.0.100 to be reused, got '${{ steps.reuse.outputs.dotnet-version }}'."
}
__tests__/verify-dotnet.ps1 -Patterns "^9\.0\.100$"

View File

@@ -14,7 +14,7 @@ jobs:
steps: steps:
- name: Checking out - name: Checking out
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Publish - name: Publish
id: publish id: publish
uses: actions/publish-immutable-action@4bc8754ffc40f27910afb20287dbbbb675a4e978 # v0.0.4 uses: actions/publish-immutable-action@4bc8754ffc40f27910afb20287dbbbb675a4e978 # v0.0.4

View File

@@ -28,7 +28,7 @@ jobs:
dotnet-version: ['8.0', '9.0', '10.0'] dotnet-version: ['8.0', '9.0', '10.0']
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clear toolcache - name: Clear toolcache
shell: pwsh shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }} run: __tests__/clear-toolcache.ps1 ${{ runner.os }}

View File

@@ -10,11 +10,8 @@ allowed:
- mit - mit
- cc0-1.0 - cc0-1.0
- unlicense - unlicense
- blueoak-1.0.0
reviewed: reviewed:
npm: npm:
- sax # ISC + MIT - sax # ISC + MIT
- "@actions/http-client" # MIT - "@actions/http-client" # MIT
- balanced-match # MIT
- brace-expansion # MIT

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,10 +1,10 @@
--- ---
name: "@actions/http-client" name: "@actions/http-client"
version: 4.0.1 version: 2.2.3
type: npm type: npm
summary: Actions Http Client summary: Actions Http Client
homepage: https://github.com/actions/toolkit/tree/main/packages/http-client homepage: https://github.com/actions/toolkit/tree/main/packages/http-client
license: other license: mit
licenses: licenses:
- sources: LICENSE - sources: LICENSE
text: | text: |

View File

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

View File

@@ -1,17 +1,16 @@
--- ---
name: xml-naming name: "@azure/abort-controller"
version: 0.3.0 version: 1.1.0
type: npm type: npm
summary: Validates XML name productions — Name, NCName, QName, NMToken, NMTokens — summary: Microsoft Azure SDK for JavaScript - Aborter
for XML 1.0 and 1.1 homepage: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/abort-controller/README.md
homepage:
license: mit license: mit
licenses: licenses:
- sources: LICENSE - sources: LICENSE
text: | text: |
MIT License The MIT License (MIT)
Copyright (c) 2026 Natural Intelligence Copyright (c) 2020 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -30,6 +29,4 @@ licenses:
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
- sources: README.md
text: MIT
notices: [] notices: []

View File

@@ -1,6 +1,6 @@
--- ---
name: "@azure/core-client" name: "@azure/core-client"
version: 1.10.2 version: 1.10.1
type: npm type: npm
summary: Core library for interfacing with AutoRest generated code summary: Core library for interfacing with AutoRest generated code
homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-client/ homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-client/

View File

@@ -1,6 +1,6 @@
--- ---
name: "@azure/core-http-compat" name: "@azure/core-http-compat"
version: 2.4.0 version: 2.3.1
type: npm type: npm
summary: Core HTTP Compatibility Library to bridge the gap between Core V1 & V2 packages. summary: Core HTTP Compatibility Library to bridge the gap between Core V1 & V2 packages.
homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-compat/ homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-compat/

View File

@@ -1,9 +1,9 @@
--- ---
name: "@azure/core-rest-pipeline" name: "@azure/core-rest-pipeline"
version: 1.24.0 version: 1.22.2
type: npm type: npm
summary: Isomorphic client library for making HTTP requests in node.js and browser. summary: Isomorphic client library for making HTTP requests in node.js and browser.
homepage: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/core-rest-pipeline/README.md homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-rest-pipeline/
license: mit license: mit
licenses: licenses:
- sources: LICENSE - sources: LICENSE

View File

@@ -1,6 +1,6 @@
--- ---
name: "@azure/core-xml" name: "@azure/core-xml"
version: 1.5.1 version: 1.5.0
type: npm type: npm
summary: Core library for interacting with XML payloads summary: Core library for interacting with XML payloads
homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-xml/ homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-xml/

View File

@@ -1,9 +1,9 @@
--- ---
name: "@azure/storage-blob" name: "@azure/storage-blob"
version: 12.32.0 version: 12.29.1
type: npm type: npm
summary: Microsoft Azure Storage SDK for JavaScript - Blob summary: Microsoft Azure Storage SDK for JavaScript - Blob
homepage: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/storage/storage-blob/README.md homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/storage/storage-blob/
license: mit license: mit
licenses: licenses:
- sources: LICENSE - sources: LICENSE

View File

@@ -1,9 +1,9 @@
--- ---
name: "@azure/storage-common" name: "@azure/storage-common"
version: 12.4.1 version: 12.1.1
type: npm type: npm
summary: Azure Storage Common Client Library for JavaScript summary: Azure Storage Common Client Library for JavaScript
homepage: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/storage/storage-common/README.md homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/storage/storage-internal-avro/
license: mit license: mit
licenses: licenses:
- sources: LICENSE - sources: LICENSE

View File

@@ -1,9 +1,9 @@
--- ---
name: "@nodable/entities" name: "@nodable/entities"
version: 3.0.0 version: 2.2.0
type: npm type: npm
summary: Entity parser for XML, HTML, External entites with security and NCR control summary: Entity parser for XML, HTML, External entites with security and NCR control
homepage: homepage:
license: mit license: mit
licenses: licenses:
- sources: README.md - sources: README.md

View File

@@ -1,6 +1,6 @@
--- ---
name: "@octokit/auth-token" name: "@octokit/auth-token"
version: 6.0.0 version: 4.0.0
type: npm type: npm
summary: GitHub API token authentication for browsers and Node.js summary: GitHub API token authentication for browsers and Node.js
homepage: homepage:

View File

@@ -1,6 +1,6 @@
--- ---
name: "@octokit/core" name: "@octokit/core"
version: 7.0.6 version: 5.0.1
type: npm type: npm
summary: Extendable client for GitHub's REST & GraphQL APIs summary: Extendable client for GitHub's REST & GraphQL APIs
homepage: homepage:

View File

@@ -1,6 +1,6 @@
--- ---
name: "@octokit/endpoint" name: "@octokit/endpoint"
version: 11.0.3 version: 9.0.6
type: npm type: npm
summary: Turns REST API endpoints into generic request options summary: Turns REST API endpoints into generic request options
homepage: homepage:

View File

@@ -1,6 +1,6 @@
--- ---
name: "@octokit/graphql" name: "@octokit/graphql"
version: 9.0.3 version: 7.0.2
type: npm type: npm
summary: GitHub GraphQL API client for browsers and Node summary: GitHub GraphQL API client for browsers and Node
homepage: homepage:

View File

@@ -1,14 +1,14 @@
--- ---
name: "@octokit/openapi-types" name: "@octokit/openapi-types"
version: 27.0.0 version: 20.0.0
type: npm type: npm
summary: Generated TypeScript definitions based on GitHub's OpenAPI spec for api.github.com summary: Generated TypeScript definitions based on GitHub's OpenAPI spec for api.github.com
homepage: homepage:
license: mit license: mit
licenses: licenses:
- sources: LICENSE - sources: LICENSE
text: | text: |-
Copyright (c) GitHub 2025 - Licensed as MIT. Copyright 2020 Gregor Martynus
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: 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:

View File

@@ -1,20 +1,20 @@
--- ---
name: "@actions/glob" name: "@octokit/openapi-types"
version: 0.7.0 version: 24.2.0
type: npm type: npm
summary: Actions glob lib summary: Generated TypeScript definitions based on GitHub's OpenAPI spec for api.github.com
homepage: https://github.com/actions/toolkit/tree/main/packages/glob homepage:
license: mit license: mit
licenses: licenses:
- sources: LICENSE.md - sources: LICENSE
text: |- text: |-
The MIT License (MIT) Copyright 2020 Gregor Martynus
Copyright 2019 GitHub
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 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 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. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- sources: README.md
text: "[MIT](LICENSE)"
notices: [] notices: []

View File

@@ -1,6 +1,6 @@
--- ---
name: "@octokit/plugin-paginate-rest" name: "@octokit/plugin-paginate-rest"
version: 14.0.0 version: 9.2.2
type: npm type: npm
summary: Octokit plugin to paginate REST API endpoint responses summary: Octokit plugin to paginate REST API endpoint responses
homepage: homepage:

View File

@@ -1,6 +1,6 @@
--- ---
name: "@octokit/plugin-rest-endpoint-methods" name: "@octokit/plugin-rest-endpoint-methods"
version: 17.0.0 version: 10.4.1
type: npm type: npm
summary: Octokit plugin adding one method for all of api.github.com REST API endpoints summary: Octokit plugin adding one method for all of api.github.com REST API endpoints
homepage: homepage:

View File

@@ -1,6 +1,6 @@
--- ---
name: "@octokit/request-error" name: "@octokit/request-error"
version: 7.1.0 version: 5.1.1
type: npm type: npm
summary: Error class for Octokit request errors summary: Error class for Octokit request errors
homepage: homepage:

View File

@@ -1,6 +1,6 @@
--- ---
name: "@octokit/request" name: "@octokit/request"
version: 10.0.10 version: 8.4.1
type: npm type: npm
summary: Send parameterized requests to GitHub's APIs with sensible defaults in browsers summary: Send parameterized requests to GitHub's APIs with sensible defaults in browsers
and Node and Node

View File

@@ -1,6 +1,6 @@
--- ---
name: "@octokit/types" name: "@octokit/types"
version: 16.0.0 version: 12.6.0
type: npm type: npm
summary: Shared TypeScript definitions for Octokit projects summary: Shared TypeScript definitions for Octokit projects
homepage: homepage:

View File

@@ -0,0 +1,20 @@
---
name: "@octokit/types"
version: 13.10.0
type: npm
summary: Shared TypeScript definitions for Octokit projects
homepage:
license: mit
licenses:
- sources: LICENSE
text: |
MIT License Copyright (c) 2019 Octokit 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 (including the next paragraph) shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- sources: README.md
text: "[MIT](LICENSE)"
notices: []

View File

@@ -1,9 +1,9 @@
--- ---
name: "@typespec/ts-http-runtime" name: "@typespec/ts-http-runtime"
version: 0.3.6 version: 0.3.2
type: npm type: npm
summary: Isomorphic client library for making HTTP requests in node.js and browser. summary: Isomorphic client library for making HTTP requests in node.js and browser.
homepage: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/ts-http-runtime/README.md homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/ts-http-runtime/
license: mit license: mit
licenses: licenses:
- sources: LICENSE - sources: LICENSE

View File

@@ -1,34 +0,0 @@
---
name: balanced-match
version: 4.0.4
type: npm
summary: Match balanced character pairs, like "{" and "}"
homepage:
license: other
licenses:
- sources: LICENSE.md
text: |
(MIT)
Original code Copyright Julian Gruber <julian@juliangruber.com>
Port to TypeScript Copyright Isaac Z. Schlueter <i@izs.me>
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,6 +1,6 @@
--- ---
name: before-after-hook name: before-after-hook
version: 4.0.0 version: 2.2.3
type: npm type: npm
summary: asynchronous before/error/after hooks for internal functionality summary: asynchronous before/error/after hooks for internal functionality
homepage: homepage:

View File

@@ -1,34 +0,0 @@
---
name: brace-expansion
version: 5.0.9
type: npm
summary: Brace expansion as known from sh/bash
homepage:
license: other
licenses:
- sources: LICENSE
text: |
MIT License
Copyright Julian Gruber <julian@juliangruber.com>
TypeScript port Copyright Isaac Z. Schlueter <i@izs.me>
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,6 +1,6 @@
--- ---
name: brace-expansion name: brace-expansion
version: 1.1.18 version: 1.1.15
type: npm type: npm
summary: Brace expansion as known from sh/bash summary: Brace expansion as known from sh/bash
homepage: https://github.com/juliangruber/brace-expansion homepage: https://github.com/juliangruber/brace-expansion

View File

@@ -1,47 +0,0 @@
---
name: content-type
version: 2.0.0
type: npm
summary: Create and parse HTTP Content-Type header
homepage:
license: mit
licenses:
- sources: LICENSE
text: |
(The MIT License)
Copyright (c) 2015 Douglas Christopher Wilson
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- sources: README.md
text: |-
[MIT](LICENSE)
[npm-image]: https://img.shields.io/npm/v/content-type
[npm-url]: https://npmjs.org/package/content-type
[downloads-image]: https://img.shields.io/npm/dm/content-type
[downloads-url]: https://npmjs.org/package/content-type
[build-image]: https://img.shields.io/github/actions/workflow/status/jshttp/content-type/ci.yml?branch=master
[build-url]: https://github.com/jshttp/content-type/actions/workflows/ci.yml?query=branch%3Amaster
[coverage-image]: https://img.shields.io/codecov/c/gh/jshttp/content-type
[coverage-url]: https://codecov.io/gh/jshttp/content-type
[license-image]: http://img.shields.io/npm/l/content-type.svg?style=flat
[license-url]: LICENSE
notices: []

View File

@@ -1,6 +1,6 @@
--- ---
name: debug name: debug
version: 4.4.3 version: 4.3.4
type: npm type: npm
summary: Lightweight debugging utility for Node.js and the browser summary: Lightweight debugging utility for Node.js and the browser
homepage: homepage:

28
.licenses/npm/deprecation.dep.yml generated Normal file
View File

@@ -0,0 +1,28 @@
---
name: deprecation
version: 2.3.1
type: npm
summary: Log a deprecation message with stack
homepage: https://github.com/gr2m/deprecation#readme
license: isc
licenses:
- sources: LICENSE
text: |
The ISC License
Copyright (c) Gregor Martynus and contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- sources: README.md
text: "[ISC](LICENSE)"
notices: []

View File

@@ -1,9 +1,9 @@
--- ---
name: fast-xml-parser name: fast-xml-parser
version: 5.10.1 version: 5.9.2
type: npm type: npm
summary: Validate XML, Parse XML, Build XML without C/C++ based libraries summary: Validate XML, Parse XML, Build XML without C/C++ based libraries
homepage: homepage:
license: mit license: mit
licenses: licenses:
- sources: LICENSE - sources: LICENSE

View File

@@ -1,10 +1,10 @@
--- ---
name: is-unsafe name: is-unsafe
version: 2.0.0 version: 1.0.1
type: npm type: npm
summary: Zero-dependency, DOM-free, pure predicate for detecting unsafe strings across summary: Zero-dependency, DOM-free, pure predicate for detecting unsafe strings across
HTML, XML, SVG, SQL, SHELL, and REGEX contexts HTML, XML, SVG, SQL, SHELL, and REGEX contexts
homepage: homepage:
license: mit license: mit
licenses: licenses:
- sources: LICENSE - sources: LICENSE

View File

@@ -1,33 +0,0 @@
---
name: json-with-bigint
version: 3.5.8
type: npm
summary: JS library that allows you to easily serialize and deserialize data with
BigInt values
homepage:
license: mit
licenses:
- sources: LICENSE
text: |
MIT License
Copyright (c) 2023 Ivan Korolenko
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: []

26
.licenses/npm/lru-cache.dep.yml generated Normal file
View File

@@ -0,0 +1,26 @@
---
name: lru-cache
version: 6.0.0
type: npm
summary: A cache object that deletes the least-recently-used items.
homepage:
license: isc
licenses:
- sources: LICENSE
text: |
The ISC License
Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
notices: []

View File

@@ -1,66 +0,0 @@
---
name: minimatch
version: 10.2.5
type: npm
summary: a glob matcher in javascript
homepage:
license: blueoak-1.0.0
licenses:
- sources: LICENSE.md
text: |
# Blue Oak Model License
Version 1.0.0
## Purpose
This license gives everyone as much permission to work with
this software as possible, while protecting contributors
from liability.
## Acceptance
In order to receive this license, you must agree to its
rules. The rules of this license are both obligations
under that agreement and conditions to your license.
You must not do anything with this software that triggers
a rule that you cannot or will not follow.
## Copyright
Each contributor licenses you to do everything with this
software that would otherwise infringe that contributor's
copyright in it.
## Notices
You must ensure that everyone who gets a copy of
any part of this software from you, with or without
changes, also gets the text of this license or a link to
<https://blueoakcouncil.org/license/1.0.0>.
## Excuse
If anyone notifies you in writing that you have not
complied with [Notices](#notices), you can keep your
license by taking all practical steps to comply within 30
days after the notice. If you do not do so, your license
ends immediately.
## Patent
Each contributor licenses you to do everything with this
software that would otherwise infringe any patent claims
they can license or become able to license.
## Reliability
No contributor can revoke this license.
## No Liability
**_As far as the law allows, this software comes as is,
without any warranty or condition, and no contributor
will be liable to anyone for any damages related to this
software or this license, under any kind of legal claim._**
notices: []

View File

@@ -1,6 +1,6 @@
--- ---
name: ms name: ms
version: 2.1.3 version: 2.1.2
type: npm type: npm
summary: Tiny millisecond conversion utility summary: Tiny millisecond conversion utility
homepage: homepage:
@@ -10,7 +10,7 @@ licenses:
text: | text: |
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2020 Vercel, Inc. Copyright (c) 2016 Zeit, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

26
.licenses/npm/once.dep.yml generated Normal file
View File

@@ -0,0 +1,26 @@
---
name: once
version: 1.4.0
type: npm
summary: Run a function exactly one time
homepage: https://github.com/isaacs/once#readme
license: isc
licenses:
- sources: LICENSE
text: |
The ISC License
Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
notices: []

View File

@@ -1,6 +1,6 @@
--- ---
name: path-expression-matcher name: path-expression-matcher
version: 1.6.2 version: 1.5.0
type: npm type: npm
summary: Efficient path tracking and pattern matching for XML/JSON parsers summary: Efficient path tracking and pattern matching for XML/JSON parsers
homepage: https://github.com/NaturalIntelligence/path-expression-matcher#readme homepage: https://github.com/NaturalIntelligence/path-expression-matcher#readme

View File

@@ -1,6 +1,6 @@
--- ---
name: semver name: semver
version: 7.8.5 version: 6.3.1
type: npm type: npm
summary: The semantic version parser used by npm. summary: The semantic version parser used by npm.
homepage: homepage:

26
.licenses/npm/semver-7.6.0.dep.yml generated Normal file
View File

@@ -0,0 +1,26 @@
---
name: semver
version: 7.6.0
type: npm
summary: The semantic version parser used by npm.
homepage:
license: isc
licenses:
- sources: LICENSE
text: |
The ISC License
Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
notices: []

View File

@@ -1,6 +1,6 @@
--- ---
name: undici name: undici
version: 6.28.0 version: 6.27.0
type: npm type: npm
summary: An HTTP/1.1 client, written from scratch for Node.js summary: An HTTP/1.1 client, written from scratch for Node.js
homepage: https://undici.nodejs.org homepage: https://undici.nodejs.org

View File

@@ -1,8 +1,8 @@
--- ---
name: universal-user-agent name: universal-user-agent
version: 7.0.3 version: 6.0.1
type: npm type: npm
summary: Get a user agent string across all JavaScript Runtime Environments summary: Get a user agent string in both browser and node
homepage: homepage:
license: isc license: isc
licenses: licenses:
@@ -10,7 +10,7 @@ licenses:
text: | text: |
# [ISC License](https://spdx.org/licenses/ISC) # [ISC License](https://spdx.org/licenses/ISC)
Copyright (c) 2018-2021, Gregor Martynus (https://github.com/gr2m) Copyright (c) 2018, Gregor Martynus (https://github.com/gr2m)
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.

26
.licenses/npm/wrappy.dep.yml generated Normal file
View File

@@ -0,0 +1,26 @@
---
name: wrappy
version: 1.0.2
type: npm
summary: Callback wrapping utility
homepage: https://github.com/npm/wrappy
license: isc
licenses:
- sources: LICENSE
text: |
The ISC License
Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
notices: []

View File

@@ -4,7 +4,7 @@ version: 0.1.0
type: npm type: npm
summary: Validates XML name productions — Name, NCName, QName, NMToken, NMTokens — summary: Validates XML name productions — Name, NCName, QName, NMToken, NMTokens —
for XML 1.0 and 1.1 for XML 1.0 and 1.1
homepage: homepage:
license: mit license: mit
licenses: licenses:
- sources: README.md - sources: README.md

26
.licenses/npm/yallist.dep.yml generated Normal file
View File

@@ -0,0 +1,26 @@
---
name: yallist
version: 4.0.0
type: npm
summary: Yet Another Linked List
homepage:
license: isc
licenses:
- sources: LICENSE
text: |
The ISC License
Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
notices: []

11
.prettierrc.js Normal file
View File

@@ -0,0 +1,11 @@
// This is a reusable configuration file copied from https://github.com/actions/reusable-workflows/tree/main/reusable-configurations. Please don't make changes to this file as it's the subject of an automatic update.
module.exports = {
printWidth: 80,
tabWidth: 2,
useTabs: false,
semi: true,
singleQuote: true,
trailingComma: 'none',
bracketSpacing: false,
arrowParens: 'avoid'
};

120
README.md
View File

@@ -5,7 +5,7 @@
This action sets up a [.NET CLI](https://github.com/dotnet/sdk) environment for use in actions by: This action sets up a [.NET CLI](https://github.com/dotnet/sdk) environment for use in actions by:
- optionally download and install the requested .NET SDK version(s) and add them to the PATH - optionally downloading and caching a version(s) of dotnet by SDK version(s) and adding to PATH
- registering problem matchers for error output - registering problem matchers for error output
- setting up authentication to private package sources like GitHub Packages - setting up authentication to private package sources like GitHub Packages
@@ -15,16 +15,12 @@ documentation:
[Software installed on github hosted runners](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#supported-software) [Software installed on github hosted runners](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#supported-software)
for .NET SDK versions that are currently available. for .NET SDK versions that are currently available.
## What's new in V6
- Migrated action internals to ESM for compatibility with latest `@actions/*` packages. No changes to action inputs, outputs, or behavior.
## Breaking changes in V5 ## Breaking changes in V5
- Upgraded action from node20 to node24 - Upgraded action from node20 to node24
> Make sure your runner is on version v2.327.1 or later to ensure compatibility with this release. see [Release Notes](https://github.com/actions/runner/releases/tag/v2.327.1) > Make sure your runner is on version v2.327.1 or later to ensure compatibility with this release. see [Release Notes](https://github.com/actions/runner/releases/tag/v2.327.1)
For more details, see the full release notes on the [release page](https://github.com/actions/setup-dotnet/releases) For more details, see the full release notes on the [release page](https://github.com/actions/setup-dotnet/releases/tag/v5.0.0)
## Usage ## Usage
@@ -33,8 +29,8 @@ See [action.yml](action.yml)
**Basic**: **Basic**:
```yaml ```yaml
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v6
- uses: actions/setup-dotnet@v6 - uses: actions/setup-dotnet@v5
with: with:
dotnet-version: '8.0.x' dotnet-version: '8.0.x'
- run: dotnet build <my project> - run: dotnet build <my project>
@@ -44,9 +40,9 @@ steps:
**Multiple version installation**: **Multiple version installation**:
```yml ```yml
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v6
- name: Setup dotnet - name: Setup dotnet
uses: actions/setup-dotnet@v6 uses: actions/setup-dotnet@v5
with: with:
dotnet-version: | dotnet-version: |
8.0.x 8.0.x
@@ -79,8 +75,8 @@ The optional `dotnet-channel` input specifies the source channel for the install
**Install latest LTS version:** **Install latest LTS version:**
```yaml ```yaml
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v6
- uses: actions/setup-dotnet@v6 - uses: actions/setup-dotnet@v5
with: with:
dotnet-version: latest dotnet-version: latest
dotnet-channel: LTS dotnet-channel: LTS
@@ -92,9 +88,9 @@ Using the architecture input, it is possible to specify the required .NET SDK ar
**Example: Install multiple SDK versions for a specific architecture** **Example: Install multiple SDK versions for a specific architecture**
```yml ```yml
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v6
- name: Setup dotnet (x86) - name: Setup dotnet (x86)
uses: actions/setup-dotnet@v6 uses: actions/setup-dotnet@v5
with: with:
dotnet-version: | dotnet-version: |
8.0.x 8.0.x
@@ -105,28 +101,14 @@ steps:
## Using the `dotnet-quality` input ## Using the `dotnet-quality` input
The `dotnet-quality` input installs the latest build of the specified quality in the channel. Supported values: `daily`, `preview`, `ga`. For more details about quality options, see the [official .NET documentation](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script#options). The `dotnet-quality` input installs the latest build of the specified quality in the channel. Supported values: `daily`, `preview`, `ga`.
> **Important**: `dotnet-quality` is a single input shared across all versions listed in `dotnet-version` for the same step (and is only applied where supported by the version format), so per-version quality is not supported. For example, setting `dotnet-quality: preview` for `10.0.x` and `11.0.x` resolves both versions as previews. To install a released SDK alongside a preview SDK, use separate steps:
```yaml
steps:
- uses: actions/setup-dotnet@v6
with:
dotnet-version: '10.0.x'
- uses: actions/setup-dotnet@v6
with:
dotnet-version: '11.0.x'
dotnet-quality: 'preview'
```
> **Note**: When used with a specific SDK version, `dotnet-quality` supports only `A.B`, `A.B.x`, `A`, `A.x`, and `A.B.Cxx` formats where the major version is higher than 5. For all other formats, `dotnet-quality` will be ignored. > **Note**: When used with a specific SDK version, `dotnet-quality` supports only `A.B`, `A.B.x`, `A`, `A.x`, and `A.B.Cxx` formats where the major version is higher than 5. For all other formats, `dotnet-quality` will be ignored.
```yml ```yml
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v6
- uses: actions/setup-dotnet@v6 - uses: actions/setup-dotnet@v5
with: with:
dotnet-version: '8.0.x' dotnet-version: '8.0.x'
dotnet-quality: 'preview' dotnet-quality: 'preview'
@@ -137,8 +119,8 @@ steps:
```yaml ```yaml
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v6
- uses: actions/setup-dotnet@v6 - uses: actions/setup-dotnet@v5
with: with:
dotnet-version: latest dotnet-version: latest
dotnet-channel: LTS dotnet-channel: LTS
@@ -152,8 +134,8 @@ steps:
```yml ```yml
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v6
- uses: actions/setup-dotnet@v6 - uses: actions/setup-dotnet@v5
with: with:
global-json-file: csharp/global.json global-json-file: csharp/global.json
- run: dotnet build <my project> - run: dotnet build <my project>
@@ -162,8 +144,6 @@ steps:
> **Note**: The action supports `latest*` variants of the [rollForward](https://learn.microsoft.com/en-us/dotnet/core/tools/global-json#rollforward) field in `global.json`. When set to `latestPatch`, `latestFeature`, `latestMinor`, or `latestMajor`, the action installs the appropriate SDK version. For prerelease versions, the exact pinned version is always installed regardless of the `rollForward` setting. > **Note**: The action supports `latest*` variants of the [rollForward](https://learn.microsoft.com/en-us/dotnet/core/tools/global-json#rollforward) field in `global.json`. When set to `latestPatch`, `latestFeature`, `latestMinor`, or `latestMajor`, the action installs the appropriate SDK version. For prerelease versions, the exact pinned version is always installed regardless of the `rollForward` setting.
> **Important**: When using `rollForward` in `global.json`, the `sdk.version` field must be a fully-qualified SDK version (e.g., `8.0.100`, `10.0.100`). Wildcard versions (e.g., `10.0.*`) and runtime-style versions (e.g., `8.0.0`) are not supported. See the [.NET SDK version specification](https://learn.microsoft.com/en-us/dotnet/core/tools/global-json#version) for details.
## Caching NuGet Packages ## Caching NuGet Packages
The action has a built-in functionality for caching and restoring dependencies. It uses [toolkit/cache](https://github.com/actions/toolkit/tree/main/packages/cache) under the hood for caching global packages data but requires less configuration settings. The `cache` input is optional, and caching is turned off by default. The action has a built-in functionality for caching and restoring dependencies. It uses [toolkit/cache](https://github.com/actions/toolkit/tree/main/packages/cache) under the hood for caching global packages data but requires less configuration settings. The `cache` input is optional, and caching is turned off by default.
@@ -173,8 +153,8 @@ The action searches for [NuGet Lock files](https://learn.microsoft.com/nuget/con
```yaml ```yaml
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v6
- uses: actions/setup-dotnet@v6 - uses: actions/setup-dotnet@v5
with: with:
dotnet-version: 8.x dotnet-version: 8.x
cache: true cache: true
@@ -198,8 +178,8 @@ steps:
env: env:
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v6
- uses: actions/setup-dotnet@v6 - uses: actions/setup-dotnet@v5
with: with:
dotnet-version: 8.x dotnet-version: 8.x
cache: true cache: true
@@ -212,8 +192,8 @@ steps:
env: env:
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v6
- uses: actions/setup-dotnet@v6 - uses: actions/setup-dotnet@v5
with: with:
dotnet-version: 8.x dotnet-version: 8.x
cache: true cache: true
@@ -232,9 +212,9 @@ jobs:
dotnet: [ '8.0.x', '9.0.x', '10.0.x' ] dotnet: [ '8.0.x', '9.0.x', '10.0.x' ]
name: Dotnet ${{ matrix.dotnet }} sample name: Dotnet ${{ matrix.dotnet }} sample
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v6
- name: Setup dotnet - name: Setup dotnet
uses: actions/setup-dotnet@v6 uses: actions/setup-dotnet@v5
with: with:
dotnet-version: ${{ matrix.dotnet }} dotnet-version: ${{ matrix.dotnet }}
- name: Execute dotnet - name: Execute dotnet
@@ -252,9 +232,9 @@ jobs:
dotnet: [ '8.0.x', '9.0.x', '10.0.x' ] dotnet: [ '8.0.x', '9.0.x', '10.0.x' ]
name: Dotnet ${{ matrix.dotnet }} sample name: Dotnet ${{ matrix.dotnet }} sample
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v6
- name: Setup dotnet - name: Setup dotnet
uses: actions/setup-dotnet@v6 uses: actions/setup-dotnet@v5
id: stepid id: stepid
with: with:
dotnet-version: ${{ matrix.dotnet }} dotnet-version: ${{ matrix.dotnet }}
@@ -270,8 +250,8 @@ jobs:
### Github Package Registry (GPR) ### Github Package Registry (GPR)
```yml ```yml
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v6
- uses: actions/setup-dotnet@v6 - uses: actions/setup-dotnet@v5
with: with:
dotnet-version: '8.0.x' dotnet-version: '8.0.x'
source-url: https://nuget.pkg.github.com/<owner>/index.json source-url: https://nuget.pkg.github.com/<owner>/index.json
@@ -286,7 +266,7 @@ steps:
### Azure Artifacts ### Azure Artifacts
```yml ```yml
- uses: actions/setup-dotnet@v6 - uses: actions/setup-dotnet@v5
with: with:
source-url: https://pkgs.dev.azure.com/<your-organization>/_packaging/<your-feed-name>/nuget/v3/index.json source-url: https://pkgs.dev.azure.com/<your-organization>/_packaging/<your-feed-name>/nuget/v3/index.json
env: env:
@@ -297,7 +277,7 @@ steps:
### nuget.org ### nuget.org
```yml ```yml
- uses: actions/setup-dotnet@v6 - uses: actions/setup-dotnet@v5
with: with:
dotnet-version: 8.0.x dotnet-version: 8.0.x
- name: Publish the package to nuget.org - name: Publish the package to nuget.org
@@ -314,7 +294,7 @@ The `workloads` input allows you to install .NET workloads as part of the SDK se
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v5
- name: Setup .NET with workloads - name: Setup .NET with workloads
uses: actions/setup-dotnet@v6 uses: actions/setup-dotnet@v5
with: with:
dotnet-version: '9.0.x' dotnet-version: '9.0.x'
workloads: workload1, workload2 # Specify the workloads required for the project, such as wasm-tools, maui, etc. workloads: workload1, workload2 # Specify the workloads required for the project, such as wasm-tools, maui, etc.
@@ -323,29 +303,6 @@ steps:
> **Note**: Ensure workloads are compatible with your runner's OS, architecture, and .NET SDK version before enabling workload installation. Some workloads may require additional installation time due to large toolchain downloads. > **Note**: Ensure workloads are compatible with your runner's OS, architecture, and .NET SDK version before enabling workload installation. Some workloads may require additional installation time due to large toolchain downloads.
## Using the `check-latest` input
By default (`check-latest: true`) the action resolves and installs the latest version matching the request online, which is the historical behavior. With `check-latest: false` it first looks for an SDK already installed under [`DOTNET_INSTALL_DIR`](#environment-variables) and reuses it, skipping SDK resolution and download — useful for air-gapped or preloaded runners (the `cache` and `workloads` inputs still use the network). If none matches, it installs online as usual.
```yaml
steps:
- uses: actions/checkout@v7
- name: Reuse a preinstalled SDK when available
uses: actions/setup-dotnet@v6
with:
dotnet-version: '8.0.x'
check-latest: false
- run: dotnet build <my project>
```
An installed SDK is reused only when it matches the requested spec (`A.B.C`, `A.B`, `A.B.x`, `A.B.Cxx`, `A`, `A.x` or `latest`; `x`, `X` and `*` interchange except in a feature band, which is lowercase `Cxx`), satisfies `dotnet-quality`, is not older than the `sdk.version` declared in `global.json`, and sits next to a runnable `dotnet` executable. As online, `dotnet-quality` is ignored for a full `A.B.C` request, so such a request always resolves to a GA SDK. Cross-architecture requests, `latest` with an `LTS` or `STS` channel, and a bare wildcard always install online.
When the request comes from `global.json`, the SDK is picked the way the .NET resolver picks one: `latestPatch`, `latestFeature`, `latestMinor` and `latestMajor` take the **highest** SDK the policy allows, while `feature`, `minor` and `major` roll forward to the **nearest** higher feature band, minor or major and then take its latest patch. `patch` — the default when `rollForward` is omitted — prefers the declared version, otherwise the latest patch in its band. `disable` and a prerelease `sdk.version` require an exact match, and `allowPrerelease` is not used: `dotnet-quality` is the only prerelease control.
### Setting `check-latest` from the environment
When the input is not set, the action reads the `DOTNET_CHECK_LATEST` environment variable (`true` or `false`, case-insensitive; an unsupported value warns and is ignored), which covers workflows you cannot edit. Setting it on a self-hosted runner alongside SDKs preinstalled under [`DOTNET_INSTALL_DIR`](#environment-variables) lets those workflows run without reaching `aka.ms`, `builds.dotnet.microsoft.com` or `ci.dot.net`. It applies to every job on that runner, so a dedicated runner is recommended; any workflow can still override it with an explicit `check-latest` input.
# Outputs and environment variables # Outputs and environment variables
## Outputs ## Outputs
@@ -359,7 +316,7 @@ Using the **dotnet-version** output it's possible to get the installed by the ac
In case of a single version installation, the `dotnet-version` output contains the version that is installed by the action. In case of a single version installation, the `dotnet-version` output contains the version that is installed by the action.
```yaml ```yaml
- uses: actions/setup-dotnet@v6 - uses: actions/setup-dotnet@v5
id: stepid id: stepid
with: with:
dotnet-version: 8.0.416 dotnet-version: 8.0.416
@@ -371,7 +328,7 @@ In case of a single version installation, the `dotnet-version` output contains t
In case of a multiple version installation, the `dotnet-version` output contains the latest version that is installed by the action. In case of a multiple version installation, the `dotnet-version` output contains the latest version that is installed by the action.
```yaml ```yaml
- uses: actions/setup-dotnet@v6 - uses: actions/setup-dotnet@v5
id: stepid id: stepid
with: with:
dotnet-version: | dotnet-version: |
@@ -384,7 +341,7 @@ In case of a multiple version installation, the `dotnet-version` output contains
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`. 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 ```yaml
- uses: actions/setup-dotnet@v6 - uses: actions/setup-dotnet@v5
id: stepid id: stepid
with: with:
dotnet-version: | dotnet-version: |
@@ -404,7 +361,6 @@ Some environment variables may be necessary for your particular case or to impro
| **Env.variable** | **Description** | **Default value** | | **Env.variable** | **Description** | **Default value** |
| ----------- | ----------- | ----------- | | ----------- | ----------- | ----------- |
| DOTNET_INSTALL_DIR |Specifies a directory where .NET SDKs should be installed by the action.|*default value for each OS* | | DOTNET_INSTALL_DIR |Specifies a directory where .NET SDKs should be installed by the action.|*default value for each OS* |
| DOTNET_CHECK_LATEST |Fallback for the [`check-latest`](#setting-check-latest-from-the-environment) input, for workflows that cannot set it. Ignored when the input is set.|*true*|
| DOTNET_NOLOGO |Removes logo and telemetry message from first run of dotnet cli|*false*| | DOTNET_NOLOGO |Removes logo and telemetry message from first run of dotnet cli|*false*|
| DOTNET_CLI_TELEMETRY_OPTOUT |Opt-out of telemetry being sent to Microsoft|*false*| | DOTNET_CLI_TELEMETRY_OPTOUT |Opt-out of telemetry being sent to Microsoft|*false*|
| DOTNET_MULTILEVEL_LOOKUP |Configures whether the global install location is used as a fall-back|*true*| | DOTNET_MULTILEVEL_LOOKUP |Configures whether the global install location is used as a fall-back|*true*|
@@ -425,8 +381,8 @@ build:
DOTNET_INSTALL_DIR: "path/to/directory" DOTNET_INSTALL_DIR: "path/to/directory"
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v6
- uses: actions/setup-dotnet@v6 - uses: actions/setup-dotnet@v5
with: with:
dotnet-version: '8.0.x' dotnet-version: '8.0.x'
cache: true cache: true
@@ -454,4 +410,4 @@ The scripts and documentation in this project are released under the [MIT Licens
## 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,4 +1,4 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`authutil tests existing config not in repo root, sets up a partial NuGet.config user/PAT for GPR 1`] = ` exports[`authutil tests existing config not in repo root, sets up a partial NuGet.config user/PAT for GPR 1`] = `
"<?xml version="1.0"?> "<?xml version="1.0"?>

View File

@@ -1,10 +1,6 @@
import {afterAll, beforeEach, describe, expect, it} from '@jest/globals';
import * as io from '@actions/io'; import * as io from '@actions/io';
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import {fileURLToPath} from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const fakeSourcesDirForTesting = path.join( const fakeSourcesDirForTesting = path.join(
__dirname, __dirname,
@@ -75,7 +71,7 @@ const azureartifactsnugetorgNuGetConfig = `<?xml version="1.0" encoding="utf-8"?
const nugetConfigFile = path.join(fakeSourcesDirForTesting, '../nuget.config'); const nugetConfigFile = path.join(fakeSourcesDirForTesting, '../nuget.config');
process.env['GITHUB_REPOSITORY'] = 'OwnerName/repo'; process.env['GITHUB_REPOSITORY'] = 'OwnerName/repo';
import * as auth from '../src/authutil.js'; import * as auth from '../src/authutil';
describe('authutil tests', () => { describe('authutil tests', () => {
beforeEach(async () => { beforeEach(async () => {

View File

@@ -1,40 +1,16 @@
import { import {readdir} from 'node:fs/promises';
afterEach, import * as cache from '@actions/cache';
beforeAll, import * as core from '@actions/core';
beforeEach, import * as glob from '@actions/glob';
describe, import {restoreCache} from '../src/cache-restore';
expect, import {getNuGetFolderPath} from '../src/cache-utils';
it, import {lockFilePatterns} from '../src/constants';
jest
} from '@jest/globals';
jest.unstable_mockModule('node:fs/promises', () => ({ jest.mock('node:fs/promises');
readdir: jest.fn() jest.mock('@actions/cache');
})); jest.mock('@actions/core');
jest.unstable_mockModule('@actions/cache', () => ({ jest.mock('@actions/glob');
restoreCache: jest.fn() jest.mock('../src/cache-utils');
}));
jest.unstable_mockModule('@actions/core', () => ({
saveState: jest.fn(),
setOutput: jest.fn(),
info: jest.fn(),
warning: jest.fn(),
debug: jest.fn()
}));
jest.unstable_mockModule('@actions/glob', () => ({
hashFiles: jest.fn()
}));
jest.unstable_mockModule('../src/cache-utils', () => ({
getNuGetFolderPath: jest.fn()
}));
const {readdir} = await import('node:fs/promises');
const cache = await import('@actions/cache');
const core = await import('@actions/core');
const glob = await import('@actions/glob');
const {restoreCache} = await import('../src/cache-restore.js');
const {getNuGetFolderPath} = await import('../src/cache-utils.js');
const {lockFilePatterns} = await import('../src/constants.js');
describe('cache-restore tests', () => { describe('cache-restore tests', () => {
describe.each(lockFilePatterns)('restoreCache("%s")', lockFilePattern => { describe.each(lockFilePatterns)('restoreCache("%s")', lockFilePattern => {
@@ -56,9 +32,7 @@ describe('cache-restore tests', () => {
jest.mocked(core.setOutput).mockClear(); jest.mocked(core.setOutput).mockClear();
jest.mocked(cache.restoreCache).mockClear(); jest.mocked(cache.restoreCache).mockClear();
}); });
afterEach(() => { afterEach(() => (process.env.GITHUB_WORKSPACE = githubWorkspace));
process.env.GITHUB_WORKSPACE = githubWorkspace;
});
it('throws error when lock file is not found', async () => { it('throws error when lock file is not found', async () => {
jest.mocked(glob.hashFiles).mockResolvedValue(''); jest.mocked(glob.hashFiles).mockResolvedValue('');

View File

@@ -1,32 +1,14 @@
import {beforeAll, beforeEach, describe, expect, it, jest} from '@jest/globals'; import * as cache from '@actions/cache';
import * as core from '@actions/core';
import fs from 'node:fs';
import {run} from '../src/cache-save';
import {getNuGetFolderPath} from '../src/cache-utils';
import {State} from '../src/constants';
jest.unstable_mockModule('@actions/cache', () => ({ jest.mock('@actions/cache');
saveCache: jest.fn() jest.mock('@actions/core');
})); jest.mock('node:fs');
jest.unstable_mockModule('@actions/core', () => ({ jest.mock('../src/cache-utils');
setFailed: jest.fn(),
getState: jest.fn(),
setOutput: jest.fn(),
getBooleanInput: jest.fn(),
debug: jest.fn(),
info: jest.fn(),
warning: jest.fn()
}));
jest.unstable_mockModule('node:fs', () => ({
default: {
existsSync: jest.fn()
}
}));
jest.unstable_mockModule('../src/cache-utils', () => ({
getNuGetFolderPath: jest.fn()
}));
const cache = await import('@actions/cache');
const core = await import('@actions/core');
const fs = (await import('node:fs')).default;
const {run} = await import('../src/cache-save.js');
const {getNuGetFolderPath} = await import('../src/cache-utils.js');
const {State} = await import('../src/constants.js');
describe('cache-save tests', () => { describe('cache-save tests', () => {
beforeAll(() => { beforeAll(() => {

View File

@@ -1,29 +1,11 @@
import { import * as cache from '@actions/cache';
afterEach, import * as exec from '@actions/exec';
beforeAll,
beforeEach,
describe,
expect,
it,
jest
} from '@jest/globals';
jest.unstable_mockModule('@actions/cache', () => ({ import {getNuGetFolderPath, isCacheFeatureAvailable} from '../src/cache-utils';
isFeatureAvailable: jest.fn()
}));
jest.unstable_mockModule('@actions/core', () => ({
warning: jest.fn(),
info: jest.fn(),
debug: jest.fn()
}));
jest.unstable_mockModule('@actions/exec', () => ({
getExecOutput: jest.fn()
}));
const cache = await import('@actions/cache'); jest.mock('@actions/cache');
const exec = await import('@actions/exec'); jest.mock('@actions/core');
const {getNuGetFolderPath, isCacheFeatureAvailable} = jest.mock('@actions/exec');
await import('../src/cache-utils.js');
describe('cache-utils tests', () => { describe('cache-utils tests', () => {
describe('getNuGetFolderPath()', () => { describe('getNuGetFolderPath()', () => {
@@ -122,15 +104,9 @@ Options:
url => { url => {
// Save & Restore env // Save & Restore env
let serverUrlEnv: string | undefined; let serverUrlEnv: string | undefined;
beforeAll(() => { beforeAll(() => (serverUrlEnv = process.env['GITHUB_SERVER_URL']));
serverUrlEnv = process.env['GITHUB_SERVER_URL']; beforeEach(() => (process.env['GITHUB_SERVER_URL'] = url));
}); afterEach(() => (process.env['GITHUB_SERVER_URL'] = serverUrlEnv));
beforeEach(() => {
process.env['GITHUB_SERVER_URL'] = url;
});
afterEach(() => {
process.env['GITHUB_SERVER_URL'] = serverUrlEnv;
});
it('returns true when cache.isFeatureAvailable() === true', () => { it('returns true when cache.isFeatureAvailable() === true', () => {
jest.mocked(cache.isFeatureAvailable).mockReturnValue(true); jest.mocked(cache.isFeatureAvailable).mockReturnValue(true);

View File

@@ -1,5 +1,4 @@
import {describe, expect, test} from '@jest/globals'; import cscFile from '../.github/csc.json';
import cscFile from '../.github/csc.json' with {type: 'json'};
describe('csc tests', () => { describe('csc tests', () => {
const regexPattern = cscFile['problemMatcher'][0]['pattern'][0]['regexp']; const regexPattern = cscFile['problemMatcher'][0]['pattern'][0]['regexp'];
const regexResultsMap = cscFile['problemMatcher'][0]['pattern'][0]; const regexResultsMap = cscFile['problemMatcher'][0]['pattern'][0];
@@ -86,7 +85,7 @@ describe('csc tests', () => {
expect(matchedResultsArray).not.toBeNull(); expect(matchedResultsArray).not.toBeNull();
for (const propName in results) { for (const propName in results) {
const propertyIndex = (regexResultsMap as any)[propName]; const propertyIndex = regexResultsMap[propName];
const expectedPropValue = results[propName]; const expectedPropValue = results[propName];
const matchedPropValue = matchedResultsArray![propertyIndex]; const matchedPropValue = matchedResultsArray![propertyIndex];
expect(matchedPropValue).toEqual(expectedPropValue); expect(matchedPropValue).toEqual(expectedPropValue);

View File

@@ -1,11 +1,7 @@
import {describe, expect, it} from '@jest/globals';
import path from 'path'; import path from 'path';
import fs from 'fs'; import fs from 'fs';
import {fileURLToPath} from 'url';
import * as hc from '@actions/http-client'; import * as hc from '@actions/http-client';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const HTTP_CLIENT_OPTIONS = {allowRetries: true, maxRetries: 10} as const; const HTTP_CLIENT_OPTIONS = {allowRetries: true, maxRetries: 10} as const;
const TEST_TIMEOUT = 30000; const TEST_TIMEOUT = 30000;

View File

@@ -1,68 +1,14 @@
import {
afterAll,
afterEach,
beforeAll,
beforeEach,
describe,
expect,
it,
jest
} from '@jest/globals';
import each from 'jest-each'; import each from 'jest-each';
import semver from 'semver'; import semver from 'semver';
import fs from 'fs';
import fspromises from 'fs/promises'; import fspromises from 'fs/promises';
import os from 'os'; import os from 'os';
import path from 'path'; import * as exec from '@actions/exec';
import * as core from '@actions/core';
import * as io from '@actions/io';
import * as installer from '../src/installer';
jest.unstable_mockModule('@actions/exec', () => ({ import {IS_WINDOWS} from '../src/utils';
getExecOutput: jest.fn()
}));
jest.unstable_mockModule('@actions/core', () => ({
warning: jest.fn(),
info: jest.fn(),
debug: jest.fn(),
setOutput: jest.fn(),
exportVariable: jest.fn((name: string, val: string) => {
process.env[name] = val;
}),
addPath: jest.fn((p: string) => {
process.env['PATH'] = `${p}${path.delimiter}${process.env['PATH']}`;
})
}));
jest.unstable_mockModule('@actions/io', () => ({
which: jest.fn()
}));
jest.unstable_mockModule('fs', () => {
const actual = jest.requireActual('fs') as typeof import('fs');
const chmodSync = jest.fn();
const readdirSync = jest.fn();
const existsSync = jest.fn(() => true);
const statSync = jest.fn(() => ({isFile: () => true}));
const accessSync = jest.fn();
return {
...actual,
chmodSync,
readdirSync,
existsSync,
statSync,
accessSync,
default: {
...actual,
chmodSync,
readdirSync,
existsSync,
statSync,
accessSync
}
};
});
const exec = await import('@actions/exec');
const core = await import('@actions/core');
const io = await import('@actions/io');
const fs = await import('fs');
const installer = await import('../src/installer.js');
const {IS_WINDOWS} = await import('../src/utils.js');
describe('installer tests', () => { describe('installer tests', () => {
const env = process.env; const env = process.env;
@@ -70,24 +16,14 @@ describe('installer tests', () => {
beforeEach(() => { beforeEach(() => {
jest.resetModules(); jest.resetModules();
process.env = {...env}; process.env = {...env};
(core.exportVariable as jest.Mock).mockImplementation(
(...args: unknown[]) => {
const [name, val] = args as [string, string];
process.env[name] = val;
}
);
(core.addPath as jest.Mock).mockImplementation((...args: unknown[]) => {
const [p] = args as [string];
process.env['PATH'] = `${p}${path.delimiter}${process.env['PATH']}`;
});
}); });
describe('DotnetCoreInstaller tests', () => { describe('DotnetCoreInstaller tests', () => {
const getExecOutputSpy = exec.getExecOutput as jest.Mock; const getExecOutputSpy = jest.spyOn(exec, 'getExecOutput');
const warningSpy = core.warning as jest.Mock; const warningSpy = jest.spyOn(core, 'warning');
const whichSpy = io.which as jest.Mock; const whichSpy = jest.spyOn(io, 'which');
const maxSatisfyingSpy = jest.spyOn(semver, 'maxSatisfying'); const maxSatisfyingSpy = jest.spyOn(semver, 'maxSatisfying');
const chmodSyncSpy = fs.chmodSync as jest.Mock; const chmodSyncSpy = jest.spyOn(fs, 'chmodSync');
const readdirSpy = jest.spyOn(fspromises, 'readdir'); const readdirSpy = jest.spyOn(fspromises, 'readdir');
describe('installDotnet() tests', () => { describe('installDotnet() tests', () => {
@@ -530,696 +466,6 @@ describe('installer tests', () => {
}); });
}); });
describe('check-latest: false (local SDK reuse) tests', () => {
const readdirSyncSpy = fs.readdirSync as unknown as jest.Mock;
const statSyncSpy = fs.statSync as unknown as jest.Mock;
const accessSyncSpy = fs.accessSync as unknown as jest.Mock;
const asFile = {isFile: () => true};
const muxerName = IS_WINDOWS ? 'dotnet.exe' : 'dotnet';
const isMuxer = (target: unknown) => String(target).endsWith(muxerName);
const throwEnoent = () => {
throw new Error('ENOENT');
};
const makeDirents = (names: string[]): any =>
names.map(name => ({
name,
isDirectory: () => true,
isSymbolicLink: () => false
}));
const makeSymlinks = (names: string[]): any =>
names.map(name => ({
name,
isDirectory: () => false,
isSymbolicLink: () => true
}));
beforeEach(() => {
getExecOutputSpy.mockClear();
getExecOutputSpy.mockImplementation(() =>
Promise.resolve({
exitCode: 0,
stdout: 'Fictitious dotnet version 1.2.3 is installed',
stderr: ''
})
);
statSyncSpy.mockReturnValue(asFile);
accessSyncSpy.mockImplementation(() => undefined);
});
afterEach(() => {
readdirSyncSpy.mockReset();
statSyncSpy.mockReset();
accessSyncSpy.mockReset();
});
interface LocalReuseCase {
name: string;
version: string;
quality?: string;
dotnetChannel?: string;
minimumVersion?: string;
installed: string[];
expected: string | null;
}
const localReuseCases: LocalReuseCase[] = [
{
name: 'reuses a locally installed pinned SDK and skips all install scripts',
version: '8.0.422',
installed: ['8.0.100', '8.0.422'],
expected: '8.0.422'
},
{
name: 'falls back to online install when no local SDK matches the pinned request',
version: '8.0.422',
installed: ['8.0.100'],
expected: null
},
{
name: 'reuses the highest matching patch for a floating A.B.x request',
version: '8.0.x',
installed: ['8.0.100', '8.0.412', '8.0.205'],
expected: '8.0.412'
},
{
name: 'matches the correct feature band for an A.B.Cxx request',
version: '8.0.1xx',
installed: ['8.0.100', '8.0.105', '8.0.203'],
expected: '8.0.105'
},
{
name: 'picks the highest installed SDK for a channel-less latest request',
version: 'latest',
installed: ['8.0.412', '9.0.101'],
expected: '9.0.101'
},
{
name: 'ignores prerelease SDKs when quality is not preview/daily',
version: '8.0.x',
installed: ['8.0.100-preview.1', '8.0.100'],
expected: '8.0.100'
},
{
name: 'reuses the highest installed SDK for a major-only request',
version: '8',
installed: ['8.0.100', '8.0.412', '8.0.205'],
expected: '8.0.412'
},
{
name: 'reuses a prerelease SDK when quality is preview',
version: '8.0.x',
quality: 'preview',
installed: ['8.0.100-preview.1', '8.0.100-preview.2'],
expected: '8.0.100-preview.2'
},
{
name: 'falls back to online install when no local SDK matches a floating request',
version: '9.0.x',
installed: ['8.0.412'],
expected: null
},
{
name: 'installs online for a latest request with an LTS channel',
version: 'latest',
dotnetChannel: 'LTS',
installed: ['8.0.412', '9.0.101'],
expected: null
},
{
name: 'reuses the SDK of the requested channel for a latest request',
version: 'latest',
dotnetChannel: '8.0',
installed: ['8.0.412', '9.0.101'],
expected: '8.0.412'
},
{
name: 'installs online for a wildcard request instead of guessing',
version: 'x',
installed: ['8.0.412', '9.0.101'],
expected: null
},
{
name: 'does not reuse a local SDK below the global.json minimum version',
version: '8.0',
minimumVersion: '8.0.400',
installed: ['8.0.100', '8.0.205'],
expected: null
},
{
name: 'reuses a local SDK at or above the global.json minimum version',
version: '8.0',
minimumVersion: '8.0.400',
installed: ['8.0.100', '8.0.412'],
expected: '8.0.412'
},
{
name: 'installs online when quality is preview but only GA SDKs are local',
version: '8.0.x',
quality: 'preview',
installed: ['8.0.412'],
expected: null
},
{
name: 'ignores the quality input for majors below 6 when matching locally',
version: '3.1',
quality: 'preview',
installed: ['3.1.426', '3.1.500-preview.1'],
expected: '3.1.426'
}
];
each(localReuseCases).it(
'$name',
async ({
version,
quality = '',
dotnetChannel,
minimumVersion,
installed,
expected
}: LocalReuseCase) => {
readdirSyncSpy.mockReturnValue(makeDirents(installed));
maxSatisfyingSpy.mockImplementation(() => '8.0.412');
const installedVersion = await new installer.DotnetCoreInstaller(
version,
quality as any,
undefined,
dotnetChannel,
false,
minimumVersion
).installDotnet();
if (expected === null) {
expect(getExecOutputSpy).toHaveBeenCalledTimes(2);
} else {
expect(installedVersion).toBe(expected);
expect(getExecOutputSpy).not.toHaveBeenCalled();
}
}
);
it('rejects an A.B.Cxx request below .NET 5 instead of reusing a local SDK', async () => {
readdirSyncSpy.mockReturnValue(makeDirents(['3.1.100']));
const dotnetInstaller = new installer.DotnetCoreInstaller(
'3.1.1xx',
'',
undefined,
undefined,
false
);
await expect(dotnetInstaller.installDotnet()).rejects.toThrow(
`The 'dotnet-version' was supplied in invalid format: 3.1.1xx! The A.B.Cxx syntax is available since the .NET 5.0 release.`
);
expect(getExecOutputSpy).not.toHaveBeenCalled();
});
each(['preview', 'daily'] as const).it(
"reuses the highest local prerelease SDK for a channel-less latest request with '%s' quality",
async quality => {
readdirSyncSpy.mockReturnValue(
makeDirents(['8.0.412', '9.0.100-preview.1', '9.0.100-preview.2'])
);
const dotnetInstaller = new installer.DotnetCoreInstaller(
'latest',
quality,
undefined,
undefined,
false
);
const installedVersion = await dotnetInstaller.installDotnet();
expect(installedVersion).toBe('9.0.100-preview.2');
expect(getExecOutputSpy).not.toHaveBeenCalled();
}
);
it('does NOT reuse a local SDK for a cross-architecture request', async () => {
readdirSyncSpy.mockReturnValue(makeDirents(['8.0.412']));
maxSatisfyingSpy.mockImplementation(() => '8.0.412');
const archSpy = jest.spyOn(os, 'arch').mockReturnValue('arm64');
const dotnetInstaller = new installer.DotnetCoreInstaller(
'8.0.x',
'',
'x64',
undefined,
false
);
await dotnetInstaller.installDotnet();
expect(getExecOutputSpy).toHaveBeenCalledTimes(2);
archSpy.mockRestore();
});
it('installs online when check-latest defaults to true even if SDK is local', async () => {
readdirSyncSpy.mockReturnValue(makeDirents(['8.0.422']));
maxSatisfyingSpy.mockImplementation(() => '8.0.422');
const dotnetInstaller = new installer.DotnetCoreInstaller(
'8.0.422',
''
);
await dotnetInstaller.installDotnet();
expect(getExecOutputSpy).toHaveBeenCalledTimes(2);
});
it('installs online when the dotnet muxer is missing', async () => {
readdirSyncSpy.mockReturnValue(makeDirents(['8.0.412']));
statSyncSpy.mockImplementation((target: string) => {
if (isMuxer(target)) {
throwEnoent();
}
return asFile;
});
maxSatisfyingSpy.mockImplementation(() => '8.0.412');
const dotnetInstaller = new installer.DotnetCoreInstaller(
'8.0.x',
'',
undefined,
undefined,
false
);
await dotnetInstaller.installDotnet();
expect(getExecOutputSpy).toHaveBeenCalledTimes(2);
});
const itOnPosix = IS_WINDOWS ? it.skip : it;
itOnPosix(
'installs online when the dotnet muxer is not executable',
async () => {
readdirSyncSpy.mockReturnValue(makeDirents(['8.0.412']));
accessSyncSpy.mockImplementation((target: string) => {
if (isMuxer(target)) {
throw new Error('EACCES');
}
});
maxSatisfyingSpy.mockImplementation(() => '8.0.412');
const dotnetInstaller = new installer.DotnetCoreInstaller(
'8.0.x',
'',
undefined,
undefined,
false
);
await dotnetInstaller.installDotnet();
expect(getExecOutputSpy).toHaveBeenCalledTimes(2);
}
);
it('installs online when the dotnet muxer path is a directory', async () => {
readdirSyncSpy.mockReturnValue(makeDirents(['8.0.412']));
statSyncSpy.mockImplementation((target: string) =>
isMuxer(target) ? {isFile: () => false} : asFile
);
maxSatisfyingSpy.mockImplementation(() => '8.0.412');
const dotnetInstaller = new installer.DotnetCoreInstaller(
'8.0.x',
'',
undefined,
undefined,
false
);
await dotnetInstaller.installDotnet();
expect(getExecOutputSpy).toHaveBeenCalledTimes(2);
});
it('reuses an SDK exposed as a symbolic link', async () => {
readdirSyncSpy.mockReturnValue(makeSymlinks(['8.0.412']));
const dotnetInstaller = new installer.DotnetCoreInstaller(
'8.0.x',
'',
undefined,
undefined,
false
);
const installedVersion = await dotnetInstaller.installDotnet();
expect(installedVersion).toBe('8.0.412');
expect(getExecOutputSpy).not.toHaveBeenCalled();
});
it('matches the online channel mapping for legacy major-only requests', async () => {
readdirSyncSpy.mockReturnValue(makeDirents(['3.0.103', '3.1.426']));
const dotnetInstaller = new installer.DotnetCoreInstaller(
'3',
'',
undefined,
undefined,
false
);
const installedVersion = await dotnetInstaller.installDotnet();
expect(installedVersion).toBe('3.1.426');
expect(getExecOutputSpy).not.toHaveBeenCalled();
});
each(['8.0.X', '8.0.x', '8.0.*', '8.0']).it(
'reuses a local SDK for the floating request %s',
async (version: string) => {
readdirSyncSpy.mockReturnValue(makeDirents(['8.0.100', '8.0.412']));
const dotnetInstaller = new installer.DotnetCoreInstaller(
version,
'',
undefined,
undefined,
false
);
const installedVersion = await dotnetInstaller.installDotnet();
expect(installedVersion).toBe('8.0.412');
expect(getExecOutputSpy).not.toHaveBeenCalled();
}
);
each(['8.X', '8.x', '8.*', '8']).it(
'reuses a local SDK for the major-only request %s',
async (version: string) => {
readdirSyncSpy.mockReturnValue(makeDirents(['8.0.100', '8.0.412']));
const dotnetInstaller = new installer.DotnetCoreInstaller(
version,
'',
undefined,
undefined,
false
);
const installedVersion = await dotnetInstaller.installDotnet();
expect(installedVersion).toBe('8.0.412');
expect(getExecOutputSpy).not.toHaveBeenCalled();
}
);
it('does not reuse a local SDK for an uppercase feature band request', async () => {
readdirSyncSpy.mockReturnValue(makeDirents(['8.0.105']));
const dotnetInstaller = new installer.DotnetCoreInstaller(
'8.0.1XX',
'',
undefined,
undefined,
false
);
await expect(dotnetInstaller.installDotnet()).rejects.toThrow(
`The 'dotnet-version' was supplied in invalid format: 8.0.1XX!`
);
});
each(['08.0.x', '8.00.x', '08']).it(
'does not reuse a local SDK for the invalid request %s',
async (version: string) => {
readdirSyncSpy.mockReturnValue(makeDirents(['8.0.412']));
const dotnetInstaller = new installer.DotnetCoreInstaller(
version,
'',
undefined,
undefined,
false
);
await expect(dotnetInstaller.installDotnet()).rejects.toThrow(
`The 'dotnet-version' was supplied in invalid format: ${version}!`
);
}
);
it('ignores an sdk folder that does not contain an SDK', async () => {
readdirSyncSpy.mockReturnValue(makeDirents(['8.0.412']));
statSyncSpy.mockImplementation((target: string) => {
if (String(target).includes('dotnet.dll')) {
throwEnoent();
}
return asFile;
});
maxSatisfyingSpy.mockImplementation(() => '8.0.412');
const dotnetInstaller = new installer.DotnetCoreInstaller(
'8.0.x',
'',
undefined,
undefined,
false
);
await dotnetInstaller.installDotnet();
expect(getExecOutputSpy).toHaveBeenCalledTimes(2);
});
describe('global.json rollForward tests', () => {
interface RollForwardCase {
name: string;
version?: string;
quality?: string;
minimumVersion?: string;
rollForward?: string;
installed: string[];
expected: string | null;
}
const rollForwardCases: RollForwardCase[] = [
{
name: 'latestMajor reuses the highest local SDK across majors',
minimumVersion: '8.0.100',
rollForward: 'latestMajor',
installed: ['8.0.412', '9.0.101'],
expected: '9.0.101'
},
{
name: 'latestMajor ignores local SDKs below the declared version',
minimumVersion: '8.0.412',
rollForward: 'latestMajor',
installed: ['8.0.100', '7.0.400'],
expected: null
},
{
name: 'latestMajor keeps requiring GA builds when quality is preview',
quality: 'preview',
minimumVersion: '8.0.100',
rollForward: 'latestMajor',
installed: ['9.0.200-preview.1'],
expected: null
},
{
name: 'latestMinor reuses a higher local minor of the same major',
version: '8',
minimumVersion: '8.1.100',
rollForward: 'latestMinor',
installed: ['8.1.200', '8.2.300'],
expected: '8.2.300'
},
{
name: 'latestMinor does not cross into another major',
version: '8',
minimumVersion: '8.1.100',
rollForward: 'latestMinor',
installed: ['9.0.101'],
expected: null
},
{
name: 'latestMinor ignores local SDKs below the declared version',
version: '8',
minimumVersion: '8.1.100',
rollForward: 'latestMinor',
installed: ['8.0.412'],
expected: null
},
{
name: 'latestFeature takes the highest band of the declared major.minor',
version: '8.0',
minimumVersion: '8.0.100',
rollForward: 'latestFeature',
installed: ['8.0.105', '8.0.400'],
expected: '8.0.400'
},
{
name: 'latestPatch stays inside the declared feature band',
version: '8.0.2xx',
minimumVersion: '8.0.200',
rollForward: 'latestPatch',
installed: ['8.0.205', '8.0.412'],
expected: '8.0.205'
},
{
name: 'latestPatch takes the highest patch even when the declared version is installed',
version: '8.0.1xx',
minimumVersion: '8.0.100',
rollForward: 'latestPatch',
installed: ['8.0.100', '8.0.105'],
expected: '8.0.105'
},
{
name: 'patch prefers the exact declared version',
version: '8.0.100',
minimumVersion: '8.0.100',
rollForward: 'patch',
installed: ['8.0.100', '8.0.105'],
expected: '8.0.100'
},
{
name: 'patch stays inside the declared feature band',
version: '8.0.100',
minimumVersion: '8.0.100',
rollForward: 'patch',
installed: ['8.0.105', '8.0.200'],
expected: '8.0.105'
},
{
name: 'feature prefers the declared band over a higher band',
version: '8.0.100',
minimumVersion: '8.0.100',
rollForward: 'feature',
installed: ['8.0.105', '8.0.400'],
expected: '8.0.105'
},
{
name: 'feature rolls to the next higher band, not the highest',
version: '8.0.100',
minimumVersion: '8.0.100',
rollForward: 'feature',
installed: ['8.0.200', '8.0.300', '8.0.400'],
expected: '8.0.200'
},
{
name: 'feature takes the latest patch of the selected band',
version: '8.0.100',
minimumVersion: '8.0.100',
rollForward: 'feature',
installed: ['8.0.201', '8.0.205', '8.0.400'],
expected: '8.0.205'
},
{
name: 'feature does not cross into another minor',
version: '8.0.100',
minimumVersion: '8.0.100',
rollForward: 'feature',
installed: ['8.1.100'],
expected: null
},
{
name: 'minor prefers a higher band of the declared minor over a higher minor',
version: '8.0.100',
minimumVersion: '8.0.100',
rollForward: 'minor',
installed: ['8.0.400', '8.1.100'],
expected: '8.0.400'
},
{
name: 'minor rolls to the next higher minor, not the highest',
version: '8.0.100',
minimumVersion: '8.0.100',
rollForward: 'minor',
installed: ['8.1.100', '8.2.100'],
expected: '8.1.100'
},
{
name: 'major prefers the declared major over a higher major',
version: '8.0.100',
minimumVersion: '8.0.100',
rollForward: 'major',
installed: ['8.0.400', '9.0.100'],
expected: '8.0.400'
},
{
name: 'major rolls to the next higher major, not the highest',
version: '8.0.100',
minimumVersion: '8.0.100',
rollForward: 'major',
installed: ['9.0.100', '10.0.100'],
expected: '9.0.100'
},
{
name: 'non-latest policies ignore dotnet-quality, as the online path does',
version: '8.0.100',
quality: 'preview',
minimumVersion: '8.0.100',
rollForward: 'patch',
installed: ['8.0.105'],
expected: '8.0.105'
},
{
name: 'non-latest policies never prefer a prerelease over a GA build',
version: '8.0.100',
quality: 'preview',
minimumVersion: '8.0.100',
rollForward: 'major',
installed: ['8.0.100', '9.0.100-rc.2'],
expected: '8.0.100'
},
{
name: 'roll-forward policies never select below the declared version',
version: '8.0.200',
minimumVersion: '8.0.200',
rollForward: 'major',
installed: ['8.0.100'],
expected: null
},
{
name: 'disable requires the exact declared version',
version: '8.0.100',
installed: ['8.0.200'],
expected: null
},
{
name: 'installs online for an empty version without a rollForward floor',
installed: ['8.0.412'],
expected: null
}
];
each(rollForwardCases).it(
'$name',
async ({
version = '',
quality = '',
minimumVersion,
rollForward,
installed,
expected
}: RollForwardCase) => {
readdirSyncSpy.mockReturnValue(makeDirents(installed));
maxSatisfyingSpy.mockImplementation(() => '8.0.412');
const installedVersion = await new installer.DotnetCoreInstaller(
version,
quality as any,
undefined,
undefined,
false,
minimumVersion,
rollForward
).installDotnet();
if (expected === null) {
expect(getExecOutputSpy).toHaveBeenCalledTimes(2);
} else {
expect(installedVersion).toBe(expected);
expect(getExecOutputSpy).not.toHaveBeenCalled();
}
}
);
});
});
describe('addToPath() tests', () => { describe('addToPath() tests', () => {
it(`should export DOTNET_ROOT env.var with value from DOTNET_INSTALL_DIR env.var`, async () => { it(`should export DOTNET_ROOT env.var with value from DOTNET_INSTALL_DIR env.var`, async () => {
process.env['DOTNET_INSTALL_DIR'] = 'fictitious/dotnet/install/dir'; process.env['DOTNET_INSTALL_DIR'] = 'fictitious/dotnet/install/dir';

View File

@@ -1,31 +1,22 @@
import {afterEach, beforeEach, describe, expect, it, jest} from '@jest/globals'; import {DotnetVersionResolver} from '../src/installer';
import * as hc from '@actions/http-client';
import * as core from '@actions/core';
jest.unstable_mockModule('@actions/http-client', () => ({ // Mock http-client
HttpClient: jest.fn() jest.mock('@actions/http-client');
}));
jest.unstable_mockModule('@actions/core', () => ({
warning: jest.fn(),
info: jest.fn(),
debug: jest.fn()
}));
const hc = await import('@actions/http-client');
const core = await import('@actions/core');
const {DotnetVersionResolver} = await import('../src/installer.js');
describe('DotnetVersionResolver with latest', () => { describe('DotnetVersionResolver with latest', () => {
let getJsonMock: jest.Mock<(...args: any[]) => Promise<any>>; let getJsonMock: jest.Mock;
let warningSpy: jest.Mock; let warningSpy: jest.SpyInstance;
beforeEach(() => { beforeEach(() => {
getJsonMock = jest.fn<(...args: any[]) => Promise<any>>(); getJsonMock = jest.fn();
(hc.HttpClient as jest.Mock).mockImplementation(() => { (hc.HttpClient as any).mockImplementation(() => {
return { return {
getJson: getJsonMock getJson: getJsonMock
}; };
}); });
warningSpy = core.warning as jest.Mock; warningSpy = jest.spyOn(core, 'warning').mockImplementation(() => {});
warningSpy.mockImplementation(() => {});
}); });
afterEach(() => { afterEach(() => {

View File

@@ -1,72 +1,26 @@
import { import * as core from '@actions/core';
afterEach, import fs from 'fs';
beforeEach,
describe,
expect,
it,
jest,
test
} from '@jest/globals';
import semver from 'semver'; import semver from 'semver';
import * as auth from '../src/authutil';
import os from 'os'; import os from 'os';
import * as setup from '../src/setup-dotnet';
jest.unstable_mockModule('@actions/core', () => ({ import {DotnetCoreInstaller, DotnetInstallDir} from '../src/installer';
getInput: jest.fn(), import * as cacheUtils from '../src/cache-utils';
getMultilineInput: jest.fn(), import * as cacheRestore from '../src/cache-restore';
getBooleanInput: jest.fn(),
setFailed: jest.fn(),
warning: jest.fn(),
debug: jest.fn(),
info: jest.fn(),
setOutput: jest.fn(),
addPath: jest.fn(),
exportVariable: jest.fn()
}));
jest.unstable_mockModule('fs', () => {
const actual = jest.requireActual('fs') as typeof import('fs');
const existsSync = jest.fn(actual.existsSync);
const readFileSync = jest.fn(actual.readFileSync);
return {
...actual,
existsSync,
readFileSync,
default: {...actual, existsSync, readFileSync}
};
});
jest.unstable_mockModule('../src/authutil', () => ({
configAuthentication: jest.fn()
}));
jest.unstable_mockModule('../src/cache-utils', () => ({
isCacheFeatureAvailable: jest.fn(),
getNuGetFolderPath: jest.fn()
}));
jest.unstable_mockModule('../src/cache-restore', () => ({
restoreCache: jest.fn()
}));
const core = await import('@actions/core');
const fs = await import('fs');
const auth = await import('../src/authutil.js');
const cacheUtils = await import('../src/cache-utils.js');
const cacheRestore = await import('../src/cache-restore.js');
const setup = await import('../src/setup-dotnet.js');
const {DotnetCoreInstaller, DotnetInstallDir} =
await import('../src/installer.js');
describe('setup-dotnet tests', () => { describe('setup-dotnet tests', () => {
const inputs = {} as any; const inputs = {} as any;
const getInputSpy = core.getInput as jest.Mock; const getInputSpy = jest.spyOn(core, 'getInput');
const getMultilineInputSpy = core.getMultilineInput as jest.Mock; const getMultilineInputSpy = jest.spyOn(core, 'getMultilineInput');
const getBooleanInputSpy = core.getBooleanInput as jest.Mock; const getBooleanInputSpy = jest.spyOn(core, 'getBooleanInput');
const setFailedSpy = core.setFailed as jest.Mock; const setFailedSpy = jest.spyOn(core, 'setFailed');
const warningSpy = core.warning as jest.Mock; const warningSpy = jest.spyOn(core, 'warning');
const debugSpy = core.debug as jest.Mock; const debugSpy = jest.spyOn(core, 'debug');
const infoSpy = core.info as jest.Mock; const infoSpy = jest.spyOn(core, 'info');
const setOutputSpy = core.setOutput as jest.Mock; const setOutputSpy = jest.spyOn(core, 'setOutput');
const existsSyncSpy = fs.existsSync as jest.Mock; const existsSyncSpy = jest.spyOn(fs, 'existsSync');
const readFileSyncSpy = fs.readFileSync as jest.Mock;
const maxSatisfyingSpy = jest.spyOn(semver, 'maxSatisfying'); const maxSatisfyingSpy = jest.spyOn(semver, 'maxSatisfying');
@@ -75,10 +29,12 @@ describe('setup-dotnet tests', () => {
'installDotnet' 'installDotnet'
); );
const isCacheFeatureAvailableSpy = const isCacheFeatureAvailableSpy = jest.spyOn(
cacheUtils.isCacheFeatureAvailable as jest.Mock; cacheUtils,
const restoreCacheSpy = cacheRestore.restoreCache as jest.Mock; 'isCacheFeatureAvailable'
const configAuthenticationSpy = auth.configAuthentication as jest.Mock; );
const restoreCacheSpy = jest.spyOn(cacheRestore, 'restoreCache');
const configAuthenticationSpy = jest.spyOn(auth, 'configAuthentication');
const addToPathOriginal = DotnetInstallDir.addToPath; const addToPathOriginal = DotnetInstallDir.addToPath;
describe('run() tests', () => { describe('run() tests', () => {
@@ -86,17 +42,11 @@ describe('setup-dotnet tests', () => {
DotnetInstallDir.addToPath = jest.fn(); DotnetInstallDir.addToPath = jest.fn();
getMultilineInputSpy.mockImplementation(input => inputs[input as string]); getMultilineInputSpy.mockImplementation(input => inputs[input as string]);
getInputSpy.mockImplementation(input => inputs[input as string]); getInputSpy.mockImplementation(input => inputs[input as string]);
getBooleanInputSpy.mockImplementation(input => { getBooleanInputSpy.mockImplementation(input => inputs[input as string]);
const value = inputs[input as string];
return typeof value === 'string'
? value.toLowerCase() === 'true'
: !!value;
});
}); });
afterEach(() => { afterEach(() => {
DotnetInstallDir.addToPath = addToPathOriginal; DotnetInstallDir.addToPath = addToPathOriginal;
delete process.env['DOTNET_CHECK_LATEST'];
jest.clearAllMocks(); jest.clearAllMocks();
jest.resetAllMocks(); jest.resetAllMocks();
}); });
@@ -296,77 +246,6 @@ describe('setup-dotnet tests', () => {
expect(DotnetInstallDir.addToPath).toHaveBeenCalledTimes(1); expect(DotnetInstallDir.addToPath).toHaveBeenCalledTimes(1);
}); });
it("should read the 'check-latest' input and pass it to DotnetCoreInstaller", async () => {
inputs['dotnet-version'] = ['10.0.101'];
inputs['dotnet-quality'] = '';
inputs['architecture'] = '';
inputs['check-latest'] = 'false';
let capturedCheckLatest: boolean | undefined;
installDotnetSpy.mockImplementation(function (this: any) {
capturedCheckLatest = this.checkLatest;
return Promise.resolve('');
});
await setup.run();
expect(getBooleanInputSpy).toHaveBeenCalledWith('check-latest');
expect(installDotnetSpy).toHaveBeenCalledTimes(1);
expect(capturedCheckLatest).toBe(false);
});
describe("'check-latest' resolution", () => {
const captureCheckLatest = async () => {
inputs['dotnet-version'] = ['10.0.101'];
inputs['dotnet-quality'] = '';
inputs['architecture'] = '';
let capturedCheckLatest: boolean | undefined;
installDotnetSpy.mockImplementation(function (this: any) {
capturedCheckLatest = this.checkLatest;
return Promise.resolve('');
});
await setup.run();
return capturedCheckLatest;
};
it('defaults to true when neither the input nor the environment variable is set', async () => {
inputs['check-latest'] = '';
expect(await captureCheckLatest()).toBe(true);
expect(getBooleanInputSpy).not.toHaveBeenCalledWith('check-latest');
});
it.each(['false', 'FALSE', 'False'])(
"reads 'check-latest' from the DOTNET_CHECK_LATEST environment variable ('%s')",
async envValue => {
inputs['check-latest'] = '';
process.env['DOTNET_CHECK_LATEST'] = envValue;
expect(await captureCheckLatest()).toBe(false);
}
);
it('lets an explicit input win over the environment variable', async () => {
inputs['check-latest'] = 'true';
process.env['DOTNET_CHECK_LATEST'] = 'false';
expect(await captureCheckLatest()).toBe(true);
});
it('warns and falls back to true when the environment variable is not a boolean', async () => {
inputs['check-latest'] = '';
process.env['DOTNET_CHECK_LATEST'] = 'yes';
expect(await captureCheckLatest()).toBe(true);
expect(warningSpy).toHaveBeenCalledWith(
`Value 'yes' is not supported for the DOTNET_CHECK_LATEST environment variable. Supported values are: true, false. The 'check-latest' option falls back to 'true'.`
);
expect(setFailedSpy).not.toHaveBeenCalled();
});
});
it('should fail the action if unsupported architecture is provided', async () => { it('should fail the action if unsupported architecture is provided', async () => {
inputs['dotnet-version'] = ['10.0.101']; inputs['dotnet-version'] = ['10.0.101'];
inputs['dotnet-quality'] = ''; inputs['dotnet-quality'] = '';
@@ -467,241 +346,5 @@ describe('setup-dotnet tests', () => {
`The 'dotnet-channel' input is only supported when 'dotnet-version' is set to 'latest'.` `The 'dotnet-channel' input is only supported when 'dotnet-version' is set to 'latest'.`
); );
}); });
it('should pass the global.json rollForward minimum version to DotnetCoreInstaller', async () => {
inputs['dotnet-version'] = [];
inputs['dotnet-quality'] = '';
inputs['dotnet-channel'] = '';
inputs['architecture'] = '';
inputs['check-latest'] = 'false';
inputs['global-json-file'] = 'global.json';
existsSyncSpy.mockReturnValue(true);
readFileSyncSpy.mockReturnValue(
JSON.stringify({
sdk: {version: '8.0.400', rollForward: 'latestFeature'}
})
);
let capturedVersion: string | undefined;
let capturedMinimumVersion: string | undefined;
installDotnetSpy.mockImplementation(function (this: any) {
capturedVersion = this.version;
capturedMinimumVersion = this.minimumVersion;
return Promise.resolve('8.0.412');
});
await setup.run();
inputs['global-json-file'] = '';
expect(capturedVersion).toBe('8.0');
expect(capturedMinimumVersion).toBe('8.0.400');
});
it('should pass non-latest rollForward policies to DotnetCoreInstaller', async () => {
inputs['dotnet-version'] = [];
inputs['dotnet-quality'] = '';
inputs['dotnet-channel'] = '';
inputs['architecture'] = '';
inputs['check-latest'] = 'false';
inputs['global-json-file'] = 'global.json';
existsSyncSpy.mockReturnValue(true);
readFileSyncSpy.mockReturnValue(
JSON.stringify({sdk: {version: '8.0.100', rollForward: 'feature'}})
);
let capturedVersion: string | undefined;
let capturedMinimumVersion: string | undefined;
let capturedRollForward: string | undefined;
installDotnetSpy.mockImplementation(function (this: any) {
capturedVersion = this.version;
capturedMinimumVersion = this.minimumVersion;
capturedRollForward = this.rollForward;
return Promise.resolve('8.0.200');
});
await setup.run();
inputs['global-json-file'] = '';
expect(capturedVersion).toBe('8.0.100');
expect(capturedMinimumVersion).toBe('8.0.100');
expect(capturedRollForward).toBe('feature');
});
it('should default an omitted rollForward to patch', async () => {
inputs['dotnet-version'] = [];
inputs['dotnet-quality'] = '';
inputs['dotnet-channel'] = '';
inputs['architecture'] = '';
inputs['check-latest'] = 'false';
inputs['global-json-file'] = 'global.json';
existsSyncSpy.mockReturnValue(true);
readFileSyncSpy.mockReturnValue(
JSON.stringify({sdk: {version: '8.0.100'}})
);
let capturedVersion: string | undefined;
let capturedMinimumVersion: string | undefined;
let capturedRollForward: string | undefined;
installDotnetSpy.mockImplementation(function (this: any) {
capturedVersion = this.version;
capturedMinimumVersion = this.minimumVersion;
capturedRollForward = this.rollForward;
return Promise.resolve('8.0.100');
});
await setup.run();
inputs['global-json-file'] = '';
expect(capturedVersion).toBe('8.0.100');
expect(capturedMinimumVersion).toBe('8.0.100');
expect(capturedRollForward).toBe('patch');
});
it('should not default to patch for a prerelease sdk version', async () => {
inputs['dotnet-version'] = [];
inputs['dotnet-quality'] = '';
inputs['dotnet-channel'] = '';
inputs['architecture'] = '';
inputs['check-latest'] = 'false';
inputs['global-json-file'] = 'global.json';
existsSyncSpy.mockReturnValue(true);
readFileSyncSpy.mockReturnValue(
JSON.stringify({sdk: {version: '8.0.100-preview.1'}})
);
let capturedMinimumVersion: string | undefined;
let capturedRollForward: string | undefined;
installDotnetSpy.mockImplementation(function (this: any) {
capturedMinimumVersion = this.minimumVersion;
capturedRollForward = this.rollForward;
return Promise.resolve('8.0.100-preview.1');
});
await setup.run();
inputs['global-json-file'] = '';
expect(capturedMinimumVersion).toBeUndefined();
expect(capturedRollForward).toBeUndefined();
});
it('should not default to patch for a version that is not a full SDK version', async () => {
inputs['dotnet-version'] = [];
inputs['dotnet-quality'] = '';
inputs['dotnet-channel'] = '';
inputs['architecture'] = '';
inputs['check-latest'] = 'false';
inputs['global-json-file'] = 'global.json';
existsSyncSpy.mockReturnValue(true);
readFileSyncSpy.mockReturnValue(
JSON.stringify({sdk: {version: '8.0.0'}})
);
let capturedMinimumVersion: string | undefined;
let capturedRollForward: string | undefined;
installDotnetSpy.mockImplementation(function (this: any) {
capturedMinimumVersion = this.minimumVersion;
capturedRollForward = this.rollForward;
return Promise.resolve('8.0.0');
});
await setup.run();
inputs['global-json-file'] = '';
expect(capturedMinimumVersion).toBeUndefined();
expect(capturedRollForward).toBeUndefined();
});
it('should not roll forward a version pinned by the dotnet-version input', async () => {
inputs['dotnet-version'] = ['8.0.100'];
inputs['dotnet-quality'] = '';
inputs['dotnet-channel'] = '';
inputs['architecture'] = '';
inputs['check-latest'] = 'false';
inputs['global-json-file'] = 'global.json';
existsSyncSpy.mockReturnValue(true);
readFileSyncSpy.mockReturnValue(
JSON.stringify({sdk: {version: '8.0.100'}})
);
let capturedMinimumVersion: string | undefined;
let capturedRollForward: string | undefined;
installDotnetSpy.mockImplementation(function (this: any) {
capturedMinimumVersion = this.minimumVersion;
capturedRollForward = this.rollForward;
return Promise.resolve('8.0.100');
});
await setup.run();
inputs['global-json-file'] = '';
expect(installDotnetSpy).toHaveBeenCalledTimes(1);
expect(capturedMinimumVersion).toBeUndefined();
expect(capturedRollForward).toBeUndefined();
});
it('should keep the global.json floor when a floating dotnet-version matches', async () => {
inputs['dotnet-version'] = ['8.0'];
inputs['dotnet-quality'] = '';
inputs['dotnet-channel'] = '';
inputs['architecture'] = '';
inputs['check-latest'] = 'false';
inputs['global-json-file'] = 'global.json';
existsSyncSpy.mockReturnValue(true);
readFileSyncSpy.mockReturnValue(
JSON.stringify({
sdk: {version: '8.0.400', rollForward: 'latestFeature'}
})
);
let capturedMinimumVersion: string | undefined;
let capturedRollForward: string | undefined;
installDotnetSpy.mockImplementation(function (this: any) {
capturedMinimumVersion = this.minimumVersion;
capturedRollForward = this.rollForward;
return Promise.resolve('8.0.400');
});
await setup.run();
inputs['global-json-file'] = '';
expect(installDotnetSpy).toHaveBeenCalledTimes(1);
expect(capturedMinimumVersion).toBe('8.0.400');
expect(capturedRollForward).toBe('latestFeature');
});
it('should not set a rollForward policy for disable', async () => {
inputs['dotnet-version'] = [];
inputs['dotnet-quality'] = '';
inputs['dotnet-channel'] = '';
inputs['architecture'] = '';
inputs['check-latest'] = 'false';
inputs['global-json-file'] = 'global.json';
existsSyncSpy.mockReturnValue(true);
readFileSyncSpy.mockReturnValue(
JSON.stringify({sdk: {version: '8.0.100', rollForward: 'disable'}})
);
let capturedMinimumVersion: string | undefined;
let capturedRollForward: string | undefined;
installDotnetSpy.mockImplementation(function (this: any) {
capturedMinimumVersion = this.minimumVersion;
capturedRollForward = this.rollForward;
return Promise.resolve('8.0.100');
});
await setup.run();
inputs['global-json-file'] = '';
expect(capturedMinimumVersion).toBeUndefined();
expect(capturedRollForward).toBeUndefined();
});
}); });
}); });

View File

@@ -74,7 +74,6 @@ $targetFrameworkVersionMap = @{
"8.0" = "net8.0"; "8.0" = "net8.0";
"9.0" = "net9.0"; "9.0" = "net9.0";
"10.0" = "net10.0"; "10.0" = "net10.0";
"11.0" = "net11.0";
} }
foreach ($version in $Versions) foreach ($version in $Versions)

View File

@@ -39,9 +39,6 @@ inputs:
architecture: architecture:
description: 'Optional architecture for the .NET install. Supported values: x64, x86, arm64, amd64, arm, s390x, ppc64le, riscv64. If not set, the installer auto-detects the current system architecture.' description: 'Optional architecture for the .NET install. Supported values: x64, x86, arm64, amd64, arm, s390x, ppc64le, riscv64. If not set, the installer auto-detects the current system architecture.'
required: false required: false
check-latest:
description: 'Optional, defaults to true. When false, a locally installed SDK that satisfies the requested version is reused without any network calls, otherwise the latest matching version is installed online. Cross-architecture requests always install online. Falls back to the DOTNET_CHECK_LATEST environment variable when this input is not set.'
required: false
outputs: outputs:
cache-hit: cache-hit:
description: 'A boolean value to indicate if a cache was hit.' description: 'A boolean value to indicate if a cache was hit.'

101900
dist/cache-save/index.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +0,0 @@
{
"type": "module"
}

114107
dist/setup/index.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +0,0 @@
{
"type": "module"
}

View File

@@ -939,7 +939,7 @@ function Extract-Dotnet-Package-Tar([string]$TarPath, [string]$OutPath) {
foreach ($dir in $versionedDirs.GetEnumerator()) { foreach ($dir in $versionedDirs.GetEnumerator()) {
if ($dir.Value) { if ($dir.Value) {
# This versioned directory already exists - exclude it from extraction # This versioned directory already exists — exclude it from extraction
$pattern = $dir.Key + '*' $pattern = $dir.Key + '*'
$excludeArgs += '--exclude' $excludeArgs += '--exclude'
$excludeArgs += $pattern $excludeArgs += $pattern
@@ -956,7 +956,7 @@ function Extract-Dotnet-Package-Tar([string]$TarPath, [string]$OutPath) {
if ($normalizedEntry.EndsWith('/')) { continue } if ($normalizedEntry.EndsWith('/')) { continue }
$match = [regex]::Match($normalizedEntry, $versionRegex) $match = [regex]::Match($normalizedEntry, $versionRegex)
if (-not $match.Success) { if (-not $match.Success) {
# Non-versioned file - exclude if it already exists locally # Non-versioned file — exclude if it already exists locally
$localPath = Join-Path -Path $OutPath -ChildPath $normalizedEntry $localPath = Join-Path -Path $OutPath -ChildPath $normalizedEntry
if (Test-Path $localPath) { if (Test-Path $localPath) {
$excludeArgs += '--exclude' $excludeArgs += '--exclude'
@@ -1487,8 +1487,8 @@ Say "Installation finished"
# SIG # Begin signature block # SIG # Begin signature block
# MIIncQYJKoZIhvcNAQcCoIInYjCCJ14CAQExDzANBglghkgBZQMEAgEFADB5Bgor # MIIncQYJKoZIhvcNAQcCoIInYjCCJ14CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDbixcRHZx4cmqV # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDmNI7+9b4lSWsX
# 58QdPY+XiwQw34JjAyv8LsJIGTKYs6CCDMkwggYEMIID7KADAgECAhMzAAACHPrN # 2kYVvqQHpZeXB6Kt5BepNOcmIqEK1aCCDMkwggYEMIID7KADAgECAhMzAAACHPrN
# xZvoL37EAAAAAAIcMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNVBAYTAlVTMR4wHAYD # xZvoL37EAAAAAAIcMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNVBAYTAlVTMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBD # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBD
# b2RlIFNpZ25pbmcgUENBIDIwMjQwHhcNMjYwNDE2MTg1OTQxWhcNMjcwNDE1MTg1 # b2RlIFNpZ25pbmcgUENBIDIwMjQwHhcNMjYwNDE2MTg1OTQxWhcNMjcwNDE1MTg1
@@ -1561,62 +1561,62 @@ Say "Installation finished"
# KDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMjQCEzMAAAIc # KDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMjQCEzMAAAIc
# +s3Fm+gvfsQAAAAAAhwwDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwG # +s3Fm+gvfsQAAAAAAhwwDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwG
# CisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZI # CisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZI
# hvcNAQkEMSIEIPGYOwqjbYcPpGhrXbJoGwiSMzNy0DFg1wPuMKjzUFU3MEIGCisG # hvcNAQkEMSIEIB5Na9P++kVnSeIy27N4IyRD4N0sjfWHRS1ht0NHdoK/MEIGCisG
# AQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3 # AQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3
# Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEBBQAEggEATEc7CdUQlF9ad/L6EImG # Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEBBQAEggEAx05EI+Kk4hoAKG/8oVdr
# GP+g++vMy0R/Hg4c+MlO/1U5MYfOdh4p0OSk0R3D9KhIvGy0pmPFjbCovy8OT1o0 # UIq/+sv+E0vpSyWQMTq/yrkfnPWqT2TxNVtcG3ZcQT5/36cjMe1umi1zzy178VRP
# /SmlfLvdZi71NTu7USS9IBaGa34XbhtETx7bqyEuFVyJi3Q6kem+/FX4X9Yy1uKa # HKH2jxMOzMqtJPsAI/yAd46EOyTBwayS+27NOvz2r3v8WV0YjuplJb1teHmJtoIf
# raasZebqi0W5Bwmm/l2W2vJoRejOf73LY/JVDJDoqC6Euy0ygFMRcXKuy0JapfNW # UVC1va6H668UMrR2Mm5l8GvtcrGmDLjq3FLTLeidco7aj7xtkwUhyXvCS/HzoF9G
# uzhOnMSTeEhxSnJulIJT9WJ27C0C3xCs15Zxog1pTCIyrUdZ+1wztImKRG6ckOMs # yrYW3NKqIy+KbNXTD8RbwDxKvx3ED9C1SfZi3fi/t1a2wjNsxVqf4XNsO2+JvuuO
# stSyISi+BDDDZlEIrqW28uhS3y1NamvJ8ParfgUUMWE6IVMfXyU3UNX9CffZlZUu # SGTZOoo/3jqtS22IcV5Z3In0D3+C/rigq0179KhwPtztz4+J9MU5gtGmVayF1MH1
# G6GCF7AwghesBgorBgEEAYI3AwMBMYIXnDCCF5gGCSqGSIb3DQEHAqCCF4kwgheF # M6GCF7AwghesBgorBgEEAYI3AwMBMYIXnDCCF5gGCSqGSIb3DQEHAqCCF4kwgheF
# AgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFaBgsqhkiG9w0BCRABBKCCAUkEggFFMIIB # AgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFaBgsqhkiG9w0BCRABBKCCAUkEggFFMIIB
# QQIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFlAwQCAQUABCAKISNs7txQuaBSV3EX # QQIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFlAwQCAQUABCDhOUY7jtQW2mTHjZaf
# ZialoNXK4+PNZXnxI6CUNBDKJwIGajVNcfmeGBMyMDI2MDcxOTAxMTk1MS40NTVa # zhylI7IWKlybklUpfwDq0GnW8AIGaeuhCndSGBMyMDI2MDUxNzAwNDk0OC4wNzFa
# MASAAgH0oIHZpIHWMIHTMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv # MASAAgH0oIHZpIHWMIHTMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
# bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0 # bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
# aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0 # aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0
# ZWQxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjo0MDFBLTA1RTAtRDk0NzElMCMG # ZWQxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjoyQTFBLTA1RTAtRDk0NzElMCMG
# A1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaCCEf4wggcoMIIFEKAD # A1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaCCEf4wggcoMIIFEKAD
# AgECAhMzAAACGV6y2FR19LGNAAEAAAIZMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNV # AgECAhMzAAACEKvN5BYY7zmwAAEAAAIQMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNV
# BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4w # BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4w
# HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29m # HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29m
# dCBUaW1lLVN0YW1wIFBDQSAyMDEwMB4XDTI1MDgxNDE4NDgyNloXDTI2MTExMzE4 # dCBUaW1lLVN0YW1wIFBDQSAyMDEwMB4XDTI1MDgxNDE4NDgxMloXDTI2MTExMzE4
# NDgyNlowgdMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYD # NDgxMlowgdMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYD
# VQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTAr # VQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTAr
# BgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEnMCUG # BgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEnMCUG
# A1UECxMeblNoaWVsZCBUU1MgRVNOOjQwMUEtMDVFMC1EOTQ3MSUwIwYDVQQDExxN # A1UECxMeblNoaWVsZCBUU1MgRVNOOjJBMUEtMDVFMC1EOTQ3MSUwIwYDVQQDExxN
# aWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNlMIICIjANBgkqhkiG9w0BAQEFAAOC # aWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNlMIICIjANBgkqhkiG9w0BAQEFAAOC
# Ag8AMIICCgKCAgEApqFIyUkzIyxpL3Q03WmLuy4G9YIUScznhKr+cHOT+/u7Parx # Ag8AMIICCgKCAgEAjcc4q057ZwIgpKu4pTXWLejvYEduRf+1mIpbiJEMFWWmU2xp
# I96gxxb1WrWuAxB8qjGLfsbImx8V3ouK1nUcf+R/nsnXas5/iTgV/Tl3QTRGT0De # ip+zK7xFxKGB1CclUXBU0/ZQZ6LG8H0gI7yvosrsPEI1DPB/XccGCvswKbAKckng
# uXBNbpHqc+wC1NiTyA76gLnirvSBEoBzlrpNQFEnuwdbPLCLpTS3KWSCu5J02b+R # OuGTEPGk7K/vEZa9h0Xt02b7m2n9MdIjkLrFl0pDriKyz0QHGpdh93X6+NApfE1T
# FWR/kcFzVxnhoE3gIaeURtrGKGBZGKLBXvqggkDENtKkvtvRT32xLvAvL/RpReu5 # L24Vo0xkeoFGpL3rX9gXhIOF59EMnTd2o45FW/oxMgY9q0y0jGO0HrCLTCZr50e7
# z18ZojCs72ZSoa74Dy8YbaWsDm3OZOpJRZxZsPKCHZ6xNqgFKf0xNHj0t9v0Q3W+ # TZRSNYAy2lyKbvKI2MKlN1wLzJvZbbc//L3s1q3J6KhS0KC2VNEImYdFgVkJej4z
# 2z5gAVaasJJCvR52Sl0XJ2AOf3l0LSetXgUA5gD5IQ1RvEslTmNnSouTrGID3D1n # ZqHfScTbx9hjFgFpVkJl4xH5VJ8tyJdXE9+vU0k9AaT2QP1Zm3WQmXedSoLjjI7L
# jY7mBu0puiIdPK2jK/1Weef2+YR4cQpWQkeBZmXidh9AuWdlwxKQL15LJ6K2dw8y # WznuHwnoGIXLiJMQzPqKqRIFL3wzcrDrZeWgtAdBPbipglZ5CQns6Baj5Mb6a/EZ
# /t/PBhmLyt6QAf0CepWRdgZnMytVAUuWHwlZRV9JLY7aX8D55eL9+cOLpX3bGNOm # C9G3faJYK5QVHeE6eLoSEwp1dz5WurLXNPsp0VWplpl/FJb8jrRT/jOoHu85qRcd
# N24UpIW8qtZaqXaesFvIOW23JNLhaaQVvObr1eu7GE/5Mn43e+/DbtdYl/bLP2IQ # YpgByU9W7IWPdrthmyfqeAw0omVWN5JxcogYbLo2pANJHlsMdWnxIpN5YwHbGEPC
# 1xYEJdSbcUkDFfW3KlZEh+nBKDtaRnNRkbgIgxIbKdT38OKQwZ/aA4uSsiAg6nEP # uosBHPk2Xd9+E/pZPQUR6v+D85eEN5A/ZM/xiPpxa8dJZ87BpTvui7/2uflUMJf2
# iWBHGuytIo5wU75M5VdjhEqqTHfXYu8BJi6GTzvWT+9ekfMXezqCkksxaG8CAwEA # Yc9ZLPgEdhQQo0LwMDSTDT48y3sV7Pdo+g5q+MqnJztN/6qt1cgUTe9u+ykCAwEA
# AaOCAUkwggFFMB0GA1UdDgQWBBSAaOo5HWatNzqZn1IF1fcD6nr3ITAfBgNVHSME # AaOCAUkwggFFMB0GA1UdDgQWBBSe42+FrpdF2avbUhlk86BLSH5kejAfBgNVHSME
# GDAWgBSfpxVdAF5iXYP05dJlpxtTNRnpcjBfBgNVHR8EWDBWMFSgUqBQhk5odHRw # GDAWgBSfpxVdAF5iXYP05dJlpxtTNRnpcjBfBgNVHR8EWDBWMFSgUqBQhk5odHRw
# Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBUaW1l # Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBUaW1l
# LVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcmwwbAYIKwYBBQUHAQEEYDBeMFwGCCsG # LVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcmwwbAYIKwYBBQUHAQEEYDBeMFwGCCsG
# AQUFBzAChlBodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01p # AQUFBzAChlBodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01p
# Y3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNydDAMBgNVHRMB # Y3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNydDAMBgNVHRMB
# Af8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMA4GA1UdDwEB/wQEAwIHgDAN # Af8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMA4GA1UdDwEB/wQEAwIHgDAN
# BgkqhkiG9w0BAQsFAAOCAgEAXxzVZLLXBFfoCCCTiY7MHXdb7civJSTfrHYJC5Ok # BgkqhkiG9w0BAQsFAAOCAgEAvs4rO3oo8czOrxPqnnSEkUVq718QzlrIiy7/EW7J
# 2NN75NpzTMT9V2TcIQjfQ3AFUbh1NBAYtMUuwxC6D4ceEXG5lXAnbvkC9YjeLVDR # mQXsJoFxHWUF0Ux0PDyKFDRXPJVv29F7kpJkBJJmcQg5HQV7blUXIMWQ1qX0KdtF
# yImXYYmft7z+Qpl9t3C/8a0tiqnOz8Ue8/DYLtMTgvWMnsqLNjILDaImOfnHI36T # QXI/MRL77Z+pK5x1jX+tbRkA7a5Ft7vWuRoAEi02HpFH5m/Akh/dfsbx8wOpecJb
# LCjGFe8RYLXGdCUdOLlfAdMGePxSTA3TAAOc+GQbmPWjrguLWbxvnl3NVjRvrBZV # YvuHuy4aG0/tGzOWFCxMMNhGAIJ4qdV87JnY/uMBmiodlm+Gz357XWW5tg3HrtNZ
# kxFMoVZH0f7qGwDOShjpnv5nYnQ48ufL0uBz52RbPGdX4Fv9+UGOrBprmcHzmIut # XuQ0tWUv26ud4nGKJo/oLZHP75p4Rpt7dMdYKUF9AuVFBwxYZYpvgk12tfK+/yOw
# FtJec2Y4kujNtTK2wBGgWscEOVhFiaVdje8VLJ7MVNKE5TmsuGM3jTLr1nuR5AFG # q84/fjXVCdM83Qnawtbenbk/lnbc9KsZom+GnvA4itAMUpSXFWrcRkqdUQLN+JrG
# s3UKkP7g3cQD4cHK7XdLiTm7e606QJ+WqeQsADYE9dvU9wIUbI9Dl4UcIErFw+FH # 6fPBoV8+D8U2Q2F4XkiCR6EU9JzYKwTuvL6t3nFuxnkLdNjbTg2/yv2j3WaDuCK5
# aWSTrkfJ4SvLmhKnl5khhpJ1sF3z6e1BxepUliXHqzRLiHWihWIWESF8IHElF3PO # lSPgsndIiH6Bku2Ui3A0aUo6D9z9v+XEuBs9ioVJaOjf/z+Urqg7ESnxG0/T1dKc
# xbP4VJqHBiYvaXMV0SyRgwoD6zXddbUnX9WR6JL2BlqAjjHxINwelsp/VhxAWThz # i7vLQ2XNgWFYO+/OlDjtGoma1ijX4m14N9qgrXTuWEGwgC7hhBgp3id/LAOf9BST
# uMA58LxvE/VAzjfFF4Wm7a1ZALmJVw3oL/s/uxo1Op4tcT+hfZ9uN1htC1JN4DuR # WA5lBrilsEoexXBrOn/1wM3rjG0hIsxvF5/YOK78mVRGY6Y7zYJ+uXt4OTOFBwad
# qFfLttjuoAmUQobO5zUFRzvCn8Ck/hiO+bzR15sqkjlxLMyMjpkc/ef4SUUikD46 # Pv8MklreQZLPnQPtiwop4rlLUYaPCiD4YUqRNbLp8Sgyo9g0iAcZYznTuc+8Q8ZI
# 8vUwggdxMIIFWaADAgECAhMzAAAAFcXna54Cm0mZAAAAAAAVMA0GCSqGSIb3DQEB # rgwwggdxMIIFWaADAgECAhMzAAAAFcXna54Cm0mZAAAAAAAVMA0GCSqGSIb3DQEB
# CwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE # CwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE
# BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYD # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYD
# VQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAxMDAe # VQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAxMDAe
@@ -1659,41 +1659,41 @@ Say "Installation finished"
# AQEwggEBoYHZpIHWMIHTMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv # AQEwggEBoYHZpIHWMIHTMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
# bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0 # bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
# aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0 # aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0
# ZWQxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjo0MDFBLTA1RTAtRDk0NzElMCMG # ZWQxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjoyQTFBLTA1RTAtRDk0NzElMCMG
# A1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsOAwIa # A1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsOAwIa
# AxUAMXYp/Wqqdyb0enigrLfxl0InAz6ggYMwgYCkfjB8MQswCQYDVQQGEwJVUzET # AxUAOsyf2b6riPKnnXlIgIL2f53PUsKggYMwgYCkfjB8MQswCQYDVQQGEwJVUzET
# MBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMV # MBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMV
# TWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1T # TWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1T
# dGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQsFAAIFAO4FXKYwIhgPMjAyNjA3MTgw # dGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQsFAAIFAO2zHvgwIhgPMjAyNjA1MTYx
# MjAwMDZaGA8yMDI2MDcxOTAyMDAwNlowdzA9BgorBgEEAYRZCgQBMS8wLTAKAgUA # NjUxMDRaGA8yMDI2MDUxNzE2NTEwNFowdzA9BgorBgEEAYRZCgQBMS8wLTAKAgUA
# 7gVcpgIBADAKAgEAAgIYywIB/zAHAgEAAgITSDAKAgUA7gauJgIBADA2BgorBgEE # 7bMe+AIBADAKAgEAAgIhcwIB/zAHAgEAAgISqjAKAgUA7bRweAIBADA2BgorBgEE
# AYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYag # AYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYag
# MA0GCSqGSIb3DQEBCwUAA4IBAQBq2r0gOT1OxJNWazOFyx2xCpcFbnegtTJkQ4PQ # MA0GCSqGSIb3DQEBCwUAA4IBAQBjb6eELCy7c+QKNzPmI4O0riW248wi0uSI0DKx
# VcbdTaxlE7ksYBeZ0zXLWiv/fSnhonUmp9ORGV6+2phlj6xeV4AyH4dVsmyRBiLN # /ZRwZgOShcyQUcjn6Q/SGMTQ9cqeJe/IhyZbzUCTATtImhIybXreibtT2cAMO4M6
# +Fb7Q5qNxhG3ciablIePFBPSFxOxJ33x6wjJF9CLx7iuhmaykYlp5jhWQ3OQerd2 # 3gGHvd96iu8Q49zOYR182At7wmlUTeMrsj51LpZkWCUy4ZSeOSri83Aong5MKGMF
# FB5vO417JsgGhZscrvZeeamXMWU6LvuPSX02oWth8FbfnIuty1OAtQh9iQwmllq4 # Kt2xnKiSYL2tXIm0zcTpX8xjXMMWFb7wa0CBnHn5ZMYJVtuntxE1B4wJyMZktBS6
# T+dLJJSkC9Mh0gqKo+v5EBAIQ1fS5TsvfMW73Pt3lydMrZjRhdnTsQ4nge+iE8CN # WkP9XpGCXB1X7VhYM3vvtBFq2vA5neloI7waPPPTU+0hK6IX7+c1U776yDnJW4jc
# XrKtIO0esovriWQVcDVYcu9DM/2P1UovTKoZ44pcxDz1zk4VMYIEDTCCBAkCAQEw # OUJsj8rjwrS+Gc/gPt98V3kMoGvxG0eGEzdjkmblUlhT1FwpMYIEDTCCBAkCAQEw
# gZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT # gZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT
# B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UE # B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UE
# AxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAIZXrLYVHX0sY0A # AxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAIQq83kFhjvObAA
# AQAAAhkwDQYJYIZIAWUDBAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0B # AQAAAhAwDQYJYIZIAWUDBAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0B
# CRABBDAvBgkqhkiG9w0BCQQxIgQg1hCY9TskS/ocjoNgKVJVguEsAjqzxBlDPM+r # CRABBDAvBgkqhkiG9w0BCQQxIgQgn7/AUpcQFhG3OcHi0Aeq56NC1uclpcmcCkGu
# Bb91Lt8wgfoGCyqGSIb3DQEJEAIvMYHqMIHnMIHkMIG9BCDckX633E1y1EF32V18 # +HK5un4wgfoGCyqGSIb3DQEJEAIvMYHqMIHnMIHkMIG9BCDD1SHufsjzY59S1iHU
# zQcrsgjzI9+3Le7mlvk2OebthjCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYD # QY9hnsKSrJPg5a9Mc4YnGmPHxjCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1w # b3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1w
# IFBDQSAyMDEwAhMzAAACGV6y2FR19LGNAAEAAAIZMCIEIDjz74g3CBfNc6GVJRjf # IFBDQSAyMDEwAhMzAAACEKvN5BYY7zmwAAEAAAIQMCIEIC5b102d224evVIH68x9
# Y0YVIg76oCasifagFFulpBDbMA0GCSqGSIb3DQEBCwUABIICADak0YxE5whyHvYr # lEf8Au5vChR0bDNP4SViDwl6MA0GCSqGSIb3DQEBCwUABIICAHMgBiQOozDAIR+S
# Zukn9brxBTp9erdA6poINujmoiK5ZrTv6SZYaJbSI0HnDxbxp9QchY3BwpI19ix5 # O28IjquhCukrxIucbxjLUxu4ltpxavA+cedbwkdNPAMFAYEaLHeEYutciK6N5f4R
# +excveLH8i0oQWql3XyZcBDcwBi9sfFDv+yuJfd1CE27X8YxGy5OJeKCK9QoQiXs # VIJX/OSx2ZL6ac/xB5A/7rdoaHV7PK+F1y807INXMA2HPnJGDVbi7HD7nJp26Fuz
# b0MgT35WaxPxvRwcUArXf8qwkP+CO4EkL9x+ZCznyvutSebHKS5fRRPgVreJKRg2 # P2K3aGE3kK06C2jXsjdqWsAZv32k1daX+OqFGJdOsmmua/qlF0AMWTXL7rsBStOH
# vNh4J2lujjEIsOduZs8o5U7woRCBgN/v6lDl9x35WHgoHSzxSwQz7HZea/gcbXa6 # 5YI/KXtAsd9vvUbqcCMGeGmnRk6V7NmsKbQIkZ3kDk6YfKoZWmSknCKHF6LzCPkI
# GRezjA7bCzS1H99feDX3KiTi1kIxtKilQOVzOO9XqrTYoZGak7NeNW12IqbmeYHF # bZSI8PNhcn19VUl9VS4WXGyWeGG5zBkOXnImAIKlaLMxR8Z9/kQVx84TrsDBl6Yh
# ZVW8XkBg5U8BdPpS/3/wD7Y8K1429YSIrJLdccR16TCwlItiqbnFrPt1+qPUH64K # 34t6ISVDkQtre8SBG6fdjyWKmCOSntciVUlEom8ZwkadixIaf8nOoUJSYq5fl+4J
# okrklXX5tYZMe9cXKCC6GlP8oSw1mBf3i85h7YkQf7MgLMbhuBKPBndY7PYfeXNY # HkcUaY79lJKL5DiENwdC4Lt6eNabRo3SPbQE7IQWbWx5h3et1QDitsZ7Gg9yAHaZ
# zjiH4lwKswYlJHqagmw2xYvT00Ekchjo9k6HGaUK1gzCK/ISGOiNb1pr6xf5hK6K # LS/t/SIAy+OXLXNxyttcyrbDvFI8A8tFE9P1w+3MC1n2cveqd6Wu07Z4l74Mj0LX
# TL9zvNOvRxOr6L/fBLjzRFCy4TiBmOAn6uq50hl/7H7hwuoxIXVHcPqZbgRfng7z # yR+0h/KjfE6SPaL+N20E4CjM0bxRKZ+CuFj/A3tykEADdzFtsEfzUzTDkD3cJpOj
# PXEyYpUtVfNMlrFfD0u6mXTp9Ez+1W0hs55SVN4CuwKAO9g1nVBc5i+7KwEpYVfU # fojWQNX1ly8Tu3G/WdAFqzrln2y8jCbVdPIqo1ntbu+BbYom1VQqAihYQB855+pG
# kJuzixuLkM8/Hhm7X6wRAwAqpA7P # D8bOWbnrvhUua7gDFFDA762iZMxD
# SIG # End signature block # SIG # End signature block

11
jest.config.js Normal file
View File

@@ -0,0 +1,11 @@
module.exports = {
clearMocks: true,
moduleFileExtensions: ['js', 'ts'],
testEnvironment: 'node',
testMatch: ['**/*.test.ts'],
testRunner: 'jest-circus/runner',
transform: {
'^.+\\.ts$': 'ts-jest'
},
verbose: true
}

View File

@@ -1,28 +0,0 @@
import type {JestConfigWithTsJest} from 'ts-jest';
const jestConfig: JestConfigWithTsJest = {
clearMocks: true,
testEnvironment: 'node',
moduleFileExtensions: ['js', 'ts'],
testMatch: ['**/*.test.ts'],
testRunner: 'jest-circus/runner',
extensionsToTreatAsEsm: ['.ts'],
moduleNameMapper: {
'^(\\.{1,2}/.*)\\.js$': '$1'
},
transform: {
'^.+\\.ts$': [
'ts-jest',
{
useESM: true,
diagnostics: {
ignoreCodes: [151002]
}
}
]
},
transformIgnorePatterns: ['node_modules/(?!(@actions)/)'],
verbose: true
};
export default jestConfig;

5073
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,6 @@
{ {
"name": "setup-dotnet", "name": "setup-dotnet",
"version": "6.0.0", "version": "5.4.0",
"type": "module",
"private": true, "private": true,
"description": "setup dotnet action", "description": "setup dotnet action",
"main": "dist/setup/index.js", "main": "dist/setup/index.js",
@@ -10,12 +9,12 @@
}, },
"scripts": { "scripts": {
"build": "ncc build -o dist/setup src/setup-dotnet.ts && ncc build -o dist/cache-save src/cache-save.ts", "build": "ncc build -o dist/setup src/setup-dotnet.ts && ncc build -o dist/cache-save src/cache-save.ts",
"format": "prettier --no-error-on-unmatched-pattern --write \"**/*.{ts,yml,yaml}\"", "format": "prettier --no-error-on-unmatched-pattern --config ./.prettierrc.js --write \"**/*.{ts,yml,yaml}\"",
"format-check": "prettier --no-error-on-unmatched-pattern --check \"**/*.{ts,yml,yaml}\"", "format-check": "prettier --no-error-on-unmatched-pattern --config ./.prettierrc.js --check \"**/*.{ts,yml,yaml}\"",
"lint": "eslint \"**/*.ts\"", "lint": "eslint --config ./.eslintrc.js \"**/*.ts\"",
"lint:fix": "eslint \"**/*.ts\" --fix", "lint:fix": "eslint --config ./.eslintrc.js \"**/*.ts\" --fix",
"prepare": "husky install", "prepare": "husky install",
"test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js --coverage", "test": "jest --coverage --config ./jest.config.js",
"update-installers": "nwget https://dot.net/v1/dotnet-install.ps1 -O externals/install-dotnet.ps1 && nwget https://dot.net/v1/dotnet-install.sh -O externals/install-dotnet.sh" "update-installers": "nwget https://dot.net/v1/dotnet-install.ps1 -O externals/install-dotnet.ps1 && nwget https://dot.net/v1/dotnet-install.sh -O externals/install-dotnet.sh"
}, },
"repository": { "repository": {
@@ -30,37 +29,41 @@
"author": "GitHub", "author": "GitHub",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/cache": "^6.2.0", "@actions/cache": "^5.1.0",
"@actions/core": "^3.0.1", "@actions/core": "^2.0.3",
"@actions/exec": "^3.0.0", "@actions/exec": "^2.0.0",
"@actions/github": "^9.1.1", "@actions/github": "^6.0.0",
"@actions/glob": "^0.7.0", "@actions/glob": "^0.5.1",
"@actions/http-client": "^4.0.1", "@actions/http-client": "^3.0.2",
"@actions/io": "^3.0.2", "@actions/io": "^2.0.0",
"fast-xml-parser": "^5.9.3", "fast-xml-parser": "^5.9.2",
"json5": "^2.2.3", "json5": "^2.2.3",
"semver": "^7.8.5" "semver": "^7.6.0"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^10.0.1", "@types/jest": "^29.5.12",
"@jest/globals": "^30.4.1", "@types/node": "^24.1.0",
"@types/node": "^24.13.2", "@types/semver": "^7.5.8",
"@types/semver": "^7.7.0", "@typescript-eslint/eslint-plugin": "^8.0.0",
"@typescript-eslint/eslint-plugin": "^8.62.0", "@typescript-eslint/parser": "^8.0.0",
"@typescript-eslint/parser": "^8.62.0", "@vercel/ncc": "^0.38.1",
"@vercel/ncc": "^0.44.0", "eslint": "^8.57.0",
"eslint": "^10.5.0", "eslint-config-prettier": "^10.1.5",
"eslint-config-prettier": "^10.1.8", "eslint-plugin-jest": "^29.0.1",
"eslint-plugin-jest": "^29.15.2", "eslint-plugin-node": "^11.1.0",
"eslint-plugin-n": "^18.1.0",
"globals": "^17.7.0",
"husky": "^9.1.7", "husky": "^9.1.7",
"jest": "^30.4.2", "jest": "^29.7.0",
"jest-circus": "^30.4.2", "jest-circus": "^29.7.0",
"jest-each": "^30.0.0", "jest-each": "^29.7.0",
"prettier": "^3.8.4", "prettier": "^3.2.5",
"ts-jest": "^29.4.11", "ts-jest": "^29.1.2",
"typescript": "^6.0.3", "typescript": "^5.9.2",
"wget-improved": "^3.2.1" "wget-improved": "^3.2.1"
},
"overrides": {
"undici": "^6.24.1"
},
"jest": {
"testEnvironment": "node"
} }
} }

View File

@@ -4,8 +4,8 @@ import * as cache from '@actions/cache';
import * as core from '@actions/core'; import * as core from '@actions/core';
import * as glob from '@actions/glob'; import * as glob from '@actions/glob';
import {getNuGetFolderPath} from './cache-utils.js'; import {getNuGetFolderPath} from './cache-utils';
import {lockFilePatterns, State, Outputs} from './constants.js'; import {lockFilePatterns, State, Outputs} from './constants';
export const restoreCache = async (cacheDependencyPath?: string) => { export const restoreCache = async (cacheDependencyPath?: string) => {
const lockFilePath = cacheDependencyPath || (await findLockFile()); const lockFilePath = cacheDependencyPath || (await findLockFile());

View File

@@ -1,8 +1,8 @@
import * as core from '@actions/core'; import * as core from '@actions/core';
import * as cache from '@actions/cache'; import * as cache from '@actions/cache';
import fs from 'node:fs'; import fs from 'node:fs';
import {getNuGetFolderPath} from './cache-utils.js'; import {getNuGetFolderPath} from './cache-utils';
import {State} from './constants.js'; import {State} from './constants';
// Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in // Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in
// @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to // @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to

View File

@@ -2,7 +2,7 @@ import * as cache from '@actions/cache';
import * as core from '@actions/core'; import * as core from '@actions/core';
import * as exec from '@actions/exec'; import * as exec from '@actions/exec';
import {cliCommand} from './constants.js'; import {cliCommand} from './constants';
type NuGetFolderName = type NuGetFolderName =
| 'http-cache' | 'http-cache'

View File

@@ -3,19 +3,12 @@ import * as core from '@actions/core';
import * as exec from '@actions/exec'; import * as exec from '@actions/exec';
import * as io from '@actions/io'; import * as io from '@actions/io';
import * as hc from '@actions/http-client'; import * as hc from '@actions/http-client';
import { import {chmodSync} from 'fs';
accessSync,
chmodSync,
constants as fsConstants,
readdirSync,
statSync
} from 'fs';
import path from 'path'; import path from 'path';
import {fileURLToPath} from 'url';
import os from 'os'; import os from 'os';
import semver from 'semver'; import semver from 'semver';
import {IS_WINDOWS, PLATFORM} from './utils.js'; import {IS_WINDOWS, PLATFORM} from './utils';
import type {QualityOptions} from './setup-dotnet.js'; import {QualityOptions} from './setup-dotnet';
export interface DotnetVersion { export interface DotnetVersion {
type: string; type: string;
@@ -35,22 +28,6 @@ interface ReleaseIndexResponse {
const QUALITY_INPUT_MINIMAL_MAJOR_TAG = 6; const QUALITY_INPUT_MINIMAL_MAJOR_TAG = 6;
const LATEST_PATCH_SYNTAX_MINIMAL_MAJOR_TAG = 5; const LATEST_PATCH_SYNTAX_MINIMAL_MAJOR_TAG = 5;
function channelForMajor(major: string): string {
// Starting with .NET 5, the minor version is always zero.
// Hardcode the earlier versions because they will not get new releases.
switch (major) {
case '1':
return '1.1';
case '2':
return '2.2';
case '3':
return '3.1';
default:
return `${major}.0`;
}
}
export class DotnetVersionResolver { export class DotnetVersionResolver {
private inputVersion: string; private inputVersion: string;
private resolvedArgument: DotnetVersion; private resolvedArgument: DotnetVersion;
@@ -148,7 +125,22 @@ export class DotnetVersionResolver {
} else if (this.isNumericTag(major) && this.isNumericTag(minor)) { } else if (this.isNumericTag(major) && this.isNumericTag(minor)) {
this.resolvedArgument.value = `${major}.${minor}`; this.resolvedArgument.value = `${major}.${minor}`;
} else if (this.isNumericTag(major)) { } else if (this.isNumericTag(major)) {
this.resolvedArgument.value = channelForMajor(major); // Starting with .NET 5, the minor version is always zero.
// Hardcode the earlier versions because they will not get new releases.
switch (major) {
case '1':
this.resolvedArgument.value = '1.1';
break;
case '2':
this.resolvedArgument.value = '2.2';
break;
case '3':
this.resolvedArgument.value = '3.1';
break;
default:
this.resolvedArgument.value = `${major}.0`;
break;
}
} else { } else {
// If "dotnet-version" is specified as *, x or X resolve latest version of .NET explicitly from LTS channel. The version argument will default to "latest" by install-dotnet script. // If "dotnet-version" is specified as *, x or X resolve latest version of .NET explicitly from LTS channel. The version argument will default to "latest" by install-dotnet script.
this.resolvedArgument.value = 'LTS'; this.resolvedArgument.value = 'LTS';
@@ -241,13 +233,7 @@ export class DotnetInstallScript {
constructor() { constructor() {
this.escapedScript = path this.escapedScript = path
.join( .join(__dirname, '..', '..', 'externals', this.scriptName)
path.dirname(fileURLToPath(import.meta.url)),
'..',
'..',
'externals',
this.scriptName
)
.replace(/'/g, "''"); .replace(/'/g, "''");
if (IS_WINDOWS) { if (IS_WINDOWS) {
@@ -384,32 +370,7 @@ export function normalizeArch(arch: string): string {
} }
} }
function isFile(filePath: string): boolean {
try {
return statSync(filePath).isFile();
} catch {
return false;
}
}
function isExecutableFile(filePath: string): boolean {
if (!isFile(filePath)) {
return false;
}
if (IS_WINDOWS) {
return true;
}
try {
accessSync(filePath, fsConstants.X_OK);
return true;
} catch {
return false;
}
}
export class DotnetCoreInstaller { export class DotnetCoreInstaller {
private static readonly FeatureBandSyntax = /^(\d+)\.(\d+)\.(\d)xx$/;
static { static {
DotnetInstallDir.setEnvironmentVariable(); DotnetInstallDir.setEnvironmentVariable();
} }
@@ -418,291 +379,10 @@ export class DotnetCoreInstaller {
private version: string, private version: string,
private quality: QualityOptions, private quality: QualityOptions,
private architecture?: string, private architecture?: string,
private dotnetChannel?: string, private dotnetChannel?: string
private checkLatest: boolean = true, ) {}
private minimumVersion?: string,
private rollForward?: string
) {
this.version = version.trim();
}
private getInstalledSdkVersions(): string[] {
const sdkDir = path.join(DotnetInstallDir.dirPath, 'sdk');
try {
const versions = readdirSync(sdkDir, {withFileTypes: true})
.filter(entry => entry.isDirectory() || entry.isSymbolicLink())
.map(entry => entry.name)
.filter(name => semver.valid(name) !== null)
.filter(name => isFile(path.join(sdkDir, name, 'dotnet.dll')));
core.debug(
`Locally installed .NET SDKs in '${sdkDir}': ${
versions.join(', ') || '<none>'
}`
);
return versions;
} catch {
core.debug(`Unable to read the SDK directory '${sdkDir}'.`);
return [];
}
}
private hasDotnetMuxer(): boolean {
return isExecutableFile(
path.join(DotnetInstallDir.dirPath, IS_WINDOWS ? 'dotnet.exe' : 'dotnet')
);
}
private qualityApplies(): boolean {
if (this.version.toLowerCase() === 'latest') {
const major = (this.dotnetChannel || '').trim().match(/^(\d+)/)?.[1];
return major ? Number(major) >= QUALITY_INPUT_MINIMAL_MAJOR_TAG : true;
}
if (semver.valid(this.version)) {
return false;
}
const major = this.version.match(/^(\d+)/)?.[1];
return major ? Number(major) >= QUALITY_INPUT_MINIMAL_MAJOR_TAG : false;
}
private findByScope(
candidates: string[],
major: string,
minor: string,
band?: string
): string | null {
return (
candidates.find(version => {
const parsed = semver.parse(version);
return (
parsed &&
parsed.major === Number(major) &&
parsed.minor === Number(minor) &&
(band === undefined ||
Math.floor(parsed.patch / 100) === Number(band))
);
}) ?? null
);
}
private static isInRollForwardScope(
version: string,
policy: string,
declared: semver.SemVer
): boolean {
const parsed = semver.parse(version);
if (!parsed) {
return false;
}
switch (policy) {
case 'patch':
case 'latestPatch':
return (
parsed.major === declared.major &&
parsed.minor === declared.minor &&
Math.floor(parsed.patch / 100) === Math.floor(declared.patch / 100)
);
case 'feature':
case 'latestFeature':
return (
parsed.major === declared.major && parsed.minor === declared.minor
);
case 'minor':
case 'latestMinor':
return parsed.major === declared.major;
case 'major':
case 'latestMajor':
return true;
default:
return false;
}
}
private static highestVersion(versions: string[]): string {
return versions.reduce((best, version) =>
semver.gt(version, best) ? version : best
);
}
private static nearestBandVersion(versions: string[]): string {
return versions.reduce((best, version) => {
const delta =
semver.major(version) - semver.major(best) ||
semver.minor(version) - semver.minor(best) ||
Math.floor(semver.patch(version) / 100) -
Math.floor(semver.patch(best) / 100);
return delta < 0 || (delta === 0 && semver.gt(version, best))
? version
: best;
});
}
private findByRollForward(
candidates: string[],
policy: string,
declaredVersion: string
): string | null {
const declared = semver.parse(declaredVersion);
if (!declared) {
return null;
}
const scoped = candidates.filter(version =>
DotnetCoreInstaller.isInRollForwardScope(version, policy, declared)
);
if (!scoped.length) {
return null;
}
switch (policy) {
case 'patch':
return (
scoped.find(version => semver.eq(version, declared)) ??
DotnetCoreInstaller.highestVersion(scoped)
);
case 'feature':
case 'minor':
case 'major':
return DotnetCoreInstaller.nearestBandVersion(scoped);
default:
return DotnetCoreInstaller.highestVersion(scoped);
}
}
private filterByQuality(allowed: string[]): string[] {
const wantsPrerelease =
['preview', 'daily'].includes((this.quality || '').toLowerCase()) &&
this.qualityApplies();
return allowed
.filter(version =>
wantsPrerelease
? semver.prerelease(version) !== null
: semver.prerelease(version) === null
)
.sort(semver.rcompare);
}
private findLocalSdkVersion(): string | null {
const installed = this.getInstalledSdkVersions();
if (!installed.length) {
return null;
}
if (!this.hasDotnetMuxer()) {
core.debug(
`The 'dotnet' executable was not found in '${DotnetInstallDir.dirPath}'. Locally installed SDKs are ignored.`
);
return null;
}
const minimumVersion = this.minimumVersion;
const allowed = minimumVersion
? installed.filter(version => semver.gte(version, minimumVersion))
: installed;
if (!allowed.length) {
core.debug(
`No locally installed .NET SDK satisfies the global.json minimum version '${minimumVersion}'.`
);
return null;
}
if (this.rollForward && minimumVersion) {
return this.findByRollForward(
this.filterByQuality(allowed),
this.rollForward,
minimumVersion
);
}
if (semver.valid(this.version)) {
return allowed.find(version => version === this.version) ?? null;
}
if (
this.version.toLowerCase() !== 'latest' &&
!DotnetCoreInstaller.FeatureBandSyntax.test(this.version) &&
!semver.validRange(this.version)
) {
core.debug(
`The requested version '${this.version}' is not a valid version spec. Locally installed SDKs are ignored.`
);
return null;
}
const candidates = this.filterByQuality(allowed);
if (!candidates.length) {
return null;
}
const input = this.version.toLowerCase();
if (input === 'latest') {
const channel = (this.dotnetChannel || '').trim();
if (!channel) {
return candidates[0];
}
const channelMinor = channel.match(/^(\d+)\.(\d+)$/);
if (channelMinor) {
return this.findByScope(candidates, channelMinor[1], channelMinor[2]);
}
const channelBand = channel.match(/^(\d+)\.(\d+)\.(\d)xx$/);
if (channelBand) {
return this.findByScope(
candidates,
channelBand[1],
channelBand[2],
channelBand[3]
);
}
return null;
}
const bandMatch = this.version.match(DotnetCoreInstaller.FeatureBandSyntax);
if (bandMatch) {
if (Number(bandMatch[1]) < LATEST_PATCH_SYNTAX_MINIMAL_MAJOR_TAG) {
return null;
}
return this.findByScope(
candidates,
bandMatch[1],
bandMatch[2],
bandMatch[3]
);
}
const minorMatch = this.version.match(/^(\d+)\.(\d+)(?:\.[xX*])?$/);
if (minorMatch) {
return this.findByScope(candidates, minorMatch[1], minorMatch[2]);
}
const majorMatch = this.version.match(/^(\d+)(?:\.[xX*])?$/);
if (majorMatch) {
const [major, minor] = channelForMajor(majorMatch[1]).split('.');
return this.findByScope(candidates, major, minor);
}
return null;
}
public async installDotnet(): Promise<string | null> { public async installDotnet(): Promise<string | null> {
const isCrossArch =
!!this.architecture &&
normalizeArch(this.architecture) !== normalizeArch(os.arch());
if (!this.checkLatest && !isCrossArch) {
const localVersion = this.findLocalSdkVersion();
if (localVersion) {
core.info(
`'check-latest' is false and a locally installed .NET SDK (${localVersion}) satisfies the '${this.version}' request. Skipping download.`
);
return localVersion;
}
core.info(
`'check-latest' is false but no locally installed .NET SDK satisfies the '${this.version}' request. Falling back to online installation.`
);
}
const versionResolver = new DotnetVersionResolver( const versionResolver = new DotnetVersionResolver(
this.version, this.version,
this.quality, this.quality,
@@ -710,14 +390,16 @@ export class DotnetCoreInstaller {
); );
const dotnetVersion = await versionResolver.createDotnetVersion(); const dotnetVersion = await versionResolver.createDotnetVersion();
const architectureArguments = isCrossArch const architectureArguments =
? [ this.architecture &&
IS_WINDOWS ? '-InstallDir' : '--install-dir', normalizeArch(this.architecture) !== normalizeArch(os.arch())
IS_WINDOWS ? [
? `"${path.join(DotnetInstallDir.dirPath, this.architecture!)}"` IS_WINDOWS ? '-InstallDir' : '--install-dir',
: path.join(DotnetInstallDir.dirPath, this.architecture!) IS_WINDOWS
] ? `"${path.join(DotnetInstallDir.dirPath, this.architecture)}"`
: []; : path.join(DotnetInstallDir.dirPath, this.architecture)
]
: [];
/** /**
* Install dotnet runtime first in order to get * Install dotnet runtime first in order to get
* the latest stable version of dotnet CLI * the latest stable version of dotnet CLI

View File

@@ -4,16 +4,15 @@ import {
DotnetCoreInstaller, DotnetCoreInstaller,
DotnetInstallDir, DotnetInstallDir,
normalizeArch normalizeArch
} from './installer.js'; } from './installer';
import * as fs from 'fs'; import * as fs from 'fs';
import path from 'path'; import path from 'path';
import {fileURLToPath} from 'url';
import semver from 'semver'; import semver from 'semver';
import os from 'os'; import os from 'os';
import * as auth from './authutil.js'; import * as auth from './authutil';
import {isCacheFeatureAvailable} from './cache-utils.js'; import {isCacheFeatureAvailable} from './cache-utils';
import {restoreCache} from './cache-restore.js'; import {restoreCache} from './cache-restore';
import {Outputs} from './constants.js'; import {Outputs} from './constants';
import JSON5 from 'json5'; import JSON5 from 'json5';
const qualityOptions = ['daily', 'preview', 'ga'] as const; const qualityOptions = ['daily', 'preview', 'ga'] as const;
@@ -31,8 +30,6 @@ type SupportedArchitecture = (typeof supportedArchitectures)[number];
export type QualityOptions = (typeof qualityOptions)[number] | ''; export type QualityOptions = (typeof qualityOptions)[number] | '';
const CHECK_LATEST_ENV_VAR = 'DOTNET_CHECK_LATEST';
function isValidChannel(channel: string): boolean { function isValidChannel(channel: string): boolean {
const upper = channel.toUpperCase(); const upper = channel.toUpperCase();
if (upper === 'LTS' || upper === 'STS') return true; if (upper === 'LTS' || upper === 'STS') return true;
@@ -56,24 +53,8 @@ export async function run() {
// Proxy, auth, (etc) are still set up, even if no version is identified // Proxy, auth, (etc) are still set up, even if no version is identified
// //
const versions = core.getMultilineInput('dotnet-version'); const versions = core.getMultilineInput('dotnet-version');
const explicitVersions = new Set(versions);
const globalJsonConstraints = new Map<
string,
{minimumVersion: string; rollForward?: string}
>();
const addVersionFromGlobalJson = (globalJsonPath: string) => {
const {version, minimumVersion, rollForward} =
getVersionFromGlobalJson(globalJsonPath);
versions.push(version);
const isRedundantExplicitPin =
explicitVersions.has(version) && version === minimumVersion;
if (minimumVersion && !isRedundantExplicitPin) {
globalJsonConstraints.set(version, {minimumVersion, rollForward});
}
};
const installedDotnetVersions: (string | null)[] = []; const installedDotnetVersions: (string | null)[] = [];
const architecture = getArchitectureInput(); const architecture = getArchitectureInput();
const checkLatest = getCheckLatestInput();
let dotnetChannel = core.getInput('dotnet-channel'); let dotnetChannel = core.getInput('dotnet-channel');
const isLatestRequested = versions.some( const isLatestRequested = versions.some(
@@ -105,7 +86,7 @@ export async function run() {
`The specified global.json file '${globalJsonFileInput}' does not exist` `The specified global.json file '${globalJsonFileInput}' does not exist`
); );
} }
addVersionFromGlobalJson(globalJsonPath); versions.push(getVersionFromGlobalJson(globalJsonPath));
} }
if (!versions.length) { if (!versions.length) {
@@ -113,7 +94,7 @@ export async function run() {
core.debug('No version found, trying to find version from global.json'); core.debug('No version found, trying to find version from global.json');
const globalJsonPath = path.join(process.cwd(), 'global.json'); const globalJsonPath = path.join(process.cwd(), 'global.json');
if (fs.existsSync(globalJsonPath)) { if (fs.existsSync(globalJsonPath)) {
addVersionFromGlobalJson(globalJsonPath); versions.push(getVersionFromGlobalJson(globalJsonPath));
} else { } else {
core.info( core.info(
`The global.json wasn't found in the root directory. No .NET version will be installed.` `The global.json wasn't found in the root directory. No .NET version will be installed.`
@@ -135,15 +116,11 @@ export async function run() {
versions.map(v => (v.toLowerCase() === 'latest' ? 'latest' : v)) versions.map(v => (v.toLowerCase() === 'latest' ? 'latest' : v))
); );
for (const version of uniqueVersions) { for (const version of uniqueVersions) {
const constraint = globalJsonConstraints.get(version);
dotnetInstaller = new DotnetCoreInstaller( dotnetInstaller = new DotnetCoreInstaller(
version, version,
quality, quality,
architecture, architecture,
version.toLowerCase() === 'latest' ? dotnetChannel : undefined, version.toLowerCase() === 'latest' ? dotnetChannel : undefined
checkLatest,
constraint?.minimumVersion,
constraint?.rollForward
); );
const installedVersion = await dotnetInstaller.installDotnet(); const installedVersion = await dotnetInstaller.installDotnet();
installedDotnetVersions.push(installedVersion); installedDotnetVersions.push(installedVersion);
@@ -175,8 +152,7 @@ export async function run() {
await exec.exec('dotnet', ['workload', 'install', ...workloads]); await exec.exec('dotnet', ['workload', 'install', ...workloads]);
} catch (err) { } catch (err) {
throw new Error( throw new Error(
`Failed to install workloads [${workloads.join(', ')}]: ${err}`, `Failed to install workloads [${workloads.join(', ')}]: ${err}`
{cause: err}
); );
} }
} }
@@ -196,12 +172,7 @@ export async function run() {
await restoreCache(cacheDependencyPath); await restoreCache(cacheDependencyPath);
} }
const matchersPath = path.join( const matchersPath = path.join(__dirname, '..', '..', '.github');
path.dirname(fileURLToPath(import.meta.url)),
'..',
'..',
'.github'
);
core.info(`##[add-matcher]${path.join(matchersPath, 'csc.json')}`); core.info(`##[add-matcher]${path.join(matchersPath, 'csc.json')}`);
} catch (error) { } catch (error) {
core.setFailed(error.message); core.setFailed(error.message);
@@ -222,51 +193,8 @@ function getArchitectureInput(): SupportedArchitecture | '' {
); );
} }
function getCheckLatestInput(): boolean { function getVersionFromGlobalJson(globalJsonPath: string): string {
if ((core.getInput('check-latest') || '').trim()) {
return core.getBooleanInput('check-latest');
}
const rawEnvValue = (process.env[CHECK_LATEST_ENV_VAR] || '').trim();
if (rawEnvValue) {
const envValue = rawEnvValue.toLowerCase();
if (envValue === 'true' || envValue === 'false') {
core.debug(
`The 'check-latest' option is set to '${envValue}' by the ${CHECK_LATEST_ENV_VAR} environment variable.`
);
return envValue === 'true';
}
core.warning(
`Value '${rawEnvValue}' is not supported for the ${CHECK_LATEST_ENV_VAR} environment variable. Supported values are: true, false. The 'check-latest' option falls back to 'true'.`
);
}
return true;
}
interface GlobalJsonVersion {
version: string;
minimumVersion?: string;
rollForward?: string;
}
const ROLL_FORWARD_POLICIES = [
'patch',
'feature',
'minor',
'major',
'latestPatch',
'latestFeature',
'latestMinor',
'latestMajor'
];
const versionPattern = /^\d+\.\d+\.[1-9]\d{2,}$/;
function getVersionFromGlobalJson(globalJsonPath: string): GlobalJsonVersion {
let version = ''; let version = '';
let minimumVersion: string | undefined;
let rollForwardPolicy: string | undefined;
const globalJson = JSON5.parse( const globalJson = JSON5.parse(
// .trim() is necessary to strip BOM https://github.com/nodejs/node/issues/20649 // .trim() is necessary to strip BOM https://github.com/nodejs/node/issues/20649
fs.readFileSync(globalJsonPath, {encoding: 'utf8'}).trim(), fs.readFileSync(globalJsonPath, {encoding: 'utf8'}).trim(),
@@ -280,6 +208,7 @@ function getVersionFromGlobalJson(globalJsonPath: string): GlobalJsonVersion {
version = globalJson.sdk.version; version = globalJson.sdk.version;
const rollForward = globalJson.sdk.rollForward; const rollForward = globalJson.sdk.rollForward;
if (rollForward && !semver.prerelease(version)) { if (rollForward && !semver.prerelease(version)) {
const versionPattern = /^\d+\.\d+\.[1-9]\d{2,}$/;
if (!versionPattern.test(version)) { if (!versionPattern.test(version)) {
throw new Error( throw new Error(
`Version '${version}' is not valid for the 'sdk.version' value in global.json. ` + `Version '${version}' is not valid for the 'sdk.version' value in global.json. ` +
@@ -308,21 +237,9 @@ function getVersionFromGlobalJson(globalJsonPath: string): GlobalJsonVersion {
version = `${major}.${minor}.${feature}xx`; version = `${major}.${minor}.${feature}xx`;
break; break;
} }
if (ROLL_FORWARD_POLICIES.includes(rollForward)) {
minimumVersion = globalJson.sdk.version;
rollForwardPolicy = rollForward;
}
} else if (
!rollForward &&
!semver.prerelease(version) &&
versionPattern.test(version)
) {
minimumVersion = version;
rollForwardPolicy = 'patch';
} }
} }
return {version, minimumVersion, rollForward: rollForwardPolicy}; return version;
} }
function outputInstalledVersion( function outputInstalledVersion(

View File

@@ -3,7 +3,7 @@
/* Basic Options */ /* Basic Options */
// "incremental": true, /* Enable incremental compilation */ // "incremental": true, /* Enable incremental compilation */
"target": "ES2022", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ "target": "ES2022", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
"module": "NodeNext", /* Specify module code generation. */ "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
"lib": [ "lib": [
"ES2022" "ES2022"
], ],
@@ -64,5 +64,5 @@
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
}, },
"exclude": ["node_modules", "**/*.test.ts", "jest.config.ts"] "exclude": ["node_modules", "**/*.test.ts"]
} }