mirror of
https://github.com/actions/setup-dotnet.git
synced 2026-05-27 01:08:17 +01:00
Compare commits
2 Commits
main
...
copilot/up
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f4ede0344 | ||
|
|
77a2bcb980 |
116
.github/workflows/e2e-tests.yml
vendored
116
.github/workflows/e2e-tests.yml
vendored
@@ -257,81 +257,6 @@ jobs:
|
|||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: __tests__/verify-dotnet.ps1 -Patterns "^9.0", "^10.0"
|
run: __tests__/verify-dotnet.ps1 -Patterns "^9.0", "^10.0"
|
||||||
|
|
||||||
test-setup-global-json-rollforward-latestmajor:
|
|
||||||
runs-on: ${{ matrix.operating-system }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
operating-system: [ubuntu-latest, windows-latest, macos-latest]
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
- name: Clear toolcache
|
|
||||||
shell: pwsh
|
|
||||||
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
|
||||||
- name: Write global.json
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
mkdir subdirectory
|
|
||||||
echo '{"sdk":{"version": "3.1.0","rollForward": "latestMajor"}}' > ./subdirectory/global.json
|
|
||||||
- name: Setup dotnet
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
global-json-file: ./subdirectory/global.json
|
|
||||||
- name: Verify dotnet
|
|
||||||
shell: pwsh
|
|
||||||
run: __tests__/verify-dotnet.ps1 -Patterns "^(?!3)"
|
|
||||||
|
|
||||||
test-setup-global-json-rollforward-latestfeature:
|
|
||||||
runs-on: ${{ matrix.operating-system }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
operating-system: [ubuntu-latest, windows-latest, macos-latest]
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
- name: Clear toolcache
|
|
||||||
shell: pwsh
|
|
||||||
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
|
||||||
- name: Write global.json
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
mkdir subdirectory
|
|
||||||
echo '{"sdk":{"version": "10.0.100","rollForward": "latestFeature"}}' > ./subdirectory/global.json
|
|
||||||
- name: Setup dotnet
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
global-json-file: ./subdirectory/global.json
|
|
||||||
- name: Verify dotnet
|
|
||||||
shell: pwsh
|
|
||||||
run: __tests__/verify-dotnet.ps1 -Patterns "^10.0.(?!1)"
|
|
||||||
|
|
||||||
test-setup-global-json-rollforward-latestpatch:
|
|
||||||
runs-on: ${{ matrix.operating-system }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
operating-system: [ubuntu-latest, windows-latest, macos-latest]
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
- name: Clear toolcache
|
|
||||||
shell: pwsh
|
|
||||||
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
|
||||||
- name: Write global.json
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
mkdir subdirectory
|
|
||||||
echo '{"sdk":{"version": "10.0.100","rollForward": "latestPatch"}}' > ./subdirectory/global.json
|
|
||||||
- name: Setup dotnet
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
global-json-file: ./subdirectory/global.json
|
|
||||||
- name: Verify dotnet
|
|
||||||
shell: pwsh
|
|
||||||
run: __tests__/verify-dotnet.ps1 -Patterns "^10.0.1(?!00)"
|
|
||||||
|
|
||||||
test-setup-global-json-only:
|
test-setup-global-json-only:
|
||||||
runs-on: ${{ matrix.operating-system }}
|
runs-on: ${{ matrix.operating-system }}
|
||||||
strategy:
|
strategy:
|
||||||
@@ -724,44 +649,3 @@ jobs:
|
|||||||
- name: Verify dotnet
|
- name: Verify dotnet
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: __tests__/verify-dotnet.ps1 -Patterns "^8.0.416$", "^9.0.308$", "^10.0.101$", "^8.0"
|
run: __tests__/verify-dotnet.ps1 -Patterns "^8.0.416$", "^9.0.308$", "^10.0.101$", "^8.0"
|
||||||
|
|
||||||
test-setup-latest-version:
|
|
||||||
runs-on: ${{ matrix.operating-system }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
operating-system: [ubuntu-latest]
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
- name: Clear toolcache
|
|
||||||
shell: pwsh
|
|
||||||
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
|
||||||
- name: Setup dotnet latest
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
dotnet-version: latest
|
|
||||||
- name: Verify dotnet
|
|
||||||
shell: pwsh
|
|
||||||
run: __tests__/verify-dotnet.ps1 -Patterns "^\d+\.\d+\.\d+"
|
|
||||||
|
|
||||||
test-setup-latest-with-channel-abcxx:
|
|
||||||
runs-on: ${{ matrix.operating-system }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
operating-system: [macos-latest]
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
- name: Clear toolcache
|
|
||||||
shell: pwsh
|
|
||||||
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
|
|
||||||
- name: Setup dotnet latest with A.B.Cxx channel
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
dotnet-version: latest
|
|
||||||
dotnet-channel: '9.0.1xx'
|
|
||||||
- name: Verify dotnet
|
|
||||||
shell: pwsh
|
|
||||||
run: __tests__/verify-dotnet.ps1 -Patterns "^9\.0\.1\d{2}"
|
|
||||||
|
|||||||
@@ -14,4 +14,3 @@ allowed:
|
|||||||
reviewed:
|
reviewed:
|
||||||
npm:
|
npm:
|
||||||
- sax # ISC + MIT
|
- sax # ISC + MIT
|
||||||
- "@actions/http-client" # MIT
|
|
||||||
|
|||||||
2
.licenses/npm/@actions/http-client-3.0.2.dep.yml
generated
2
.licenses/npm/@actions/http-client-3.0.2.dep.yml
generated
@@ -4,7 +4,7 @@ version: 3.0.2
|
|||||||
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: |
|
||||||
|
|||||||
42
README.md
42
README.md
@@ -57,30 +57,7 @@ The `dotnet-version` input supports following syntax:
|
|||||||
- **A.B** or **A.B.x** (e.g. 8.0, 8.0.x) - installs the latest patch version of .NET SDK on the channel `8.0`, including prerelease versions (preview, rc)
|
- **A.B** or **A.B.x** (e.g. 8.0, 8.0.x) - installs the latest patch version of .NET SDK on the channel `8.0`, including prerelease versions (preview, rc)
|
||||||
- **A** or **A.x** (e.g. 8, 8.x) - installs the latest minor version of the specified major tag, including prerelease versions (preview, rc)
|
- **A** or **A.x** (e.g. 8, 8.x) - installs the latest minor version of the specified major tag, including prerelease versions (preview, rc)
|
||||||
- **A.B.Cxx** (e.g. 8.0.4xx) - available since `.NET 5.0` release. Installs the latest version of the specific SDK release, including prerelease versions (preview, rc).
|
- **A.B.Cxx** (e.g. 8.0.4xx) - available since `.NET 5.0` release. Installs the latest version of the specific SDK release, including prerelease versions (preview, rc).
|
||||||
- **latest** - dynamically resolves to the highest active .NET SDK version. By default, it installs the latest **stable (GA)** version (excluding previews and end-of-life releases). Can be combined with `dotnet-channel` and `dotnet-quality`.
|
|
||||||
|
|
||||||
## Using with `dotnet-channel` input
|
|
||||||
|
|
||||||
The optional `dotnet-channel` input specifies the source channel for the installation. Supported values:
|
|
||||||
|
|
||||||
| Value | Description |
|
|
||||||
|-------|-------------|
|
|
||||||
| `STS` | The most recent Standard Term Support release |
|
|
||||||
| `LTS` | The most recent Long Term Support release |
|
|
||||||
| `A.B` (e.g. `8.0`) | A specific release channel |
|
|
||||||
| `A.B.Cxx` (e.g. `8.0.1xx`) | A specific SDK release (available since 5.0) |
|
|
||||||
|
|
||||||
> **Note**: The `dotnet-channel` input is only applied when `dotnet-version` is set to `latest`. If used with a specific version, a warning will be logged and the channel input will be ignored.
|
|
||||||
|
|
||||||
**Install latest LTS version:**
|
|
||||||
```yaml
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- uses: actions/setup-dotnet@v5
|
|
||||||
with:
|
|
||||||
dotnet-version: latest
|
|
||||||
dotnet-channel: LTS
|
|
||||||
```
|
|
||||||
|
|
||||||
## Using the `architecture` input
|
## Using the `architecture` input
|
||||||
Using the architecture input, it is possible to specify the required .NET SDK architecture. Possible values: `x64`, `x86`, `arm64`, `amd64`, `arm`, `s390x`, `ppc64le`, `riscv64`. If the input is not specified, the architecture defaults to the host OS architecture (not all of the architectures are available on all platforms).
|
Using the architecture input, it is possible to specify the required .NET SDK architecture. Possible values: `x64`, `x86`, `arm64`, `amd64`, `arm`, `s390x`, `ppc64le`, `riscv64`. If the input is not specified, the architecture defaults to the host OS architecture (not all of the architectures are available on all platforms).
|
||||||
@@ -100,10 +77,9 @@ steps:
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Using the `dotnet-quality` input
|
## Using the `dotnet-quality` input
|
||||||
|
This input sets up the action to install the latest build of the specified quality in the channel. The possible values of `dotnet-quality` are: **daily**, **signed**, **validated**, **preview**, **ga**.
|
||||||
|
|
||||||
The `dotnet-quality` input installs the latest build of the specified quality in the channel. Supported values: `daily`, `preview`, `ga`.
|
> **Note**: `dotnet-quality` input can be used only with .NET SDK version in 'A.B', 'A.B.x', 'A', 'A.x' and 'A.B.Cxx' formats where the major version is higher than 5. In other cases, `dotnet-quality` input will be ignored.
|
||||||
|
|
||||||
> **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:
|
||||||
@@ -115,18 +91,6 @@ steps:
|
|||||||
- run: dotnet build <my project>
|
- run: dotnet build <my project>
|
||||||
```
|
```
|
||||||
|
|
||||||
`dotnet-quality` can also be combined with `dotnet-version: latest` and `dotnet-channel` to target specific builds such as the latest `daily` build from the `LTS` channel.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- uses: actions/setup-dotnet@v5
|
|
||||||
with:
|
|
||||||
dotnet-version: latest
|
|
||||||
dotnet-channel: LTS
|
|
||||||
dotnet-quality: daily
|
|
||||||
```
|
|
||||||
|
|
||||||
## Using the `global-json-file` input
|
## Using the `global-json-file` input
|
||||||
`setup-dotnet` action can read .NET SDK version from a `global.json` file. Input `global-json-file` is used for specifying the path to the `global.json`. If the file that was supplied to `global-json-file` input doesn't exist, the action will fail with error.
|
`setup-dotnet` action can read .NET SDK version from a `global.json` file. Input `global-json-file` is used for specifying the path to the `global.json`. If the file that was supplied to `global-json-file` input doesn't exist, the action will fail with error.
|
||||||
|
|
||||||
@@ -407,4 +371,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)
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ $dotnetPaths = @{
|
|||||||
|
|
||||||
foreach ($srcPath in $dotnetPaths[$args[0]]) {
|
foreach ($srcPath in $dotnetPaths[$args[0]]) {
|
||||||
if (Test-Path $srcPath) {
|
if (Test-Path $srcPath) {
|
||||||
$dstPath = "$srcPath-" + [IO.Path]::GetRandomFileName()
|
Write-Host "Move $srcPath path"
|
||||||
Write-Host "Moving $srcPath to $dstPath"
|
$dstPath = Join-Path ([IO.Path]::GetTempPath()) ([IO.Path]::GetRandomFileName())
|
||||||
Move-Item -Path $srcPath -Destination $dstPath
|
Move-Item -Path $srcPath -Destination $dstPath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,7 @@ import * as io from '@actions/io';
|
|||||||
import * as installer from '../src/installer';
|
import * as installer from '../src/installer';
|
||||||
|
|
||||||
import {IS_WINDOWS} from '../src/utils';
|
import {IS_WINDOWS} from '../src/utils';
|
||||||
|
import {QualityOptions} from '../src/setup-dotnet';
|
||||||
|
|
||||||
describe('installer tests', () => {
|
describe('installer tests', () => {
|
||||||
const env = process.env;
|
const env = process.env;
|
||||||
@@ -39,7 +40,7 @@ describe('installer tests', () => {
|
|||||||
|
|
||||||
it('should throw the error in case of non-zero exit code of the installation script. The error message should contain logs.', async () => {
|
it('should throw the error in case of non-zero exit code of the installation script. The error message should contain logs.', async () => {
|
||||||
const inputVersion = '10.0.101';
|
const inputVersion = '10.0.101';
|
||||||
const inputQuality = '';
|
const inputQuality = '' as QualityOptions;
|
||||||
const errorMessage = 'fictitious error message!';
|
const errorMessage = 'fictitious error message!';
|
||||||
|
|
||||||
getExecOutputSpy.mockImplementation(() => {
|
getExecOutputSpy.mockImplementation(() => {
|
||||||
@@ -61,7 +62,7 @@ describe('installer tests', () => {
|
|||||||
|
|
||||||
it('should return version of .NET SDK after installation complete', async () => {
|
it('should return version of .NET SDK after installation complete', async () => {
|
||||||
const inputVersion = '10.0.101';
|
const inputVersion = '10.0.101';
|
||||||
const inputQuality = '';
|
const inputQuality = '' as QualityOptions;
|
||||||
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
||||||
getExecOutputSpy.mockImplementation(() => {
|
getExecOutputSpy.mockImplementation(() => {
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
@@ -83,7 +84,7 @@ describe('installer tests', () => {
|
|||||||
|
|
||||||
it(`should supply 'version' argument to the installation script if supplied version is in A.B.C syntax`, async () => {
|
it(`should supply 'version' argument to the installation script if supplied version is in A.B.C syntax`, async () => {
|
||||||
const inputVersion = '10.0.101';
|
const inputVersion = '10.0.101';
|
||||||
const inputQuality = '';
|
const inputQuality = '' as QualityOptions;
|
||||||
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
||||||
|
|
||||||
getExecOutputSpy.mockImplementation(() => {
|
getExecOutputSpy.mockImplementation(() => {
|
||||||
@@ -121,7 +122,7 @@ describe('installer tests', () => {
|
|||||||
|
|
||||||
it(`should warn if the 'quality' input is set and the supplied version is in A.B.C syntax`, async () => {
|
it(`should warn if the 'quality' input is set and the supplied version is in A.B.C syntax`, async () => {
|
||||||
const inputVersion = '10.0.101';
|
const inputVersion = '10.0.101';
|
||||||
const inputQuality = 'ga';
|
const inputQuality = 'ga' as QualityOptions;
|
||||||
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
||||||
getExecOutputSpy.mockImplementation(() => {
|
getExecOutputSpy.mockImplementation(() => {
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
@@ -146,7 +147,7 @@ describe('installer tests', () => {
|
|||||||
|
|
||||||
it(`should warn if the 'quality' input is set and version isn't in A.B.C syntax but major tag is lower then 6`, async () => {
|
it(`should warn if the 'quality' input is set and version isn't in A.B.C syntax but major tag is lower then 6`, async () => {
|
||||||
const inputVersion = '3.1';
|
const inputVersion = '3.1';
|
||||||
const inputQuality = 'ga';
|
const inputQuality = 'ga' as QualityOptions;
|
||||||
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
||||||
|
|
||||||
getExecOutputSpy.mockImplementation(() => {
|
getExecOutputSpy.mockImplementation(() => {
|
||||||
@@ -173,7 +174,7 @@ describe('installer tests', () => {
|
|||||||
each(['10', '10.0', '10.0.x', '10.0.*', '10.0.X']).test(
|
each(['10', '10.0', '10.0.x', '10.0.*', '10.0.X']).test(
|
||||||
`should supply 'quality' argument to the installation script if quality input is set and version (%s) is not in A.B.C syntax`,
|
`should supply 'quality' argument to the installation script if quality input is set and version (%s) is not in A.B.C syntax`,
|
||||||
async inputVersion => {
|
async inputVersion => {
|
||||||
const inputQuality = 'ga';
|
const inputQuality = 'ga' as QualityOptions;
|
||||||
const exitCode = 0;
|
const exitCode = 0;
|
||||||
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
||||||
getExecOutputSpy.mockImplementation(() => {
|
getExecOutputSpy.mockImplementation(() => {
|
||||||
@@ -213,7 +214,7 @@ describe('installer tests', () => {
|
|||||||
each(['10', '10.0', '10.0.x', '10.0.*', '10.0.X']).test(
|
each(['10', '10.0', '10.0.x', '10.0.*', '10.0.X']).test(
|
||||||
`should supply 'channel' argument to the installation script if version (%s) isn't in A.B.C syntax`,
|
`should supply 'channel' argument to the installation script if version (%s) isn't in A.B.C syntax`,
|
||||||
async inputVersion => {
|
async inputVersion => {
|
||||||
const inputQuality = '';
|
const inputQuality = '' as QualityOptions;
|
||||||
const exitCode = 0;
|
const exitCode = 0;
|
||||||
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
||||||
getExecOutputSpy.mockImplementation(() => {
|
getExecOutputSpy.mockImplementation(() => {
|
||||||
@@ -254,7 +255,7 @@ describe('installer tests', () => {
|
|||||||
it(`should supply '-ProxyAddress' argument to the installation script if env.variable 'https_proxy' is set`, async () => {
|
it(`should supply '-ProxyAddress' argument to the installation script if env.variable 'https_proxy' is set`, async () => {
|
||||||
process.env['https_proxy'] = 'https://proxy.com';
|
process.env['https_proxy'] = 'https://proxy.com';
|
||||||
const inputVersion = '10.0.101';
|
const inputVersion = '10.0.101';
|
||||||
const inputQuality = '';
|
const inputQuality = '' as QualityOptions;
|
||||||
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
||||||
|
|
||||||
getExecOutputSpy.mockImplementation(() => {
|
getExecOutputSpy.mockImplementation(() => {
|
||||||
@@ -292,7 +293,7 @@ describe('installer tests', () => {
|
|||||||
it(`should supply '-ProxyBypassList' argument to the installation script if env.variable 'no_proxy' is set`, async () => {
|
it(`should supply '-ProxyBypassList' argument to the installation script if env.variable 'no_proxy' is set`, async () => {
|
||||||
process.env['no_proxy'] = 'first.url,second.url';
|
process.env['no_proxy'] = 'first.url,second.url';
|
||||||
const inputVersion = '10.0.101';
|
const inputVersion = '10.0.101';
|
||||||
const inputQuality = '';
|
const inputQuality = '' as QualityOptions;
|
||||||
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
||||||
|
|
||||||
getExecOutputSpy.mockImplementation(() => {
|
getExecOutputSpy.mockImplementation(() => {
|
||||||
@@ -330,7 +331,7 @@ describe('installer tests', () => {
|
|||||||
|
|
||||||
it(`should supply 'architecture' argument to the installation script when architecture is provided`, async () => {
|
it(`should supply 'architecture' argument to the installation script when architecture is provided`, async () => {
|
||||||
const inputVersion = '10.0.101';
|
const inputVersion = '10.0.101';
|
||||||
const inputQuality = '';
|
const inputQuality = '' as QualityOptions;
|
||||||
const inputArchitecture = 'x64';
|
const inputArchitecture = 'x64';
|
||||||
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
||||||
|
|
||||||
@@ -364,7 +365,7 @@ describe('installer tests', () => {
|
|||||||
|
|
||||||
it(`should NOT supply 'architecture' argument when architecture is not provided`, async () => {
|
it(`should NOT supply 'architecture' argument when architecture is not provided`, async () => {
|
||||||
const inputVersion = '10.0.101';
|
const inputVersion = '10.0.101';
|
||||||
const inputQuality = '';
|
const inputQuality = '' as QualityOptions;
|
||||||
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
||||||
|
|
||||||
getExecOutputSpy.mockImplementation(() => {
|
getExecOutputSpy.mockImplementation(() => {
|
||||||
@@ -394,7 +395,7 @@ describe('installer tests', () => {
|
|||||||
|
|
||||||
it(`should supply 'install-dir' with arch subdirectory for cross-arch install`, async () => {
|
it(`should supply 'install-dir' with arch subdirectory for cross-arch install`, async () => {
|
||||||
const inputVersion = '10.0.101';
|
const inputVersion = '10.0.101';
|
||||||
const inputQuality = '';
|
const inputQuality = '' as QualityOptions;
|
||||||
const inputArchitecture = 'x64';
|
const inputArchitecture = 'x64';
|
||||||
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
||||||
|
|
||||||
@@ -435,7 +436,7 @@ describe('installer tests', () => {
|
|||||||
|
|
||||||
it(`should NOT supply 'install-dir' when architecture matches runner's native arch`, async () => {
|
it(`should NOT supply 'install-dir' when architecture matches runner's native arch`, async () => {
|
||||||
const inputVersion = '10.0.101';
|
const inputVersion = '10.0.101';
|
||||||
const inputQuality = '';
|
const inputQuality = '' as QualityOptions;
|
||||||
const nativeArch = os.arch().toLowerCase();
|
const nativeArch = os.arch().toLowerCase();
|
||||||
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
|
||||||
|
|
||||||
|
|||||||
@@ -1,223 +0,0 @@
|
|||||||
import {DotnetVersionResolver} from '../src/installer';
|
|
||||||
import * as hc from '@actions/http-client';
|
|
||||||
import * as core from '@actions/core';
|
|
||||||
|
|
||||||
// Mock http-client
|
|
||||||
jest.mock('@actions/http-client');
|
|
||||||
|
|
||||||
describe('DotnetVersionResolver with latest', () => {
|
|
||||||
let getJsonMock: jest.Mock;
|
|
||||||
let warningSpy: jest.SpyInstance;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
getJsonMock = jest.fn();
|
|
||||||
(hc.HttpClient as any).mockImplementation(() => {
|
|
||||||
return {
|
|
||||||
getJson: getJsonMock
|
|
||||||
};
|
|
||||||
});
|
|
||||||
warningSpy = jest.spyOn(core, 'warning').mockImplementation(() => {});
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
jest.clearAllMocks();
|
|
||||||
jest.restoreAllMocks();
|
|
||||||
});
|
|
||||||
|
|
||||||
const mockReleases = {
|
|
||||||
'releases-index': [
|
|
||||||
{
|
|
||||||
'channel-version': '10.0',
|
|
||||||
'support-phase': 'preview',
|
|
||||||
'release-type': 'lts'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'channel-version': '9.0',
|
|
||||||
'support-phase': 'active',
|
|
||||||
'release-type': 'sts'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'channel-version': '8.0',
|
|
||||||
'support-phase': 'active',
|
|
||||||
'release-type': 'lts'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'channel-version': '7.0',
|
|
||||||
'support-phase': 'eol',
|
|
||||||
'release-type': 'sts'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
it('should resolve "latest" to highest stable version by default', async () => {
|
|
||||||
getJsonMock.mockResolvedValue({result: mockReleases});
|
|
||||||
|
|
||||||
const resolver = new DotnetVersionResolver('latest');
|
|
||||||
const version = await resolver.createDotnetVersion();
|
|
||||||
|
|
||||||
expect(version.value).toBe('9.0');
|
|
||||||
expect(version.type.toLowerCase()).toContain('channel');
|
|
||||||
expect(version.qualityFlag).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should resolve "LATEST" (uppercase) to highest stable version', async () => {
|
|
||||||
getJsonMock.mockResolvedValue({result: mockReleases});
|
|
||||||
|
|
||||||
const resolver = new DotnetVersionResolver('LATEST');
|
|
||||||
const version = await resolver.createDotnetVersion();
|
|
||||||
|
|
||||||
expect(version.value).toBe('9.0');
|
|
||||||
expect(version.type.toLowerCase()).toContain('channel');
|
|
||||||
expect(version.qualityFlag).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should resolve "latest" to highest preview version if quality is preview', async () => {
|
|
||||||
getJsonMock.mockResolvedValue({result: mockReleases});
|
|
||||||
|
|
||||||
const resolver = new DotnetVersionResolver('latest', 'preview');
|
|
||||||
const version = await resolver.createDotnetVersion();
|
|
||||||
|
|
||||||
expect(version.value).toBe('10.0');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should resolve "latest" with channel filter LTS', async () => {
|
|
||||||
getJsonMock.mockResolvedValue({result: mockReleases});
|
|
||||||
|
|
||||||
const resolver = new DotnetVersionResolver('latest', '', 'LTS');
|
|
||||||
const version = await resolver.createDotnetVersion();
|
|
||||||
|
|
||||||
expect(version.value).toBe('8.0');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should resolve "latest" with channel filter STS', async () => {
|
|
||||||
getJsonMock.mockResolvedValue({result: mockReleases});
|
|
||||||
|
|
||||||
const resolver = new DotnetVersionResolver('latest', '', 'STS');
|
|
||||||
const version = await resolver.createDotnetVersion();
|
|
||||||
|
|
||||||
expect(version.value).toBe('9.0');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should resolve "latest" with channel filter STS and preview quality', async () => {
|
|
||||||
getJsonMock.mockResolvedValue({result: mockReleases});
|
|
||||||
|
|
||||||
const resolver = new DotnetVersionResolver('latest', 'preview', 'STS');
|
|
||||||
const version = await resolver.createDotnetVersion();
|
|
||||||
|
|
||||||
// preview quality includes all support-phases; STS filter → 9.0 (active, sts)
|
|
||||||
expect(version.value).toBe('9.0');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should warn if channel is provided but version is not latest', async () => {
|
|
||||||
getJsonMock.mockResolvedValue({result: mockReleases});
|
|
||||||
|
|
||||||
const resolver = new DotnetVersionResolver('8.0', '', 'LTS');
|
|
||||||
await resolver.createDotnetVersion();
|
|
||||||
|
|
||||||
expect(warningSpy).toHaveBeenCalledWith(
|
|
||||||
`The 'dotnet-channel' input is only supported when 'dotnet-version' is set to 'latest'.`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw when releases-index API returns empty active releases', async () => {
|
|
||||||
const emptyReleases = {
|
|
||||||
'releases-index': [
|
|
||||||
{
|
|
||||||
'channel-version': '7.0',
|
|
||||||
'support-phase': 'eol',
|
|
||||||
'release-type': 'sts'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
getJsonMock.mockResolvedValue({result: emptyReleases});
|
|
||||||
|
|
||||||
const resolver = new DotnetVersionResolver('latest');
|
|
||||||
|
|
||||||
await expect(resolver.createDotnetVersion()).rejects.toThrow(
|
|
||||||
/Could not find any active releases/
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw when releases-index response has unexpected format', async () => {
|
|
||||||
getJsonMock.mockResolvedValue({result: {}});
|
|
||||||
|
|
||||||
const resolver = new DotnetVersionResolver('latest');
|
|
||||||
|
|
||||||
await expect(resolver.createDotnetVersion()).rejects.toThrow(
|
|
||||||
/Unexpected response format/
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw when releases-index response is null', async () => {
|
|
||||||
getJsonMock.mockResolvedValue({result: null});
|
|
||||||
|
|
||||||
const resolver = new DotnetVersionResolver('latest');
|
|
||||||
|
|
||||||
await expect(resolver.createDotnetVersion()).rejects.toThrow(
|
|
||||||
/Unexpected response format/
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should resolve "latest" with ga quality same as default (no previews)', async () => {
|
|
||||||
getJsonMock.mockResolvedValue({result: mockReleases});
|
|
||||||
|
|
||||||
const resolver = new DotnetVersionResolver('latest', 'ga');
|
|
||||||
const version = await resolver.createDotnetVersion();
|
|
||||||
|
|
||||||
// ga should behave like no quality — skip preview (10.0), pick 9.0
|
|
||||||
expect(version.value).toBe('9.0');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should resolve "latest" with LTS channel and daily quality', async () => {
|
|
||||||
getJsonMock.mockResolvedValue({result: mockReleases});
|
|
||||||
|
|
||||||
const resolver = new DotnetVersionResolver('latest', 'daily', 'LTS');
|
|
||||||
const version = await resolver.createDotnetVersion();
|
|
||||||
|
|
||||||
// daily allows previews, LTS filter applies — 10.0 (preview, lts) is the highest LTS
|
|
||||||
expect(version.value).toBe('10.0');
|
|
||||||
expect(version.qualityFlag).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should resolve "latest" with A.B channel directly without API call', async () => {
|
|
||||||
const resolver = new DotnetVersionResolver('latest', '', '8.0');
|
|
||||||
const version = await resolver.createDotnetVersion();
|
|
||||||
|
|
||||||
expect(version.value).toBe('8.0');
|
|
||||||
expect(version.type.toLowerCase()).toContain('channel');
|
|
||||||
expect(version.qualityFlag).toBe(true);
|
|
||||||
// Should NOT call the API
|
|
||||||
expect(getJsonMock).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should resolve "latest" with A.B.Cxx channel directly without API call', async () => {
|
|
||||||
const resolver = new DotnetVersionResolver('latest', '', '8.0.1xx');
|
|
||||||
const version = await resolver.createDotnetVersion();
|
|
||||||
|
|
||||||
expect(version.value).toBe('8.0.1xx');
|
|
||||||
expect(version.type.toLowerCase()).toContain('channel');
|
|
||||||
expect(version.qualityFlag).toBe(true);
|
|
||||||
// Should NOT call the API
|
|
||||||
expect(getJsonMock).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should resolve "latest" with A.B channel for older version with qualityFlag false', async () => {
|
|
||||||
const resolver = new DotnetVersionResolver('latest', '', '3.1');
|
|
||||||
const version = await resolver.createDotnetVersion();
|
|
||||||
|
|
||||||
expect(version.value).toBe('3.1');
|
|
||||||
expect(version.type.toLowerCase()).toContain('channel');
|
|
||||||
// major 3 < 6 → qualityFlag false
|
|
||||||
expect(version.qualityFlag).toBe(false);
|
|
||||||
expect(getJsonMock).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should resolve "latest" with A.B.Cxx channel and quality', async () => {
|
|
||||||
const resolver = new DotnetVersionResolver('latest', 'ga', '8.0.2xx');
|
|
||||||
const version = await resolver.createDotnetVersion();
|
|
||||||
|
|
||||||
expect(version.value).toBe('8.0.2xx');
|
|
||||||
expect(version.qualityFlag).toBe(true);
|
|
||||||
expect(getJsonMock).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -84,7 +84,7 @@ describe('setup-dotnet tests', () => {
|
|||||||
inputs['dotnet-version'] = ['10.0'];
|
inputs['dotnet-version'] = ['10.0'];
|
||||||
inputs['dotnet-quality'] = 'fictitiousQuality';
|
inputs['dotnet-quality'] = 'fictitiousQuality';
|
||||||
|
|
||||||
const expectedErrorMessage = `Value '${inputs['dotnet-quality']}' is not supported for the 'dotnet-quality' option. Supported values are: daily, preview, ga.`;
|
const expectedErrorMessage = `Value '${inputs['dotnet-quality']}' is not supported for the 'dotnet-quality' option. Supported values are: daily, signed, validated, preview, ga.`;
|
||||||
|
|
||||||
await setup.run();
|
await setup.run();
|
||||||
expect(setFailedSpy).toHaveBeenCalledWith(expectedErrorMessage);
|
expect(setFailedSpy).toHaveBeenCalledWith(expectedErrorMessage);
|
||||||
@@ -256,95 +256,5 @@ describe('setup-dotnet tests', () => {
|
|||||||
await setup.run();
|
await setup.run();
|
||||||
expect(setFailedSpy).toHaveBeenCalledWith(expectedErrorMessage);
|
expect(setFailedSpy).toHaveBeenCalledWith(expectedErrorMessage);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fail the action if unsupported dotnet-channel value is provided with latest', async () => {
|
|
||||||
inputs['dotnet-version'] = ['latest'];
|
|
||||||
inputs['dotnet-quality'] = '';
|
|
||||||
inputs['dotnet-channel'] = 'invalid';
|
|
||||||
inputs['architecture'] = '';
|
|
||||||
|
|
||||||
const expectedErrorMessage = `Value 'invalid' is not supported for the 'dotnet-channel' option. Supported values are: LTS, STS, A.B (e.g. 8.0), A.B.Cxx (e.g. 8.0.1xx).`;
|
|
||||||
|
|
||||||
await setup.run();
|
|
||||||
expect(setFailedSpy).toHaveBeenCalledWith(expectedErrorMessage);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should warn but not fail if unsupported dotnet-channel value is provided with a specific version', async () => {
|
|
||||||
inputs['dotnet-version'] = ['8.0.x'];
|
|
||||||
inputs['dotnet-quality'] = '';
|
|
||||||
inputs['dotnet-channel'] = 'invalid';
|
|
||||||
inputs['architecture'] = '';
|
|
||||||
|
|
||||||
installDotnetSpy.mockImplementation(() => Promise.resolve(''));
|
|
||||||
|
|
||||||
await setup.run();
|
|
||||||
expect(setFailedSpy).not.toHaveBeenCalled();
|
|
||||||
expect(warningSpy).toHaveBeenCalledWith(
|
|
||||||
`Value 'invalid' is not supported for the 'dotnet-channel' option and will be ignored because 'dotnet-version' is not set to 'latest'. Supported values are: LTS, STS, A.B (e.g. 8.0), A.B.Cxx (e.g. 8.0.1xx).`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should pass valid dotnet-channel value through without error', async () => {
|
|
||||||
inputs['dotnet-version'] = ['latest'];
|
|
||||||
inputs['dotnet-quality'] = '';
|
|
||||||
inputs['dotnet-channel'] = 'LTS';
|
|
||||||
inputs['architecture'] = '';
|
|
||||||
|
|
||||||
installDotnetSpy.mockImplementation(() => Promise.resolve(''));
|
|
||||||
|
|
||||||
await setup.run();
|
|
||||||
expect(setFailedSpy).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should pass A.B channel value through without error when used with latest', async () => {
|
|
||||||
inputs['dotnet-version'] = ['latest'];
|
|
||||||
inputs['dotnet-quality'] = '';
|
|
||||||
inputs['dotnet-channel'] = '8.0';
|
|
||||||
inputs['architecture'] = '';
|
|
||||||
|
|
||||||
installDotnetSpy.mockImplementation(() => Promise.resolve(''));
|
|
||||||
|
|
||||||
await setup.run();
|
|
||||||
expect(setFailedSpy).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should pass A.B.Cxx channel value through without error when used with latest', async () => {
|
|
||||||
inputs['dotnet-version'] = ['latest'];
|
|
||||||
inputs['dotnet-quality'] = '';
|
|
||||||
inputs['dotnet-channel'] = '8.0.1xx';
|
|
||||||
inputs['architecture'] = '';
|
|
||||||
|
|
||||||
installDotnetSpy.mockImplementation(() => Promise.resolve(''));
|
|
||||||
|
|
||||||
await setup.run();
|
|
||||||
expect(setFailedSpy).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should fail with A.B.Cxx channel if major version is below 5', async () => {
|
|
||||||
inputs['dotnet-version'] = ['latest'];
|
|
||||||
inputs['dotnet-quality'] = '';
|
|
||||||
inputs['dotnet-channel'] = '3.1.1xx';
|
|
||||||
inputs['architecture'] = '';
|
|
||||||
|
|
||||||
const expectedErrorMessage = `Value '3.1.1xx' is not supported for the 'dotnet-channel' option. Supported values are: LTS, STS, A.B (e.g. 8.0), A.B.Cxx (e.g. 8.0.1xx).`;
|
|
||||||
|
|
||||||
await setup.run();
|
|
||||||
expect(setFailedSpy).toHaveBeenCalledWith(expectedErrorMessage);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should warn and not fail if valid dotnet-channel is provided with a non-latest version', async () => {
|
|
||||||
inputs['dotnet-version'] = ['8.0.x'];
|
|
||||||
inputs['dotnet-quality'] = '';
|
|
||||||
inputs['dotnet-channel'] = 'LTS';
|
|
||||||
inputs['architecture'] = '';
|
|
||||||
|
|
||||||
installDotnetSpy.mockImplementation(() => Promise.resolve(''));
|
|
||||||
|
|
||||||
await setup.run();
|
|
||||||
expect(setFailedSpy).not.toHaveBeenCalled();
|
|
||||||
expect(warningSpy).toHaveBeenCalledWith(
|
|
||||||
`The 'dotnet-channel' input is only supported when 'dotnet-version' is set to 'latest'.`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,11 +6,9 @@ branding:
|
|||||||
color: green
|
color: green
|
||||||
inputs:
|
inputs:
|
||||||
dotnet-version:
|
dotnet-version:
|
||||||
description: 'Optional SDK version(s) to use. If not provided, will install global.json version when available. Examples: 2.2.104, 3.1, 3.1.x, 3.x, 6.0.2xx, latest'
|
description: 'Optional SDK version(s) to use. If not provided, will install global.json version when available. Examples: 2.2.104, 3.1, 3.1.x, 3.x, 6.0.2xx'
|
||||||
dotnet-quality:
|
dotnet-quality:
|
||||||
description: 'Optional quality of the build. The possible values are: daily, preview, ga.'
|
description: 'Optional quality of the build. The possible values are: daily, signed, validated, preview, ga.'
|
||||||
dotnet-channel:
|
|
||||||
description: 'Optional channel for the installation. The possible values are: STS, LTS, A.B (e.g. 8.0), A.B.Cxx (e.g. 8.0.1xx, available since 5.0). To be used with "dotnet-version: latest".'
|
|
||||||
global-json-file:
|
global-json-file:
|
||||||
description: 'Optional global.json location, if your global.json isn''t located in the root of the repo.'
|
description: 'Optional global.json location, if your global.json isn''t located in the root of the repo.'
|
||||||
source-url:
|
source-url:
|
||||||
@@ -41,4 +39,4 @@ runs:
|
|||||||
using: 'node24'
|
using: 'node24'
|
||||||
main: 'dist/setup/index.js'
|
main: 'dist/setup/index.js'
|
||||||
post: 'dist/cache-save/index.js'
|
post: 'dist/cache-save/index.js'
|
||||||
post-if: success()
|
post-if: success()
|
||||||
|
|||||||
166
dist/setup/index.js
vendored
166
dist/setup/index.js
vendored
@@ -78690,51 +78690,15 @@ const utils_1 = __nccwpck_require__(71314);
|
|||||||
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;
|
||||||
class DotnetVersionResolver {
|
class DotnetVersionResolver {
|
||||||
quality;
|
|
||||||
dotnetChannel;
|
|
||||||
inputVersion;
|
inputVersion;
|
||||||
resolvedArgument;
|
resolvedArgument;
|
||||||
constructor(version, quality = '', dotnetChannel) {
|
constructor(version) {
|
||||||
this.quality = quality;
|
|
||||||
this.dotnetChannel = dotnetChannel;
|
|
||||||
this.inputVersion = version.trim();
|
this.inputVersion = version.trim();
|
||||||
this.resolvedArgument = { type: '', value: '', qualityFlag: false };
|
this.resolvedArgument = { type: '', value: '', qualityFlag: false };
|
||||||
}
|
}
|
||||||
isVersionChannel(channel) {
|
|
||||||
// A.B format (e.g., 3.1, 8.0)
|
|
||||||
if (/^\d+\.\d+$/.test(channel))
|
|
||||||
return true;
|
|
||||||
// A.B.Cxx format (e.g., 8.0.1xx) is supported only for .NET 5.0+
|
|
||||||
const latestPatchMatch = channel.match(/^(\d+)\.\d+\.\d{1}xx$/);
|
|
||||||
if (latestPatchMatch) {
|
|
||||||
const major = Number(latestPatchMatch[1]);
|
|
||||||
return (!Number.isNaN(major) && major >= LATEST_PATCH_SYNTAX_MINIMAL_MAJOR_TAG);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
async resolveVersionInput() {
|
async resolveVersionInput() {
|
||||||
if (this.inputVersion.toLowerCase() === 'latest') {
|
|
||||||
const channel = this.dotnetChannel || '';
|
|
||||||
if (this.isVersionChannel(channel)) {
|
|
||||||
// A.B or A.B.Cxx channels are passed directly to the install script
|
|
||||||
this.resolvedArgument.value = channel;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// LTS, STS, or empty — resolve via releases index API
|
|
||||||
this.resolvedArgument.value = await this.getLatestVersion(channel);
|
|
||||||
}
|
|
||||||
this.resolvedArgument.type = 'channel';
|
|
||||||
const latestChannelMajorTag = Number(this.resolvedArgument.value.split('.')[0]);
|
|
||||||
this.resolvedArgument.qualityFlag =
|
|
||||||
!Number.isNaN(latestChannelMajorTag) &&
|
|
||||||
latestChannelMajorTag >= QUALITY_INPUT_MINIMAL_MAJOR_TAG;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.dotnetChannel) {
|
|
||||||
core.warning(`The 'dotnet-channel' input is only supported when 'dotnet-version' is set to 'latest'.`);
|
|
||||||
}
|
|
||||||
if (!semver_1.default.validRange(this.inputVersion) && !this.isLatestPatchSyntax()) {
|
if (!semver_1.default.validRange(this.inputVersion) && !this.isLatestPatchSyntax()) {
|
||||||
throw new Error(`The 'dotnet-version' was supplied in invalid format: ${this.inputVersion}! Supported syntax: A.B.C, A.B, A.B.x, A, A.x, A.B.Cxx, latest`);
|
throw new Error(`The 'dotnet-version' was supplied in invalid format: ${this.inputVersion}! Supported syntax: A.B.C, A.B, A.B.x, A, A.x, A.B.Cxx`);
|
||||||
}
|
}
|
||||||
if (semver_1.default.valid(this.inputVersion)) {
|
if (semver_1.default.valid(this.inputVersion)) {
|
||||||
this.createVersionArgument();
|
this.createVersionArgument();
|
||||||
@@ -78768,22 +78732,7 @@ class DotnetVersionResolver {
|
|||||||
this.resolvedArgument.value = `${major}.${minor}`;
|
this.resolvedArgument.value = `${major}.${minor}`;
|
||||||
}
|
}
|
||||||
else if (this.isNumericTag(major)) {
|
else if (this.isNumericTag(major)) {
|
||||||
// Starting with .NET 5, the minor version is always zero.
|
this.resolvedArgument.value = await this.getLatestByMajorTag(major);
|
||||||
// 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.
|
||||||
@@ -78807,45 +78756,22 @@ class DotnetVersionResolver {
|
|||||||
}
|
}
|
||||||
return this.resolvedArgument;
|
return this.resolvedArgument;
|
||||||
}
|
}
|
||||||
async getLatestVersion(channelFilter) {
|
async getLatestByMajorTag(majorTag) {
|
||||||
const httpClient = new hc.HttpClient('actions/setup-dotnet', [], {
|
const httpClient = new hc.HttpClient('actions/setup-dotnet', [], {
|
||||||
allowRetries: true,
|
allowRetries: true,
|
||||||
maxRetries: 3
|
maxRetries: 3
|
||||||
});
|
});
|
||||||
const response = await httpClient.getJson(DotnetVersionResolver.DotnetCoreIndexUrl);
|
const response = await httpClient.getJson(DotnetVersionResolver.DotnetCoreIndexUrl);
|
||||||
const result = response.result;
|
const result = response.result || {};
|
||||||
const rawReleasesInfo = result?.['releases-index'];
|
const releasesInfo = result['releases-index'];
|
||||||
if (!Array.isArray(rawReleasesInfo)) {
|
const releaseInfo = releasesInfo.find(info => {
|
||||||
throw new Error('Unexpected response format from .NET releases index.');
|
const sdkParts = info['channel-version'].split('.');
|
||||||
}
|
return sdkParts[0] === majorTag;
|
||||||
let releasesInfo = rawReleasesInfo;
|
|
||||||
// Filter out EOL versions
|
|
||||||
releasesInfo = releasesInfo.filter(info => info['support-phase'] !== 'eol');
|
|
||||||
// Filter out preview versions if quality is not 'preview' or 'daily'
|
|
||||||
// If quality is not specified, we assume strict stability (GA only)
|
|
||||||
const normalizedQuality = (this.quality || '').toLowerCase();
|
|
||||||
if (!['preview', 'daily'].includes(normalizedQuality)) {
|
|
||||||
releasesInfo = releasesInfo.filter(info => info['support-phase'] !== 'preview');
|
|
||||||
}
|
|
||||||
// Apply channel filter (LTS/STS)
|
|
||||||
if (channelFilter) {
|
|
||||||
const type = channelFilter.toLowerCase();
|
|
||||||
releasesInfo = releasesInfo.filter(info => info['release-type'] === type);
|
|
||||||
}
|
|
||||||
releasesInfo.sort((a, b) => {
|
|
||||||
const partsA = a['channel-version'].split('.').map(Number);
|
|
||||||
const partsB = b['channel-version'].split('.').map(Number);
|
|
||||||
for (let i = 0; i < Math.max(partsA.length, partsB.length); i++) {
|
|
||||||
const diff = (partsB[i] || 0) - (partsA[i] || 0);
|
|
||||||
if (diff !== 0)
|
|
||||||
return diff;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
});
|
});
|
||||||
if (releasesInfo.length === 0) {
|
if (!releaseInfo) {
|
||||||
throw new Error(`Could not find any active releases matching channel '${channelFilter || 'any'}'`);
|
throw new Error(`Could not find info for version with major tag: "${majorTag}" at ${DotnetVersionResolver.DotnetCoreIndexUrl}`);
|
||||||
}
|
}
|
||||||
return releasesInfo[0]['channel-version'];
|
return releaseInfo['channel-version'];
|
||||||
}
|
}
|
||||||
static DotnetCoreIndexUrl = 'https://builds.dotnet.microsoft.com/dotnet/release-metadata/releases-index.json';
|
static DotnetCoreIndexUrl = 'https://builds.dotnet.microsoft.com/dotnet/release-metadata/releases-index.json';
|
||||||
}
|
}
|
||||||
@@ -78965,18 +78891,16 @@ class DotnetCoreInstaller {
|
|||||||
version;
|
version;
|
||||||
quality;
|
quality;
|
||||||
architecture;
|
architecture;
|
||||||
dotnetChannel;
|
|
||||||
static {
|
static {
|
||||||
DotnetInstallDir.setEnvironmentVariable();
|
DotnetInstallDir.setEnvironmentVariable();
|
||||||
}
|
}
|
||||||
constructor(version, quality, architecture, dotnetChannel) {
|
constructor(version, quality, architecture) {
|
||||||
this.version = version;
|
this.version = version;
|
||||||
this.quality = quality;
|
this.quality = quality;
|
||||||
this.architecture = architecture;
|
this.architecture = architecture;
|
||||||
this.dotnetChannel = dotnetChannel;
|
|
||||||
}
|
}
|
||||||
async installDotnet() {
|
async installDotnet() {
|
||||||
const versionResolver = new DotnetVersionResolver(this.version, this.quality, this.dotnetChannel);
|
const versionResolver = new DotnetVersionResolver(this.version);
|
||||||
const dotnetVersion = await versionResolver.createDotnetVersion();
|
const dotnetVersion = await versionResolver.createDotnetVersion();
|
||||||
const architectureArguments = this.architecture &&
|
const architectureArguments = this.architecture &&
|
||||||
normalizeArch(this.architecture) !== normalizeArch(os_1.default.arch())
|
normalizeArch(this.architecture) !== normalizeArch(os_1.default.arch())
|
||||||
@@ -79095,7 +79019,13 @@ const cache_utils_1 = __nccwpck_require__(41678);
|
|||||||
const cache_restore_1 = __nccwpck_require__(19517);
|
const cache_restore_1 = __nccwpck_require__(19517);
|
||||||
const constants_1 = __nccwpck_require__(69042);
|
const constants_1 = __nccwpck_require__(69042);
|
||||||
const json5_1 = __importDefault(__nccwpck_require__(86904));
|
const json5_1 = __importDefault(__nccwpck_require__(86904));
|
||||||
const qualityOptions = ['daily', 'preview', 'ga'];
|
const qualityOptions = [
|
||||||
|
'daily',
|
||||||
|
'signed',
|
||||||
|
'validated',
|
||||||
|
'preview',
|
||||||
|
'ga'
|
||||||
|
];
|
||||||
const supportedArchitectures = [
|
const supportedArchitectures = [
|
||||||
'x64',
|
'x64',
|
||||||
'x86',
|
'x86',
|
||||||
@@ -79106,19 +79036,6 @@ const supportedArchitectures = [
|
|||||||
'ppc64le',
|
'ppc64le',
|
||||||
'riscv64'
|
'riscv64'
|
||||||
];
|
];
|
||||||
function isValidChannel(channel) {
|
|
||||||
const upper = channel.toUpperCase();
|
|
||||||
if (upper === 'LTS' || upper === 'STS')
|
|
||||||
return true;
|
|
||||||
// A.B format (e.g., 3.1, 8.0)
|
|
||||||
if (/^\d+\.\d+$/.test(channel))
|
|
||||||
return true;
|
|
||||||
// A.B.Cxx format (e.g., 8.0.1xx) - available since 5.0
|
|
||||||
const match = channel.match(/^(?<major>\d+)\.\d+\.\d{1}xx$/);
|
|
||||||
if (match && parseInt(match.groups.major) >= 5)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
async function run() {
|
async function run() {
|
||||||
try {
|
try {
|
||||||
//
|
//
|
||||||
@@ -79133,21 +79050,6 @@ async function run() {
|
|||||||
const versions = core.getMultilineInput('dotnet-version');
|
const versions = core.getMultilineInput('dotnet-version');
|
||||||
const installedDotnetVersions = [];
|
const installedDotnetVersions = [];
|
||||||
const architecture = getArchitectureInput();
|
const architecture = getArchitectureInput();
|
||||||
let dotnetChannel = core.getInput('dotnet-channel');
|
|
||||||
const isLatestRequested = versions.some(version => version && version.toLowerCase() === 'latest');
|
|
||||||
if (dotnetChannel && !isValidChannel(dotnetChannel)) {
|
|
||||||
if (isLatestRequested) {
|
|
||||||
throw new Error(`Value '${dotnetChannel}' is not supported for the 'dotnet-channel' option. Supported values are: LTS, STS, A.B (e.g. 8.0), A.B.Cxx (e.g. 8.0.1xx).`);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
core.warning(`Value '${dotnetChannel}' is not supported for the 'dotnet-channel' option and will be ignored because 'dotnet-version' is not set to 'latest'. Supported values are: LTS, STS, A.B (e.g. 8.0), A.B.Cxx (e.g. 8.0.1xx).`);
|
|
||||||
dotnetChannel = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (dotnetChannel && !isLatestRequested) {
|
|
||||||
core.warning(`The 'dotnet-channel' input is only supported when 'dotnet-version' is set to 'latest'.`);
|
|
||||||
dotnetChannel = '';
|
|
||||||
}
|
|
||||||
const globalJsonFileInput = core.getInput('global-json-file');
|
const globalJsonFileInput = core.getInput('global-json-file');
|
||||||
if (globalJsonFileInput) {
|
if (globalJsonFileInput) {
|
||||||
const globalJsonPath = path_1.default.resolve(process.cwd(), globalJsonFileInput);
|
const globalJsonPath = path_1.default.resolve(process.cwd(), globalJsonFileInput);
|
||||||
@@ -79170,12 +79072,12 @@ async function run() {
|
|||||||
if (versions.length) {
|
if (versions.length) {
|
||||||
const quality = core.getInput('dotnet-quality');
|
const quality = core.getInput('dotnet-quality');
|
||||||
if (quality && !qualityOptions.includes(quality)) {
|
if (quality && !qualityOptions.includes(quality)) {
|
||||||
throw new Error(`Value '${quality}' is not supported for the 'dotnet-quality' option. Supported values are: daily, preview, ga.`);
|
throw new Error(`Value '${quality}' is not supported for the 'dotnet-quality' option. Supported values are: daily, signed, validated, preview, ga.`);
|
||||||
}
|
}
|
||||||
let dotnetInstaller;
|
let dotnetInstaller;
|
||||||
const uniqueVersions = new Set(versions.map(v => (v.toLowerCase() === 'latest' ? 'latest' : v)));
|
const uniqueVersions = new Set(versions);
|
||||||
for (const version of uniqueVersions) {
|
for (const version of uniqueVersions) {
|
||||||
dotnetInstaller = new installer_1.DotnetCoreInstaller(version, quality, architecture, version.toLowerCase() === 'latest' ? dotnetChannel : undefined);
|
dotnetInstaller = new installer_1.DotnetCoreInstaller(version, quality, architecture);
|
||||||
const installedVersion = await dotnetInstaller.installDotnet();
|
const installedVersion = await dotnetInstaller.installDotnet();
|
||||||
installedDotnetVersions.push(installedVersion);
|
installedDotnetVersions.push(installedVersion);
|
||||||
}
|
}
|
||||||
@@ -79244,23 +79146,9 @@ function getVersionFromGlobalJson(globalJsonPath) {
|
|||||||
if (globalJson.sdk && globalJson.sdk.version) {
|
if (globalJson.sdk && globalJson.sdk.version) {
|
||||||
version = globalJson.sdk.version;
|
version = globalJson.sdk.version;
|
||||||
const rollForward = globalJson.sdk.rollForward;
|
const rollForward = globalJson.sdk.rollForward;
|
||||||
if (rollForward) {
|
if (rollForward && rollForward === 'latestFeature') {
|
||||||
const [major, minor, featurePatch] = version.split('.');
|
const [major, minor] = version.split('.');
|
||||||
const feature = featurePatch.substring(0, 1);
|
version = `${major}.${minor}`;
|
||||||
switch (rollForward) {
|
|
||||||
case 'latestMajor':
|
|
||||||
version = '';
|
|
||||||
break;
|
|
||||||
case 'latestMinor':
|
|
||||||
version = `${major}`;
|
|
||||||
break;
|
|
||||||
case 'latestFeature':
|
|
||||||
version = `${major}.${minor}`;
|
|
||||||
break;
|
|
||||||
case 'latestPatch':
|
|
||||||
version = `${major}.${minor}.${feature}xx`;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return version;
|
return version;
|
||||||
|
|||||||
570
externals/install-dotnet.ps1
vendored
570
externals/install-dotnet.ps1
vendored
@@ -94,9 +94,9 @@
|
|||||||
Determines timeout duration in seconds for downloading of the SDK file
|
Determines timeout duration in seconds for downloading of the SDK file
|
||||||
Default: 1200 seconds (20 minutes)
|
Default: 1200 seconds (20 minutes)
|
||||||
.PARAMETER KeepZip
|
.PARAMETER KeepZip
|
||||||
If set, downloaded archive file is kept. Applies to both .zip and .tar.gz formats.
|
If set, downloaded file is kept
|
||||||
.PARAMETER ZipPath
|
.PARAMETER ZipPath
|
||||||
Use that path to store the downloaded archive, generated by default. Applies to both .zip and .tar.gz formats.
|
Use that path to store installer, generated by default
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
dotnet-install.ps1 -Version 7.0.401
|
dotnet-install.ps1 -Version 7.0.401
|
||||||
Installs the .NET SDK version 7.0.401
|
Installs the .NET SDK version 7.0.401
|
||||||
@@ -341,36 +341,6 @@ function Get-NormalizedProduct([string]$Runtime) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Test-TarAvailable {
|
|
||||||
if ($env:DOTNET_INSTALL_SKIP_TAR -eq "1") {
|
|
||||||
Say-Verbose "Skipping tar detection due to DOTNET_INSTALL_SKIP_TAR environment variable."
|
|
||||||
return $false
|
|
||||||
}
|
|
||||||
$tarCommand = Get-Command -Name "tar" -ErrorAction SilentlyContinue
|
|
||||||
return $null -ne $tarCommand
|
|
||||||
}
|
|
||||||
|
|
||||||
function Get-FileExtension-For-Version([string]$VersionOrChannel) {
|
|
||||||
if (-not $script:TarAvailable) {
|
|
||||||
return ".zip"
|
|
||||||
}
|
|
||||||
if ($VersionOrChannel -match '^(\d+)\.') {
|
|
||||||
$majorVersion = [int]$Matches[1]
|
|
||||||
if ($majorVersion -ge 11) {
|
|
||||||
# Windows tarballs are only available starting with 11.0 preview 3
|
|
||||||
if ($VersionOrChannel -match 'preview\.(\d+)') {
|
|
||||||
$previewNum = [int]$Matches[1]
|
|
||||||
if ($majorVersion -eq 11 -and $previewNum -lt 3) {
|
|
||||||
Say-Verbose "Version '$VersionOrChannel' predates tar.gz availability; using zip."
|
|
||||||
return ".zip"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Say-Verbose "Using tar.gz archive format for version/channel '$VersionOrChannel'."
|
|
||||||
return ".tar.gz"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ".zip"
|
|
||||||
}
|
|
||||||
|
|
||||||
# The version text returned from the feeds is a 1-line or 2-line string:
|
# The version text returned from the feeds is a 1-line or 2-line string:
|
||||||
# For the SDK and the dotnet runtime (2 lines):
|
# For the SDK and the dotnet runtime (2 lines):
|
||||||
@@ -624,27 +594,24 @@ function Get-Download-Link([string]$AzureFeed, [string]$SpecificVersion, [string
|
|||||||
# If anything fails in this lookup it will default to $SpecificVersion
|
# If anything fails in this lookup it will default to $SpecificVersion
|
||||||
$SpecificProductVersion = Get-Product-Version -AzureFeed $AzureFeed -SpecificVersion $SpecificVersion
|
$SpecificProductVersion = Get-Product-Version -AzureFeed $AzureFeed -SpecificVersion $SpecificVersion
|
||||||
|
|
||||||
# For .NET 11.0+, tar.gz is the preferred archive format on Windows
|
|
||||||
$ext = Get-FileExtension-For-Version $SpecificVersion
|
|
||||||
|
|
||||||
if ($Runtime -eq "dotnet") {
|
if ($Runtime -eq "dotnet") {
|
||||||
$PayloadURL = "$AzureFeed/Runtime/$SpecificVersion/dotnet-runtime-$SpecificProductVersion-win-$CLIArchitecture$ext"
|
$PayloadURL = "$AzureFeed/Runtime/$SpecificVersion/dotnet-runtime-$SpecificProductVersion-win-$CLIArchitecture.zip"
|
||||||
}
|
}
|
||||||
elseif ($Runtime -eq "aspnetcore") {
|
elseif ($Runtime -eq "aspnetcore") {
|
||||||
$PayloadURL = "$AzureFeed/aspnetcore/Runtime/$SpecificVersion/aspnetcore-runtime-$SpecificProductVersion-win-$CLIArchitecture$ext"
|
$PayloadURL = "$AzureFeed/aspnetcore/Runtime/$SpecificVersion/aspnetcore-runtime-$SpecificProductVersion-win-$CLIArchitecture.zip"
|
||||||
}
|
}
|
||||||
elseif ($Runtime -eq "windowsdesktop") {
|
elseif ($Runtime -eq "windowsdesktop") {
|
||||||
# The windows desktop runtime is part of the core runtime layout prior to 5.0
|
# The windows desktop runtime is part of the core runtime layout prior to 5.0
|
||||||
$PayloadURL = "$AzureFeed/Runtime/$SpecificVersion/windowsdesktop-runtime-$SpecificProductVersion-win-$CLIArchitecture$ext"
|
$PayloadURL = "$AzureFeed/Runtime/$SpecificVersion/windowsdesktop-runtime-$SpecificProductVersion-win-$CLIArchitecture.zip"
|
||||||
if ($SpecificVersion -match '^(\d+)\.(.*)$') {
|
if ($SpecificVersion -match '^(\d+)\.(.*)$') {
|
||||||
$majorVersion = [int]$Matches[1]
|
$majorVersion = [int]$Matches[1]
|
||||||
if ($majorVersion -ge 5) {
|
if ($majorVersion -ge 5) {
|
||||||
$PayloadURL = "$AzureFeed/WindowsDesktop/$SpecificVersion/windowsdesktop-runtime-$SpecificProductVersion-win-$CLIArchitecture$ext"
|
$PayloadURL = "$AzureFeed/WindowsDesktop/$SpecificVersion/windowsdesktop-runtime-$SpecificProductVersion-win-$CLIArchitecture.zip"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elseif (-not $Runtime) {
|
elseif (-not $Runtime) {
|
||||||
$PayloadURL = "$AzureFeed/Sdk/$SpecificVersion/dotnet-sdk-$SpecificProductVersion-win-$CLIArchitecture$ext"
|
$PayloadURL = "$AzureFeed/Sdk/$SpecificVersion/dotnet-sdk-$SpecificProductVersion-win-$CLIArchitecture.zip"
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw "Invalid value for `$Runtime"
|
throw "Invalid value for `$Runtime"
|
||||||
@@ -910,80 +877,6 @@ function Extract-Dotnet-Package([string]$ZipPath, [string]$OutPath) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Extract-Dotnet-Package-Tar([string]$TarPath, [string]$OutPath) {
|
|
||||||
Say-Invocation $MyInvocation
|
|
||||||
|
|
||||||
New-Item -ItemType Directory -Force -Path $OutPath | Out-Null
|
|
||||||
|
|
||||||
# Build an exclude list of versioned directories that already exist locally.
|
|
||||||
# This matches the zip extraction behavior: if shared/Microsoft.NETCore.App/11.0.0/
|
|
||||||
# already exists, we skip all files under that version to avoid overwriting a
|
|
||||||
# previously installed version.
|
|
||||||
$excludeArgs = @()
|
|
||||||
$versionRegex = '.*/\d+\.\d+[^/]+/'
|
|
||||||
|
|
||||||
# Read the tarball's file listing to discover versioned directory prefixes
|
|
||||||
$tarListing = & tar -tzf $TarPath 2>$null
|
|
||||||
$versionedDirs = @{}
|
|
||||||
foreach ($entry in $tarListing) {
|
|
||||||
$normalizedEntry = $entry.Replace('\', '/')
|
|
||||||
$match = [regex]::Match($normalizedEntry, $versionRegex)
|
|
||||||
if ($match.Success) {
|
|
||||||
$versionedPrefix = $normalizedEntry.Substring(0, $match.Index + $match.Length)
|
|
||||||
if (-not $versionedDirs.ContainsKey($versionedPrefix)) {
|
|
||||||
$localDir = Join-Path -Path $OutPath -ChildPath $versionedPrefix
|
|
||||||
$versionedDirs[$versionedPrefix] = (Test-Path $localDir -PathType Container)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($dir in $versionedDirs.GetEnumerator()) {
|
|
||||||
if ($dir.Value) {
|
|
||||||
# This versioned directory already exists — exclude it from extraction
|
|
||||||
$pattern = $dir.Key + '*'
|
|
||||||
$excludeArgs += '--exclude'
|
|
||||||
$excludeArgs += $pattern
|
|
||||||
Say-Verbose "Excluding pre-existing versioned directory: $($dir.Key)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Handle non-versioned file override logic.
|
|
||||||
# If OverrideNonVersionedFiles is false, exclude non-versioned files that already exist.
|
|
||||||
if (-not $OverrideNonVersionedFiles) {
|
|
||||||
foreach ($entry in $tarListing) {
|
|
||||||
$normalizedEntry = $entry.Replace('\', '/')
|
|
||||||
# Skip directory entries (end with /)
|
|
||||||
if ($normalizedEntry.EndsWith('/')) { continue }
|
|
||||||
$match = [regex]::Match($normalizedEntry, $versionRegex)
|
|
||||||
if (-not $match.Success) {
|
|
||||||
# Non-versioned file — exclude if it already exists locally
|
|
||||||
$localPath = Join-Path -Path $OutPath -ChildPath $normalizedEntry
|
|
||||||
if (Test-Path $localPath) {
|
|
||||||
$excludeArgs += '--exclude'
|
|
||||||
$excludeArgs += $normalizedEntry
|
|
||||||
Say-Verbose "Excluding pre-existing non-versioned file: $normalizedEntry"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
# Extract directly to install root, preserving hard links
|
|
||||||
$tarOutput = & tar -xzf $TarPath -C $OutPath @excludeArgs 2>&1
|
|
||||||
if ($LASTEXITCODE -ne 0) {
|
|
||||||
$tarOutputText = ($tarOutput | Out-String).Trim()
|
|
||||||
if ([string]::IsNullOrWhiteSpace($tarOutputText)) {
|
|
||||||
throw "Tar extraction failed with exit code $LASTEXITCODE."
|
|
||||||
}
|
|
||||||
throw "Tar extraction failed with exit code $LASTEXITCODE. tar output: $tarOutputText"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Say-Error "Failed to extract tar package. Exception: $_"
|
|
||||||
throw
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function DownloadFile($Source, [string]$OutPath) {
|
function DownloadFile($Source, [string]$OutPath) {
|
||||||
if ($Source -notlike "http*") {
|
if ($Source -notlike "http*") {
|
||||||
# Using System.IO.Path.GetFullPath to get the current directory
|
# Using System.IO.Path.GetFullPath to get the current directory
|
||||||
@@ -1098,7 +991,7 @@ function PrintDryRunOutput($Invocation, $DownloadLinks) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Get-AkaMSDownloadLink([string]$Channel, [string]$Quality, [bool]$Internal, [string]$Product, [string]$Architecture, [string]$FileExtension = ".zip") {
|
function Get-AkaMSDownloadLink([string]$Channel, [string]$Quality, [bool]$Internal, [string]$Product, [string]$Architecture) {
|
||||||
Say-Invocation $MyInvocation
|
Say-Invocation $MyInvocation
|
||||||
|
|
||||||
#quality is not supported for LTS or STS channel
|
#quality is not supported for LTS or STS channel
|
||||||
@@ -1117,7 +1010,7 @@ function Get-AkaMSDownloadLink([string]$Channel, [string]$Quality, [bool]$Intern
|
|||||||
if (-not [string]::IsNullOrEmpty($Quality)) {
|
if (-not [string]::IsNullOrEmpty($Quality)) {
|
||||||
$akaMsLink += "/$Quality"
|
$akaMsLink += "/$Quality"
|
||||||
}
|
}
|
||||||
$akaMsLink += "/$Product-win-$Architecture$FileExtension"
|
$akaMsLink += "/$Product-win-$Architecture.zip"
|
||||||
Say-Verbose "Constructed aka.ms link: '$akaMsLink'."
|
Say-Verbose "Constructed aka.ms link: '$akaMsLink'."
|
||||||
$akaMsDownloadLink = $null
|
$akaMsDownloadLink = $null
|
||||||
|
|
||||||
@@ -1169,23 +1062,7 @@ function Get-AkaMSDownloadLink([string]$Channel, [string]$Quality, [bool]$Intern
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Get-AkaMsLink-And-Version([string] $NormalizedChannel, [string] $NormalizedQuality, [bool] $Internal, [string] $ProductName, [string] $Architecture) {
|
function Get-AkaMsLink-And-Version([string] $NormalizedChannel, [string] $NormalizedQuality, [bool] $Internal, [string] $ProductName, [string] $Architecture) {
|
||||||
|
$AkaMsDownloadLink = Get-AkaMSDownloadLink -Channel $NormalizedChannel -Quality $NormalizedQuality -Internal $Internal -Product $ProductName -Architecture $Architecture
|
||||||
# When tar is available, try .tar.gz first via aka.ms, then fall back to .zip.
|
|
||||||
# This handles symbolic channels (STS/LTS) and numeric channels where tar.gz
|
|
||||||
# may not yet be available (e.g. pre-11.0 versions).
|
|
||||||
$extensionsToTry = @(".zip")
|
|
||||||
if ($script:TarAvailable) {
|
|
||||||
$extensionsToTry = @(".tar.gz", ".zip")
|
|
||||||
}
|
|
||||||
|
|
||||||
$AkaMsDownloadLink = $null
|
|
||||||
foreach ($ext in $extensionsToTry) {
|
|
||||||
$AkaMsDownloadLink = Get-AkaMSDownloadLink -Channel $NormalizedChannel -Quality $NormalizedQuality -Internal $Internal -Product $ProductName -Architecture $Architecture -FileExtension $ext
|
|
||||||
if (-not [string]::IsNullOrEmpty($AkaMsDownloadLink)) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
Say-Verbose "aka.ms link resolution with '$ext' extension failed, trying next format."
|
|
||||||
}
|
|
||||||
|
|
||||||
if ([string]::IsNullOrEmpty($AkaMsDownloadLink)) {
|
if ([string]::IsNullOrEmpty($AkaMsDownloadLink)) {
|
||||||
if (-not [string]::IsNullOrEmpty($NormalizedQuality)) {
|
if (-not [string]::IsNullOrEmpty($NormalizedQuality)) {
|
||||||
@@ -1314,8 +1191,6 @@ Measure-Action "Product discovery" {
|
|||||||
$script:NormalizedProduct = Get-NormalizedProduct $Runtime
|
$script:NormalizedProduct = Get-NormalizedProduct $Runtime
|
||||||
Say-Verbose "Normalized product: '$NormalizedProduct'"
|
Say-Verbose "Normalized product: '$NormalizedProduct'"
|
||||||
$script:FeedCredential = ValidateFeedCredential $FeedCredential
|
$script:FeedCredential = ValidateFeedCredential $FeedCredential
|
||||||
$script:TarAvailable = Test-TarAvailable
|
|
||||||
Say-Verbose "Tar available: '$TarAvailable'"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$InstallRoot = Resolve-Installation-Path $InstallDir
|
$InstallRoot = Resolve-Installation-Path $InstallDir
|
||||||
@@ -1444,12 +1319,7 @@ if (-not $DownloadSucceeded) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Say "Extracting the archive."
|
Say "Extracting the archive."
|
||||||
if ($DownloadedLink.downloadLink.EndsWith(".tar.gz")) {
|
Measure-Action "Package extraction" { Extract-Dotnet-Package -ZipPath $ZipPath -OutPath $InstallRoot }
|
||||||
Measure-Action "Package extraction" { Extract-Dotnet-Package-Tar -TarPath $ZipPath -OutPath $InstallRoot }
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Measure-Action "Package extraction" { Extract-Dotnet-Package -ZipPath $ZipPath -OutPath $InstallRoot }
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check if the SDK version is installed; if not, fail the installation.
|
# Check if the SDK version is installed; if not, fail the installation.
|
||||||
$isAssetInstalled = $false
|
$isAssetInstalled = $false
|
||||||
@@ -1485,215 +1355,219 @@ Say "Installed version is $($DownloadedLink.effectiveVersion)"
|
|||||||
Say "Installation finished"
|
Say "Installation finished"
|
||||||
|
|
||||||
# SIG # Begin signature block
|
# SIG # Begin signature block
|
||||||
# MIIncQYJKoZIhvcNAQcCoIInYjCCJ14CAQExDzANBglghkgBZQMEAgEFADB5Bgor
|
# MIIoKgYJKoZIhvcNAQcCoIIoGzCCKBcCAQExDzANBglghkgBZQMEAgEFADB5Bgor
|
||||||
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
|
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
|
||||||
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDmNI7+9b4lSWsX
|
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCyKn7B6ieM6Y2C
|
||||||
# 2kYVvqQHpZeXB6Kt5BepNOcmIqEK1aCCDMkwggYEMIID7KADAgECAhMzAAACHPrN
|
# rr9TCFvTSv2mMIh9mBGXh4z2gOksEqCCDXYwggX0MIID3KADAgECAhMzAAAEhV6Z
|
||||||
# xZvoL37EAAAAAAIcMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNVBAYTAlVTMR4wHAYD
|
# 7A5ZL83XAAAAAASFMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
|
||||||
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBD
|
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
|
||||||
# b2RlIFNpZ25pbmcgUENBIDIwMjQwHhcNMjYwNDE2MTg1OTQxWhcNMjcwNDE1MTg1
|
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
|
||||||
# OTQxWjB0MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE
|
# bmcgUENBIDIwMTEwHhcNMjUwNjE5MTgyMTM3WhcNMjYwNjE3MTgyMTM3WjB0MQsw
|
||||||
# BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYD
|
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
|
||||||
# VQQDExVNaWNyb3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IB
|
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
|
||||||
# DwAwggEKAoIBAQDVsZfgOKmM31HPfoWOoNEiw0SlCiIxUMC0I9NMWbucKOw/e9lP
|
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
|
||||||
# oAoehQVu6SG65V4EPzrYsnBnFPNoi4/HoOdjhz1qkrEt4I6tEcxXU6oOeY9zGveC
|
# AQDASkh1cpvuUqfbqxele7LCSHEamVNBfFE4uY1FkGsAdUF/vnjpE1dnAD9vMOqy
|
||||||
# /3iBeuhLYxM3M/PkcUoebF+Nednm8OkdSPoDu8imViHPQq/8CQUu0WRR4rE+dMRf
|
# 5ZO49ILhP4jiP/P2Pn9ao+5TDtKmcQ+pZdzbG7t43yRXJC3nXvTGQroodPi9USQi
|
||||||
# rpVqfmNi2qWCX94T4MsepijGVkwE//tJg0ryAiYdHT34LSnlG/RSBZmQRGWZ5g8j
|
# 9rI+0gwuXRKBII7L+k3kMkKLmFrsWUjzgXVCLYa6ZH7BCALAcJWZTwWPoiT4HpqQ
|
||||||
# qnKjRParSqMft1gvjuUTVgtWNZfgcLFSK5Wa0myrq8OPcgTGGsRgun+tnSS+IxDT
|
# hJcYLB7pfetAVCeBEVZD8itKQ6QA5/LQR+9X6dlSj4Vxta4JnpxvgSrkjXCz+tlJ
|
||||||
# xVsAPH1OzvPjwomguByhUe/OcvUN0D5Wmp7xAgMBAAGjggGqMIIBpjAOBgNVHQ8B
|
# 67ABZ551lw23RWU1uyfgCfEFhBfiyPR2WSjskPl9ap6qrf8fNQ1sGYun2p4JdXxe
|
||||||
# Af8EBAMCB4AwHwYDVR0lBBgwFgYKKwYBBAGCN0wIAQYIKwYBBQUHAwMwHQYDVR0O
|
# UAKf1hVa/3TQXjvPTiRXCnJPAgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE
|
||||||
# BBYEFNoH7a2YDjOSwpkp6DHcmUS7J+0yMFQGA1UdEQRNMEukSTBHMS0wKwYDVQQL
|
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUuCZyGiCuLYE0aU7j5TFqY05kko0w
|
||||||
# EyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxFjAUBgNVBAUT
|
# RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW
|
||||||
# DTIzMDAxMis1MDc1NjkwHwYDVR0jBBgwFoAUf1k/VCHarU/vBeXmo9ctBpQSCDEw
|
# MBQGA1UEBRMNMjMwMDEyKzUwNTM1OTAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci
|
||||||
# YAYDVR0fBFkwVzBVoFOgUYZPaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9w
|
# tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j
|
||||||
# cy9jcmwvTWljcm9zb2Z0JTIwQ29kZSUyMFNpZ25pbmclMjBQQ0ElMjAyMDI0LmNy
|
# b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG
|
||||||
# bDBtBggrBgEFBQcBAQRhMF8wXQYIKwYBBQUHMAKGUWh0dHA6Ly93d3cubWljcm9z
|
# CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu
|
||||||
# b2Z0LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwQ29kZSUyMFNpZ25pbmcl
|
# Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0
|
||||||
# MjBQQ0ElMjAyMDI0LmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IC
|
# MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBACjmqAp2Ci4sTHZci+qk
|
||||||
# AQAUnEqhaRXe0T3hIJjvdQErEkrA/7bByjn6t5IArODkkRjzkYwtKMc2yYj2quaN
|
# tEAKsFk5HNVGKyWR2rFGXsd7cggZ04H5U4SV0fAL6fOE9dLvt4I7HBHLhpGdE5Uj
|
||||||
# rLutWw2YZcngKPy1b71YyDJQTy4NDRwaSh9Tw5thrk3NmcPrAHia5vtcBJ1CgtKK
|
# Ly4NxLTG2bDAkeAVmxmd2uKWVGKym1aarDxXfv3GCN4mRX+Pn4c+py3S/6Kkt5eS
|
||||||
# 7mQbIcQ22d/N3813ayCDDFewu1+jsZmX+r/aTEqaOM4TVxVtRSkuCy8nAXKuChOK
|
# DAIIsrzKw3Kh2SW1hCwXX/k1v4b+NH1Fjl+i/xPJspXCFuZB4aC5FLT5fgbRKqns
|
||||||
# Li/zA4XuH8iEYqIsj2YoNaeSxVmeGiERXpKdo3dDmYi0kO5w2D8VS4c3+9h6gElY
|
# WeAdn8DsrYQhT3QXLt6Nv3/dMzv7G/Cdpbdcoul8FYl+t3dmXM+SIClC3l2ae0wO
|
||||||
# BaAAg/dYErBg27qT3vv0zRDJhJufvCNylA8S7/+8H5E/PV5cng6na9VV/w9OV3qu
|
# lNrQ42yQEycuPU5OoqLT85jsZ7+4CaScfFINlO7l7Y7r/xauqHbSPQ1r3oIC+e71
|
||||||
# uND6zdGa2EX38Glp50F9AIQk3p2xXmcvorDeM4XJ7UlWYBi6g80J1SSOQnInCYFE
|
# 5s2G3ClZa3y99aYx2lnXYe1srcrIx8NAXTViiypXVn9ZGmEkfNcfDiqGQwkml5z9
|
||||||
# msfUNn3+1AaTJKSJL83quKArTac2pKhu0Yzzzrzo6HrsRiQKzpnRBb1/dMa6P3hz
|
# nm3pWiBZ69adaBBbAFEjyJG4y0a76bel/4sDCVvaZzLM3TFbxVO9BQrjZRtbJZbk
|
||||||
# 75XbMRBctNsFhZC07WCmjExdLg2eHW5uV0TY8D5+6wozJf7vF3+WHkYPO85Z+BC6
|
# C3XArpLqZSfx53SuYdddxPX8pvcqFuEu8wcUeD05t9xNbJ4TtdAECJlEi0vvBxlm
|
||||||
# U4FkNbYNycZ9cE4j1tXRdyDCfml6c0HWPHjNVDObrv9lKt3qUqFpX38VCqVCyNOO
|
# M5tzFXy2qZeqPMXHSQYqPgZ9jvScZ6NwznFD0+33kbzyhOSz/WuGbAu4cHZG8gKn
|
||||||
# 1UcXfQiVjJw32U2WUKZjt/neJKHEBsm9kFsLuWzkQ53+qcaSaytmsCnk2gOglrlD
|
# lQVT4uA2Diex9DMs2WHiokNknYlLoUeWXW1QrJLpqO82TLyKTbBM/oZHAdIc0kzo
|
||||||
# 5d3kKyvvAw+rzm0lT8K38P6PLxfZQHhu4W8dV7Av8N2ZmDCCBr0wggSloAMCAQIC
|
# STro9b3+vjn2809D0+SOOCVZMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq
|
||||||
# EzMAAAA5O7Y3Gb8GHWcAAAAAADkwDQYJKoZIhvcNAQEMBQAwgYgxCzAJBgNVBAYT
|
# hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x
|
||||||
# AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD
|
# EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv
|
||||||
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBS
|
# bjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5
|
||||||
# b290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDExMB4XDTI0MDgwODIwNTQxOFoX
|
# IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEwOTA5WjB+MQswCQYDVQQG
|
||||||
# DTM2MDMyMjIyMTMwNFowVzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29m
|
# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG
|
||||||
# dCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9zb2Z0IENvZGUgU2lnbmluZyBQ
|
# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQg
|
||||||
# Q0EgMjAyNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANgBnB7jOMeq
|
# Q29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
|
||||||
# lRYHNa265v4IY9fH8TKhemHfPINe1gpLaV3dhg324WwH06LcHbpnsBukCDNitryo
|
# CgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+laUKq4BjgaBEm6f8MMHt03
|
||||||
# 0dtS/EW6I/yEL/bLSY8hKpbfQuWusBPr9qazYcDxCW/qnjb5JsI1s8bNOg3bVATv
|
# a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc6Whe0t+bU7IKLMOv2akr
|
||||||
# QVL4tcf03aTycsz8QeCdM0l/yHRObJ9QqazM1r6VPEOJ7LL+uEEb73w6QCuhs89a
|
# rnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4Ddato88tt8zpcoRb0Rrrg
|
||||||
# 1uv1zerOYMnsneRRwCbpyW11IcggU0cRKDDq1pjVJzIbIF6+oiXXbReOsgeI8zu1
|
# OGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+lD3v++MrWhAfTVYoonpy
|
||||||
# FyQfK0fVkaya8SmVHQ/tOf23mZ4W9k0Ri22QW9p3UgSC5OUDktKxxcCmGL6tXLfO
|
# 4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nkkDstrjNYxbc+/jLTswM9
|
||||||
# GSWHIIV4YrTJTT6PNty5REojHJuZHArkF9VnHTERWoTjAzfI3kP+5b4alUdhgAZ7
|
# sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6A4aN91/w0FK/jJSHvMAh
|
||||||
# ttOu1bVnXfHaqPYl2rPs20ji03LOVWsh/radgE17es5hL+t6lV0eVHrVhsssROWJ
|
# dCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmdX4jiJV3TIUs+UsS1Vz8k
|
||||||
# uz2MXMCt7iw7lFPG9LXKGjsmonn2gotGdHIuEg5JnJMJVmixd5LRlkmgYRZKzhxS
|
# A/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL5zmhD+kjSbwYuER8ReTB
|
||||||
# CwyoGIq0PhaA7Y+VPct5pCHkijcIIDm0nlkK+0KyepolcqGm0T/GYQRMhHJlGOOm
|
# w3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zdsGbiwZeBe+3W7UvnSSmn
|
||||||
# VQop36wUVUYklUy++vDWeEgEo4s7hxN6mIbf2MSIQ/iIfMZgJxC69oukMUXCrOC3
|
# Eyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3T8HhhUSJxAlMxdSlQy90
|
||||||
# SkE/xIkgpfl22MM1itkZ35nNXkMolU1lAgMBAAGjggFOMIIBSjAOBgNVHQ8BAf8E
|
# lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS4NaIjAsCAwEAAaOCAe0w
|
||||||
# BAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFH9ZP1Qh2q1P7wXl5qPX
|
# ggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRIbmTlUAXTgqoXNzcitW2o
|
||||||
# LQaUEggxMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMA8GA1UdEwEB/wQFMAMB
|
# ynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYD
|
||||||
# Af8wHwYDVR0jBBgwFoAUci06AjGQQ7kUBU7h6qfHMdEjiTQwWgYDVR0fBFMwUTBP
|
# VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBDuRQFTuHqp8cx0SOJNDBa
|
||||||
# oE2gS4ZJaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMv
|
# BgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny
|
||||||
# TWljUm9vQ2VyQXV0MjAxMV8yMDExXzAzXzIyLmNybDBeBggrBgEFBQcBAQRSMFAw
|
# bC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3JsMF4GCCsG
|
||||||
# TgYIKwYBBQUHMAKGQmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMv
|
# AQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3dy5taWNyb3NvZnQuY29t
|
||||||
# TWljUm9vQ2VyQXV0MjAxMV8yMDExXzAzXzIyLmNydDANBgkqhkiG9w0BAQwFAAOC
|
# L3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3J0MIGfBgNV
|
||||||
# AgEAFJQfOChP7onn6fLIMKrSlN1WYKwDFgAddymOUO3FrM8d7B/W/iQ6DxXsDn7D
|
# HSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEFBQcCARYzaHR0cDovL3d3
|
||||||
# 5W4wMwYeLystcEqfkjz4NURRgazyMu5yRzQh4LqjA4tStTcJh1opExo7nn5PuPBY
|
# dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1hcnljcHMuaHRtMEAGCCsG
|
||||||
# nbu0+THSuVHTe0VTTPVhily/piFrDo3axQ9P4C+Ol5yet+2gTfekICS5xS+cYfSI
|
# AQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkAYwB5AF8AcwB0AGEAdABl
|
||||||
# vgn0JksVBVMYVI5QFu/qhnLhsEFEUzG8fvv0hjgkO+lkpV9ty6GkN4vdnd7ya6Q6
|
# AG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn8oalmOBUeRou09h0ZyKb
|
||||||
# aR9y34aiM1qmxaxBi6OUnyNl6fkuun/diTFnYDLTppOkr/mg5WSfCiDVMNCxtj4w
|
# C5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7v0epo/Np22O/IjWll11l
|
||||||
# PKC5OmHm1DQIt/MNokbbH3UGsFP1QbzsLocuSqLCvH09Io3fDPTmscR9Y75G4qX7
|
# hJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0bpdS1HXeUOeLpZMlEPXh6
|
||||||
# RTX8AdBPo0I6OEojf39zuFZt0qOHm65YWQE69cZM2ueE1MB05dNNgHK9gTE7zKvK
|
# I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/KmtYSWMfCWluWpiW5IP0
|
||||||
# /fg8B2qjW88MT/WF5V5uvZGtqa9FSL2RazArA+rDPuf6JGYz4HpgMZHB4S6szWSK
|
# wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvyCInWH8MyGOLwxS3OW560
|
||||||
# YBv0VisCzfxgeU+dquXW9bd0auYlOB58DPcOYKdc3Se94g+xL4pcEhbB54JOgAkw
|
# STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBpmLJZiWhub6e3dMNABQam
|
||||||
# YTu/9dLeH2pDqeJZAABVDWRQCaXfO5LgyKwKCLYXpigrZYCjUSBcr+Ve8PFWMhVT
|
# ASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJihsMdYzaXht/a8/jyFqGa
|
||||||
# Ql0v4q8J/AUmQN5W4n101cY2L4A7GTQG1h32HHAvfQESWP0xghn+MIIZ+gIBATBu
|
# J+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYbBL7fQccOKO7eZS/sl/ah
|
||||||
# MFcxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x
|
# XJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbSoqKfenoi+kiVH6v7RyOA
|
||||||
# KDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMjQCEzMAAAIc
|
# 9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sLgOppO6/8MO0ETI7f33Vt
|
||||||
# +s3Fm+gvfsQAAAAAAhwwDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwG
|
# Y5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtXcVZOSEXAQsmbdlsKgEhr
|
||||||
# CisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZI
|
# /Xmfwb1tbWrJUnMTDXpQzTGCGgowghoGAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw
|
||||||
# hvcNAQkEMSIEIB5Na9P++kVnSeIy27N4IyRD4N0sjfWHRS1ht0NHdoK/MEIGCisG
|
|
||||||
# AQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3
|
|
||||||
# Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEBBQAEggEAx05EI+Kk4hoAKG/8oVdr
|
|
||||||
# UIq/+sv+E0vpSyWQMTq/yrkfnPWqT2TxNVtcG3ZcQT5/36cjMe1umi1zzy178VRP
|
|
||||||
# HKH2jxMOzMqtJPsAI/yAd46EOyTBwayS+27NOvz2r3v8WV0YjuplJb1teHmJtoIf
|
|
||||||
# UVC1va6H668UMrR2Mm5l8GvtcrGmDLjq3FLTLeidco7aj7xtkwUhyXvCS/HzoF9G
|
|
||||||
# yrYW3NKqIy+KbNXTD8RbwDxKvx3ED9C1SfZi3fi/t1a2wjNsxVqf4XNsO2+JvuuO
|
|
||||||
# SGTZOoo/3jqtS22IcV5Z3In0D3+C/rigq0179KhwPtztz4+J9MU5gtGmVayF1MH1
|
|
||||||
# M6GCF7AwghesBgorBgEEAYI3AwMBMYIXnDCCF5gGCSqGSIb3DQEHAqCCF4kwgheF
|
|
||||||
# AgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFaBgsqhkiG9w0BCRABBKCCAUkEggFFMIIB
|
|
||||||
# QQIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFlAwQCAQUABCDhOUY7jtQW2mTHjZaf
|
|
||||||
# zhylI7IWKlybklUpfwDq0GnW8AIGaeuhCndSGBMyMDI2MDUxNzAwNDk0OC4wNzFa
|
|
||||||
# MASAAgH0oIHZpIHWMIHTMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
|
|
||||||
# bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
|
|
||||||
# aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0
|
|
||||||
# ZWQxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjoyQTFBLTA1RTAtRDk0NzElMCMG
|
|
||||||
# A1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaCCEf4wggcoMIIFEKAD
|
|
||||||
# AgECAhMzAAACEKvN5BYY7zmwAAEAAAIQMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNV
|
|
||||||
# BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4w
|
|
||||||
# HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29m
|
|
||||||
# dCBUaW1lLVN0YW1wIFBDQSAyMDEwMB4XDTI1MDgxNDE4NDgxMloXDTI2MTExMzE4
|
|
||||||
# NDgxMlowgdMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYD
|
|
||||||
# VQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTAr
|
|
||||||
# BgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEnMCUG
|
|
||||||
# A1UECxMeblNoaWVsZCBUU1MgRVNOOjJBMUEtMDVFMC1EOTQ3MSUwIwYDVQQDExxN
|
|
||||||
# aWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNlMIICIjANBgkqhkiG9w0BAQEFAAOC
|
|
||||||
# Ag8AMIICCgKCAgEAjcc4q057ZwIgpKu4pTXWLejvYEduRf+1mIpbiJEMFWWmU2xp
|
|
||||||
# ip+zK7xFxKGB1CclUXBU0/ZQZ6LG8H0gI7yvosrsPEI1DPB/XccGCvswKbAKckng
|
|
||||||
# OuGTEPGk7K/vEZa9h0Xt02b7m2n9MdIjkLrFl0pDriKyz0QHGpdh93X6+NApfE1T
|
|
||||||
# L24Vo0xkeoFGpL3rX9gXhIOF59EMnTd2o45FW/oxMgY9q0y0jGO0HrCLTCZr50e7
|
|
||||||
# TZRSNYAy2lyKbvKI2MKlN1wLzJvZbbc//L3s1q3J6KhS0KC2VNEImYdFgVkJej4z
|
|
||||||
# ZqHfScTbx9hjFgFpVkJl4xH5VJ8tyJdXE9+vU0k9AaT2QP1Zm3WQmXedSoLjjI7L
|
|
||||||
# WznuHwnoGIXLiJMQzPqKqRIFL3wzcrDrZeWgtAdBPbipglZ5CQns6Baj5Mb6a/EZ
|
|
||||||
# C9G3faJYK5QVHeE6eLoSEwp1dz5WurLXNPsp0VWplpl/FJb8jrRT/jOoHu85qRcd
|
|
||||||
# YpgByU9W7IWPdrthmyfqeAw0omVWN5JxcogYbLo2pANJHlsMdWnxIpN5YwHbGEPC
|
|
||||||
# uosBHPk2Xd9+E/pZPQUR6v+D85eEN5A/ZM/xiPpxa8dJZ87BpTvui7/2uflUMJf2
|
|
||||||
# Yc9ZLPgEdhQQo0LwMDSTDT48y3sV7Pdo+g5q+MqnJztN/6qt1cgUTe9u+ykCAwEA
|
|
||||||
# AaOCAUkwggFFMB0GA1UdDgQWBBSe42+FrpdF2avbUhlk86BLSH5kejAfBgNVHSME
|
|
||||||
# GDAWgBSfpxVdAF5iXYP05dJlpxtTNRnpcjBfBgNVHR8EWDBWMFSgUqBQhk5odHRw
|
|
||||||
# Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBUaW1l
|
|
||||||
# LVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcmwwbAYIKwYBBQUHAQEEYDBeMFwGCCsG
|
|
||||||
# AQUFBzAChlBodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01p
|
|
||||||
# Y3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNydDAMBgNVHRMB
|
|
||||||
# Af8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMA4GA1UdDwEB/wQEAwIHgDAN
|
|
||||||
# BgkqhkiG9w0BAQsFAAOCAgEAvs4rO3oo8czOrxPqnnSEkUVq718QzlrIiy7/EW7J
|
|
||||||
# mQXsJoFxHWUF0Ux0PDyKFDRXPJVv29F7kpJkBJJmcQg5HQV7blUXIMWQ1qX0KdtF
|
|
||||||
# QXI/MRL77Z+pK5x1jX+tbRkA7a5Ft7vWuRoAEi02HpFH5m/Akh/dfsbx8wOpecJb
|
|
||||||
# YvuHuy4aG0/tGzOWFCxMMNhGAIJ4qdV87JnY/uMBmiodlm+Gz357XWW5tg3HrtNZ
|
|
||||||
# XuQ0tWUv26ud4nGKJo/oLZHP75p4Rpt7dMdYKUF9AuVFBwxYZYpvgk12tfK+/yOw
|
|
||||||
# q84/fjXVCdM83Qnawtbenbk/lnbc9KsZom+GnvA4itAMUpSXFWrcRkqdUQLN+JrG
|
|
||||||
# 6fPBoV8+D8U2Q2F4XkiCR6EU9JzYKwTuvL6t3nFuxnkLdNjbTg2/yv2j3WaDuCK5
|
|
||||||
# lSPgsndIiH6Bku2Ui3A0aUo6D9z9v+XEuBs9ioVJaOjf/z+Urqg7ESnxG0/T1dKc
|
|
||||||
# i7vLQ2XNgWFYO+/OlDjtGoma1ijX4m14N9qgrXTuWEGwgC7hhBgp3id/LAOf9BST
|
|
||||||
# WA5lBrilsEoexXBrOn/1wM3rjG0hIsxvF5/YOK78mVRGY6Y7zYJ+uXt4OTOFBwad
|
|
||||||
# Pv8MklreQZLPnQPtiwop4rlLUYaPCiD4YUqRNbLp8Sgyo9g0iAcZYznTuc+8Q8ZI
|
|
||||||
# rgwwggdxMIIFWaADAgECAhMzAAAAFcXna54Cm0mZAAAAAAAVMA0GCSqGSIb3DQEB
|
|
||||||
# CwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE
|
|
||||||
# BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYD
|
|
||||||
# VQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAxMDAe
|
|
||||||
# Fw0yMTA5MzAxODIyMjVaFw0zMDA5MzAxODMyMjVaMHwxCzAJBgNVBAYTAlVTMRMw
|
|
||||||
# EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN
|
# EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN
|
||||||
# aWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0
|
# aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp
|
||||||
# YW1wIFBDQSAyMDEwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5OGm
|
# Z25pbmcgUENBIDIwMTECEzMAAASFXpnsDlkvzdcAAAAABIUwDQYJYIZIAWUDBAIB
|
||||||
# TOe0ciELeaLL1yR5vQ7VgtP97pwHB9KpbE51yMo1V/YBf2xK4OK9uT4XYDP/XE/H
|
# BQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO
|
||||||
# ZveVU3Fa4n5KWv64NmeFRiMMtY0Tz3cywBAY6GB9alKDRLemjkZrBxTzxXb1hlDc
|
# MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEID8/Z0hz8wCpH2YjVYR3wACO
|
||||||
# wUTIcVxRMTegCjhuje3XD9gmU3w5YQJ6xKr9cmmvHaus9ja+NSZk2pg7uhp7M62A
|
# qi7toMi0S892RCpCiXnDMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8A
|
||||||
# W36MEBydUv626GIl3GoPz130/o5Tz9bshVZN7928jaTjkY+yOSxRnOlwaQ3KNi1w
|
# cwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEB
|
||||||
# jjHINSi947SHJMPgyY9+tVSP3PoFVZhtaDuaRr3tpK56KTesy+uDRedGbsoy1cCG
|
# BQAEggEAR3ofVJe8H1PSnVv5GEV/iNRKzDHBYXTNKjw6gaEwywGiLnvok4fIy+o/
|
||||||
# MFxPLOJiss254o2I5JasAUq7vnGpF1tnYN74kpEeHT39IM9zfUGaRnXNxF803RKJ
|
# pgoyuM4RLT6jq9o/62LWZPnRCXiQiidnt9u6BtjAQFoy9Hyz39SnG3SIfcXwQU6S
|
||||||
# 1v2lIH1+/NmeRd+2ci/bfV+AutuqfjbsNkz2K26oElHovwUDo9Fzpk03dJQcNIIP
|
# Kn6sdIdkCnp9zgCw0A1um1l9ZESP36cub7lCkog6Qd1N+d5KAMuDMHX4MybWYjva
|
||||||
# 8BDyt0cY7afomXw/TNuvXsLz1dhzPUNOwTM5TI4CvEJoLhDqhFFG4tG9ahhaYQFz
|
# YmW+c3RMH4HoBd6igF/hUaz0VTf+yrdIUaBIJ9UlWTMVkwokmQ9I79IwPU5hHnRu
|
||||||
# ymeiXtcodgLiMxhy16cg8ML6EgrXY28MyTZki1ugpoMhXV8wdJGUlNi5UPkLiWHz
|
# Ao8D6p++BagDKmVHo4bY/ADy4GDn4nrLA09mwd0YQPDZvb3K3Z2rIABM0UdS4+lG
|
||||||
# NgY1GIRH29wb0f2y1BzFa/ZcUlFdEtsluq9QBXpsxREdcu+N+VLEhReTwDwV2xo3
|
# c/pZsaRUT7TE8NzWXP+vWQ9bdkhNbaGCF5QwgheQBgorBgEEAYI3AwMBMYIXgDCC
|
||||||
# xwgVGD94q0W29R6HXtqPnhZyacaue7e3PmriLq0CAwEAAaOCAd0wggHZMBIGCSsG
|
# F3wGCSqGSIb3DQEHAqCCF20wghdpAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFSBgsq
|
||||||
# AQQBgjcVAQQFAgMBAAEwIwYJKwYBBAGCNxUCBBYEFCqnUv5kxJq+gpE8RjUpzxD/
|
# hkiG9w0BCRABBKCCAUEEggE9MIIBOQIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFl
|
||||||
# LwTuMB0GA1UdDgQWBBSfpxVdAF5iXYP05dJlpxtTNRnpcjBcBgNVHSAEVTBTMFEG
|
# AwQCAQUABCAd+KomD6n/vMp0PpchU0Vc9uK1oIZ/s0smWP9W6KAY4QIGaSc7gduW
|
||||||
# DCsGAQQBgjdMg30BATBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29m
|
# GBMyMDI1MTIxMDIyNDQ0NC41NjdaMASAAgH0oIHRpIHOMIHLMQswCQYDVQQGEwJV
|
||||||
# dC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0wEwYDVR0lBAwwCgYIKwYB
|
# UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE
|
||||||
# BQUHAwgwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGGMA8G
|
# ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1l
|
||||||
# A1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU1fZWy4/oolxiaNE9lJBb186aGMQw
|
# cmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046REMwMC0w
|
||||||
# VgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9j
|
# NUUwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2Wg
|
||||||
# cmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3JsMFoGCCsGAQUF
|
# ghHqMIIHIDCCBQigAwIBAgITMwAAAgO7HlwAOGx0ygABAAACAzANBgkqhkiG9w0B
|
||||||
# BwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3Br
|
# AQsFADB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE
|
||||||
# aS9jZXJ0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcnQwDQYJKoZIhvcNAQEL
|
# BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYD
|
||||||
# BQADggIBAJ1VffwqreEsH2cBMSRb4Z5yS/ypb+pcFLY+TkdkeLEGk5c9MTO1OdfC
|
# VQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDAeFw0yNTAxMzAxOTQy
|
||||||
# cTY/2mRsfNB1OW27DzHkwo/7bNGhlBgi7ulmZzpTTd2YurYeeNg2LpypglYAA7AF
|
# NDZaFw0yNjA0MjIxOTQyNDZaMIHLMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz
|
||||||
# vonoaeC6Ce5732pvvinLbtg/SHUB2RjebYIM9W0jVOR4U3UkV7ndn/OOPcbzaN9l
|
# aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv
|
||||||
# 9qRWqveVtihVJ9AkvUCgvxm2EhIRXT0n4ECWOKz3+SmJw7wXsFSFQrP8DJ6LGYnn
|
# cnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25z
|
||||||
# 8AtqgcKBGUIZUnWKNsIdw2FzLixre24/LAl4FOmRsqlb30mjdAy87JGA0j3mSj5m
|
# MScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046REMwMC0wNUUwLUQ5NDcxJTAjBgNV
|
||||||
# O0+7hvoyGtmW9I/2kQH2zsZ0/fZMcm8Qq3UwxTSwethQ/gpY3UA8x1RtnWN0SCyx
|
# BAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggIiMA0GCSqGSIb3DQEB
|
||||||
# TkctwRQEcb9k+SS+c23Kjgm9swFXSVRk2XPXfx5bRAGOWhmRaw2fpCjcZxkoJLo4
|
# AQUAA4ICDwAwggIKAoICAQChl0MH5wAnOx8Uh8RtidF0J0yaFDHJYHTpPvRR16X1
|
||||||
# S5pu+yFUa2pFEUep8beuyOiJXk+d0tBMdrVXVAmxaQFEfnyhYWxz/gq77EFmPWn9
|
# KxGDYfT8PrcGjCLCiaOu3K1DmUIU4Rc5olndjappNuOgzwUoj43VbbJx5PFTY/a1
|
||||||
# y8FBSX5+k77L+DvktxW/tM4+pTFRhLy/AsGConsXHRWJjXD+57XQKBqJC4822rpM
|
# Z80tpqVP0OoKJlUkfDPSBLFgXWj6VgayRCINtLsUasy0w5gysD7ILPZuiQjace5K
|
||||||
# +Zv/Cuk0+CQ1ZyvgDbjmjJnW4SLq8CdCPSWU5nR0W2rRnj7tfqAxM328y+l7vzhw
|
# xASjKf2MVX1qfEzYBbTGNEijSQCKwwyc0eavr4Fo3X/+sCuuAtkTWissU64k8rK6
|
||||||
# RNGQ8cirOoo6CGJ/2XBjU02N7oJtpQUQwXEGahC0HVUzWLOhcGbyoYIDWTCCAkEC
|
# 0jsGRApiESdfuHr0yWAmc7jTOPNeGAx6KCL2ktpnGegLDd1IlE6Bu6BSwAIFHr7z
|
||||||
# AQEwggEBoYHZpIHWMIHTMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
|
# OwIlFqyQuCe0SQALCbJhsT9y9iy61RJAXsU0u0TC5YYmTSbEI7g10dYx8Uj+vh9I
|
||||||
# bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
|
# nLoKYC5DpKb311bYVd0bytbzlfTRslRTJgotnfCAIGMLqEqk9/2VRGu9klJi1j9n
|
||||||
# aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0
|
# VfqyYHYrMPOBXcrQYW0jmKNjOL47CaEArNzhDBia1wXdJANKqMvJ8pQe2m8/ciby
|
||||||
# ZWQxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjoyQTFBLTA1RTAtRDk0NzElMCMG
|
# DM+1BVZquNAov9N4tJF4ACtjX0jjXNDUMtSZoVFQH+FkWdfPWx1uBIkc97R+xRLu
|
||||||
# A1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsOAwIa
|
# PjUypHZ5A3AALSke4TaRBvbvTBYyW2HenOT7nYLKTO4jw5Qq6cw3Z9zTKSPQ6D5l
|
||||||
# AxUAOsyf2b6riPKnnXlIgIL2f53PUsKggYMwgYCkfjB8MQswCQYDVQQGEwJVUzET
|
# yiYpes5RR2MdMvJS4fCcPJFeaVOvuWFSQ/EGtVBShhmLB+5ewzFzdpf1UuJmuOQT
|
||||||
# MBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMV
|
# TwIDAQABo4IBSTCCAUUwHQYDVR0OBBYEFLIpWUB+EeeQ29sWe0VdzxWQGJJ9MB8G
|
||||||
# TWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1T
|
# A1UdIwQYMBaAFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMF8GA1UdHwRYMFYwVKBSoFCG
|
||||||
# dGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQsFAAIFAO2zHvgwIhgPMjAyNjA1MTYx
|
# Tmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUy
|
||||||
# NjUxMDRaGA8yMDI2MDUxNzE2NTEwNFowdzA9BgorBgEEAYRZCgQBMS8wLTAKAgUA
|
# MFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNybDBsBggrBgEFBQcBAQRgMF4w
|
||||||
# 7bMe+AIBADAKAgEAAgIhcwIB/zAHAgEAAgISqjAKAgUA7bRweAIBADA2BgorBgEE
|
# XAYIKwYBBQUHMAKGUGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2Vy
|
||||||
# AYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYag
|
# dHMvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3J0MAwG
|
||||||
# MA0GCSqGSIb3DQEBCwUAA4IBAQBjb6eELCy7c+QKNzPmI4O0riW248wi0uSI0DKx
|
# A1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwDgYDVR0PAQH/BAQD
|
||||||
# /ZRwZgOShcyQUcjn6Q/SGMTQ9cqeJe/IhyZbzUCTATtImhIybXreibtT2cAMO4M6
|
# AgeAMA0GCSqGSIb3DQEBCwUAA4ICAQCQEMbesD6TC08R0oYCdSC452AQrGf/O89G
|
||||||
# 3gGHvd96iu8Q49zOYR182At7wmlUTeMrsj51LpZkWCUy4ZSeOSri83Aong5MKGMF
|
# Q54CtgEsbxzwGDVUcmjXFcnaJSTNedBKVXkBgawRonP1LgxH4bzzVj2eWNmzGIwO
|
||||||
# Kt2xnKiSYL2tXIm0zcTpX8xjXMMWFb7wa0CBnHn5ZMYJVtuntxE1B4wJyMZktBS6
|
# 1FlhldAPOHAzLBEHRoSZ4pddFtaQxoabU/N1vWyICiN60It85gnF5JD4MMXyd6pS
|
||||||
# WkP9XpGCXB1X7VhYM3vvtBFq2vA5neloI7waPPPTU+0hK6IX7+c1U776yDnJW4jc
|
# 8eADIi6TtjfgKPoumWa0BFQ/aEzjUrfPN1r7crK+qkmLztw/ENS7zemfyx4kGRgw
|
||||||
# OUJsj8rjwrS+Gc/gPt98V3kMoGvxG0eGEzdjkmblUlhT1FwpMYIEDTCCBAkCAQEw
|
# Y1WBfFqm/nFlJDPQBicqeU3dOp9hj7WqD0Rc+/4VZ6wQjesIyCkv5uhUNy2LhNDi
|
||||||
# gZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT
|
# 2leYtAiIFpmjfNk4GngLvC2Tj9IrOMv20Srym5J/Fh7yWAiPeGs3yA3QapjZTtfr
|
||||||
# B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UE
|
# 7NfzpBIJQ4xT/ic4WGWqhGlRlVBI5u6Ojw3ZxSZCLg3vRC4KYypkh8FdIWoKirji
|
||||||
# AxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAIQq83kFhjvObAA
|
# dEGlXsNOo+UP/YG5KhebiudTBxGecfJCuuUspIdRhStHAQsjv/dAqWBLlhorq2OC
|
||||||
# AQAAAhAwDQYJYIZIAWUDBAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0B
|
# aP+wFhE3WPgnnx5pflvlujocPgsN24++ddHrl3O1FFabW8m0UkDHSKCh8QTwTkYO
|
||||||
# CRABBDAvBgkqhkiG9w0BCQQxIgQgn7/AUpcQFhG3OcHi0Aeq56NC1uclpcmcCkGu
|
# wu99iExBVWlbYZRz2qOIBjL/ozEhtCB0auKhfTLLeuNGBUaBz+oZZ+X9UAECoMhk
|
||||||
# +HK5un4wgfoGCyqGSIb3DQEJEAIvMYHqMIHnMIHkMIG9BCDD1SHufsjzY59S1iHU
|
# ETjb6YfNaI1T7vVAaiuhBoV/JCOQT+RYZrgykyPpzpmwMNFBD1vdW/29q9nkTWoE
|
||||||
# QY9hnsKSrJPg5a9Mc4YnGmPHxjCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYD
|
# hcEOO0L9NzCCB3EwggVZoAMCAQICEzMAAAAVxedrngKbSZkAAAAAABUwDQYJKoZI
|
||||||
|
# hvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw
|
||||||
|
# DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x
|
||||||
|
# MjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAy
|
||||||
|
# MDEwMB4XDTIxMDkzMDE4MjIyNVoXDTMwMDkzMDE4MzIyNVowfDELMAkGA1UEBhMC
|
||||||
|
# VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV
|
||||||
|
# BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp
|
||||||
|
# bWUtU3RhbXAgUENBIDIwMTAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
|
||||||
|
# AQDk4aZM57RyIQt5osvXJHm9DtWC0/3unAcH0qlsTnXIyjVX9gF/bErg4r25Phdg
|
||||||
|
# M/9cT8dm95VTcVrifkpa/rg2Z4VGIwy1jRPPdzLAEBjoYH1qUoNEt6aORmsHFPPF
|
||||||
|
# dvWGUNzBRMhxXFExN6AKOG6N7dcP2CZTfDlhAnrEqv1yaa8dq6z2Nr41JmTamDu6
|
||||||
|
# GnszrYBbfowQHJ1S/rboYiXcag/PXfT+jlPP1uyFVk3v3byNpOORj7I5LFGc6XBp
|
||||||
|
# Dco2LXCOMcg1KL3jtIckw+DJj361VI/c+gVVmG1oO5pGve2krnopN6zL64NF50Zu
|
||||||
|
# yjLVwIYwXE8s4mKyzbnijYjklqwBSru+cakXW2dg3viSkR4dPf0gz3N9QZpGdc3E
|
||||||
|
# XzTdEonW/aUgfX782Z5F37ZyL9t9X4C626p+Nuw2TPYrbqgSUei/BQOj0XOmTTd0
|
||||||
|
# lBw0gg/wEPK3Rxjtp+iZfD9M269ewvPV2HM9Q07BMzlMjgK8QmguEOqEUUbi0b1q
|
||||||
|
# GFphAXPKZ6Je1yh2AuIzGHLXpyDwwvoSCtdjbwzJNmSLW6CmgyFdXzB0kZSU2LlQ
|
||||||
|
# +QuJYfM2BjUYhEfb3BvR/bLUHMVr9lxSUV0S2yW6r1AFemzFER1y7435UsSFF5PA
|
||||||
|
# PBXbGjfHCBUYP3irRbb1Hode2o+eFnJpxq57t7c+auIurQIDAQABo4IB3TCCAdkw
|
||||||
|
# EgYJKwYBBAGCNxUBBAUCAwEAATAjBgkrBgEEAYI3FQIEFgQUKqdS/mTEmr6CkTxG
|
||||||
|
# NSnPEP8vBO4wHQYDVR0OBBYEFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMFwGA1UdIARV
|
||||||
|
# MFMwUQYMKwYBBAGCN0yDfQEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWlj
|
||||||
|
# cm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0bTATBgNVHSUEDDAK
|
||||||
|
# BggrBgEFBQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMC
|
||||||
|
# AYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvX
|
||||||
|
# zpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20v
|
||||||
|
# cGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYI
|
||||||
|
# KwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5j
|
||||||
|
# b20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDANBgkqhkiG
|
||||||
|
# 9w0BAQsFAAOCAgEAnVV9/Cqt4SwfZwExJFvhnnJL/Klv6lwUtj5OR2R4sQaTlz0x
|
||||||
|
# M7U518JxNj/aZGx80HU5bbsPMeTCj/ts0aGUGCLu6WZnOlNN3Zi6th542DYunKmC
|
||||||
|
# VgADsAW+iehp4LoJ7nvfam++Kctu2D9IdQHZGN5tggz1bSNU5HhTdSRXud2f8449
|
||||||
|
# xvNo32X2pFaq95W2KFUn0CS9QKC/GbYSEhFdPSfgQJY4rPf5KYnDvBewVIVCs/wM
|
||||||
|
# nosZiefwC2qBwoEZQhlSdYo2wh3DYXMuLGt7bj8sCXgU6ZGyqVvfSaN0DLzskYDS
|
||||||
|
# PeZKPmY7T7uG+jIa2Zb0j/aRAfbOxnT99kxybxCrdTDFNLB62FD+CljdQDzHVG2d
|
||||||
|
# Y3RILLFORy3BFARxv2T5JL5zbcqOCb2zAVdJVGTZc9d/HltEAY5aGZFrDZ+kKNxn
|
||||||
|
# GSgkujhLmm77IVRrakURR6nxt67I6IleT53S0Ex2tVdUCbFpAUR+fKFhbHP+Crvs
|
||||||
|
# QWY9af3LwUFJfn6Tvsv4O+S3Fb+0zj6lMVGEvL8CwYKiexcdFYmNcP7ntdAoGokL
|
||||||
|
# jzbaukz5m/8K6TT4JDVnK+ANuOaMmdbhIurwJ0I9JZTmdHRbatGePu1+oDEzfbzL
|
||||||
|
# 6Xu/OHBE0ZDxyKs6ijoIYn/ZcGNTTY3ugm2lBRDBcQZqELQdVTNYs6FwZvKhggNN
|
||||||
|
# MIICNQIBATCB+aGB0aSBzjCByzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp
|
||||||
|
# bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw
|
||||||
|
# b3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEn
|
||||||
|
# MCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOkRDMDAtMDVFMC1EOTQ3MSUwIwYDVQQD
|
||||||
|
# ExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloiMKAQEwBwYFKw4DAhoDFQDN
|
||||||
|
# rxRX/iz6ss1lBCXG8P1LFxD0e6CBgzCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYD
|
||||||
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
|
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
|
||||||
# b3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1w
|
# b3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1w
|
||||||
# IFBDQSAyMDEwAhMzAAACEKvN5BYY7zmwAAEAAAIQMCIEIC5b102d224evVIH68x9
|
# IFBDQSAyMDEwMA0GCSqGSIb3DQEBCwUAAgUA7OQtPTAiGA8yMDI1MTIxMDE3MzI0
|
||||||
# lEf8Au5vChR0bDNP4SViDwl6MA0GCSqGSIb3DQEBCwUABIICAHMgBiQOozDAIR+S
|
# NVoYDzIwMjUxMjExMTczMjQ1WjB0MDoGCisGAQQBhFkKBAExLDAqMAoCBQDs5C09
|
||||||
# O28IjquhCukrxIucbxjLUxu4ltpxavA+cedbwkdNPAMFAYEaLHeEYutciK6N5f4R
|
# AgEAMAcCAQACAgjlMAcCAQACAhNOMAoCBQDs5X69AgEAMDYGCisGAQQBhFkKBAIx
|
||||||
# VIJX/OSx2ZL6ac/xB5A/7rdoaHV7PK+F1y807INXMA2HPnJGDVbi7HD7nJp26Fuz
|
# KDAmMAwGCisGAQQBhFkKAwKgCjAIAgEAAgMHoSChCjAIAgEAAgMBhqAwDQYJKoZI
|
||||||
# P2K3aGE3kK06C2jXsjdqWsAZv32k1daX+OqFGJdOsmmua/qlF0AMWTXL7rsBStOH
|
# hvcNAQELBQADggEBAFXCcBVLkxGEigIad7gAMsj2+SQdBANpzq4qPJXOu81TM3HC
|
||||||
# 5YI/KXtAsd9vvUbqcCMGeGmnRk6V7NmsKbQIkZ3kDk6YfKoZWmSknCKHF6LzCPkI
|
# rAkCUTm3FRNc6YPdpfvl07lGlv/NHFCLyXL20d6PZ/1wlF5+WR2OvWjrktwDxYv8
|
||||||
# bZSI8PNhcn19VUl9VS4WXGyWeGG5zBkOXnImAIKlaLMxR8Z9/kQVx84TrsDBl6Yh
|
# cZqk7BrV9SB8xBe/GwVi7smKmlXhznqA6lFPO+VNfOwWcxn0H2yxEsAJKyDmgx/7
|
||||||
# 34t6ISVDkQtre8SBG6fdjyWKmCOSntciVUlEom8ZwkadixIaf8nOoUJSYq5fl+4J
|
# M8xnMTKeK8ulgSy4EoyGgFIO+nGHqxS0yaXe+OgzErkaavB1Qw7jfmm5/wlBCnwz
|
||||||
# HkcUaY79lJKL5DiENwdC4Lt6eNabRo3SPbQE7IQWbWx5h3et1QDitsZ7Gg9yAHaZ
|
# 0UsbaequeL9UjA6FUw3Cc3F+3/D38BzyjJtTxjUVn+QiVWwOfikRJ2F7oZwpsJo3
|
||||||
# LS/t/SIAy+OXLXNxyttcyrbDvFI8A8tFE9P1w+3MC1n2cveqd6Wu07Z4l74Mj0LX
|
# yNIVpwJFpIV6VsqtxzaF0KQZBpS2lBGxVA17pFcxggQNMIIECQIBATCBkzB8MQsw
|
||||||
# yR+0h/KjfE6SPaL+N20E4CjM0bxRKZ+CuFj/A3tykEADdzFtsEfzUzTDkD3cJpOj
|
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
|
||||||
# fojWQNX1ly8Tu3G/WdAFqzrln2y8jCbVdPIqo1ntbu+BbYom1VQqAihYQB855+pG
|
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNy
|
||||||
# D8bOWbnrvhUua7gDFFDA762iZMxD
|
# b3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAAgO7HlwAOGx0ygABAAACAzAN
|
||||||
|
# BglghkgBZQMEAgEFAKCCAUowGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMC8G
|
||||||
|
# CSqGSIb3DQEJBDEiBCApggCahSc04fWyIz1KF4aeejwqHefyj2gzz7p9QsluFTCB
|
||||||
|
# +gYLKoZIhvcNAQkQAi8xgeowgecwgeQwgb0EIEsD3RtxlvaTxFOZZnpQw0DksPmV
|
||||||
|
# duo5SyK9h9w++hMtMIGYMIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh
|
||||||
|
# c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD
|
||||||
|
# b3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIw
|
||||||
|
# MTACEzMAAAIDux5cADhsdMoAAQAAAgMwIgQgwIRXpw5w7cRbWSfOFZ15Z2Nf90Hi
|
||||||
|
# Ms/hZSpx+kv4aHcwDQYJKoZIhvcNAQELBQAEggIAM+zwgqPLhBOAumqVnUO/YRh7
|
||||||
|
# sePgzUWqveSw/J01TAD8JVXufiGmu4neLrGFki/Nz8ytun2DhJP/3xDRu39y/9Pb
|
||||||
|
# t2qKabzaoASwH95fTjHLYEp0PhqkEZ1hkaaYjVC3TAG0LgU2mrvkEjL3doD5MXu8
|
||||||
|
# WWQGcnB0Wera/3POf4ylyQbUUnzo/Pl9qUbjPVW/JouzzDzijObLcYp7IDgIDxGL
|
||||||
|
# sVJqMgzP1ZWBWsjjx4J0YiYORUnIVKWKPXt/0O3X9VO3zDfOnWRLF8mJj+ybEnqa
|
||||||
|
# Wd8LxLJnCxpmTAjtELLgC46UB0N4GHR0+ymSba35Ciz4Kzc+7R9E1Ajy1yd2rmGR
|
||||||
|
# M2u/eAV8MvKybIzgTd9Lukk9KJ5lvzV52CuYyzHOzYgcNt/mFgvM6gfMAef3CeN0
|
||||||
|
# EU7ECvTEYqno7krSRi6+HD+R14+7EwXbiR0E+KAB2Ppgj7GqHWKeL/Owyv0A1oEa
|
||||||
|
# 4ocdqMApLcY908U7IzNu5qo7PPas/RBsB9J52++fyZ/9RyP31IYKu8/5xI5Ef7aH
|
||||||
|
# XIopbEpuMHpHeuWlYWlfkULa5tjk4iPVCTRVsgn7IimLY/wgVOLL4ueOzZZ6aNws
|
||||||
|
# Q37w/ocvXIH/qXUllulfh5vINVYqXK3d+l0QT8LCMIxXpJSSgtcFcPJG6aSdOFRQ
|
||||||
|
# r6EOj+C9DH5MueMd9SY=
|
||||||
# SIG # End signature block
|
# SIG # End signature block
|
||||||
|
|||||||
10
externals/install-dotnet.sh
vendored
10
externals/install-dotnet.sh
vendored
@@ -1003,12 +1003,12 @@ copy_files_or_dirs_from_list() {
|
|||||||
cat | uniq | while read -r file_path; do
|
cat | uniq | while read -r file_path; do
|
||||||
local path="$(remove_beginning_slash "${file_path#$root_path}")"
|
local path="$(remove_beginning_slash "${file_path#$root_path}")"
|
||||||
local target="$out_path/$path"
|
local target="$out_path/$path"
|
||||||
if [ "$override" = true ] || (! ([ -d "$target" ] || [ -e "$target" ] || [ -L "$target" ])); then
|
if [ "$override" = true ] || (! ([ -d "$target" ] || [ -e "$target" ])); then
|
||||||
mkdir -p "$out_path/$(dirname "$path")"
|
mkdir -p "$out_path/$(dirname "$path")"
|
||||||
if [ -d "$target" ] || [ -L "$target" ]; then
|
if [ -d "$target" ]; then
|
||||||
rm -rf "$target"
|
rm -rf "$target"
|
||||||
fi
|
fi
|
||||||
cp -RP $override_switch "$root_path/$path" "$target"
|
cp -R $override_switch "$root_path/$path" "$target"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
@@ -1053,8 +1053,8 @@ extract_dotnet_package() {
|
|||||||
tar -xzf "$zip_path" -C "$temp_out_path" > /dev/null || failed=true
|
tar -xzf "$zip_path" -C "$temp_out_path" > /dev/null || failed=true
|
||||||
|
|
||||||
local folders_with_version_regex='^.*/[0-9]+\.[0-9]+[^/]+/'
|
local folders_with_version_regex='^.*/[0-9]+\.[0-9]+[^/]+/'
|
||||||
find "$temp_out_path" \( -type f -o -type l \) | grep -Eo "$folders_with_version_regex" | sort | copy_files_or_dirs_from_list "$temp_out_path" "$out_path" false
|
find "$temp_out_path" -type f | grep -Eo "$folders_with_version_regex" | sort | copy_files_or_dirs_from_list "$temp_out_path" "$out_path" false
|
||||||
find "$temp_out_path" \( -type f -o -type l \) | grep -Ev "$folders_with_version_regex" | copy_files_or_dirs_from_list "$temp_out_path" "$out_path" "$override_non_versioned_files"
|
find "$temp_out_path" -type f | grep -Ev "$folders_with_version_regex" | copy_files_or_dirs_from_list "$temp_out_path" "$out_path" "$override_non_versioned_files"
|
||||||
|
|
||||||
validate_remote_local_file_sizes "$zip_path" "$remote_file_size"
|
validate_remote_local_file_sizes "$zip_path" "$remote_file_size"
|
||||||
|
|
||||||
|
|||||||
134
src/installer.ts
134
src/installer.ts
@@ -16,74 +16,21 @@ export interface DotnetVersion {
|
|||||||
qualityFlag: boolean;
|
qualityFlag: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ReleaseIndexEntry {
|
|
||||||
'channel-version': string;
|
|
||||||
'support-phase': string;
|
|
||||||
'release-type': string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ReleaseIndexResponse {
|
|
||||||
'releases-index': ReleaseIndexEntry[];
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
||||||
export class DotnetVersionResolver {
|
export class DotnetVersionResolver {
|
||||||
private inputVersion: string;
|
private inputVersion: string;
|
||||||
private resolvedArgument: DotnetVersion;
|
private resolvedArgument: DotnetVersion;
|
||||||
|
|
||||||
constructor(
|
constructor(version: string) {
|
||||||
version: string,
|
|
||||||
private quality: QualityOptions = '',
|
|
||||||
private dotnetChannel?: string
|
|
||||||
) {
|
|
||||||
this.inputVersion = version.trim();
|
this.inputVersion = version.trim();
|
||||||
this.resolvedArgument = {type: '', value: '', qualityFlag: false};
|
this.resolvedArgument = {type: '', value: '', qualityFlag: false};
|
||||||
}
|
}
|
||||||
|
|
||||||
private isVersionChannel(channel: string): boolean {
|
|
||||||
// A.B format (e.g., 3.1, 8.0)
|
|
||||||
if (/^\d+\.\d+$/.test(channel)) return true;
|
|
||||||
// A.B.Cxx format (e.g., 8.0.1xx) is supported only for .NET 5.0+
|
|
||||||
const latestPatchMatch = channel.match(/^(\d+)\.\d+\.\d{1}xx$/);
|
|
||||||
if (latestPatchMatch) {
|
|
||||||
const major = Number(latestPatchMatch[1]);
|
|
||||||
return (
|
|
||||||
!Number.isNaN(major) && major >= LATEST_PATCH_SYNTAX_MINIMAL_MAJOR_TAG
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async resolveVersionInput(): Promise<void> {
|
private async resolveVersionInput(): Promise<void> {
|
||||||
if (this.inputVersion.toLowerCase() === 'latest') {
|
|
||||||
const channel = this.dotnetChannel || '';
|
|
||||||
if (this.isVersionChannel(channel)) {
|
|
||||||
// A.B or A.B.Cxx channels are passed directly to the install script
|
|
||||||
this.resolvedArgument.value = channel;
|
|
||||||
} else {
|
|
||||||
// LTS, STS, or empty — resolve via releases index API
|
|
||||||
this.resolvedArgument.value = await this.getLatestVersion(channel);
|
|
||||||
}
|
|
||||||
this.resolvedArgument.type = 'channel';
|
|
||||||
const latestChannelMajorTag = Number(
|
|
||||||
this.resolvedArgument.value.split('.')[0]
|
|
||||||
);
|
|
||||||
this.resolvedArgument.qualityFlag =
|
|
||||||
!Number.isNaN(latestChannelMajorTag) &&
|
|
||||||
latestChannelMajorTag >= QUALITY_INPUT_MINIMAL_MAJOR_TAG;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.dotnetChannel) {
|
|
||||||
core.warning(
|
|
||||||
`The 'dotnet-channel' input is only supported when 'dotnet-version' is set to 'latest'.`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!semver.validRange(this.inputVersion) && !this.isLatestPatchSyntax()) {
|
if (!semver.validRange(this.inputVersion) && !this.isLatestPatchSyntax()) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`The 'dotnet-version' was supplied in invalid format: ${this.inputVersion}! Supported syntax: A.B.C, A.B, A.B.x, A, A.x, A.B.Cxx, latest`
|
`The 'dotnet-version' was supplied in invalid format: ${this.inputVersion}! Supported syntax: A.B.C, A.B, A.B.x, A, A.x, A.B.Cxx`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (semver.valid(this.inputVersion)) {
|
if (semver.valid(this.inputVersion)) {
|
||||||
@@ -125,22 +72,7 @@ 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)) {
|
||||||
// Starting with .NET 5, the minor version is always zero.
|
this.resolvedArgument.value = await this.getLatestByMajorTag(major);
|
||||||
// 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';
|
||||||
@@ -164,62 +96,31 @@ export class DotnetVersionResolver {
|
|||||||
return this.resolvedArgument;
|
return this.resolvedArgument;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getLatestVersion(channelFilter: string): Promise<string> {
|
private async getLatestByMajorTag(majorTag: string): Promise<string> {
|
||||||
const httpClient = new hc.HttpClient('actions/setup-dotnet', [], {
|
const httpClient = new hc.HttpClient('actions/setup-dotnet', [], {
|
||||||
allowRetries: true,
|
allowRetries: true,
|
||||||
maxRetries: 3
|
maxRetries: 3
|
||||||
});
|
});
|
||||||
|
|
||||||
const response = await httpClient.getJson<ReleaseIndexResponse>(
|
const response = await httpClient.getJson<any>(
|
||||||
DotnetVersionResolver.DotnetCoreIndexUrl
|
DotnetVersionResolver.DotnetCoreIndexUrl
|
||||||
);
|
);
|
||||||
|
|
||||||
const result = response.result;
|
const result = response.result || {};
|
||||||
const rawReleasesInfo = result?.['releases-index'];
|
const releasesInfo: any[] = result['releases-index'];
|
||||||
|
|
||||||
if (!Array.isArray(rawReleasesInfo)) {
|
const releaseInfo = releasesInfo.find(info => {
|
||||||
throw new Error('Unexpected response format from .NET releases index.');
|
const sdkParts: string[] = info['channel-version'].split('.');
|
||||||
}
|
return sdkParts[0] === majorTag;
|
||||||
|
|
||||||
let releasesInfo = rawReleasesInfo;
|
|
||||||
|
|
||||||
// Filter out EOL versions
|
|
||||||
releasesInfo = releasesInfo.filter(info => info['support-phase'] !== 'eol');
|
|
||||||
|
|
||||||
// Filter out preview versions if quality is not 'preview' or 'daily'
|
|
||||||
// If quality is not specified, we assume strict stability (GA only)
|
|
||||||
const normalizedQuality = (this.quality || '').toLowerCase();
|
|
||||||
if (!['preview', 'daily'].includes(normalizedQuality)) {
|
|
||||||
releasesInfo = releasesInfo.filter(
|
|
||||||
info => info['support-phase'] !== 'preview'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply channel filter (LTS/STS)
|
|
||||||
if (channelFilter) {
|
|
||||||
const type = channelFilter.toLowerCase();
|
|
||||||
releasesInfo = releasesInfo.filter(info => info['release-type'] === type);
|
|
||||||
}
|
|
||||||
|
|
||||||
releasesInfo.sort((a, b) => {
|
|
||||||
const partsA = a['channel-version'].split('.').map(Number);
|
|
||||||
const partsB = b['channel-version'].split('.').map(Number);
|
|
||||||
for (let i = 0; i < Math.max(partsA.length, partsB.length); i++) {
|
|
||||||
const diff = (partsB[i] || 0) - (partsA[i] || 0);
|
|
||||||
if (diff !== 0) return diff;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (releasesInfo.length === 0) {
|
if (!releaseInfo) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Could not find any active releases matching channel '${
|
`Could not find info for version with major tag: "${majorTag}" at ${DotnetVersionResolver.DotnetCoreIndexUrl}`
|
||||||
channelFilter || 'any'
|
|
||||||
}'`
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return releasesInfo[0]['channel-version'];
|
return releaseInfo['channel-version'];
|
||||||
}
|
}
|
||||||
|
|
||||||
static DotnetCoreIndexUrl =
|
static DotnetCoreIndexUrl =
|
||||||
@@ -378,16 +279,11 @@ export class DotnetCoreInstaller {
|
|||||||
constructor(
|
constructor(
|
||||||
private version: string,
|
private version: string,
|
||||||
private quality: QualityOptions,
|
private quality: QualityOptions,
|
||||||
private architecture?: string,
|
private architecture?: string
|
||||||
private dotnetChannel?: string
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async installDotnet(): Promise<string | null> {
|
public async installDotnet(): Promise<string | null> {
|
||||||
const versionResolver = new DotnetVersionResolver(
|
const versionResolver = new DotnetVersionResolver(this.version);
|
||||||
this.version,
|
|
||||||
this.quality,
|
|
||||||
this.dotnetChannel
|
|
||||||
);
|
|
||||||
const dotnetVersion = await versionResolver.createDotnetVersion();
|
const dotnetVersion = await versionResolver.createDotnetVersion();
|
||||||
|
|
||||||
const architectureArguments =
|
const architectureArguments =
|
||||||
|
|||||||
@@ -15,7 +15,13 @@ import {restoreCache} from './cache-restore';
|
|||||||
import {Outputs} from './constants';
|
import {Outputs} from './constants';
|
||||||
import JSON5 from 'json5';
|
import JSON5 from 'json5';
|
||||||
|
|
||||||
const qualityOptions = ['daily', 'preview', 'ga'] as const;
|
const qualityOptions = [
|
||||||
|
'daily',
|
||||||
|
'signed',
|
||||||
|
'validated',
|
||||||
|
'preview',
|
||||||
|
'ga'
|
||||||
|
] as const;
|
||||||
const supportedArchitectures = [
|
const supportedArchitectures = [
|
||||||
'x64',
|
'x64',
|
||||||
'x86',
|
'x86',
|
||||||
@@ -28,18 +34,7 @@ const supportedArchitectures = [
|
|||||||
] as const;
|
] as const;
|
||||||
type SupportedArchitecture = (typeof supportedArchitectures)[number];
|
type SupportedArchitecture = (typeof supportedArchitectures)[number];
|
||||||
|
|
||||||
export type QualityOptions = (typeof qualityOptions)[number] | '';
|
export type QualityOptions = (typeof qualityOptions)[number];
|
||||||
|
|
||||||
function isValidChannel(channel: string): boolean {
|
|
||||||
const upper = channel.toUpperCase();
|
|
||||||
if (upper === 'LTS' || upper === 'STS') return true;
|
|
||||||
// A.B format (e.g., 3.1, 8.0)
|
|
||||||
if (/^\d+\.\d+$/.test(channel)) return true;
|
|
||||||
// A.B.Cxx format (e.g., 8.0.1xx) - available since 5.0
|
|
||||||
const match = channel.match(/^(?<major>\d+)\.\d+\.\d{1}xx$/);
|
|
||||||
if (match && parseInt(match.groups!.major) >= 5) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function run() {
|
export async function run() {
|
||||||
try {
|
try {
|
||||||
@@ -55,28 +50,6 @@ export async function run() {
|
|||||||
const versions = core.getMultilineInput('dotnet-version');
|
const versions = core.getMultilineInput('dotnet-version');
|
||||||
const installedDotnetVersions: (string | null)[] = [];
|
const installedDotnetVersions: (string | null)[] = [];
|
||||||
const architecture = getArchitectureInput();
|
const architecture = getArchitectureInput();
|
||||||
let dotnetChannel = core.getInput('dotnet-channel');
|
|
||||||
|
|
||||||
const isLatestRequested = versions.some(
|
|
||||||
version => version && version.toLowerCase() === 'latest'
|
|
||||||
);
|
|
||||||
if (dotnetChannel && !isValidChannel(dotnetChannel)) {
|
|
||||||
if (isLatestRequested) {
|
|
||||||
throw new Error(
|
|
||||||
`Value '${dotnetChannel}' is not supported for the 'dotnet-channel' option. Supported values are: LTS, STS, A.B (e.g. 8.0), A.B.Cxx (e.g. 8.0.1xx).`
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
core.warning(
|
|
||||||
`Value '${dotnetChannel}' is not supported for the 'dotnet-channel' option and will be ignored because 'dotnet-version' is not set to 'latest'. Supported values are: LTS, STS, A.B (e.g. 8.0), A.B.Cxx (e.g. 8.0.1xx).`
|
|
||||||
);
|
|
||||||
dotnetChannel = '';
|
|
||||||
}
|
|
||||||
} else if (dotnetChannel && !isLatestRequested) {
|
|
||||||
core.warning(
|
|
||||||
`The 'dotnet-channel' input is only supported when 'dotnet-version' is set to 'latest'.`
|
|
||||||
);
|
|
||||||
dotnetChannel = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
const globalJsonFileInput = core.getInput('global-json-file');
|
const globalJsonFileInput = core.getInput('global-json-file');
|
||||||
if (globalJsonFileInput) {
|
if (globalJsonFileInput) {
|
||||||
@@ -107,20 +80,17 @@ export async function run() {
|
|||||||
|
|
||||||
if (quality && !qualityOptions.includes(quality)) {
|
if (quality && !qualityOptions.includes(quality)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Value '${quality}' is not supported for the 'dotnet-quality' option. Supported values are: daily, preview, ga.`
|
`Value '${quality}' is not supported for the 'dotnet-quality' option. Supported values are: daily, signed, validated, preview, ga.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let dotnetInstaller: DotnetCoreInstaller;
|
let dotnetInstaller: DotnetCoreInstaller;
|
||||||
const uniqueVersions = new Set<string>(
|
const uniqueVersions = new Set<string>(versions);
|
||||||
versions.map(v => (v.toLowerCase() === 'latest' ? 'latest' : v))
|
|
||||||
);
|
|
||||||
for (const version of uniqueVersions) {
|
for (const version of uniqueVersions) {
|
||||||
dotnetInstaller = new DotnetCoreInstaller(
|
dotnetInstaller = new DotnetCoreInstaller(
|
||||||
version,
|
version,
|
||||||
quality,
|
quality,
|
||||||
architecture,
|
architecture
|
||||||
version.toLowerCase() === 'latest' ? dotnetChannel : undefined
|
|
||||||
);
|
);
|
||||||
const installedVersion = await dotnetInstaller.installDotnet();
|
const installedVersion = await dotnetInstaller.installDotnet();
|
||||||
installedDotnetVersions.push(installedVersion);
|
installedDotnetVersions.push(installedVersion);
|
||||||
@@ -207,27 +177,9 @@ function getVersionFromGlobalJson(globalJsonPath: string): string {
|
|||||||
if (globalJson.sdk && globalJson.sdk.version) {
|
if (globalJson.sdk && globalJson.sdk.version) {
|
||||||
version = globalJson.sdk.version;
|
version = globalJson.sdk.version;
|
||||||
const rollForward = globalJson.sdk.rollForward;
|
const rollForward = globalJson.sdk.rollForward;
|
||||||
if (rollForward) {
|
if (rollForward && rollForward === 'latestFeature') {
|
||||||
const [major, minor, featurePatch] = version.split('.');
|
const [major, minor] = version.split('.');
|
||||||
const feature = featurePatch.substring(0, 1);
|
version = `${major}.${minor}`;
|
||||||
|
|
||||||
switch (rollForward) {
|
|
||||||
case 'latestMajor':
|
|
||||||
version = '';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'latestMinor':
|
|
||||||
version = `${major}`;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'latestFeature':
|
|
||||||
version = `${major}.${minor}`;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'latestPatch':
|
|
||||||
version = `${major}.${minor}.${feature}xx`;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return version;
|
return version;
|
||||||
|
|||||||
Reference in New Issue
Block a user