mirror of
https://github.com/actions/runner.git
synced 2025-12-10 20:36:49 +00:00
Compare commits
26 Commits
v2.276.1
...
users/tihu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc9de4cf0e | ||
|
|
b4809d447f | ||
|
|
baacb145ad | ||
|
|
183a3dd9a0 | ||
|
|
9821c13992 | ||
|
|
a0fa09ddcc | ||
|
|
6cbfbc3186 | ||
|
|
195c2db5ef | ||
|
|
50994bbb3b | ||
|
|
7b03699fbe | ||
|
|
8a4cb76508 | ||
|
|
bc3099793f | ||
|
|
b76d229da0 | ||
|
|
fe3994bf1d | ||
|
|
0ae09e6713 | ||
|
|
2b4d5542aa | ||
|
|
6b0f0c00b1 | ||
|
|
09760c0d69 | ||
|
|
8f14466cbb | ||
|
|
fe8a56f81a | ||
|
|
59b30262ac | ||
|
|
9efcec38cc | ||
|
|
5972bd0060 | ||
|
|
239cc0d7ca | ||
|
|
3fb915450a | ||
|
|
4b6ded0a01 |
13
.github/workflows/build.yml
vendored
13
.github/workflows/build.yml
vendored
@@ -71,3 +71,16 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: runner-package-${{ matrix.runtime }}
|
name: runner-package-${{ matrix.runtime }}
|
||||||
path: _package
|
path: _package
|
||||||
|
|
||||||
|
# compute shas and set as job outputs to use in release notes
|
||||||
|
- run: brew install coreutils #needed for shasum util
|
||||||
|
if: ${{ matrix.os == 'macOS-latest' }}
|
||||||
|
name: Install Dependencies for SHA Calculation (osx)
|
||||||
|
- run: |
|
||||||
|
file=$(ls)
|
||||||
|
sha=$(sha256sum $file | awk '{ print $1 }')
|
||||||
|
echo "Computed sha256: $sha for $file"
|
||||||
|
shell: bash
|
||||||
|
id: sha
|
||||||
|
name: Compute SHA256
|
||||||
|
working-directory: _package
|
||||||
|
|||||||
32
.github/workflows/release.yml
vendored
32
.github/workflows/release.yml
vendored
@@ -45,6 +45,12 @@ jobs:
|
|||||||
|
|
||||||
build:
|
build:
|
||||||
needs: check
|
needs: check
|
||||||
|
outputs:
|
||||||
|
linux-x64-sha: ${{ steps.sha.outputs.linux-x64-sha256 }}
|
||||||
|
linux-arm64-sha: ${{ steps.sha.outputs.linux-arm64-sha256 }}
|
||||||
|
linux-arm-sha: ${{ steps.sha.outputs.linux-arm-sha256 }}
|
||||||
|
win-x64-sha: ${{ steps.sha.outputs.win-x64-sha256 }}
|
||||||
|
osx-x64-sha: ${{ steps.sha.outputs.osx-x64-sha256 }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64 ]
|
runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64 ]
|
||||||
@@ -101,7 +107,19 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: runner-packages
|
name: runner-packages
|
||||||
path: _package
|
path: _package
|
||||||
|
# compute shas and set as job outputs to use in release notes
|
||||||
|
- run: brew install coreutils #needed for shasum util
|
||||||
|
if: ${{ matrix.os == 'macOS-latest' }}
|
||||||
|
name: Install Dependencies for SHA Calculation (osx)
|
||||||
|
- run: |
|
||||||
|
file=$(ls)
|
||||||
|
sha=$(sha256sum $file | awk '{ print $1 }')
|
||||||
|
echo "Computed sha256: $sha for $file"
|
||||||
|
echo "::set-output name=${{matrix.runtime}}-sha256::$sha"
|
||||||
|
shell: bash
|
||||||
|
id: sha
|
||||||
|
name: Compute SHA256
|
||||||
|
working-directory: _package
|
||||||
release:
|
release:
|
||||||
needs: build
|
needs: build
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -126,11 +144,15 @@ jobs:
|
|||||||
const core = require('@actions/core')
|
const core = require('@actions/core')
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const runnerVersion = fs.readFileSync('${{ github.workspace }}/src/runnerversion', 'utf8').replace(/\n$/g, '')
|
const runnerVersion = fs.readFileSync('${{ github.workspace }}/src/runnerversion', 'utf8').replace(/\n$/g, '')
|
||||||
const releaseNote = fs.readFileSync('${{ github.workspace }}/releaseNote.md', 'utf8').replace(/<RUNNER_VERSION>/g, runnerVersion)
|
var releaseNote = fs.readFileSync('${{ github.workspace }}/releaseNote.md', 'utf8').replace(/<RUNNER_VERSION>/g, runnerVersion)
|
||||||
|
releaseNote = releaseNote.replace(/<WIN_X64_SHA>/g, '${{needs.build.outputs.win-x64-sha}}')
|
||||||
|
releaseNote = releaseNote.replace(/<OSX_X64_SHA>/g, '${{needs.build.outputs.osx-x64-sha}}')
|
||||||
|
releaseNote = releaseNote.replace(/<LINUX_X64_SHA>/g, '${{needs.build.outputs.linux-x64-sha}}')
|
||||||
|
releaseNote = releaseNote.replace(/<LINUX_ARM_SHA>/g, '${{needs.build.outputs.linux-arm-sha}}')
|
||||||
|
releaseNote = releaseNote.replace(/<LINUX_ARM64_SHA>/g, '${{needs.build.outputs.linux-arm64-sha}}')
|
||||||
console.log(releaseNote)
|
console.log(releaseNote)
|
||||||
core.setOutput('version', runnerVersion);
|
core.setOutput('version', runnerVersion);
|
||||||
core.setOutput('note', releaseNote);
|
core.setOutput('note', releaseNote);
|
||||||
|
|
||||||
# Create GitHub release
|
# Create GitHub release
|
||||||
- uses: actions/create-release@master
|
- uses: actions/create-release@master
|
||||||
id: createRelease
|
id: createRelease
|
||||||
@@ -193,4 +215,4 @@ jobs:
|
|||||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||||
asset_path: ${{ github.workspace }}/actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
asset_path: ${{ github.workspace }}/actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
||||||
asset_name: actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
asset_name: actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ This gives us good coverage across the board for secrets and secrets with a pref
|
|||||||
|
|
||||||
However, we don't have great coverage for cases where the secret has a string appended to it before it is base64 encoded (i.e.: `base64($pass\n))`).
|
However, we don't have great coverage for cases where the secret has a string appended to it before it is base64 encoded (i.e.: `base64($pass\n))`).
|
||||||
|
|
||||||
Most notably we've seen this as a result of user error where a user accidentially appends a newline or space character before encoding their secret in base64.
|
Most notably we've seen this as a result of user error where a user accidentally appends a newline or space character before encoding their secret in base64.
|
||||||
|
|
||||||
## Decision
|
## Decision
|
||||||
|
|
||||||
@@ -45,4 +45,4 @@ This will result in us only revealing length or bit information when a prefix or
|
|||||||
|
|
||||||
- In the case where a secret has a prefix or suffix added before base64 encoding, we may now reveal up to 20 bits of information and the length of the original string modulo 3, rather then the original 16 bits and no length information
|
- In the case where a secret has a prefix or suffix added before base64 encoding, we may now reveal up to 20 bits of information and the length of the original string modulo 3, rather then the original 16 bits and no length information
|
||||||
- Secrets with a suffix appended before encoding will now be masked across the board. Previously it was only masked if it was a multiple of 3 characters
|
- Secrets with a suffix appended before encoding will now be masked across the board. Previously it was only masked if it was a multiple of 3 characters
|
||||||
- Performance will suffer in a neglible way
|
- Performance will suffer in a negligible way
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ Make sure the runner has access to actions service for GitHub.com or GitHub Ente
|
|||||||
- DNS lookup for pipelines.actions.githubusercontent.com using dotnet
|
- DNS lookup for pipelines.actions.githubusercontent.com using dotnet
|
||||||
- Ping pipelines.actions.githubusercontent.com using dotnet
|
- Ping pipelines.actions.githubusercontent.com using dotnet
|
||||||
- Make HTTP GET to https://pipelines.actions.githubusercontent.com/_apis/health or https://myGHES.com/_services/pipelines/_apis/health using dotnet, check response headers contains `x-vss-e2eid`
|
- Make HTTP GET to https://pipelines.actions.githubusercontent.com/_apis/health or https://myGHES.com/_services/pipelines/_apis/health using dotnet, check response headers contains `x-vss-e2eid`
|
||||||
|
- Make HTTP POST to https://pipelines.actions.githubusercontent.com/_apis/health or https://myGHES.com/_services/pipelines/_apis/health using dotnet, check response headers contains `x-vss-e2eid`
|
||||||
|
|
||||||
## How to fix the issue?
|
## How to fix the issue?
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ The test also set environment variable `GIT_TRACE=1` and `GIT_CURL_VERBOSE=1` be
|
|||||||
|
|
||||||
### 1. Check the common network issue
|
### 1. Check the common network issue
|
||||||
|
|
||||||
> Please check the [network doc](./network.md)
|
> Please check the [network doc](./network.md)
|
||||||
|
|
||||||
### 2. SSL certificate related issue
|
### 2. SSL certificate related issue
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
- Proxy try to decrypt and exam HTTPS traffic for security purpose but cause the actions-runner to fail to finish SSL handshake due to the lack of trusting proxy's CA.
|
- Proxy try to decrypt and exam HTTPS traffic for security purpose but cause the actions-runner to fail to finish SSL handshake due to the lack of trusting proxy's CA.
|
||||||
|
|
||||||
|
- Proxy try to modify the HTTPS request (like add or change some http headers) and causes the request become incompatible with the Actions Service (ASP.NetCore), Ex: [Nginx](https://github.com/dotnet/aspnetcore/issues/17081)
|
||||||
|
|
||||||
- Firewall rules that block action runner from accessing certain hosts, ex: `*.github.com`, `*.actions.githubusercontent.com`, etc.
|
- Firewall rules that block action runner from accessing certain hosts, ex: `*.github.com`, `*.actions.githubusercontent.com`, etc.
|
||||||
|
|
||||||
|
|
||||||
@@ -21,6 +23,7 @@ Use a 3rd party tool to make the same requests as the runner did would be a good
|
|||||||
|
|
||||||
- Use `nslookup` to check DNS
|
- Use `nslookup` to check DNS
|
||||||
- Use `ping` to check Ping
|
- Use `ping` to check Ping
|
||||||
|
- Use `traceroute`, `tracepath`, or `tracert` to check the network route between the runner and the Actions service
|
||||||
- Use `curl -v` to check the network stack, good for verifying default certificate/proxy settings.
|
- Use `curl -v` to check the network stack, good for verifying default certificate/proxy settings.
|
||||||
- Use `Invoke-WebRequest` from `pwsh` (`PowerShell Core`) to check the dotnet network stack, good for verifying bugs in the dotnet framework.
|
- Use `Invoke-WebRequest` from `pwsh` (`PowerShell Core`) to check the dotnet network stack, good for verifying bugs in the dotnet framework.
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,11 @@
|
|||||||
## Features
|
## Features
|
||||||
- Support config runner via GitHub PAT. (#874)
|
|
||||||
- Update runner to .NET 5 (#799)
|
|
||||||
- Add new ANDROID_SDK_ROOT environment variable (#892)
|
|
||||||
- Add warning when running out of disk. (#873)
|
|
||||||
- Always use FIPS Cryptography (#896)
|
|
||||||
- Add `--check` to run a serials network test against GitHub or GHES. (#900)
|
|
||||||
|
|
||||||
## Bugs
|
## Bugs
|
||||||
- Ignore certain scenarios so they are not counted as infra failures (#889)
|
- Fixed an issue where docker containers failed to initialize (#977)
|
||||||
|
|
||||||
## Misc
|
## Misc
|
||||||
- Add runner e2e test workflow (#885)
|
|
||||||
- Add on: pull_request trigger to CodeQL workflow (#907)
|
|
||||||
|
|
||||||
## Windows x64
|
## Windows x64
|
||||||
We recommend configuring the runner in a root folder of the Windows drive (e.g. "C:\actions-runner"). This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows.
|
We recommend configuring the runner in a root folder of the Windows drive (e.g. "C:\actions-runner"). This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows.
|
||||||
@@ -73,3 +67,13 @@ tar xzf ./actions-runner-linux-arm-<RUNNER_VERSION>.tar.gz
|
|||||||
|
|
||||||
## Using your self hosted runner
|
## Using your self hosted runner
|
||||||
For additional details about configuring, running, or shutting down the runner please check out our [product docs.](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/adding-self-hosted-runners)
|
For additional details about configuring, running, or shutting down the runner please check out our [product docs.](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/adding-self-hosted-runners)
|
||||||
|
|
||||||
|
## SHA-256 Checksums
|
||||||
|
|
||||||
|
The SHA-256 checksums for the packages included in this build are shown below:
|
||||||
|
|
||||||
|
- actions-runner-win-x64-<RUNNER_VERSION>.zip <!-- BEGIN SHA win-x64 --><WIN_X64_SHA><!-- END SHA win-x64 -->
|
||||||
|
- actions-runner-osx-x64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA osx-x64 --><OSX_X64_SHA><!-- END SHA osx-x64 -->
|
||||||
|
- actions-runner-linux-x64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA linux-x64 --><LINUX_X64_SHA><!-- END SHA linux-x64 -->
|
||||||
|
- actions-runner-linux-arm64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA linux-arm64 --><LINUX_ARM64_SHA><!-- END SHA linux-arm64 -->
|
||||||
|
- actions-runner-linux-arm-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA linux-arm --><LINUX_ARM_SHA><!-- END SHA linux-arm -->
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
<Update to ./src/runnerversion when creating release>
|
2.277.1
|
||||||
|
|||||||
568
src/Misc/dotnet-install.ps1
vendored
568
src/Misc/dotnet-install.ps1
vendored
@@ -23,8 +23,6 @@
|
|||||||
Default: latest
|
Default: latest
|
||||||
Represents a build version on specific channel. Possible values:
|
Represents a build version on specific channel. Possible values:
|
||||||
- latest - most latest build on specific channel
|
- latest - most latest build on specific channel
|
||||||
- coherent - most latest coherent build on specific channel
|
|
||||||
coherent applies only to SDK downloads
|
|
||||||
- 3-part version in a format A.B.C - represents specific version of build
|
- 3-part version in a format A.B.C - represents specific version of build
|
||||||
examples: 2.0.0-preview2-006120, 1.1.0
|
examples: 2.0.0-preview2-006120, 1.1.0
|
||||||
.PARAMETER InstallDir
|
.PARAMETER InstallDir
|
||||||
@@ -122,24 +120,42 @@ $VersionRegEx="/\d+\.\d+[^/]+/"
|
|||||||
$OverrideNonVersionedFiles = !$SkipNonVersionedFiles
|
$OverrideNonVersionedFiles = !$SkipNonVersionedFiles
|
||||||
|
|
||||||
function Say($str) {
|
function Say($str) {
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
Write-Host "dotnet-install: $str"
|
Write-Host "dotnet-install: $str"
|
||||||
}
|
}
|
||||||
catch
|
catch {
|
||||||
{
|
|
||||||
# Some platforms cannot utilize Write-Host (Azure Functions, for instance). Fall back to Write-Output
|
# Some platforms cannot utilize Write-Host (Azure Functions, for instance). Fall back to Write-Output
|
||||||
Write-Output "dotnet-install: $str"
|
Write-Output "dotnet-install: $str"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Say-Warning($str) {
|
||||||
|
try {
|
||||||
|
Write-Warning "dotnet-install: $str"
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
# Some platforms cannot utilize Write-Warning (Azure Functions, for instance). Fall back to Write-Output
|
||||||
|
Write-Output "dotnet-install: Warning: $str"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Writes a line with error style settings.
|
||||||
|
# Use this function to show a human-readable comment along with an exception.
|
||||||
|
function Say-Error($str) {
|
||||||
|
try {
|
||||||
|
# Write-Error is quite oververbose for the purpose of the function, let's write one line with error style settings.
|
||||||
|
$Host.UI.WriteErrorLine("dotnet-install: $str")
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Output "dotnet-install: Error: $str"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function Say-Verbose($str) {
|
function Say-Verbose($str) {
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
Write-Verbose "dotnet-install: $str"
|
Write-Verbose "dotnet-install: $str"
|
||||||
}
|
}
|
||||||
catch
|
catch {
|
||||||
{
|
|
||||||
# Some platforms cannot utilize Write-Verbose (Azure Functions, for instance). Fall back to Write-Output
|
# Some platforms cannot utilize Write-Verbose (Azure Functions, for instance). Fall back to Write-Output
|
||||||
Write-Output "dotnet-install: $str"
|
Write-Output "dotnet-install: $str"
|
||||||
}
|
}
|
||||||
@@ -156,7 +172,7 @@ function Invoke-With-Retry([ScriptBlock]$ScriptBlock, [int]$MaxAttempts = 3, [in
|
|||||||
|
|
||||||
while ($true) {
|
while ($true) {
|
||||||
try {
|
try {
|
||||||
return $ScriptBlock.Invoke()
|
return & $ScriptBlock
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
$Attempts++
|
$Attempts++
|
||||||
@@ -270,18 +286,41 @@ function GetHTTPResponse([Uri] $Uri)
|
|||||||
# Default timeout for HttpClient is 100s. For a 50 MB download this assumes 500 KB/s average, any less will time out
|
# Default timeout for HttpClient is 100s. For a 50 MB download this assumes 500 KB/s average, any less will time out
|
||||||
# 20 minutes allows it to work over much slower connections.
|
# 20 minutes allows it to work over much slower connections.
|
||||||
$HttpClient.Timeout = New-TimeSpan -Minutes 20
|
$HttpClient.Timeout = New-TimeSpan -Minutes 20
|
||||||
$Response = $HttpClient.GetAsync("${Uri}${FeedCredential}").Result
|
$Task = $HttpClient.GetAsync("${Uri}${FeedCredential}").ConfigureAwait("false");
|
||||||
if (($Response -eq $null) -or (-not ($Response.IsSuccessStatusCode))) {
|
$Response = $Task.GetAwaiter().GetResult();
|
||||||
# The feed credential is potentially sensitive info. Do not log FeedCredential to console output.
|
|
||||||
$ErrorMsg = "Failed to download $Uri."
|
if (($null -eq $Response) -or (-not ($Response.IsSuccessStatusCode))) {
|
||||||
if ($Response -ne $null) {
|
# The feed credential is potentially sensitive info. Do not log FeedCredential to console output.
|
||||||
$ErrorMsg += " $Response"
|
$DownloadException = [System.Exception] "Unable to download $Uri."
|
||||||
|
|
||||||
|
if ($null -ne $Response) {
|
||||||
|
$DownloadException.Data["StatusCode"] = [int] $Response.StatusCode
|
||||||
|
$DownloadException.Data["ErrorMessage"] = "Unable to download $Uri. Returned HTTP status code: " + $DownloadException.Data["StatusCode"]
|
||||||
}
|
}
|
||||||
|
|
||||||
throw $ErrorMsg
|
throw $DownloadException
|
||||||
}
|
}
|
||||||
|
|
||||||
return $Response
|
return $Response
|
||||||
|
}
|
||||||
|
catch [System.Net.Http.HttpRequestException] {
|
||||||
|
$DownloadException = [System.Exception] "Unable to download $Uri."
|
||||||
|
|
||||||
|
# Pick up the exception message and inner exceptions' messages if they exist
|
||||||
|
$CurrentException = $PSItem.Exception
|
||||||
|
$ErrorMsg = $CurrentException.Message + "`r`n"
|
||||||
|
while ($CurrentException.InnerException) {
|
||||||
|
$CurrentException = $CurrentException.InnerException
|
||||||
|
$ErrorMsg += $CurrentException.Message + "`r`n"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if there is an issue concerning TLS.
|
||||||
|
if ($ErrorMsg -like "*SSL/TLS*") {
|
||||||
|
$ErrorMsg += "Ensure that TLS 1.2 or higher is enabled to use this script.`r`n"
|
||||||
|
}
|
||||||
|
|
||||||
|
$DownloadException.Data["ErrorMessage"] = $ErrorMsg
|
||||||
|
throw $DownloadException
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if ($HttpClient -ne $null) {
|
if ($HttpClient -ne $null) {
|
||||||
@@ -291,7 +330,7 @@ function GetHTTPResponse([Uri] $Uri)
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function Get-Latest-Version-Info([string]$AzureFeed, [string]$Channel, [bool]$Coherent) {
|
function Get-Latest-Version-Info([string]$AzureFeed, [string]$Channel) {
|
||||||
Say-Invocation $MyInvocation
|
Say-Invocation $MyInvocation
|
||||||
|
|
||||||
$VersionFileUrl = $null
|
$VersionFileUrl = $null
|
||||||
@@ -306,12 +345,7 @@ function Get-Latest-Version-Info([string]$AzureFeed, [string]$Channel, [bool]$Co
|
|||||||
$VersionFileUrl = "$UncachedFeed/Runtime/$Channel/latest.version"
|
$VersionFileUrl = "$UncachedFeed/Runtime/$Channel/latest.version"
|
||||||
}
|
}
|
||||||
elseif (-not $Runtime) {
|
elseif (-not $Runtime) {
|
||||||
if ($Coherent) {
|
$VersionFileUrl = "$UncachedFeed/Sdk/$Channel/latest.version"
|
||||||
$VersionFileUrl = "$UncachedFeed/Sdk/$Channel/latest.coherent.version"
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$VersionFileUrl = "$UncachedFeed/Sdk/$Channel/latest.version"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw "Invalid value for `$Runtime"
|
throw "Invalid value for `$Runtime"
|
||||||
@@ -320,7 +354,8 @@ function Get-Latest-Version-Info([string]$AzureFeed, [string]$Channel, [bool]$Co
|
|||||||
$Response = GetHTTPResponse -Uri $VersionFileUrl
|
$Response = GetHTTPResponse -Uri $VersionFileUrl
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
throw "Could not resolve version information."
|
Say-Error "Could not resolve version information."
|
||||||
|
throw
|
||||||
}
|
}
|
||||||
$StringContent = $Response.Content.ReadAsStringAsync().Result
|
$StringContent = $Response.Content.ReadAsStringAsync().Result
|
||||||
|
|
||||||
@@ -346,7 +381,8 @@ function Parse-Jsonfile-For-Version([string]$JSonFile) {
|
|||||||
$JSonContent = Get-Content($JSonFile) -Raw | ConvertFrom-Json | Select-Object -expand "sdk" -ErrorAction SilentlyContinue
|
$JSonContent = Get-Content($JSonFile) -Raw | ConvertFrom-Json | Select-Object -expand "sdk" -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
throw "Json file unreadable: '$JSonFile'"
|
Say-Error "Json file unreadable: '$JSonFile'"
|
||||||
|
throw
|
||||||
}
|
}
|
||||||
if ($JSonContent) {
|
if ($JSonContent) {
|
||||||
try {
|
try {
|
||||||
@@ -359,7 +395,8 @@ function Parse-Jsonfile-For-Version([string]$JSonFile) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
throw "Unable to parse the SDK node in '$JSonFile'"
|
Say-Error "Unable to parse the SDK node in '$JSonFile'"
|
||||||
|
throw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -375,16 +412,12 @@ function Get-Specific-Version-From-Version([string]$AzureFeed, [string]$Channel,
|
|||||||
Say-Invocation $MyInvocation
|
Say-Invocation $MyInvocation
|
||||||
|
|
||||||
if (-not $JSonFile) {
|
if (-not $JSonFile) {
|
||||||
switch ($Version.ToLower()) {
|
if ($Version.ToLower() -eq "latest") {
|
||||||
{ $_ -eq "latest" } {
|
$LatestVersionInfo = Get-Latest-Version-Info -AzureFeed $AzureFeed -Channel $Channel
|
||||||
$LatestVersionInfo = Get-Latest-Version-Info -AzureFeed $AzureFeed -Channel $Channel -Coherent $False
|
return $LatestVersionInfo.Version
|
||||||
return $LatestVersionInfo.Version
|
}
|
||||||
}
|
else {
|
||||||
{ $_ -eq "coherent" } {
|
return $Version
|
||||||
$LatestVersionInfo = Get-Latest-Version-Info -AzureFeed $AzureFeed -Channel $Channel -Coherent $True
|
|
||||||
return $LatestVersionInfo.Version
|
|
||||||
}
|
|
||||||
default { return $Version }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -619,6 +652,23 @@ function DownloadFile($Source, [string]$OutPath) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function SafeRemoveFile($Path) {
|
||||||
|
try {
|
||||||
|
if (Test-Path $Path) {
|
||||||
|
Remove-Item $Path
|
||||||
|
Say-Verbose "The temporary file `"$Path`" was removed."
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Say-Verbose "The temporary file `"$Path`" does not exist, therefore is not removed."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Say-Warning "Failed to remove the temporary file: `"$Path`", remove it manually."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function Prepend-Sdk-InstallRoot-To-Path([string]$InstallRoot, [string]$BinFolderRelativePath) {
|
function Prepend-Sdk-InstallRoot-To-Path([string]$InstallRoot, [string]$BinFolderRelativePath) {
|
||||||
$BinPath = Get-Absolute-Path $(Join-Path -Path $InstallRoot -ChildPath $BinFolderRelativePath)
|
$BinPath = Get-Absolute-Path $(Join-Path -Path $InstallRoot -ChildPath $BinFolderRelativePath)
|
||||||
if (-Not $NoPath) {
|
if (-Not $NoPath) {
|
||||||
@@ -673,7 +723,7 @@ if ($DryRun) {
|
|||||||
Say "NOTE: Due to finding a version manifest with this runtime, it would actually install with version '$EffectiveVersion'"
|
Say "NOTE: Due to finding a version manifest with this runtime, it would actually install with version '$EffectiveVersion'"
|
||||||
}
|
}
|
||||||
|
|
||||||
exit 0
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($Runtime -eq "dotnet") {
|
if ($Runtime -eq "dotnet") {
|
||||||
@@ -707,7 +757,7 @@ $isAssetInstalled = Is-Dotnet-Package-Installed -InstallRoot $InstallRoot -Relat
|
|||||||
if ($isAssetInstalled) {
|
if ($isAssetInstalled) {
|
||||||
Say "$assetName version $SpecificVersion is already installed."
|
Say "$assetName version $SpecificVersion is already installed."
|
||||||
Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot -BinFolderRelativePath $BinFolderRelativePath
|
Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot -BinFolderRelativePath $BinFolderRelativePath
|
||||||
exit 0
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
New-Item -ItemType Directory -Force -Path $InstallRoot | Out-Null
|
New-Item -ItemType Directory -Force -Path $InstallRoot | Out-Null
|
||||||
@@ -715,30 +765,69 @@ New-Item -ItemType Directory -Force -Path $InstallRoot | Out-Null
|
|||||||
$installDrive = $((Get-Item $InstallRoot).PSDrive.Name);
|
$installDrive = $((Get-Item $InstallRoot).PSDrive.Name);
|
||||||
$diskInfo = Get-PSDrive -Name $installDrive
|
$diskInfo = Get-PSDrive -Name $installDrive
|
||||||
if ($diskInfo.Free / 1MB -le 100) {
|
if ($diskInfo.Free / 1MB -le 100) {
|
||||||
Say "There is not enough disk space on drive ${installDrive}:"
|
throw "There is not enough disk space on drive ${installDrive}:"
|
||||||
exit 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$ZipPath = [System.IO.Path]::combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName())
|
$ZipPath = [System.IO.Path]::combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName())
|
||||||
Say-Verbose "Zip path: $ZipPath"
|
Say-Verbose "Zip path: $ZipPath"
|
||||||
|
|
||||||
$DownloadFailed = $false
|
$DownloadFailed = $false
|
||||||
Say "Downloading link: $DownloadLink"
|
|
||||||
|
$PrimaryDownloadStatusCode = 0
|
||||||
|
$LegacyDownloadStatusCode = 0
|
||||||
|
|
||||||
|
$PrimaryDownloadFailedMsg = ""
|
||||||
|
$LegacyDownloadFailedMsg = ""
|
||||||
|
|
||||||
|
Say "Downloading primary link $DownloadLink"
|
||||||
try {
|
try {
|
||||||
DownloadFile -Source $DownloadLink -OutPath $ZipPath
|
DownloadFile -Source $DownloadLink -OutPath $ZipPath
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
Say "Cannot download: $DownloadLink"
|
if ($PSItem.Exception.Data.Contains("StatusCode")) {
|
||||||
|
$PrimaryDownloadStatusCode = $PSItem.Exception.Data["StatusCode"]
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($PSItem.Exception.Data.Contains("ErrorMessage")) {
|
||||||
|
$PrimaryDownloadFailedMsg = $PSItem.Exception.Data["ErrorMessage"]
|
||||||
|
} else {
|
||||||
|
$PrimaryDownloadFailedMsg = $PSItem.Exception.Message
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($PrimaryDownloadStatusCode -eq 404) {
|
||||||
|
Say "The resource at $DownloadLink is not available."
|
||||||
|
} else {
|
||||||
|
Say $PSItem.Exception.Message
|
||||||
|
}
|
||||||
|
|
||||||
|
SafeRemoveFile -Path $ZipPath
|
||||||
|
|
||||||
if ($LegacyDownloadLink) {
|
if ($LegacyDownloadLink) {
|
||||||
$DownloadLink = $LegacyDownloadLink
|
$DownloadLink = $LegacyDownloadLink
|
||||||
$ZipPath = [System.IO.Path]::combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName())
|
$ZipPath = [System.IO.Path]::combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName())
|
||||||
Say-Verbose "Legacy zip path: $ZipPath"
|
Say-Verbose "Legacy zip path: $ZipPath"
|
||||||
Say "Downloading legacy link: $DownloadLink"
|
Say "Downloading legacy link $DownloadLink"
|
||||||
try {
|
try {
|
||||||
DownloadFile -Source $DownloadLink -OutPath $ZipPath
|
DownloadFile -Source $DownloadLink -OutPath $ZipPath
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
Say "Cannot download: $DownloadLink"
|
if ($PSItem.Exception.Data.Contains("StatusCode")) {
|
||||||
|
$LegacyDownloadStatusCode = $PSItem.Exception.Data["StatusCode"]
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($PSItem.Exception.Data.Contains("ErrorMessage")) {
|
||||||
|
$LegacyDownloadFailedMsg = $PSItem.Exception.Data["ErrorMessage"]
|
||||||
|
} else {
|
||||||
|
$LegacyDownloadFailedMsg = $PSItem.Exception.Message
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($LegacyDownloadStatusCode -eq 404) {
|
||||||
|
Say "The resource at $DownloadLink is not available."
|
||||||
|
} else {
|
||||||
|
Say $PSItem.Exception.Message
|
||||||
|
}
|
||||||
|
|
||||||
|
SafeRemoveFile -Path $ZipPath
|
||||||
$DownloadFailed = $true
|
$DownloadFailed = $true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -748,7 +837,19 @@ catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($DownloadFailed) {
|
if ($DownloadFailed) {
|
||||||
throw "Could not find/download: `"$assetName`" with version = $SpecificVersion`nRefer to: https://aka.ms/dotnet-os-lifecycle for information on .NET Core support"
|
if (($PrimaryDownloadStatusCode -eq 404) -and ((-not $LegacyDownloadLink) -or ($LegacyDownloadStatusCode -eq 404))) {
|
||||||
|
throw "Could not find `"$assetName`" with version = $SpecificVersion`nRefer to: https://aka.ms/dotnet-os-lifecycle for information on .NET Core support"
|
||||||
|
} else {
|
||||||
|
# 404-NotFound is an expected response if it goes from only one of the links, do not show that error.
|
||||||
|
# If primary path is available (not 404-NotFound) then show the primary error else show the legacy error.
|
||||||
|
if ($PrimaryDownloadStatusCode -ne 404) {
|
||||||
|
throw "Could not download `"$assetName`" with version = $SpecificVersion`r`n$PrimaryDownloadFailedMsg"
|
||||||
|
}
|
||||||
|
if (($LegacyDownloadLink) -and ($LegacyDownloadStatusCode -ne 404)) {
|
||||||
|
throw "Could not download `"$assetName`" with version = $SpecificVersion`r`n$LegacyDownloadFailedMsg"
|
||||||
|
}
|
||||||
|
throw "Could not download `"$assetName`" with version = $SpecificVersion"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Say "Extracting zip from $DownloadLink"
|
Say "Extracting zip from $DownloadLink"
|
||||||
@@ -770,207 +871,208 @@ if (!$isAssetInstalled) {
|
|||||||
$isAssetInstalled = Is-Dotnet-Package-Installed -InstallRoot $InstallRoot -RelativePathToPackage $dotnetPackageRelativePath -SpecificVersion $SpecificVersion
|
$isAssetInstalled = Is-Dotnet-Package-Installed -InstallRoot $InstallRoot -RelativePathToPackage $dotnetPackageRelativePath -SpecificVersion $SpecificVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Version verification failed. More likely something is wrong either with the downloaded content or with the verification algorithm.
|
||||||
if (!$isAssetInstalled) {
|
if (!$isAssetInstalled) {
|
||||||
|
Say-Error "Failed to verify the version of installed `"$assetName`".`nInstallation source: $DownloadLink.`nInstallation location: $InstallRoot.`nReport the bug at https://github.com/dotnet/install-scripts/issues."
|
||||||
throw "`"$assetName`" with version = $SpecificVersion failed to install with an unknown error."
|
throw "`"$assetName`" with version = $SpecificVersion failed to install with an unknown error."
|
||||||
}
|
}
|
||||||
|
|
||||||
Remove-Item $ZipPath
|
SafeRemoveFile -Path $ZipPath
|
||||||
|
|
||||||
Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot -BinFolderRelativePath $BinFolderRelativePath
|
Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot -BinFolderRelativePath $BinFolderRelativePath
|
||||||
|
|
||||||
Say "Note that the script does not resolve dependencies during installation."
|
Say "Note that the script does not resolve dependencies during installation."
|
||||||
Say "To check the list of dependencies, go to https://docs.microsoft.com/dotnet/core/install/windows#dependencies"
|
Say "To check the list of dependencies, go to https://docs.microsoft.com/dotnet/core/install/windows#dependencies"
|
||||||
Say "Installation finished"
|
Say "Installation finished"
|
||||||
exit 0
|
|
||||||
# SIG # Begin signature block
|
# SIG # Begin signature block
|
||||||
# MIIjlgYJKoZIhvcNAQcCoIIjhzCCI4MCAQExDzANBglghkgBZQMEAgEFADB5Bgor
|
# MIIjkgYJKoZIhvcNAQcCoIIjgzCCI38CAQExDzANBglghkgBZQMEAgEFADB5Bgor
|
||||||
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
|
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
|
||||||
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCA+isugNMwZSGLd
|
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCD2c707qnCLOLIC
|
||||||
# kfBd0C2Ud//U2Nbj31s1jg3Yf9gh4KCCDYUwggYDMIID66ADAgECAhMzAAABiK9S
|
# n6Mu5Gr4+Xp68foyZlGlTycnycc5l6CCDYEwggX/MIID56ADAgECAhMzAAABh3IX
|
||||||
# 1rmSbej5AAAAAAGIMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
|
# chVZQMcJAAAAAAGHMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
|
||||||
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
|
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
|
||||||
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
|
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
|
||||||
# bmcgUENBIDIwMTEwHhcNMjAwMzA0MTgzOTQ4WhcNMjEwMzAzMTgzOTQ4WjB0MQsw
|
# bmcgUENBIDIwMTEwHhcNMjAwMzA0MTgzOTQ3WhcNMjEwMzAzMTgzOTQ3WjB0MQsw
|
||||||
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
|
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
|
||||||
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
|
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
|
||||||
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
|
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
|
||||||
# AQCSCNryE+Cewy2m4t/a74wZ7C9YTwv1PyC4BvM/kSWPNs8n0RTe+FvYfU+E9uf0
|
# AQDOt8kLc7P3T7MKIhouYHewMFmnq8Ayu7FOhZCQabVwBp2VS4WyB2Qe4TQBT8aB
|
||||||
# t7nYlAzHjK+plif2BhD+NgdhIUQ8sVwWO39tjvQRHjP2//vSvIfmmkRoML1Ihnjs
|
# znANDEPjHKNdPT8Xz5cNali6XHefS8i/WXtF0vSsP8NEv6mBHuA2p1fw2wB/F0dH
|
||||||
# 9kQiZQzYRDYYRp9xSQYmRwQjk5hl8/U7RgOiQDitVHaU7BT1MI92lfZRuIIDDYBd
|
# sJ3GfZ5c0sPJjklsiYqPw59xJ54kM91IOgiO2OUzjNAljPibjCWfH7UzQ1TPHc4d
|
||||||
# vXtbclYJMVOwqZtv0O9zQCret6R+fRSGaDNfEEpcILL+D7RV3M4uaJE4Ta6KAOdv
|
# weils8GEIrbBRb7IWwiObL12jWT4Yh71NQgvJ9Fn6+UhD9x2uk3dLj84vwt1NuFQ
|
||||||
# V+MVaJp1YXFTZPKtpjHO6d9pHQPZiG7NdC6QbnRGmsa48uNQrb6AfmLKDI1Lp31W
|
# itKJxIV0fVsRNR3abQVOLqpDugbr0SzNL6o8xzOHL5OXiGGwg6ekiXA1/2XXY7yV
|
||||||
# MogTaX5tZf+CZT9PSuvjOCLNAgMBAAGjggGCMIIBfjAfBgNVHSUEGDAWBgorBgEE
|
# Fc39tledDtZjSjNbex1zzwSXAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE
|
||||||
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUj9RJL9zNrPcL10RZdMQIXZN7MG8w
|
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUhov4ZyO96axkJdMjpzu2zVXOJcsw
|
||||||
# VAYDVR0RBE0wS6RJMEcxLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh
|
# UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1
|
||||||
# dGlvbnMgTGltaXRlZDEWMBQGA1UEBRMNMjMwMDEyKzQ1ODM4NjAfBgNVHSMEGDAW
|
# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDU4Mzg1MB8GA1UdIwQYMBaAFEhu
|
||||||
# gBRIbmTlUAXTgqoXNzcitW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8v
|
# ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu
|
||||||
# d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIw
|
# bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w
|
||||||
# MTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDov
|
# Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3
|
||||||
# L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDEx
|
# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx
|
||||||
# XzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIB
|
# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAixmy
|
||||||
# ACnXo8hjp7FeT+H6iQlV3CcGnkSbFvIpKYafgzYCFo3UHY1VHYJVb5jHEO8oG26Q
|
# S6E6vprWD9KFNIB9G5zyMuIjZAOuUJ1EK/Vlg6Fb3ZHXjjUwATKIcXbFuFC6Wr4K
|
||||||
# qBELmak6MTI+ra3WKMTGhE1sEIlowTcp4IAs8a5wpCh6Vf4Z/bAtIppP3p3gXk2X
|
# NrU4DY/sBVqmab5AC/je3bpUpjtxpEyqUqtPc30wEg/rO9vmKmqKoLPT37svc2NV
|
||||||
# 8UXTc+WxjQYsDkFiSzo/OBa5hkdW1g4EpO43l9mjToBdqEPtIXsZ7Hi1/6y4gK0P
|
# BmGNl+85qO4fV/w7Cx7J0Bbqk19KcRNdjt6eKoTnTPHBHlVHQIHZpMxacbFOAkJr
|
||||||
# mMiwG8LMpSn0n/oSHGjrUNBgHJPxgs63Slf58QGBznuXiRaXmfTUDdrvhRocdxIM
|
# qAVkYZdz7ikNXTxV+GRb36tC4ByMNxE2DF7vFdvaiZP0CVZ5ByJ2gAhXMdK9+usx
|
||||||
# i8nXQwWACMiQzJSRzBP5S2wUq7nMAqjaTbeXhJqD2SFVHdUYlKruvtPSwbnqSRWT
|
# zVk913qKde1OAuWdv+rndqkAIm8fUlRnr4saSCg7cIbUwCCf116wUJ7EuJDg0vHe
|
||||||
# GI8s4FEXt+TL3w5JnwVZmZkUFoioQDMMjFyaKurdJ6pnzbr1h6QW0R97fWc8xEIz
|
# yhnCeHnBbyH3RZkHEi2ofmfgnFISJZDdMAeVZGVOh20Jp50XBzqokpPzeZ6zc1/g
|
||||||
# LIOiU2rjwWAtlQqFO8KNiykjYGyEf5LyAJKAO+rJd9fsYR+VBauIEQoYmjnUbTXM
|
# yILNyiVgE+RPkjnUQshd1f1PMgn3tns2Cz7bJiVUaqEO3n9qRFgy5JuLae6UweGf
|
||||||
# SY2Lf5KMluWlDOGVh8q6XjmBccpaT+8tCfxpaVYPi1ncnwTwaPQvVq8RjWDRB7Pa
|
# AeOo3dgLZxikKzYs3hDMaEtJq8IP71cX7QXe6lnMmXU/Hdfz2p897Zd+kU+vZvKI
|
||||||
# 8ruHgj2HJFi69+hcq7mWx5nTUtzzFa7RSZfE5a1a5AuBmGNRr7f8cNfa01+tiWjV
|
# 3cwLfuVQgK2RZ2z+Kc3K3dRPz2rXycK5XCuRZmvGab/WbrZiC7wJQapgBodltMI5
|
||||||
# Kk1a+gJUBSP0sIxecFbVSXTZ7bqeal45XSDIisZBkWb+83TbXdTGMDSUFKTAdtC+
|
# GMdFrBg9IeF7/rP4EqVQXeKtevTlZXjpuNhhjuR+2DMt/dWufjXpiW91bo3aH6Ea
|
||||||
# r35GfsN8QVy59Hb5ZYzAXczhgRmk7NyE6jD0Ym5TKiW5MIIHejCCBWKgAwIBAgIK
|
# jOALXmoxgltCp1K7hrS6gmsvj94cLRf50QQ4U8Qwggd6MIIFYqADAgECAgphDpDS
|
||||||
# YQ6Q0gAAAAAAAzANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV
|
# AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK
|
||||||
# BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv
|
|
||||||
# c29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlm
|
|
||||||
# aWNhdGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEw
|
|
||||||
# OTA5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE
|
|
||||||
# BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYD
|
|
||||||
# VQQDEx9NaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG
|
|
||||||
# 9w0BAQEFAAOCAg8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+la
|
|
||||||
# UKq4BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc
|
|
||||||
# 6Whe0t+bU7IKLMOv2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4D
|
|
||||||
# dato88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+
|
|
||||||
# lD3v++MrWhAfTVYoonpy4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nk
|
|
||||||
# kDstrjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6
|
|
||||||
# A4aN91/w0FK/jJSHvMAhdCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmd
|
|
||||||
# X4jiJV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL
|
|
||||||
# 5zmhD+kjSbwYuER8ReTBw3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zd
|
|
||||||
# sGbiwZeBe+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3
|
|
||||||
# T8HhhUSJxAlMxdSlQy90lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS
|
|
||||||
# 4NaIjAsCAwEAAaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRI
|
|
||||||
# bmTlUAXTgqoXNzcitW2oynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAL
|
|
||||||
# BgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBD
|
|
||||||
# uRQFTuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jv
|
|
||||||
# c29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf
|
|
||||||
# MDNfMjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3
|
|
||||||
# dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf
|
|
||||||
# MDNfMjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEF
|
|
||||||
# BQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1h
|
|
||||||
# cnljcHMuaHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkA
|
|
||||||
# YwB5AF8AcwB0AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn
|
|
||||||
# 8oalmOBUeRou09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7
|
|
||||||
# v0epo/Np22O/IjWll11lhJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0b
|
|
||||||
# pdS1HXeUOeLpZMlEPXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/
|
|
||||||
# KmtYSWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvy
|
|
||||||
# CInWH8MyGOLwxS3OW560STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBp
|
|
||||||
# mLJZiWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJi
|
|
||||||
# hsMdYzaXht/a8/jyFqGaJ+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYb
|
|
||||||
# BL7fQccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbS
|
|
||||||
# oqKfenoi+kiVH6v7RyOA9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sL
|
|
||||||
# gOppO6/8MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtX
|
|
||||||
# cVZOSEXAQsmbdlsKgEhr/Xmfwb1tbWrJUnMTDXpQzTGCFWcwghVjAgEBMIGVMH4x
|
|
||||||
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
|
|
||||||
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01p
|
|
||||||
# Y3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTECEzMAAAGIr1LWuZJt6PkAAAAA
|
|
||||||
# AYgwDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQw
|
|
||||||
# HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIK4I
|
|
||||||
# CDH7/r/eeMqTtDETJ67ogfneVRo0/P6ogV2vy4tXMEIGCisGAQQBgjcCAQwxNDAy
|
|
||||||
# oBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5j
|
|
||||||
# b20wDQYJKoZIhvcNAQEBBQAEggEAOnmVmILEjI6ZiuuSOvvTvijidkBez61Vz97A
|
|
||||||
# jV3AOsfmUvLpVaTVa1Mt2iPDuq1QLqRPaT7BD8PAUwr91pYllVgEd8NqivCIaCZg
|
|
||||||
# QyIRiTmHQxbozWsLcjxMvX2VxSmNKDw7IOHzUbXtmiEGhygyZpdh/uiCj7ziSxp3
|
|
||||||
# lQBR8mUE1NL9dxaxKWLhGeORqAepw6nId9oO+mHRh4JRK7uqZOFAES7/21M9vPZi
|
|
||||||
# XYilJLgIoyMkvqYSdoouzn6+m74kgzkNkyK9GYz2mmO2BCMnai9Njze2d0+kY+37
|
|
||||||
# kt10BmJDw3FHaZ+/fH/TMTgo0ZcAOicP9ccdIh/CzzpU52o+Q6GCEvEwghLtBgor
|
|
||||||
# BgEEAYI3AwMBMYIS3TCCEtkGCSqGSIb3DQEHAqCCEsowghLGAgEDMQ8wDQYJYIZI
|
|
||||||
# AWUDBAIBBQAwggFVBgsqhkiG9w0BCRABBKCCAUQEggFAMIIBPAIBAQYKKwYBBAGE
|
|
||||||
# WQoDATAxMA0GCWCGSAFlAwQCAQUABCBSbhMJwNER+BICn3iLUnPrP8dptyUphcFC
|
|
||||||
# A/NsIgnPLwIGX4hEzP6WGBMyMDIwMTEwOTE0NDY1Mi4yMzNaMASAAgH0oIHUpIHR
|
|
||||||
# MIHOMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
|
|
||||||
# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSkwJwYDVQQL
|
|
||||||
# EyBNaWNyb3NvZnQgT3BlcmF0aW9ucyBQdWVydG8gUmljbzEmMCQGA1UECxMdVGhh
|
|
||||||
# bGVzIFRTUyBFU046MEE1Ni1FMzI5LTRENEQxJTAjBgNVBAMTHE1pY3Jvc29mdCBU
|
|
||||||
# aW1lLVN0YW1wIFNlcnZpY2Wggg5EMIIE9TCCA92gAwIBAgITMwAAAScvbqPvkagZ
|
|
||||||
# qAAAAAABJzANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMK
|
|
||||||
# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
|
# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
|
||||||
# IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0Eg
|
# IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0
|
||||||
# MjAxMDAeFw0xOTEyMTkwMTE0NTlaFw0yMTAzMTcwMTE0NTlaMIHOMQswCQYDVQQG
|
# ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla
|
||||||
# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG
|
# MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS
|
||||||
# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSkwJwYDVQQLEyBNaWNyb3NvZnQg
|
# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT
|
||||||
# T3BlcmF0aW9ucyBQdWVydG8gUmljbzEmMCQGA1UECxMdVGhhbGVzIFRTUyBFU046
|
# H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB
|
||||||
# MEE1Ni1FMzI5LTRENEQxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNl
|
# AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG
|
||||||
# cnZpY2UwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD4Ad5xEZ5On0uN
|
# OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S
|
||||||
# L71ng9xwoDPRKeMUyEIj5yVxPRPh5GVbU7D3pqDsoXzQMhfeRP61L1zlU1HCRS+1
|
# 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz
|
||||||
# 29eo0yj1zjbAlmPAwosUgyIonesWt9E4hFlXCGUcIg5XMdvQ+Ouzk2r+awNRuk8A
|
# y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7
|
||||||
# BGOa0I4VBy6zqCYHyX2pGauiB43frJSNP6pcrO0CBmpBZNjgepof5Z/50vBuJDUS
|
# 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u
|
||||||
# ug6OIMQ7ZwUhSzX4bEmZUUjAycBb62dhQpGqHsXe6ypVDTgAEnGONdSBKkHiNT8H
|
# M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33
|
||||||
# 0Zt2lm0vCLwHyTwtgIdi67T/LCp+X2mlPHqXsY3u72X3GYn/3G8YFCkrSc6m3b0w
|
# X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl
|
||||||
# TXPd5/2fAgMBAAGjggEbMIIBFzAdBgNVHQ4EFgQU5fSWVYBfOTEkW2JTiV24WNNt
|
# XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP
|
||||||
# lfIwHwYDVR0jBBgwFoAU1WM6XIoxkPNDe3xGG8UzaFqFbVUwVgYDVR0fBE8wTTBL
|
# 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB
|
||||||
# oEmgR4ZFaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMv
|
# l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF
|
||||||
# TWljVGltU3RhUENBXzIwMTAtMDctMDEuY3JsMFoGCCsGAQUFBwEBBE4wTDBKBggr
|
# RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM
|
||||||
# BgEFBQcwAoY+aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNU
|
# CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ
|
||||||
# aW1TdGFQQ0FfMjAxMC0wNy0wMS5jcnQwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAK
|
# BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud
|
||||||
# BggrBgEFBQcDCDANBgkqhkiG9w0BAQsFAAOCAQEACsqNfNFVxwalZ42cEMuzZc12
|
# DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO
|
||||||
# 6Nvluanx8UewDVeUQZEZHRmppMFHAzS/g6RzmxTyR2tKE3mChNGW5dTL730vEbRh
|
# 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0
|
||||||
# nYRmBgiX/gT3f4AQrOPnZGXY7zszcrlbgzxpakOX+x0u4rkP3Ashh3B2CdJ11XsB
|
# LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
|
||||||
# di5PiZa1spB6U5S8D15gqTUfoIniLT4v1DBdkWExsKI1vsiFcDcjGJ4xRlMRF+fw
|
# Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p
|
||||||
# 7SY0WZoOzwRzKxDTdg4DusAXpaeKbch9iithLFk/vIxQrqCr/niW8tEA+eSzeX/E
|
# Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
|
||||||
# q1D0ZyvOn4e2lTnwoJUKH6OQAWSBogyK4OCbFeJOqdKAUiBTgHKkQIYh/tbKQjCC
|
# Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB
|
||||||
# BnEwggRZoAMCAQICCmEJgSoAAAAAAAIwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNV
|
# FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw
|
||||||
# BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4w
|
# cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA
|
||||||
# HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29m
|
# XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY
|
||||||
# dCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDEwMB4XDTEwMDcwMTIxMzY1
|
# 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj
|
||||||
# NVoXDTI1MDcwMTIxNDY1NVowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp
|
# 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd
|
||||||
# bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw
|
# d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ
|
||||||
# b3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAw
|
# Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf
|
||||||
# ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpHQ28dxGKOiDs/BOX9fp/
|
# wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ
|
||||||
# aZRrdFQQ1aUKAIKF++18aEssX8XD5WHCdrc+Zitb8BVTJwQxH0EbGpUdzgkTjnxh
|
# aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j
|
||||||
# MFmxMEQP8WCIhFRDDNdNuDgIs0Ldk6zWczBXJoKjRQ3Q6vVHgc2/JGAyWGBG8lhH
|
# NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B
|
||||||
# hjKEHnRhZ5FfgVSxz5NMksHEpl3RYRNuKMYa+YaAu99h/EbBJx0kZxJyGiGKr0tk
|
# xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96
|
||||||
# iVBisV39dx898Fd1rL2KQk1AUdEPnAY+Z3/1ZsADlkR+79BL/W7lmsqxqPJ6Kgox
|
# eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7
|
||||||
# 8NpOBpG2iAg16HgcsOmZzTznL0S6p/TcZL2kAcEgCZN4zfy8wMlEXV4WnAEFTyJN
|
# r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I
|
||||||
# AgMBAAGjggHmMIIB4jAQBgkrBgEEAYI3FQEEAwIBADAdBgNVHQ4EFgQU1WM6XIox
|
# RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIVZzCCFWMCAQEwgZUwfjELMAkG
|
||||||
# kPNDe3xGG8UzaFqFbVUwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYDVR0P
|
# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
|
||||||
# BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU1fZWy4/oolxiaNE9
|
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z
|
||||||
# lJBb186aGMQwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5taWNyb3NvZnQu
|
# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAYdyF3IVWUDHCQAAAAABhzAN
|
||||||
# Y29tL3BraS9jcmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3Js
|
# BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor
|
||||||
# MFoGCCsGAQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0cDovL3d3dy5taWNyb3Nv
|
# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgE/MRhWyu
|
||||||
# ZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcnQwgaAG
|
# Zg+EA2WKcxYC31nHVCTE6guHppZppc70RtkwQgYKKwYBBAGCNwIBDDE0MDKgFIAS
|
||||||
# A1UdIAEB/wSBlTCBkjCBjwYJKwYBBAGCNy4DMIGBMD0GCCsGAQUFBwIBFjFodHRw
|
# AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN
|
||||||
# Oi8vd3d3Lm1pY3Jvc29mdC5jb20vUEtJL2RvY3MvQ1BTL2RlZmF1bHQuaHRtMEAG
|
# BgkqhkiG9w0BAQEFAASCAQBvcYCjRDXUYEIz9j2j0r4GFI2Y3g/CoNxDDBaeQ+gV
|
||||||
# CCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAFAAbwBsAGkAYwB5AF8AUwB0AGEA
|
# khO0fK0oLh18RbV271Mg6SF7X7+mXB5MnL68voVQDqHnsCYrIAuMF/AEpv9YuDDp
|
||||||
# dABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQAH5ohRDeLG4Jg/gXED
|
# ZRJuqN7Vwg3HM02l/FyATBIMgf/V79aYzJL3jjtt9bRIyxk6aPU4XcwMeA4usnUQ
|
||||||
# PZ2joSFvs+umzPUxvs8F4qn++ldtGTCzwsVmyWrf9efweL3HqJ4l4/m87WtUVwgr
|
# rMhIiQz07DgfSrcQWe4AvGFAIvqTAKE4P944EZWWVnWI/10rvatEAefqJZX3XljW
|
||||||
# UYJEEvu5U4zM9GASinbMQEBBm9xcF/9c+V4XNZgkVkt070IQyK+/f8Z/8jd9Wj8c
|
# sK/6NY/0MyAyiILOuXbvVS0YFbHaR2qd1jUXbrY79fS+H4Ts6qnbufOkHQvmcDxs
|
||||||
# 8pl5SpFSAK84Dxf1L3mBZdmptWvkx872ynoAb0swRCQiPM/tA6WWj1kpvLb9BOFw
|
# 801wKLHumMdPTtMVzfVMCwPvrHP0wtzsFlmCcKjBbGpvoYIS8TCCEu0GCisGAQQB
|
||||||
# nzJKJ/1Vry/+tuWOM7tiX5rbV0Dp8c6ZZpCM/2pif93FSguRJuI57BlKcWOdeyFt
|
# gjcDAwExghLdMIIS2QYJKoZIhvcNAQcCoIISyjCCEsYCAQMxDzANBglghkgBZQME
|
||||||
# w5yjojz6f32WapB4pm3S4Zz5Hfw42JT0xqUKloakvZ4argRCg7i1gJsiOCC1JeVk
|
# AgEFADCCAVUGCyqGSIb3DQEJEAEEoIIBRASCAUAwggE8AgEBBgorBgEEAYRZCgMB
|
||||||
# 7Pf0v35jWSUPei45V3aicaoGig+JFrphpxHLmtgOR5qAxdDNp9DvfYPw4TtxCd9d
|
# MDEwDQYJYIZIAWUDBAIBBQAEINdeoXtuzW+Dihw6n+VdG+91si0f6TvWhJXaPtvW
|
||||||
# dJgiCGHasFAeb73x4QDf5zEHpJM692VHeOj4qEir995yfmFrb3epgcunCaw5u+zG
|
# oF4cAgZfu+i3IT8YEzIwMjAxMjE3MDYzMDM2LjU0M1owBIACAfSggdSkgdEwgc4x
|
||||||
# y9iCtHLNHfS4hQEegPsbiSpUObJb2sgNVZl6h3M7COaYLeqN4DMuEin1wC9UJyH3
|
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
|
||||||
# yKxO2ii4sanblrKnQqLJzxlBTeCG+SqaoxFmMNO7dDJL32N79ZmKLxvHIa9Zta7c
|
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1p
|
||||||
# RDyXUHHXodLFVeNp3lfB0d4wwP3M5k37Db9dT+mdHhk4L7zPWAUu7w2gUDXa7wkn
|
# Y3Jvc29mdCBPcGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMg
|
||||||
# HNWzfjUeCLraNtvTX4/edIhJEqGCAtIwggI7AgEBMIH8oYHUpIHRMIHOMQswCQYD
|
# VFNTIEVTTjo4OTdBLUUzNTYtMTcwMTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUt
|
||||||
# VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEe
|
# U3RhbXAgU2VydmljZaCCDkQwggT1MIID3aADAgECAhMzAAABLCKvRZd1+RvuAAAA
|
||||||
# MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSkwJwYDVQQLEyBNaWNyb3Nv
|
# AAEsMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo
|
||||||
# ZnQgT3BlcmF0aW9ucyBQdWVydG8gUmljbzEmMCQGA1UECxMdVGhhbGVzIFRTUyBF
|
# aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y
|
||||||
# U046MEE1Ni1FMzI5LTRENEQxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1w
|
# cG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEw
|
||||||
# IFNlcnZpY2WiIwoBATAHBgUrDgMCGgMVALOVuE5sgxzETO4s+poBqI6r1x8zoIGD
|
# MB4XDTE5MTIxOTAxMTUwM1oXDTIxMDMxNzAxMTUwM1owgc4xCzAJBgNVBAYTAlVT
|
||||||
# MIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV
|
# MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK
|
||||||
# BAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQG
|
# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVy
|
||||||
# A1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwDQYJKoZIhvcNAQEF
|
# YXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjo4OTdB
|
||||||
# BQACBQDjU7byMCIYDzIwMjAxMTA5MTYzOTE0WhgPMjAyMDExMTAxNjM5MTRaMHcw
|
# LUUzNTYtMTcwMTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vydmlj
|
||||||
# PQYKKwYBBAGEWQoEATEvMC0wCgIFAONTtvICAQAwCgIBAAICIt0CAf8wBwIBAAIC
|
# ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPK1zgSSq+MxAYo3qpCt
|
||||||
# EcQwCgIFAONVCHICAQAwNgYKKwYBBAGEWQoEAjEoMCYwDAYKKwYBBAGEWQoDAqAK
|
# QDxSMPPJy6mm/wfEJNjNUnYtLFBwl1BUS5trEk/t41ldxITKehs+ABxYqo4Qxsg3
|
||||||
# MAgCAQACAwehIKEKMAgCAQACAwGGoDANBgkqhkiG9w0BAQUFAAOBgQAQhyIIAC/A
|
# Gy1ugKiwHAnYiiekfC+ZhptNFgtnDZIn45zC0AlVr/6UfLtsLcHCh1XElLUHfEC0
|
||||||
# P+VJdbhL9IQgm8WTa1DmPPE+BQSuRbBy2MmzC1KostixdEkr2OaNSjcYuZBNIJgv
|
# nBuQcM/SpYo9e3l1qY5NdMgDGxCsmCKdiZfYXIu+U0UYIBhdzmSHnB3fxZOBVcr5
|
||||||
# vE8CWhVDD+sbBpVcOdoSfoBwHXKfvqSTiWvovoexkF0X5aon7yr3PkJ/kEqoLyUM
|
# htFHEBBNt/rFJlm/A4yb8oBsp+Uf0p5QwmO/bCcdqB15JpylOhZmWs0sUfJKlK9E
|
||||||
# xRvdWKJdHOL1sT0/aWHn048c6aGin/zc8DGCAw0wggMJAgEBMIGTMHwxCzAJBgNV
|
# rAhBwGki2eIRFKsQBdkXS9PWpF1w2gIJRvSkDEaCf+lbGTPdSzHSbfREWOF9wY3i
|
||||||
# BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4w
|
# Yj8CAwEAAaOCARswggEXMB0GA1UdDgQWBBRRahZSGfrCQhCyIyGH9DkiaW7L0zAf
|
||||||
# HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29m
|
# BgNVHSMEGDAWgBTVYzpcijGQ80N7fEYbxTNoWoVtVTBWBgNVHR8ETzBNMEugSaBH
|
||||||
# dCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABJy9uo++RqBmoAAAAAAEnMA0GCWCG
|
# hkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNU
|
||||||
# SAFlAwQCAQUAoIIBSjAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwLwYJKoZI
|
# aW1TdGFQQ0FfMjAxMC0wNy0wMS5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUF
|
||||||
# hvcNAQkEMSIEIJZkrbvF4R8oqYYpN6ZPGOj+QEZTQriEi/Yw9gW6zMqRMIH6Bgsq
|
# BzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1RpbVN0
|
||||||
# hkiG9w0BCRACLzGB6jCB5zCB5DCBvQQgG5LoSxKGHWoW/wVMlbMztlQ4upAdzEmq
|
# YVBDQV8yMDEwLTA3LTAxLmNydDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsG
|
||||||
# H//vLu0jPiIwgZgwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu
|
# AQUFBwMIMA0GCSqGSIb3DQEBCwUAA4IBAQBPFxHIwi4vAH49w9Svmz6K3tM55RlW
|
||||||
# Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv
|
# 5pPeULXdut2Rqy6Ys0+VpZsbuaEoxs6Z1C3hMbkiqZFxxyltxJpuHTyGTg61zfNI
|
||||||
# cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAIT
|
# F5n6RsYF3s7IElDXNfZznF1/2iWc6uRPZK8rxxUJ/7emYXZCYwuUY0XjsCpP9pbR
|
||||||
# MwAAAScvbqPvkagZqAAAAAABJzAiBCDwhEViCRvqKwQV3MxociF2iGYrDP4p1BK+
|
# RKeJi6r5arSyI+NfKxvgoM21JNt1BcdlXuAecdd/k8UjxCscffanoK2n6LFw1PcZ
|
||||||
# s4tStO4vSDANBgkqhkiG9w0BAQsFAASCAQAkgmDo8lVmar0ZIqTG1it3skG8PZC9
|
# lEO7NId7o+soM2C0QY5BYdghpn7uqopB6ixyFIIkDXFub+1E7GmAEwfU6VwEHL7y
|
||||||
# iqEEC1vxcz8OSfsjl2QSkQ5T2+3xWpxWA4uy2+Byv0bi8EsfQEnnn4vtdthS6/kb
|
# 9rNE8bd+JrQs+yAtkkHy9FmXg/PsGq1daVzX1So7CJ6nyphpuHSN3VfTMIIGcTCC
|
||||||
# vB/LLQiqoMhJ0rasf3/y/4KnQZEtztpg1+cCaNwFUgI6o+E8YEFt1frhLwFs/0WH
|
# BFmgAwIBAgIKYQmBKgAAAAAAAjANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMC
|
||||||
# 5pyBFx9ECEs0M22SLIpW13gexv9fgk6ZboIfSreAI28DLveeJpkgwggxHRpuVOVD
|
# VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV
|
||||||
# 4D7QQJAvJ0VU6p+yJlbvQXR9iltwb1REhlsJ5mADJ/FkzPVX/swMSUIoyE2inlxK
|
# BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJv
|
||||||
# LEiPkkZYwiFYCifFYUTnQjWU1Ls0EV+ysosL+jhzCxO8S6oRdp5TAi4F
|
# b3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMTAwNzAxMjEzNjU1WhcN
|
||||||
|
# MjUwNzAxMjE0NjU1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
|
||||||
|
# bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
|
||||||
|
# aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCCASIw
|
||||||
|
# DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkdDbx3EYo6IOz8E5f1+n9plGt0
|
||||||
|
# VBDVpQoAgoX77XxoSyxfxcPlYcJ2tz5mK1vwFVMnBDEfQRsalR3OCROOfGEwWbEw
|
||||||
|
# RA/xYIiEVEMM1024OAizQt2TrNZzMFcmgqNFDdDq9UeBzb8kYDJYYEbyWEeGMoQe
|
||||||
|
# dGFnkV+BVLHPk0ySwcSmXdFhE24oxhr5hoC732H8RsEnHSRnEnIaIYqvS2SJUGKx
|
||||||
|
# Xf13Hz3wV3WsvYpCTUBR0Q+cBj5nf/VmwAOWRH7v0Ev9buWayrGo8noqCjHw2k4G
|
||||||
|
# kbaICDXoeByw6ZnNPOcvRLqn9NxkvaQBwSAJk3jN/LzAyURdXhacAQVPIk0CAwEA
|
||||||
|
# AaOCAeYwggHiMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBTVYzpcijGQ80N7
|
||||||
|
# fEYbxTNoWoVtVTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMC
|
||||||
|
# AYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvX
|
||||||
|
# zpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20v
|
||||||
|
# cGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYI
|
||||||
|
# KwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5j
|
||||||
|
# b20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDCBoAYDVR0g
|
||||||
|
# AQH/BIGVMIGSMIGPBgkrBgEEAYI3LgMwgYEwPQYIKwYBBQUHAgEWMWh0dHA6Ly93
|
||||||
|
# d3cubWljcm9zb2Z0LmNvbS9QS0kvZG9jcy9DUFMvZGVmYXVsdC5odG0wQAYIKwYB
|
||||||
|
# BQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AUABvAGwAaQBjAHkAXwBTAHQAYQB0AGUA
|
||||||
|
# bQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAAfmiFEN4sbgmD+BcQM9naOh
|
||||||
|
# IW+z66bM9TG+zwXiqf76V20ZMLPCxWbJat/15/B4vceoniXj+bzta1RXCCtRgkQS
|
||||||
|
# +7lTjMz0YBKKdsxAQEGb3FwX/1z5Xhc1mCRWS3TvQhDIr79/xn/yN31aPxzymXlK
|
||||||
|
# kVIArzgPF/UveYFl2am1a+THzvbKegBvSzBEJCI8z+0DpZaPWSm8tv0E4XCfMkon
|
||||||
|
# /VWvL/625Y4zu2JfmttXQOnxzplmkIz/amJ/3cVKC5Em4jnsGUpxY517IW3DnKOi
|
||||||
|
# PPp/fZZqkHimbdLhnPkd/DjYlPTGpQqWhqS9nhquBEKDuLWAmyI4ILUl5WTs9/S/
|
||||||
|
# fmNZJQ96LjlXdqJxqgaKD4kWumGnEcua2A5HmoDF0M2n0O99g/DhO3EJ3110mCII
|
||||||
|
# YdqwUB5vvfHhAN/nMQekkzr3ZUd46PioSKv33nJ+YWtvd6mBy6cJrDm77MbL2IK0
|
||||||
|
# cs0d9LiFAR6A+xuJKlQ5slvayA1VmXqHczsI5pgt6o3gMy4SKfXAL1QnIffIrE7a
|
||||||
|
# KLixqduWsqdCosnPGUFN4Ib5KpqjEWYw07t0MkvfY3v1mYovG8chr1m1rtxEPJdQ
|
||||||
|
# cdeh0sVV42neV8HR3jDA/czmTfsNv11P6Z0eGTgvvM9YBS7vDaBQNdrvCScc1bN+
|
||||||
|
# NR4Iuto229Nfj950iEkSoYIC0jCCAjsCAQEwgfyhgdSkgdEwgc4xCzAJBgNVBAYT
|
||||||
|
# AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD
|
||||||
|
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBP
|
||||||
|
# cGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjo4
|
||||||
|
# OTdBLUUzNTYtMTcwMTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vy
|
||||||
|
# dmljZaIjCgEBMAcGBSsOAwIaAxUADE5OKSMoNx/mYxYWap1RTOohbJ2ggYMwgYCk
|
||||||
|
# fjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
|
||||||
|
# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD
|
||||||
|
# Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIF
|
||||||
|
# AOOFYaowIhgPMjAyMDEyMTcwODQ4NDJaGA8yMDIwMTIxODA4NDg0MlowdzA9Bgor
|
||||||
|
# BgEEAYRZCgQBMS8wLTAKAgUA44VhqgIBADAKAgEAAgIoWgIB/zAHAgEAAgISJTAK
|
||||||
|
# AgUA44azKgIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIB
|
||||||
|
# AAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAB53NDoDDF4vqFWY
|
||||||
|
# fwUnSvAy3z0CtqSFeA9RzDKGklPRwVkya5DtmVBDTZUbVQ2ST9hvRAVxhktfyVBZ
|
||||||
|
# ewapGJsvwMhg7nnEqBOumt6TvueIZpbs+p5z//3+iFYGkT3YFQI0Gd2JkvgBxfs5
|
||||||
|
# +GptO6JKtiyA+zkKijxqXZvMqMxBMYIDDTCCAwkCAQEwgZMwfDELMAkGA1UEBhMC
|
||||||
|
# VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV
|
||||||
|
# BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp
|
||||||
|
# bWUtU3RhbXAgUENBIDIwMTACEzMAAAEsIq9Fl3X5G+4AAAAAASwwDQYJYIZIAWUD
|
||||||
|
# BAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0B
|
||||||
|
# CQQxIgQg3wEUtEvxwCp3aAFB2vGXOOqg/AXHyXZh9P9J+0uArDMwgfoGCyqGSIb3
|
||||||
|
# DQEJEAIvMYHqMIHnMIHkMIG9BCBbn/0uFFh42hTM5XOoKdXevBaiSxmYK9Ilcn9n
|
||||||
|
# u5ZH4TCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u
|
||||||
|
# MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp
|
||||||
|
# b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAB
|
||||||
|
# LCKvRZd1+RvuAAAAAAEsMCIEINBRtGID6jvA2ptfwIuPyG7qPcLRYb9YrJ8aKfVg
|
||||||
|
# TulFMA0GCSqGSIb3DQEBCwUABIIBACQQpFGWW6JmH5MTKwhaE/8+gyzI2bT8XJnA
|
||||||
|
# t8k7PHFvEGA7whgp9eNgW+wWJm1gnsmswjx2l7FW4DLg9lghM8FK77JRCg7CJfse
|
||||||
|
# dSbnTv81/4VhSXOAO0jMP2dALP7DF59vQmlDh50u8/Wu61ActMOt6cArkoUhBRXO
|
||||||
|
# LnqOQCOEEku5Xy2ES9g9eUfLUvTvlWo6HiAq+cJnNV08QRBOnGWRxdwy8YJ5vwNW
|
||||||
|
# Pwx0ZG3rTvMtGzOaW6Ve5O36H2ynoEdzCmpakeDaF2sZ86/LNERKyIXiykV/Uig1
|
||||||
|
# SZh2VLY/Yni9SCVHbYgvTOCh5ZZE5eOi6BwLf0T4xl5alHUx+AA=
|
||||||
# SIG # End signature block
|
# SIG # End signature block
|
||||||
|
|||||||
211
src/Misc/dotnet-install.sh
vendored
211
src/Misc/dotnet-install.sh
vendored
@@ -40,7 +40,7 @@ if [ -t 1 ] && command -v tput > /dev/null; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
say_warning() {
|
say_warning() {
|
||||||
printf "%b\n" "${yellow:-}dotnet_install: Warning: $1${normal:-}"
|
printf "%b\n" "${yellow:-}dotnet_install: Warning: $1${normal:-}" >&3
|
||||||
}
|
}
|
||||||
|
|
||||||
say_err() {
|
say_err() {
|
||||||
@@ -183,6 +183,9 @@ get_current_os_name() {
|
|||||||
elif is_musl_based_distro; then
|
elif is_musl_based_distro; then
|
||||||
echo "linux-musl"
|
echo "linux-musl"
|
||||||
return 0
|
return 0
|
||||||
|
elif [ "$linux_platform_name" = "linux-musl" ]; then
|
||||||
|
echo "linux-musl"
|
||||||
|
return 0
|
||||||
else
|
else
|
||||||
echo "linux"
|
echo "linux"
|
||||||
return 0
|
return 0
|
||||||
@@ -296,7 +299,7 @@ get_machine_architecture() {
|
|||||||
if command -v uname > /dev/null; then
|
if command -v uname > /dev/null; then
|
||||||
CPUName=$(uname -m)
|
CPUName=$(uname -m)
|
||||||
case $CPUName in
|
case $CPUName in
|
||||||
armv7l)
|
armv*l)
|
||||||
echo "arm"
|
echo "arm"
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
@@ -341,6 +344,30 @@ get_normalized_architecture_from_architecture() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# args:
|
||||||
|
# user_defined_os - $1
|
||||||
|
get_normalized_os() {
|
||||||
|
eval $invocation
|
||||||
|
|
||||||
|
local osname="$(to_lowercase "$1")"
|
||||||
|
if [ ! -z "$osname" ]; then
|
||||||
|
case "$osname" in
|
||||||
|
osx | freebsd | rhel.6 | linux-musl | linux)
|
||||||
|
echo "$osname"
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
say_err "'$user_defined_os' is not a supported value for --os option, supported values are: osx, linux, linux-musl, freebsd, rhel.6. If you think this is a bug, report it at https://github.com/dotnet/install-scripts/issues."
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
osname="$(get_current_os_name)" || return 1
|
||||||
|
fi
|
||||||
|
echo "$osname"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
# 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):
|
||||||
# Line 1: # commit_hash
|
# Line 1: # commit_hash
|
||||||
@@ -382,14 +409,12 @@ is_dotnet_package_installed() {
|
|||||||
# azure_feed - $1
|
# azure_feed - $1
|
||||||
# channel - $2
|
# channel - $2
|
||||||
# normalized_architecture - $3
|
# normalized_architecture - $3
|
||||||
# coherent - $4
|
|
||||||
get_latest_version_info() {
|
get_latest_version_info() {
|
||||||
eval $invocation
|
eval $invocation
|
||||||
|
|
||||||
local azure_feed="$1"
|
local azure_feed="$1"
|
||||||
local channel="$2"
|
local channel="$2"
|
||||||
local normalized_architecture="$3"
|
local normalized_architecture="$3"
|
||||||
local coherent="$4"
|
|
||||||
|
|
||||||
local version_file_url=null
|
local version_file_url=null
|
||||||
if [[ "$runtime" == "dotnet" ]]; then
|
if [[ "$runtime" == "dotnet" ]]; then
|
||||||
@@ -397,11 +422,7 @@ get_latest_version_info() {
|
|||||||
elif [[ "$runtime" == "aspnetcore" ]]; then
|
elif [[ "$runtime" == "aspnetcore" ]]; then
|
||||||
version_file_url="$uncached_feed/aspnetcore/Runtime/$channel/latest.version"
|
version_file_url="$uncached_feed/aspnetcore/Runtime/$channel/latest.version"
|
||||||
elif [ -z "$runtime" ]; then
|
elif [ -z "$runtime" ]; then
|
||||||
if [ "$coherent" = true ]; then
|
version_file_url="$uncached_feed/Sdk/$channel/latest.version"
|
||||||
version_file_url="$uncached_feed/Sdk/$channel/latest.coherent.version"
|
|
||||||
else
|
|
||||||
version_file_url="$uncached_feed/Sdk/$channel/latest.version"
|
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
say_err "Invalid value for \$runtime"
|
say_err "Invalid value for \$runtime"
|
||||||
return 1
|
return 1
|
||||||
@@ -468,26 +489,16 @@ get_specific_version_from_version() {
|
|||||||
local json_file="$5"
|
local json_file="$5"
|
||||||
|
|
||||||
if [ -z "$json_file" ]; then
|
if [ -z "$json_file" ]; then
|
||||||
case "$version" in
|
if [[ "$version" == "latest" ]]; then
|
||||||
latest)
|
local version_info
|
||||||
local version_info
|
version_info="$(get_latest_version_info "$azure_feed" "$channel" "$normalized_architecture" false)" || return 1
|
||||||
version_info="$(get_latest_version_info "$azure_feed" "$channel" "$normalized_architecture" false)" || return 1
|
say_verbose "get_specific_version_from_version: version_info=$version_info"
|
||||||
say_verbose "get_specific_version_from_version: version_info=$version_info"
|
echo "$version_info" | get_version_from_version_info
|
||||||
echo "$version_info" | get_version_from_version_info
|
return 0
|
||||||
return 0
|
else
|
||||||
;;
|
echo "$version"
|
||||||
coherent)
|
return 0
|
||||||
local version_info
|
fi
|
||||||
version_info="$(get_latest_version_info "$azure_feed" "$channel" "$normalized_architecture" true)" || return 1
|
|
||||||
say_verbose "get_specific_version_from_version: version_info=$version_info"
|
|
||||||
echo "$version_info" | get_version_from_version_info
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "$version"
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
else
|
else
|
||||||
local version_info
|
local version_info
|
||||||
version_info="$(parse_jsonfile_for_version "$json_file")" || return 1
|
version_info="$(parse_jsonfile_for_version "$json_file")" || return 1
|
||||||
@@ -501,6 +512,7 @@ get_specific_version_from_version() {
|
|||||||
# channel - $2
|
# channel - $2
|
||||||
# normalized_architecture - $3
|
# normalized_architecture - $3
|
||||||
# specific_version - $4
|
# specific_version - $4
|
||||||
|
# normalized_os - $5
|
||||||
construct_download_link() {
|
construct_download_link() {
|
||||||
eval $invocation
|
eval $invocation
|
||||||
|
|
||||||
@@ -509,10 +521,8 @@ construct_download_link() {
|
|||||||
local normalized_architecture="$3"
|
local normalized_architecture="$3"
|
||||||
local specific_version="${4//[$'\t\r\n']}"
|
local specific_version="${4//[$'\t\r\n']}"
|
||||||
local specific_product_version="$(get_specific_product_version "$1" "$4")"
|
local specific_product_version="$(get_specific_product_version "$1" "$4")"
|
||||||
|
local osname="$5"
|
||||||
local osname
|
|
||||||
osname="$(get_current_os_name)" || return 1
|
|
||||||
|
|
||||||
local download_link=null
|
local download_link=null
|
||||||
if [[ "$runtime" == "dotnet" ]]; then
|
if [[ "$runtime" == "dotnet" ]]; then
|
||||||
download_link="$azure_feed/Runtime/$specific_version/dotnet-runtime-$specific_product_version-$osname-$normalized_architecture.tar.gz"
|
download_link="$azure_feed/Runtime/$specific_version/dotnet-runtime-$specific_product_version-$osname-$normalized_architecture.tar.gz"
|
||||||
@@ -692,11 +702,31 @@ extract_dotnet_package() {
|
|||||||
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"
|
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"
|
||||||
|
|
||||||
rm -rf "$temp_out_path"
|
rm -rf "$temp_out_path"
|
||||||
|
rm -f "$zip_path" && say_verbose "Temporary zip file $zip_path was removed"
|
||||||
|
|
||||||
if [ "$failed" = true ]; then
|
if [ "$failed" = true ]; then
|
||||||
say_err "Extraction failed"
|
say_err "Extraction failed"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
get_http_header_curl() {
|
||||||
|
eval $invocation
|
||||||
|
local remote_path="$1"
|
||||||
|
remote_path_with_credential="${remote_path}${feed_credential}"
|
||||||
|
curl_options="-I -sSL --retry 5 --retry-delay 2 --connect-timeout 15 "
|
||||||
|
curl $curl_options "$remote_path_with_credential" || return 1
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
get_http_header_wget() {
|
||||||
|
eval $invocation
|
||||||
|
local remote_path="$1"
|
||||||
|
remote_path_with_credential="${remote_path}${feed_credential}"
|
||||||
|
wget_options="-q -S --spider --tries 5 --waitretry 2 --connect-timeout 15 "
|
||||||
|
wget $wget_options "$remote_path_with_credential" 2>&1 || return 1
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# args:
|
# args:
|
||||||
@@ -728,44 +758,56 @@ download() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Updates global variables $http_code and $download_error_msg
|
||||||
downloadcurl() {
|
downloadcurl() {
|
||||||
eval $invocation
|
eval $invocation
|
||||||
local remote_path="$1"
|
local remote_path="$1"
|
||||||
local out_path="${2:-}"
|
local out_path="${2:-}"
|
||||||
|
|
||||||
# Append feed_credential as late as possible before calling curl to avoid logging feed_credential
|
# Append feed_credential as late as possible before calling curl to avoid logging feed_credential
|
||||||
remote_path="${remote_path}${feed_credential}"
|
local remote_path_with_credential="${remote_path}${feed_credential}"
|
||||||
|
|
||||||
local curl_options="--retry 20 --retry-delay 2 --connect-timeout 15 -sSL -f --create-dirs "
|
local curl_options="--retry 20 --retry-delay 2 --connect-timeout 15 -sSL -f --create-dirs "
|
||||||
local failed=false
|
local failed=false
|
||||||
if [ -z "$out_path" ]; then
|
if [ -z "$out_path" ]; then
|
||||||
curl $curl_options "$remote_path" || failed=true
|
curl $curl_options "$remote_path_with_credential" || failed=true
|
||||||
else
|
else
|
||||||
curl $curl_options -o "$out_path" "$remote_path" || failed=true
|
curl $curl_options -o "$out_path" "$remote_path_with_credential" || failed=true
|
||||||
fi
|
fi
|
||||||
if [ "$failed" = true ]; then
|
if [ "$failed" = true ]; then
|
||||||
say_verbose "Curl download failed"
|
local response=$(get_http_header_curl $remote_path_with_credential)
|
||||||
|
http_code=$( echo "$response" | awk '/^HTTP/{print $2}' | tail -1 )
|
||||||
|
download_error_msg="Unable to download $remote_path."
|
||||||
|
if [[ $http_code != 2* ]]; then
|
||||||
|
download_error_msg+=" Returned HTTP status code: $http_code."
|
||||||
|
fi
|
||||||
|
say_verbose "$download_error_msg"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Updates global variables $http_code and $download_error_msg
|
||||||
downloadwget() {
|
downloadwget() {
|
||||||
eval $invocation
|
eval $invocation
|
||||||
local remote_path="$1"
|
local remote_path="$1"
|
||||||
local out_path="${2:-}"
|
local out_path="${2:-}"
|
||||||
|
|
||||||
# Append feed_credential as late as possible before calling wget to avoid logging feed_credential
|
# Append feed_credential as late as possible before calling wget to avoid logging feed_credential
|
||||||
remote_path="${remote_path}${feed_credential}"
|
local remote_path_with_credential="${remote_path}${feed_credential}"
|
||||||
local wget_options="--tries 20 --waitretry 2 --connect-timeout 15 "
|
local wget_options="--tries 20 --waitretry 2 --connect-timeout 15 "
|
||||||
local failed=false
|
local failed=false
|
||||||
if [ -z "$out_path" ]; then
|
if [ -z "$out_path" ]; then
|
||||||
wget -q $wget_options -O - "$remote_path" || failed=true
|
wget -q $wget_options -O - "$remote_path_with_credential" || failed=true
|
||||||
else
|
else
|
||||||
wget $wget_options -O "$out_path" "$remote_path" || failed=true
|
wget $wget_options -O "$out_path" "$remote_path_with_credential" || failed=true
|
||||||
fi
|
fi
|
||||||
if [ "$failed" = true ]; then
|
if [ "$failed" = true ]; then
|
||||||
say_verbose "Wget download failed"
|
local response=$(get_http_header_wget $remote_path_with_credential)
|
||||||
|
http_code=$( echo "$response" | awk '/^ HTTP/{print $2}' | tail -1 )
|
||||||
|
download_error_msg="Unable to download $remote_path."
|
||||||
|
if [[ $http_code != 2* ]]; then
|
||||||
|
download_error_msg+=" Returned HTTP status code: $http_code."
|
||||||
|
fi
|
||||||
|
say_verbose "$download_error_msg"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
@@ -778,6 +820,9 @@ calculate_vars() {
|
|||||||
normalized_architecture="$(get_normalized_architecture_from_architecture "$architecture")"
|
normalized_architecture="$(get_normalized_architecture_from_architecture "$architecture")"
|
||||||
say_verbose "normalized_architecture=$normalized_architecture"
|
say_verbose "normalized_architecture=$normalized_architecture"
|
||||||
|
|
||||||
|
normalized_os="$(get_normalized_os "$user_defined_os")"
|
||||||
|
say_verbose "normalized_os=$normalized_os"
|
||||||
|
|
||||||
specific_version="$(get_specific_version_from_version "$azure_feed" "$channel" "$normalized_architecture" "$version" "$json_file")"
|
specific_version="$(get_specific_version_from_version "$azure_feed" "$channel" "$normalized_architecture" "$version" "$json_file")"
|
||||||
specific_product_version="$(get_specific_product_version "$azure_feed" "$specific_version")"
|
specific_product_version="$(get_specific_product_version "$azure_feed" "$specific_version")"
|
||||||
say_verbose "specific_version=$specific_version"
|
say_verbose "specific_version=$specific_version"
|
||||||
@@ -786,7 +831,7 @@ calculate_vars() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
download_link="$(construct_download_link "$azure_feed" "$channel" "$normalized_architecture" "$specific_version")"
|
download_link="$(construct_download_link "$azure_feed" "$channel" "$normalized_architecture" "$specific_version" "$normalized_os")"
|
||||||
say_verbose "Constructed primary named payload URL: $download_link"
|
say_verbose "Constructed primary named payload URL: $download_link"
|
||||||
|
|
||||||
legacy_download_link="$(construct_legacy_download_link "$azure_feed" "$channel" "$normalized_architecture" "$specific_version")" || valid_legacy_download_link=false
|
legacy_download_link="$(construct_legacy_download_link "$azure_feed" "$channel" "$normalized_architecture" "$specific_version")" || valid_legacy_download_link=false
|
||||||
@@ -831,38 +876,76 @@ install_dotnet() {
|
|||||||
zip_path="$(mktemp "$temporary_file_template")"
|
zip_path="$(mktemp "$temporary_file_template")"
|
||||||
say_verbose "Zip path: $zip_path"
|
say_verbose "Zip path: $zip_path"
|
||||||
|
|
||||||
say "Downloading link: $download_link"
|
|
||||||
|
|
||||||
# Failures are normal in the non-legacy case for ultimately legacy downloads.
|
# Failures are normal in the non-legacy case for ultimately legacy downloads.
|
||||||
# Do not output to stderr, since output to stderr is considered an error.
|
# Do not output to stderr, since output to stderr is considered an error.
|
||||||
|
say "Downloading primary link $download_link"
|
||||||
|
|
||||||
|
# The download function will set variables $http_code and $download_error_msg in case of failure.
|
||||||
|
http_code=""; download_error_msg=""
|
||||||
download "$download_link" "$zip_path" 2>&1 || download_failed=true
|
download "$download_link" "$zip_path" 2>&1 || download_failed=true
|
||||||
|
primary_path_http_code="$http_code"; primary_path_download_error_msg="$download_error_msg"
|
||||||
|
|
||||||
# if the download fails, download the legacy_download_link
|
# if the download fails, download the legacy_download_link
|
||||||
if [ "$download_failed" = true ]; then
|
if [ "$download_failed" = true ]; then
|
||||||
say "Cannot download: $download_link"
|
case $primary_path_http_code in
|
||||||
|
404)
|
||||||
|
say "The resource at $download_link is not available."
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
say "$primary_path_download_error_msg"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
rm -f "$zip_path" 2>&1 && say_verbose "Temporary zip file $zip_path was removed"
|
||||||
if [ "$valid_legacy_download_link" = true ]; then
|
if [ "$valid_legacy_download_link" = true ]; then
|
||||||
download_failed=false
|
download_failed=false
|
||||||
download_link="$legacy_download_link"
|
download_link="$legacy_download_link"
|
||||||
zip_path="$(mktemp "$temporary_file_template")"
|
zip_path="$(mktemp "$temporary_file_template")"
|
||||||
say_verbose "Legacy zip path: $zip_path"
|
say_verbose "Legacy zip path: $zip_path"
|
||||||
say "Downloading legacy link: $download_link"
|
|
||||||
|
say "Downloading legacy link $download_link"
|
||||||
|
|
||||||
|
# The download function will set variables $http_code and $download_error_msg in case of failure.
|
||||||
|
http_code=""; download_error_msg=""
|
||||||
download "$download_link" "$zip_path" 2>&1 || download_failed=true
|
download "$download_link" "$zip_path" 2>&1 || download_failed=true
|
||||||
|
legacy_path_http_code="$http_code"; legacy_path_download_error_msg="$download_error_msg"
|
||||||
|
|
||||||
if [ "$download_failed" = true ]; then
|
if [ "$download_failed" = true ]; then
|
||||||
say "Cannot download: $download_link"
|
case $legacy_path_http_code in
|
||||||
|
404)
|
||||||
|
say "The resource at $download_link is not available."
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
say "$legacy_path_download_error_msg"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
rm -f "$zip_path" 2>&1 && say_verbose "Temporary zip file $zip_path was removed"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$download_failed" = true ]; then
|
if [ "$download_failed" = true ]; then
|
||||||
say_err "Could not find/download: \`$asset_name\` with version = $specific_version"
|
if [[ "$primary_path_http_code" = "404" && ( "$valid_legacy_download_link" = false || "$legacy_path_http_code" = "404") ]]; then
|
||||||
say_err "Refer to: https://aka.ms/dotnet-os-lifecycle for information on .NET Core support"
|
say_err "Could not find \`$asset_name\` with version = $specific_version"
|
||||||
|
say_err "Refer to: https://aka.ms/dotnet-os-lifecycle for information on .NET Core support"
|
||||||
|
else
|
||||||
|
say_err "Could not download: \`$asset_name\` with version = $specific_version"
|
||||||
|
# 404-NotFound is an expected response if it goes from only one of the links, do not show that error.
|
||||||
|
# If primary path is available (not 404-NotFound) then show the primary error else show the legacy error.
|
||||||
|
if [ "$primary_path_http_code" != "404" ]; then
|
||||||
|
say_err "$primary_path_download_error_msg"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if [[ "$valid_legacy_download_link" = true && "$legacy_path_http_code" != "404" ]]; then
|
||||||
|
say_err "$legacy_path_download_error_msg"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
say "Extracting zip from $download_link"
|
say "Extracting zip from $download_link"
|
||||||
extract_dotnet_package "$zip_path" "$install_root"
|
extract_dotnet_package "$zip_path" "$install_root" || return 1
|
||||||
|
|
||||||
# Check if the SDK version is installed; if not, fail the installation.
|
# Check if the SDK version is installed; if not, fail the installation.
|
||||||
# if the version contains "RTM" or "servicing"; check if a 'release-type' SDK version is installed.
|
# if the version contains "RTM" or "servicing"; check if a 'release-type' SDK version is installed.
|
||||||
@@ -883,6 +966,8 @@ install_dotnet() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Version verification failed. More likely something is wrong either with the downloaded content or with the verification algorithm.
|
||||||
|
say_err "Failed to verify the version of installed \`$asset_name\`.\nInstallation source: $download_link.\nInstallation location: $install_root.\nReport the bug at https://github.com/dotnet/install-scripts/issues."
|
||||||
say_err "\`$asset_name\` with version = $specific_product_version failed to install with an unknown error."
|
say_err "\`$asset_name\` with version = $specific_product_version failed to install with an unknown error."
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
@@ -909,6 +994,7 @@ runtime=""
|
|||||||
runtime_id=""
|
runtime_id=""
|
||||||
override_non_versioned_files=true
|
override_non_versioned_files=true
|
||||||
non_dynamic_parameters=""
|
non_dynamic_parameters=""
|
||||||
|
user_defined_os=""
|
||||||
|
|
||||||
while [ $# -ne 0 ]
|
while [ $# -ne 0 ]
|
||||||
do
|
do
|
||||||
@@ -930,6 +1016,10 @@ do
|
|||||||
shift
|
shift
|
||||||
architecture="$1"
|
architecture="$1"
|
||||||
;;
|
;;
|
||||||
|
--os|-[Oo][SS])
|
||||||
|
shift
|
||||||
|
user_defined_os="$1"
|
||||||
|
;;
|
||||||
--shared-runtime|-[Ss]hared[Rr]untime)
|
--shared-runtime|-[Ss]hared[Rr]untime)
|
||||||
say_warning "The --shared-runtime flag is obsolete and may be removed in a future version of this script. The recommended usage is to specify '--runtime dotnet'."
|
say_warning "The --shared-runtime flag is obsolete and may be removed in a future version of this script. The recommended usage is to specify '--runtime dotnet'."
|
||||||
if [ -z "$runtime" ]; then
|
if [ -z "$runtime" ]; then
|
||||||
@@ -981,6 +1071,7 @@ do
|
|||||||
shift
|
shift
|
||||||
runtime_id="$1"
|
runtime_id="$1"
|
||||||
non_dynamic_parameters+=" $name "\""$1"\"""
|
non_dynamic_parameters+=" $name "\""$1"\"""
|
||||||
|
say_warning "Use of --runtime-id is obsolete and should be limited to the versions below 2.1. To override architecture, use --architecture option instead. To override OS, use --os option instead."
|
||||||
;;
|
;;
|
||||||
--jsonfile|-[Jj][Ss]on[Ff]ile)
|
--jsonfile|-[Jj][Ss]on[Ff]ile)
|
||||||
shift
|
shift
|
||||||
@@ -1013,8 +1104,6 @@ do
|
|||||||
echo " -Version"
|
echo " -Version"
|
||||||
echo " Possible values:"
|
echo " Possible values:"
|
||||||
echo " - latest - most latest build on specific channel"
|
echo " - latest - most latest build on specific channel"
|
||||||
echo " - coherent - most latest coherent build on specific channel"
|
|
||||||
echo " coherent applies only to SDK downloads"
|
|
||||||
echo " - 3-part version in a format A.B.C - represents specific version of build"
|
echo " - 3-part version in a format A.B.C - represents specific version of build"
|
||||||
echo " examples: 2.0.0-preview2-006120; 1.1.0"
|
echo " examples: 2.0.0-preview2-006120; 1.1.0"
|
||||||
echo " -i,--install-dir <DIR> Install under specified location (see Install Location below)"
|
echo " -i,--install-dir <DIR> Install under specified location (see Install Location below)"
|
||||||
@@ -1022,6 +1111,11 @@ do
|
|||||||
echo " --architecture <ARCHITECTURE> Architecture of dotnet binaries to be installed, Defaults to \`$architecture\`."
|
echo " --architecture <ARCHITECTURE> Architecture of dotnet binaries to be installed, Defaults to \`$architecture\`."
|
||||||
echo " --arch,-Architecture,-Arch"
|
echo " --arch,-Architecture,-Arch"
|
||||||
echo " Possible values: x64, arm, and arm64"
|
echo " Possible values: x64, arm, and arm64"
|
||||||
|
echo " --os <system> Specifies operating system to be used when selecting the installer."
|
||||||
|
echo " Overrides the OS determination approach used by the script. Supported values: osx, linux, linux-musl, freebsd, rhel.6."
|
||||||
|
echo " In case any other value is provided, the platform will be determined by the script based on machine configuration."
|
||||||
|
echo " Not supported for legacy links. Use --runtime-id to specify platform for legacy links."
|
||||||
|
echo " Refer to: https://aka.ms/dotnet-os-lifecycle for more information."
|
||||||
echo " --runtime <RUNTIME> Installs a shared runtime only, without the SDK."
|
echo " --runtime <RUNTIME> Installs a shared runtime only, without the SDK."
|
||||||
echo " -Runtime"
|
echo " -Runtime"
|
||||||
echo " Possible values:"
|
echo " Possible values:"
|
||||||
@@ -1038,14 +1132,15 @@ do
|
|||||||
echo " --no-cdn,-NoCdn Disable downloading from the Azure CDN, and use the uncached feed directly."
|
echo " --no-cdn,-NoCdn Disable downloading from the Azure CDN, and use the uncached feed directly."
|
||||||
echo " --jsonfile <JSONFILE> Determines the SDK version from a user specified global.json file."
|
echo " --jsonfile <JSONFILE> Determines the SDK version from a user specified global.json file."
|
||||||
echo " Note: global.json must have a value for 'SDK:Version'"
|
echo " Note: global.json must have a value for 'SDK:Version'"
|
||||||
echo " --runtime-id Installs the .NET Tools for the given platform (use linux-x64 for portable linux)."
|
|
||||||
echo " -RuntimeId"
|
|
||||||
echo " -?,--?,-h,--help,-Help Shows this help message"
|
echo " -?,--?,-h,--help,-Help Shows this help message"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Obsolete parameters:"
|
echo "Obsolete parameters:"
|
||||||
echo " --shared-runtime The recommended alternative is '--runtime dotnet'."
|
echo " --shared-runtime The recommended alternative is '--runtime dotnet'."
|
||||||
echo " This parameter is obsolete and may be removed in a future version of this script."
|
echo " This parameter is obsolete and may be removed in a future version of this script."
|
||||||
echo " Installs just the shared runtime bits, not the entire SDK."
|
echo " Installs just the shared runtime bits, not the entire SDK."
|
||||||
|
echo " --runtime-id Installs the .NET Tools for the given platform (use linux-x64 for portable linux)."
|
||||||
|
echo " -RuntimeId" The parameter is obsolete and may be removed in a future version of this script. Should be used only for versions below 2.1.
|
||||||
|
echo " For primary links to override OS or/and architecture, use --os and --architecture option instead."
|
||||||
echo ""
|
echo ""
|
||||||
echo "Install Location:"
|
echo "Install Location:"
|
||||||
echo " Location is chosen in following order:"
|
echo " Location is chosen in following order:"
|
||||||
@@ -1082,7 +1177,7 @@ if [ "$dry_run" = true ]; then
|
|||||||
if [ "$valid_legacy_download_link" = true ]; then
|
if [ "$valid_legacy_download_link" = true ]; then
|
||||||
say "Legacy named payload URL: $legacy_download_link"
|
say "Legacy named payload URL: $legacy_download_link"
|
||||||
fi
|
fi
|
||||||
repeatable_command="./$script_name --version "\""$specific_version"\"" --install-dir "\""$install_root"\"" --architecture "\""$normalized_architecture"\"""
|
repeatable_command="./$script_name --version "\""$specific_version"\"" --install-dir "\""$install_root"\"" --architecture "\""$normalized_architecture"\"" --os "\""$normalized_os"\"""
|
||||||
if [[ "$runtime" == "dotnet" ]]; then
|
if [[ "$runtime" == "dotnet" ]]; then
|
||||||
repeatable_command+=" --runtime "\""dotnet"\"""
|
repeatable_command+=" --runtime "\""dotnet"\"""
|
||||||
elif [[ "$runtime" == "aspnetcore" ]]; then
|
elif [[ "$runtime" == "aspnetcore" ]]; then
|
||||||
|
|||||||
@@ -16,11 +16,11 @@ if (supported.indexOf(process.platform) == -1) {
|
|||||||
var stopping = false;
|
var stopping = false;
|
||||||
var listener = null;
|
var listener = null;
|
||||||
|
|
||||||
var runService = function() {
|
var runService = function () {
|
||||||
var listenerExePath = path.join(__dirname, '../bin/Runner.Listener');
|
var listenerExePath = path.join(__dirname, '../bin/Runner.Listener');
|
||||||
var interactive = process.argv[2] === "interactive";
|
var interactive = process.argv[2] === "interactive";
|
||||||
|
|
||||||
if(!stopping) {
|
if (!stopping) {
|
||||||
try {
|
try {
|
||||||
if (interactive) {
|
if (interactive) {
|
||||||
console.log('Starting Runner listener interactively');
|
console.log('Starting Runner listener interactively');
|
||||||
@@ -30,8 +30,8 @@ var runService = function() {
|
|||||||
listener = childProcess.spawn(listenerExePath, ['run', '--startuptype', 'service'], { env: process.env });
|
listener = childProcess.spawn(listenerExePath, ['run', '--startuptype', 'service'], { env: process.env });
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Started listener process');
|
console.log(`Started listener process, pid: ${listener.pid}`);
|
||||||
|
|
||||||
listener.stdout.on('data', (data) => {
|
listener.stdout.on('data', (data) => {
|
||||||
process.stdout.write(data.toString('utf8'));
|
process.stdout.write(data.toString('utf8'));
|
||||||
});
|
});
|
||||||
@@ -40,6 +40,10 @@ var runService = function() {
|
|||||||
process.stdout.write(data.toString('utf8'));
|
process.stdout.write(data.toString('utf8'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
listener.on("error", (err) => {
|
||||||
|
console.log(`Runner listener fail to start with error ${err.message}`);
|
||||||
|
});
|
||||||
|
|
||||||
listener.on('close', (code) => {
|
listener.on('close', (code) => {
|
||||||
console.log(`Runner listener exited with error code ${code}`);
|
console.log(`Runner listener exited with error code ${code}`);
|
||||||
|
|
||||||
@@ -56,13 +60,13 @@ var runService = function() {
|
|||||||
} else {
|
} else {
|
||||||
console.log('Runner listener exit with undefined return code, re-launch runner in 5 seconds.');
|
console.log('Runner listener exit with undefined return code, re-launch runner in 5 seconds.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!stopping) {
|
if (!stopping) {
|
||||||
setTimeout(runService, 5000);
|
setTimeout(runService, 5000);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch(ex) {
|
} catch (ex) {
|
||||||
console.log(ex);
|
console.log(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,7 +75,7 @@ var runService = function() {
|
|||||||
runService();
|
runService();
|
||||||
console.log('Started running service');
|
console.log('Started running service');
|
||||||
|
|
||||||
var gracefulShutdown = function(code) {
|
var gracefulShutdown = function (code) {
|
||||||
console.log('Shutting down runner listener');
|
console.log('Shutting down runner listener');
|
||||||
stopping = true;
|
stopping = true;
|
||||||
if (listener) {
|
if (listener) {
|
||||||
|
|||||||
@@ -48,7 +48,10 @@ then
|
|||||||
echo "--------Debian Version--------"
|
echo "--------Debian Version--------"
|
||||||
cat /etc/debian_version
|
cat /etc/debian_version
|
||||||
echo "------------------------------"
|
echo "------------------------------"
|
||||||
|
|
||||||
|
mv /etc/apt/sources.list.d/sbt.list sbt.list
|
||||||
|
mv /etc/apt/sources.list.d/sbt.list.save sbt.list.save
|
||||||
|
|
||||||
# prefer apt-get over apt
|
# prefer apt-get over apt
|
||||||
command -v apt-get
|
command -v apt-get
|
||||||
if [ $? -eq 0 ]
|
if [ $? -eq 0 ]
|
||||||
|
|||||||
@@ -26,25 +26,23 @@ if [[ "$1" == "localRun" ]]; then
|
|||||||
else
|
else
|
||||||
"$DIR"/bin/Runner.Listener run $*
|
"$DIR"/bin/Runner.Listener run $*
|
||||||
|
|
||||||
# Return code 4 means the run once runner received an update message.
|
# Return code 3 means the run once runner received an update message.
|
||||||
# Sleep 5 seconds to wait for the update process finish and run the runner again.
|
# Sleep 5 seconds to wait for the update process finish
|
||||||
returnCode=$?
|
returnCode=$?
|
||||||
if [[ $returnCode == 4 ]]; then
|
if [[ $returnCode == 3 ]]; then
|
||||||
if [ ! -x "$(command -v sleep)" ]; then
|
if [ ! -x "$(command -v sleep)" ]; then
|
||||||
if [ ! -x "$(command -v ping)" ]; then
|
if [ ! -x "$(command -v ping)" ]; then
|
||||||
COUNT="0"
|
COUNT="0"
|
||||||
while [[ $COUNT != 5000 ]]; do
|
while [[ $COUNT != 5000 ]]; do
|
||||||
echo "SLEEP" >nul
|
echo "SLEEP" > /dev/null
|
||||||
COUNT=$[$COUNT+1]
|
COUNT=$[$COUNT+1]
|
||||||
done
|
done
|
||||||
else
|
else
|
||||||
ping -n 5 127.0.0.1 >nul
|
ping -c 5 127.0.0.1 > /dev/null
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
sleep 5 >nul
|
sleep 5
|
||||||
fi
|
fi
|
||||||
|
|
||||||
"$DIR"/bin/Runner.Listener run $*
|
|
||||||
else
|
else
|
||||||
exit $returnCode
|
exit $returnCode
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
|
|||||||
@@ -45,8 +45,8 @@ namespace GitHub.Runner.Common
|
|||||||
Task<TaskAgentJobRequest> FinishAgentRequestAsync(int poolId, long requestId, Guid lockToken, DateTime finishTime, TaskResult result, CancellationToken cancellationToken);
|
Task<TaskAgentJobRequest> FinishAgentRequestAsync(int poolId, long requestId, Guid lockToken, DateTime finishTime, TaskResult result, CancellationToken cancellationToken);
|
||||||
|
|
||||||
// agent package
|
// agent package
|
||||||
Task<List<PackageMetadata>> GetPackagesAsync(string packageType, string platform, int top, CancellationToken cancellationToken);
|
Task<List<PackageMetadata>> GetPackagesAsync(string packageType, string platform, int top, bool includeToken, CancellationToken cancellationToken);
|
||||||
Task<PackageMetadata> GetPackageAsync(string packageType, string platform, string version, CancellationToken cancellationToken);
|
Task<PackageMetadata> GetPackageAsync(string packageType, string platform, string version, bool includeToken, CancellationToken cancellationToken);
|
||||||
|
|
||||||
// agent update
|
// agent update
|
||||||
Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, int agentId, string currentState);
|
Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, int agentId, string currentState);
|
||||||
@@ -317,16 +317,16 @@ namespace GitHub.Runner.Common
|
|||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
// Agent Package
|
// Agent Package
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
public Task<List<PackageMetadata>> GetPackagesAsync(string packageType, string platform, int top, CancellationToken cancellationToken)
|
public Task<List<PackageMetadata>> GetPackagesAsync(string packageType, string platform, int top, bool includeToken, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
CheckConnection(RunnerConnectionType.Generic);
|
CheckConnection(RunnerConnectionType.Generic);
|
||||||
return _genericTaskAgentClient.GetPackagesAsync(packageType, platform, top, cancellationToken: cancellationToken);
|
return _genericTaskAgentClient.GetPackagesAsync(packageType, platform, top, includeToken, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<PackageMetadata> GetPackageAsync(string packageType, string platform, string version, CancellationToken cancellationToken)
|
public Task<PackageMetadata> GetPackageAsync(string packageType, string platform, string version, bool includeToken, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
CheckConnection(RunnerConnectionType.Generic);
|
CheckConnection(RunnerConnectionType.Generic);
|
||||||
return _genericTaskAgentClient.GetPackageAsync(packageType, platform, version, cancellationToken: cancellationToken);
|
return _genericTaskAgentClient.GetPackageAsync(packageType, platform, version, includeToken, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, int agentId, string currentState)
|
public Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, int agentId, string currentState)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace GitHub.Runner.Listener.Check
|
|||||||
|
|
||||||
public string CheckName => "GitHub Actions Connection";
|
public string CheckName => "GitHub Actions Connection";
|
||||||
|
|
||||||
public string CheckDescription => "Make sure the actions runner have access to the GitHub Actions Service.";
|
public string CheckDescription => "Check if the Actions runner has access to the GitHub Actions service.";
|
||||||
|
|
||||||
public string CheckLog => _logFile;
|
public string CheckLog => _logFile;
|
||||||
|
|
||||||
@@ -61,17 +61,20 @@ namespace GitHub.Runner.Listener.Check
|
|||||||
// check github api
|
// check github api
|
||||||
checkTasks.Add(CheckUtil.CheckDns(githubApiUrl));
|
checkTasks.Add(CheckUtil.CheckDns(githubApiUrl));
|
||||||
checkTasks.Add(CheckUtil.CheckPing(githubApiUrl));
|
checkTasks.Add(CheckUtil.CheckPing(githubApiUrl));
|
||||||
checkTasks.Add(HostContext.CheckHttpsRequests(githubApiUrl, pat, expectedHeader: "X-GitHub-Request-Id"));
|
checkTasks.Add(HostContext.CheckHttpsGetRequests(githubApiUrl, pat, expectedHeader: "X-GitHub-Request-Id"));
|
||||||
|
|
||||||
// check actions token service
|
// check actions token service
|
||||||
checkTasks.Add(CheckUtil.CheckDns(actionsTokenServiceUrl));
|
checkTasks.Add(CheckUtil.CheckDns(actionsTokenServiceUrl));
|
||||||
checkTasks.Add(CheckUtil.CheckPing(actionsTokenServiceUrl));
|
checkTasks.Add(CheckUtil.CheckPing(actionsTokenServiceUrl));
|
||||||
checkTasks.Add(HostContext.CheckHttpsRequests(actionsTokenServiceUrl, pat, expectedHeader: "x-vss-e2eid"));
|
checkTasks.Add(HostContext.CheckHttpsGetRequests(actionsTokenServiceUrl, pat, expectedHeader: "x-vss-e2eid"));
|
||||||
|
|
||||||
// check actions pipelines service
|
// check actions pipelines service
|
||||||
checkTasks.Add(CheckUtil.CheckDns(actionsPipelinesServiceUrl));
|
checkTasks.Add(CheckUtil.CheckDns(actionsPipelinesServiceUrl));
|
||||||
checkTasks.Add(CheckUtil.CheckPing(actionsPipelinesServiceUrl));
|
checkTasks.Add(CheckUtil.CheckPing(actionsPipelinesServiceUrl));
|
||||||
checkTasks.Add(HostContext.CheckHttpsRequests(actionsPipelinesServiceUrl, pat, expectedHeader: "x-vss-e2eid"));
|
checkTasks.Add(HostContext.CheckHttpsGetRequests(actionsPipelinesServiceUrl, pat, expectedHeader: "x-vss-e2eid"));
|
||||||
|
|
||||||
|
// check HTTP POST to actions pipelines service
|
||||||
|
checkTasks.Add(HostContext.CheckHttpsPostRequests(actionsPipelinesServiceUrl, pat, expectedHeader: "x-vss-e2eid"));
|
||||||
|
|
||||||
var result = true;
|
var result = true;
|
||||||
while (checkTasks.Count > 0)
|
while (checkTasks.Count > 0)
|
||||||
|
|||||||
@@ -117,14 +117,14 @@ namespace GitHub.Runner.Listener.Check
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<CheckResult> CheckHttpsRequests(this IHostContext hostContext, string url, string pat, string expectedHeader)
|
public static async Task<CheckResult> CheckHttpsGetRequests(this IHostContext hostContext, string url, string pat, string expectedHeader)
|
||||||
{
|
{
|
||||||
var result = new CheckResult();
|
var result = new CheckResult();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ***************************************************************************************************************");
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ***************************************************************************************************************");
|
||||||
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} **** ****");
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} **** ****");
|
||||||
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} **** Send HTTPS Request to {url} ");
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} **** Send HTTPS Request (GET) to {url} ");
|
||||||
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} **** ****");
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} **** ****");
|
||||||
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ***************************************************************************************************************");
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ***************************************************************************************************************");
|
||||||
using (var _ = new HttpEventSourceListener(result.Logs))
|
using (var _ = new HttpEventSourceListener(result.Logs))
|
||||||
@@ -159,7 +159,7 @@ namespace GitHub.Runner.Listener.Check
|
|||||||
{
|
{
|
||||||
result.Pass = false;
|
result.Pass = false;
|
||||||
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ***************************************************************************************************************");
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ***************************************************************************************************************");
|
||||||
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} Http request 'GET' to {url} succeed but doesn't have expected HTTP Header.");
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} Http request 'GET' to {url} succeed but doesn't have expected HTTP response Header '{expectedHeader}'.");
|
||||||
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ***************************************************************************************************************");
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ***************************************************************************************************************");
|
||||||
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ");
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ");
|
||||||
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ");
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ");
|
||||||
@@ -189,6 +189,67 @@ namespace GitHub.Runner.Listener.Check
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task<CheckResult> CheckHttpsPostRequests(this IHostContext hostContext, string url, string pat, string expectedHeader)
|
||||||
|
{
|
||||||
|
var result = new CheckResult();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ***************************************************************************************************************");
|
||||||
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} **** ****");
|
||||||
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} **** Send HTTPS Request (POST) to {url} ");
|
||||||
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} **** ****");
|
||||||
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ***************************************************************************************************************");
|
||||||
|
using (var _ = new HttpEventSourceListener(result.Logs))
|
||||||
|
using (var httpClientHandler = hostContext.CreateHttpClientHandler())
|
||||||
|
using (var httpClient = new HttpClient(httpClientHandler))
|
||||||
|
{
|
||||||
|
httpClient.DefaultRequestHeaders.UserAgent.AddRange(hostContext.UserAgents);
|
||||||
|
if (!string.IsNullOrEmpty(pat))
|
||||||
|
{
|
||||||
|
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("token", pat);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send empty JSON '{}' to service
|
||||||
|
var response = await httpClient.PostAsJsonAsync<Dictionary<string, string>>(url, new Dictionary<string, string>());
|
||||||
|
|
||||||
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} Http status code: {response.StatusCode}");
|
||||||
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} Http response headers: {response.Headers}");
|
||||||
|
|
||||||
|
var responseContent = await response.Content.ReadAsStringAsync();
|
||||||
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} Http response body: {responseContent}");
|
||||||
|
if (response.Headers.Contains(expectedHeader))
|
||||||
|
{
|
||||||
|
result.Pass = true;
|
||||||
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ***************************************************************************************************************");
|
||||||
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} Http request 'POST' to {url} has expected HTTP response header");
|
||||||
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ***************************************************************************************************************");
|
||||||
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ");
|
||||||
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.Pass = false;
|
||||||
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ***************************************************************************************************************");
|
||||||
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} Http request 'POST' to {url} doesn't have expected HTTP response Header '{expectedHeader}'.");
|
||||||
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ***************************************************************************************************************");
|
||||||
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ");
|
||||||
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
result.Pass = false;
|
||||||
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ***************************************************************************************************************");
|
||||||
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} **** ****");
|
||||||
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} **** Https request 'POST' to {url} failed with error: {ex}");
|
||||||
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} **** ****");
|
||||||
|
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ***************************************************************************************************************");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public static async Task<CheckResult> DownloadExtraCA(this IHostContext hostContext, string url, string pat)
|
public static async Task<CheckResult> DownloadExtraCA(this IHostContext hostContext, string url, string pat)
|
||||||
{
|
{
|
||||||
var result = new CheckResult();
|
var result = new CheckResult();
|
||||||
@@ -289,18 +350,23 @@ namespace GitHub.Runner.Listener.Check
|
|||||||
private readonly Dictionary<string, HashSet<string>> _ignoredEvent = new Dictionary<string, HashSet<string>>
|
private readonly Dictionary<string, HashSet<string>> _ignoredEvent = new Dictionary<string, HashSet<string>>
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
"Private.InternalDiagnostics.System.Net.Http",
|
"Microsoft-System-Net-Http",
|
||||||
new HashSet<string>
|
new HashSet<string>
|
||||||
{
|
{
|
||||||
"Info",
|
"Info",
|
||||||
"Associate"
|
"Associate",
|
||||||
|
"Enter",
|
||||||
|
"Exit"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Private.InternalDiagnostics.System.Net.Security",
|
"Microsoft-System-Net-Security",
|
||||||
new HashSet<string>
|
new HashSet<string>
|
||||||
{
|
{
|
||||||
|
"Enter",
|
||||||
|
"Exit",
|
||||||
"Info",
|
"Info",
|
||||||
|
"DumpBuffer",
|
||||||
"SslStreamCtor",
|
"SslStreamCtor",
|
||||||
"SecureChannelCtor",
|
"SecureChannelCtor",
|
||||||
"NoDelegateNoClientCert",
|
"NoDelegateNoClientCert",
|
||||||
@@ -324,8 +390,8 @@ namespace GitHub.Runner.Listener.Check
|
|||||||
{
|
{
|
||||||
base.OnEventSourceCreated(eventSource);
|
base.OnEventSourceCreated(eventSource);
|
||||||
|
|
||||||
if (eventSource.Name == "Private.InternalDiagnostics.System.Net.Http" ||
|
if (eventSource.Name == "Microsoft-System-Net-Http" ||
|
||||||
eventSource.Name == "Private.InternalDiagnostics.System.Net.Security")
|
eventSource.Name == "Microsoft-System-Net-Security")
|
||||||
{
|
{
|
||||||
EnableEvents(eventSource, EventLevel.Verbose, EventKeywords.All);
|
EnableEvents(eventSource, EventLevel.Verbose, EventKeywords.All);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace GitHub.Runner.Listener.Check
|
|||||||
|
|
||||||
public string CheckName => "Git Certificate/Proxy Validation";
|
public string CheckName => "Git Certificate/Proxy Validation";
|
||||||
|
|
||||||
public string CheckDescription => "Make sure the git cli can access to GitHub.com or the GitHub Enterprise Server.";
|
public string CheckDescription => "Check if the Git CLI can access GitHub.com or GitHub Enterprise Server.";
|
||||||
|
|
||||||
public string CheckLog => _logFile;
|
public string CheckLog => _logFile;
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace GitHub.Runner.Listener.Check
|
|||||||
|
|
||||||
public string CheckName => "Internet Connection";
|
public string CheckName => "Internet Connection";
|
||||||
|
|
||||||
public string CheckDescription => "Make sure the actions runner have access to public internet.";
|
public string CheckDescription => "Check if the Actions runner has internet access.";
|
||||||
|
|
||||||
public string CheckLog => _logFile;
|
public string CheckLog => _logFile;
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ namespace GitHub.Runner.Listener.Check
|
|||||||
checkTasks.Add(CheckUtil.CheckPing("https://api.github.com"));
|
checkTasks.Add(CheckUtil.CheckPing("https://api.github.com"));
|
||||||
|
|
||||||
// We don't need to pass a PAT since it might be a token for GHES.
|
// We don't need to pass a PAT since it might be a token for GHES.
|
||||||
checkTasks.Add(HostContext.CheckHttpsRequests("https://api.github.com", pat: null, expectedHeader: "X-GitHub-Request-Id"));
|
checkTasks.Add(HostContext.CheckHttpsGetRequests("https://api.github.com", pat: null, expectedHeader: "X-GitHub-Request-Id"));
|
||||||
|
|
||||||
var result = true;
|
var result = true;
|
||||||
while (checkTasks.Count > 0)
|
while (checkTasks.Count > 0)
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace GitHub.Runner.Listener.Check
|
|||||||
|
|
||||||
public string CheckName => "Node.js Certificate/Proxy Validation";
|
public string CheckName => "Node.js Certificate/Proxy Validation";
|
||||||
|
|
||||||
public string CheckDescription => "Make sure the node.js have access to GitHub.com or the GitHub Enterprise Server.";
|
public string CheckDescription => "Check if Node.js has access to GitHub.com or GitHub Enterprise Server.";
|
||||||
|
|
||||||
public string CheckLog => _logFile;
|
public string CheckLog => _logFile;
|
||||||
|
|
||||||
|
|||||||
@@ -263,6 +263,7 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
{
|
{
|
||||||
{ "clientId", agent.Authorization.ClientId.ToString("D") },
|
{ "clientId", agent.Authorization.ClientId.ToString("D") },
|
||||||
{ "authorizationUrl", agent.Authorization.AuthorizationUrl.AbsoluteUri },
|
{ "authorizationUrl", agent.Authorization.AuthorizationUrl.AbsoluteUri },
|
||||||
|
{ "requireFipsCryptography", agent.Properties.GetValue("RequireFipsCryptography", false).ToString() }
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
// We expect the key to be in the machine store at this point. Configuration should have set all of
|
// We expect the key to be in the machine store at this point. Configuration should have set all of
|
||||||
// this up correctly so we can use the key to generate access tokens.
|
// this up correctly so we can use the key to generate access tokens.
|
||||||
var keyManager = context.GetService<IRSAKeyManager>();
|
var keyManager = context.GetService<IRSAKeyManager>();
|
||||||
var signingCredentials = VssSigningCredentials.Create(() => keyManager.GetKey(), requireFipsCryptography: true);
|
var signingCredentials = VssSigningCredentials.Create(() => keyManager.GetKey(), StringUtil.ConvertToBoolean(CredentialData.Data.GetValueOrDefault("requireFipsCryptography"), false));
|
||||||
var clientCredential = new VssOAuthJwtBearerClientCredential(clientId, authorizationUrl, signingCredentials);
|
var clientCredential = new VssOAuthJwtBearerClientCredential(clientId, authorizationUrl, signingCredentials);
|
||||||
var agentCredential = new VssOAuthCredential(new Uri(oauthEndpointUrl, UriKind.Absolute), VssOAuthGrant.ClientCredentials, clientCredential);
|
var agentCredential = new VssOAuthCredential(new Uri(oauthEndpointUrl, UriKind.Absolute), VssOAuthGrant.ClientCredentials, clientCredential);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
|
|||||||
@@ -501,6 +501,7 @@ Options:
|
|||||||
--help Prints the help for each command
|
--help Prints the help for each command
|
||||||
--version Prints the runner version
|
--version Prints the runner version
|
||||||
--commit Prints the runner commit
|
--commit Prints the runner commit
|
||||||
|
--check Check the runner's network connectivity with GitHub server
|
||||||
|
|
||||||
Config Options:
|
Config Options:
|
||||||
--unattended Disable interactive prompts for missing arguments. Defaults will be used for missing options
|
--unattended Disable interactive prompts for missing arguments. Defaults will be used for missing options
|
||||||
@@ -510,7 +511,8 @@ Config Options:
|
|||||||
--runnergroup string Name of the runner group to add this runner to (defaults to the default runner group)
|
--runnergroup string Name of the runner group to add this runner to (defaults to the default runner group)
|
||||||
--labels string Extra labels in addition to the default: 'self-hosted,{Constants.Runner.Platform},{Constants.Runner.PlatformArchitecture}'
|
--labels string Extra labels in addition to the default: 'self-hosted,{Constants.Runner.Platform},{Constants.Runner.PlatformArchitecture}'
|
||||||
--work string Relative runner work directory (default {Constants.Path.WorkDirectory})
|
--work string Relative runner work directory (default {Constants.Path.WorkDirectory})
|
||||||
--replace Replace any existing runner with the same name (default false)");
|
--replace Replace any existing runner with the same name (default false)
|
||||||
|
--pat GitHub personal access token used for checking network connectivity when executing `.{separator}run.{ext} --check`");
|
||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
_term.WriteLine($@" --runasservice Run the runner as a service");
|
_term.WriteLine($@" --runasservice Run the runner as a service");
|
||||||
_term.WriteLine($@" --windowslogonaccount string Account to run the service as. Requires runasservice");
|
_term.WriteLine($@" --windowslogonaccount string Account to run the service as. Requires runasservice");
|
||||||
@@ -518,6 +520,8 @@ Config Options:
|
|||||||
#endif
|
#endif
|
||||||
_term.WriteLine($@"
|
_term.WriteLine($@"
|
||||||
Examples:
|
Examples:
|
||||||
|
Check GitHub server network connectivity:
|
||||||
|
.{separator}run.{ext} --check --url <url> --pat <pat>
|
||||||
Configure a runner non-interactively:
|
Configure a runner non-interactively:
|
||||||
.{separator}config.{ext} --unattended --url <url> --token <token>
|
.{separator}config.{ext} --unattended --url <url> --token <token>
|
||||||
Configure a runner non-interactively, replacing any existing runner with the same name:
|
Configure a runner non-interactively, replacing any existing runner with the same name:
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ using System.Linq;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Security.Cryptography;
|
||||||
using GitHub.Services.WebApi;
|
using GitHub.Services.WebApi;
|
||||||
|
using GitHub.Services.Common;
|
||||||
using GitHub.Runner.Common;
|
using GitHub.Runner.Common;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
|
|
||||||
@@ -110,7 +112,7 @@ namespace GitHub.Runner.Listener
|
|||||||
// old server won't send target version as part of update message.
|
// old server won't send target version as part of update message.
|
||||||
if (string.IsNullOrEmpty(targetVersion))
|
if (string.IsNullOrEmpty(targetVersion))
|
||||||
{
|
{
|
||||||
var packages = await _runnerServer.GetPackagesAsync(_packageType, _platform, 1, token);
|
var packages = await _runnerServer.GetPackagesAsync(_packageType, _platform, 1, true, token);
|
||||||
if (packages == null || packages.Count == 0)
|
if (packages == null || packages.Count == 0)
|
||||||
{
|
{
|
||||||
Trace.Info($"There is no package for {_packageType} and {_platform}.");
|
Trace.Info($"There is no package for {_packageType} and {_platform}.");
|
||||||
@@ -121,7 +123,7 @@ namespace GitHub.Runner.Listener
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_targetPackage = await _runnerServer.GetPackageAsync(_packageType, _platform, targetVersion, token);
|
_targetPackage = await _runnerServer.GetPackageAsync(_packageType, _platform, targetVersion, true, token);
|
||||||
if (_targetPackage == null)
|
if (_targetPackage == null)
|
||||||
{
|
{
|
||||||
Trace.Info($"There is no package for {_packageType} and {_platform} with version {targetVersion}.");
|
Trace.Info($"There is no package for {_packageType} and {_platform} with version {targetVersion}.");
|
||||||
@@ -211,12 +213,22 @@ namespace GitHub.Runner.Listener
|
|||||||
|
|
||||||
//open zip stream in async mode
|
//open zip stream in async mode
|
||||||
using (HttpClient httpClient = new HttpClient(HostContext.CreateHttpClientHandler()))
|
using (HttpClient httpClient = new HttpClient(HostContext.CreateHttpClientHandler()))
|
||||||
using (FileStream fs = new FileStream(archiveFile, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true))
|
|
||||||
using (Stream result = await httpClient.GetStreamAsync(_targetPackage.DownloadUrl))
|
|
||||||
{
|
{
|
||||||
//81920 is the default used by System.IO.Stream.CopyTo and is under the large object heap threshold (85k).
|
if (!string.IsNullOrEmpty(_targetPackage.Token))
|
||||||
await result.CopyToAsync(fs, 81920, downloadCts.Token);
|
{
|
||||||
await fs.FlushAsync(downloadCts.Token);
|
Trace.Info($"Adding authorization token ({_targetPackage.Token.Length} chars)");
|
||||||
|
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _targetPackage.Token);
|
||||||
|
}
|
||||||
|
|
||||||
|
Trace.Info($"Downloading {_targetPackage.DownloadUrl}");
|
||||||
|
|
||||||
|
using (FileStream fs = new FileStream(archiveFile, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true))
|
||||||
|
using (Stream result = await httpClient.GetStreamAsync(_targetPackage.DownloadUrl))
|
||||||
|
{
|
||||||
|
//81920 is the default used by System.IO.Stream.CopyTo and is under the large object heap threshold (85k).
|
||||||
|
await result.CopyToAsync(fs, 81920, downloadCts.Token);
|
||||||
|
await fs.FlushAsync(downloadCts.Token);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Trace.Info($"Download runner: finished download");
|
Trace.Info($"Download runner: finished download");
|
||||||
@@ -246,6 +258,24 @@ namespace GitHub.Runner.Listener
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If we got this far, we know that we've successfully downloaded the runner package
|
// If we got this far, we know that we've successfully downloaded the runner package
|
||||||
|
// Validate Hash Matches if it is provided
|
||||||
|
using (FileStream stream = File.OpenRead(archiveFile))
|
||||||
|
{
|
||||||
|
if (!String.IsNullOrEmpty(_targetPackage.HashValue))
|
||||||
|
{
|
||||||
|
using (SHA256 sha256 = SHA256.Create())
|
||||||
|
{
|
||||||
|
byte[] srcHashBytes = await sha256.ComputeHashAsync(stream);
|
||||||
|
var hash = PrimitiveExtensions.ConvertToHexString(srcHashBytes);
|
||||||
|
if (hash != _targetPackage.HashValue)
|
||||||
|
{
|
||||||
|
// Hash did not match, we can't recover from this, just throw
|
||||||
|
throw new Exception($"Computed runner hash {hash} did not match expected Runner Hash {_targetPackage.HashValue} for {_targetPackage.Filename}");
|
||||||
|
}
|
||||||
|
Trace.Info($"Validated Runner Hash matches {_targetPackage.Filename} : {_targetPackage.HashValue}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (archiveFile.EndsWith(".zip", StringComparison.OrdinalIgnoreCase))
|
if (archiveFile.EndsWith(".zip", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
ZipFile.ExtractToDirectory(archiveFile, latestRunnerDirectory);
|
ZipFile.ExtractToDirectory(archiveFile, latestRunnerDirectory);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
|
|||||||
@@ -444,7 +444,7 @@ namespace GitHub.Runner.Plugins.Artifact
|
|||||||
{
|
{
|
||||||
// We should never
|
// We should never
|
||||||
context.Error($"Error '{ex.Message}' when downloading file '{fileToDownload}'. (Downloader {downloaderId})");
|
context.Error($"Error '{ex.Message}' when downloading file '{fileToDownload}'. (Downloader {downloaderId})");
|
||||||
throw;
|
throw ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -528,7 +528,7 @@ namespace GitHub.Runner.Plugins.Artifact
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
context.Output($"File error '{ex.Message}' when uploading file '{fileToUpload}'.");
|
context.Output($"File error '{ex.Message}' when uploading file '{fileToUpload}'.");
|
||||||
throw;
|
throw ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -682,4 +682,4 @@ namespace GitHub.Runner.Plugins.Artifact
|
|||||||
: base(message, inner)
|
: base(message, inner)
|
||||||
{ }
|
{ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
|
|||||||
@@ -858,6 +858,10 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
_record.ParentId = parentTimelineRecordId;
|
_record.ParentId = parentTimelineRecordId;
|
||||||
}
|
}
|
||||||
|
else if (parentTimelineRecordId == null)
|
||||||
|
{
|
||||||
|
_record.AgentPlatform = VarUtil.OS;
|
||||||
|
}
|
||||||
|
|
||||||
var configuration = HostContext.GetService<IConfigurationStore>();
|
var configuration = HostContext.GetService<IConfigurationStore>();
|
||||||
_record.WorkerName = configuration.GetSettings().AgentName;
|
_record.WorkerName = configuration.GetSettings().AgentName;
|
||||||
|
|||||||
@@ -122,6 +122,26 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var tokenPermissions = jobContext.Global.Variables.Get("system.github.token.permissions") ?? "";
|
||||||
|
if (!string.IsNullOrEmpty(tokenPermissions))
|
||||||
|
{
|
||||||
|
context.Output($"##[group]GITHUB_TOKEN Permissions");
|
||||||
|
var permissions = StringUtil.ConvertFromJson<Dictionary<string, string>>(tokenPermissions);
|
||||||
|
foreach(KeyValuePair<string, string> entry in permissions)
|
||||||
|
{
|
||||||
|
context.Output($"{entry.Key}: {entry.Value}");
|
||||||
|
}
|
||||||
|
context.Output("##[endgroup]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
context.Output($"Fail to parse and display GITHUB_TOKEN permissions list: {ex.Message}");
|
||||||
|
Trace.Error(ex);
|
||||||
|
}
|
||||||
|
|
||||||
var repoFullName = context.GetGitHubContext("repository");
|
var repoFullName = context.GetGitHubContext("repository");
|
||||||
ArgUtil.NotNull(repoFullName, nameof(repoFullName));
|
ArgUtil.NotNull(repoFullName, nameof(repoFullName));
|
||||||
context.Debug($"Primary repository: {repoFullName}");
|
context.Debug($"Primary repository: {repoFullName}");
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
|
|||||||
@@ -12,9 +12,29 @@ namespace GitHub.Services.Common
|
|||||||
m_request = request;
|
m_request = request;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IHttpHeaders Headers => this;
|
public IHttpHeaders Headers
|
||||||
public Uri RequestUri => m_request.RequestUri;
|
{
|
||||||
public IDictionary<string,object> Properties => m_request.Options;
|
get
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Uri RequestUri
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return m_request.RequestUri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDictionary<string, object> Properties
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return m_request.Properties;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
IEnumerable<String> IHttpHeaders.GetValues(String name)
|
IEnumerable<String> IHttpHeaders.GetValues(String name)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace GitHub.Services.Common.Diagnostics
|
|||||||
public static VssTraceActivity GetActivity(this HttpRequestMessage message)
|
public static VssTraceActivity GetActivity(this HttpRequestMessage message)
|
||||||
{
|
{
|
||||||
Object traceActivity;
|
Object traceActivity;
|
||||||
if (!message.Options.TryGetValue(VssTraceActivity.PropertyName, out traceActivity))
|
if (!message.Properties.TryGetValue(VssTraceActivity.PropertyName, out traceActivity))
|
||||||
{
|
{
|
||||||
return VssTraceActivity.Empty;
|
return VssTraceActivity.Empty;
|
||||||
}
|
}
|
||||||
|
|||||||
27
src/Sdk/Common/Common/Utility/HashAlgorithmExtensions.cs
Normal file
27
src/Sdk/Common/Common/Utility/HashAlgorithmExtensions.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
using System.IO;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace GitHub.Services.Common
|
||||||
|
{
|
||||||
|
public static class HashAlgorithmExtensions
|
||||||
|
{
|
||||||
|
public static async Task<byte[]> ComputeHashAsync(this HashAlgorithm hashAlg, Stream inputStream)
|
||||||
|
{
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
int read = await inputStream.ReadAsync(buffer, 0, buffer.Length);
|
||||||
|
if (read == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
hashAlg.TransformBlock(buffer, 0, read, null, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
hashAlg.TransformFinalBlock(buffer, 0, 0);
|
||||||
|
return hashAlg.Hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -85,5 +85,19 @@ namespace GitHub.Services.Common
|
|||||||
var bytes = FromBase64StringNoPadding(base64String);
|
var bytes = FromBase64StringNoPadding(base64String);
|
||||||
return BitConverter.ToString(bytes).Replace("-", String.Empty);
|
return BitConverter.ToString(bytes).Replace("-", String.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts byte array into a hex string
|
||||||
|
/// </summary>
|
||||||
|
public static String ConvertToHexString(byte[] bytes)
|
||||||
|
{
|
||||||
|
// Convert byte array to string
|
||||||
|
var sBuilder = new StringBuilder();
|
||||||
|
for (int i = 0; i < bytes.Length; i++)
|
||||||
|
{
|
||||||
|
sBuilder.Append(bytes[i].ToString("x2"));
|
||||||
|
}
|
||||||
|
return sBuilder.ToString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ namespace GitHub.Services.Common
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add ourselves to the message so the underlying token issuers may use it if necessary
|
// Add ourselves to the message so the underlying token issuers may use it if necessary
|
||||||
request.Options.Set(new HttpRequestOptionsKey<VssHttpMessageHandler>(VssHttpMessageHandler.PropertyName), this);
|
request.Properties[VssHttpMessageHandler.PropertyName] = this;
|
||||||
|
|
||||||
Boolean succeeded = false;
|
Boolean succeeded = false;
|
||||||
Boolean lastResponseDemandedProxyAuth = false;
|
Boolean lastResponseDemandedProxyAuth = false;
|
||||||
@@ -409,7 +409,7 @@ namespace GitHub.Services.Common
|
|||||||
// Read the completion option provided by the caller. If we don't find the property then we
|
// Read the completion option provided by the caller. If we don't find the property then we
|
||||||
// assume it is OK to buffer by default.
|
// assume it is OK to buffer by default.
|
||||||
HttpCompletionOption completionOption;
|
HttpCompletionOption completionOption;
|
||||||
if (!request.Options.TryGetValue(VssHttpRequestSettings.HttpCompletionOptionPropertyName, out completionOption))
|
if (!request.Properties.TryGetValue(VssHttpRequestSettings.HttpCompletionOptionPropertyName, out completionOption))
|
||||||
{
|
{
|
||||||
completionOption = HttpCompletionOption.ResponseContentRead;
|
completionOption = HttpCompletionOption.ResponseContentRead;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,9 +77,9 @@ namespace GitHub.Services.Common
|
|||||||
public static void SetTraceInfo(HttpRequestMessage message, VssHttpMessageHandlerTraceInfo traceInfo)
|
public static void SetTraceInfo(HttpRequestMessage message, VssHttpMessageHandlerTraceInfo traceInfo)
|
||||||
{
|
{
|
||||||
object existingTraceInfo;
|
object existingTraceInfo;
|
||||||
if (!message.Options.TryGetValue(TfsTraceInfoKey, out existingTraceInfo))
|
if (!message.Properties.TryGetValue(TfsTraceInfoKey, out existingTraceInfo))
|
||||||
{
|
{
|
||||||
message.Options.Set(new HttpRequestOptionsKey<VssHttpMessageHandlerTraceInfo>(TfsTraceInfoKey), traceInfo);
|
message.Properties.Add(TfsTraceInfoKey, traceInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ namespace GitHub.Services.Common
|
|||||||
{
|
{
|
||||||
VssHttpMessageHandlerTraceInfo traceInfo = null;
|
VssHttpMessageHandlerTraceInfo traceInfo = null;
|
||||||
|
|
||||||
if (message.Options.TryGetValue(TfsTraceInfoKey, out object traceInfoObject))
|
if (message.Properties.TryGetValue(TfsTraceInfoKey, out object traceInfoObject))
|
||||||
{
|
{
|
||||||
traceInfo = traceInfoObject as VssHttpMessageHandlerTraceInfo;
|
traceInfo = traceInfoObject as VssHttpMessageHandlerTraceInfo;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -291,12 +291,12 @@ namespace GitHub.Services.Common
|
|||||||
protected internal virtual Boolean ApplyTo(HttpRequestMessage request)
|
protected internal virtual Boolean ApplyTo(HttpRequestMessage request)
|
||||||
{
|
{
|
||||||
// Make sure we only apply the settings to the request once
|
// Make sure we only apply the settings to the request once
|
||||||
if (request.Options.TryGetValue(new HttpRequestOptionsKey<VssHttpRequestSettings>(PropertyName), out _))
|
if (request.Properties.ContainsKey(PropertyName))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
request.Options.Set(new HttpRequestOptionsKey<VssHttpRequestSettings>(PropertyName), this);
|
request.Properties.Add(PropertyName, this);
|
||||||
|
|
||||||
if (this.AcceptLanguages != null && this.AcceptLanguages.Count > 0)
|
if (this.AcceptLanguages != null && this.AcceptLanguages.Count > 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ namespace GitHub.Services.Common
|
|||||||
// Allow overriding default retry options per request
|
// Allow overriding default retry options per request
|
||||||
VssHttpRetryOptions retryOptions = m_retryOptions;
|
VssHttpRetryOptions retryOptions = m_retryOptions;
|
||||||
object retryOptionsObject;
|
object retryOptionsObject;
|
||||||
if (request.Options.TryGetValue(HttpRetryOptionsKey, out retryOptionsObject)) // NETSTANDARD compliant, TryGetValue<T> is not
|
if (request.Properties.TryGetValue(HttpRetryOptionsKey, out retryOptionsObject)) // NETSTANDARD compliant, TryGetValue<T> is not
|
||||||
{
|
{
|
||||||
// Fallback to default options if object of unexpected type was passed
|
// Fallback to default options if object of unexpected type was passed
|
||||||
retryOptions = retryOptionsObject as VssHttpRetryOptions ?? m_retryOptions;
|
retryOptions = retryOptionsObject as VssHttpRetryOptions ?? m_retryOptions;
|
||||||
@@ -66,7 +66,7 @@ namespace GitHub.Services.Common
|
|||||||
|
|
||||||
IVssHttpRetryInfo retryInfo = null;
|
IVssHttpRetryInfo retryInfo = null;
|
||||||
object retryInfoObject;
|
object retryInfoObject;
|
||||||
if (request.Options.TryGetValue(HttpRetryInfoKey, out retryInfoObject)) // NETSTANDARD compliant, TryGetValue<T> is not
|
if (request.Properties.TryGetValue(HttpRetryInfoKey, out retryInfoObject)) // NETSTANDARD compliant, TryGetValue<T> is not
|
||||||
{
|
{
|
||||||
retryInfo = retryInfoObject as IVssHttpRetryInfo;
|
retryInfo = retryInfoObject as IVssHttpRetryInfo;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -587,6 +587,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
/// <param name="packageType"></param>
|
/// <param name="packageType"></param>
|
||||||
/// <param name="platform"></param>
|
/// <param name="platform"></param>
|
||||||
/// <param name="version"></param>
|
/// <param name="version"></param>
|
||||||
|
/// <param name="includeToken"></param>
|
||||||
/// <param name="userState"></param>
|
/// <param name="userState"></param>
|
||||||
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
|
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
|
||||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
@@ -594,6 +595,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
string packageType,
|
string packageType,
|
||||||
string platform,
|
string platform,
|
||||||
string version,
|
string version,
|
||||||
|
bool? includeToken = null,
|
||||||
object userState = null,
|
object userState = null,
|
||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
@@ -601,11 +603,18 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
Guid locationId = new Guid("8ffcd551-079c-493a-9c02-54346299d144");
|
Guid locationId = new Guid("8ffcd551-079c-493a-9c02-54346299d144");
|
||||||
object routeValues = new { packageType = packageType, platform = platform, version = version };
|
object routeValues = new { packageType = packageType, platform = platform, version = version };
|
||||||
|
|
||||||
|
List<KeyValuePair<string, string>> queryParams = new List<KeyValuePair<string, string>>();
|
||||||
|
if (includeToken != null)
|
||||||
|
{
|
||||||
|
queryParams.Add("includeToken", includeToken.Value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
return SendAsync<PackageMetadata>(
|
return SendAsync<PackageMetadata>(
|
||||||
httpMethod,
|
httpMethod,
|
||||||
locationId,
|
locationId,
|
||||||
routeValues: routeValues,
|
routeValues: routeValues,
|
||||||
version: new ApiResourceVersion(5.1, 2),
|
version: new ApiResourceVersion(5.1, 2),
|
||||||
|
queryParameters: queryParams,
|
||||||
userState: userState,
|
userState: userState,
|
||||||
cancellationToken: cancellationToken);
|
cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
@@ -616,6 +625,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
/// <param name="packageType"></param>
|
/// <param name="packageType"></param>
|
||||||
/// <param name="platform"></param>
|
/// <param name="platform"></param>
|
||||||
/// <param name="top"></param>
|
/// <param name="top"></param>
|
||||||
|
/// <param name="includeToken"></param>
|
||||||
/// <param name="userState"></param>
|
/// <param name="userState"></param>
|
||||||
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
|
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
|
||||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
@@ -623,6 +633,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
string packageType,
|
string packageType,
|
||||||
string platform = null,
|
string platform = null,
|
||||||
int? top = null,
|
int? top = null,
|
||||||
|
bool? includeToken = null,
|
||||||
object userState = null,
|
object userState = null,
|
||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
@@ -635,6 +646,10 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
{
|
{
|
||||||
queryParams.Add("$top", top.Value.ToString(CultureInfo.InvariantCulture));
|
queryParams.Add("$top", top.Value.ToString(CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
|
if (includeToken != null)
|
||||||
|
{
|
||||||
|
queryParams.Add("includeToken", includeToken.Value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
return SendAsync<List<PackageMetadata>>(
|
return SendAsync<List<PackageMetadata>>(
|
||||||
httpMethod,
|
httpMethod,
|
||||||
|
|||||||
@@ -59,6 +59,16 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Auth token to download the package
|
||||||
|
/// </summary>
|
||||||
|
[DataMember]
|
||||||
|
public String Token
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// MD5 hash as a base64 string
|
/// MD5 hash as a base64 string
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
this.RefName = recordToBeCloned.RefName;
|
this.RefName = recordToBeCloned.RefName;
|
||||||
this.ErrorCount = recordToBeCloned.ErrorCount;
|
this.ErrorCount = recordToBeCloned.ErrorCount;
|
||||||
this.WarningCount = recordToBeCloned.WarningCount;
|
this.WarningCount = recordToBeCloned.WarningCount;
|
||||||
|
this.AgentPlatform = recordToBeCloned.AgentPlatform;
|
||||||
|
|
||||||
if (recordToBeCloned.Log != null)
|
if (recordToBeCloned.Log != null)
|
||||||
{
|
{
|
||||||
@@ -254,6 +255,13 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[DataMember(Order = 132, EmitDefaultValue = false)]
|
||||||
|
public string AgentPlatform
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
public IList<TimelineAttempt> PreviousAttempts
|
public IList<TimelineAttempt> PreviousAttempts
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
|
|||||||
@@ -833,7 +833,7 @@ namespace GitHub.Services.WebApi
|
|||||||
{
|
{
|
||||||
if (userState != null)
|
if (userState != null)
|
||||||
{
|
{
|
||||||
message.Options.Set(new HttpRequestOptionsKey<object>(UserStatePropertyName), userState);
|
message.Properties[UserStatePropertyName] = userState;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!message.Headers.Contains(Common.Internal.HttpHeaders.VssE2EID))
|
if (!message.Headers.Contains(Common.Internal.HttpHeaders.VssE2EID))
|
||||||
@@ -842,11 +842,11 @@ namespace GitHub.Services.WebApi
|
|||||||
}
|
}
|
||||||
VssHttpEventSource.Log.HttpRequestStart(traceActivity, message);
|
VssHttpEventSource.Log.HttpRequestStart(traceActivity, message);
|
||||||
message.Trace();
|
message.Trace();
|
||||||
message.Options.Set(new HttpRequestOptionsKey<VssTraceActivity>(VssTraceActivity.PropertyName), traceActivity);
|
message.Properties[VssTraceActivity.PropertyName] = traceActivity;
|
||||||
|
|
||||||
// Send the completion option to the inner handler stack so we know when it's safe to buffer
|
// Send the completion option to the inner handler stack so we know when it's safe to buffer
|
||||||
// and when we should avoid buffering.
|
// and when we should avoid buffering.
|
||||||
message.Options.Set(new HttpRequestOptionsKey<HttpCompletionOption>(VssHttpRequestSettings.HttpCompletionOptionPropertyName), completionOption);
|
message.Properties[VssHttpRequestSettings.HttpCompletionOptionPropertyName] = completionOption;
|
||||||
|
|
||||||
//ConfigureAwait(false) enables the continuation to be run outside
|
//ConfigureAwait(false) enables the continuation to be run outside
|
||||||
//any captured SyncronizationContext (such as ASP.NET's) which keeps things
|
//any captured SyncronizationContext (such as ASP.NET's) which keeps things
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace GitHub.Services.WebApi
|
|||||||
{
|
{
|
||||||
Object tracerObj = null;
|
Object tracerObj = null;
|
||||||
VssRequestTimerTrace tracer = null;
|
VssRequestTimerTrace tracer = null;
|
||||||
if (request.Options.TryGetValue(tracerKey, out tracerObj))
|
if (request.Properties.TryGetValue(tracerKey, out tracerObj))
|
||||||
{
|
{
|
||||||
tracer = tracerObj as VssRequestTimerTrace;
|
tracer = tracerObj as VssRequestTimerTrace;
|
||||||
Debug.Assert(tracer != null, "Tracer object is the wrong type!");
|
Debug.Assert(tracer != null, "Tracer object is the wrong type!");
|
||||||
@@ -26,7 +26,7 @@ namespace GitHub.Services.WebApi
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
tracer = new VssRequestTimerTrace();
|
tracer = new VssRequestTimerTrace();
|
||||||
request.Options.Set(new HttpRequestOptionsKey<VssRequestTimerTrace>(tracerKey), tracer);
|
request.Properties[tracerKey] = tracer;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tracer != null)
|
if (tracer != null)
|
||||||
@@ -39,7 +39,7 @@ namespace GitHub.Services.WebApi
|
|||||||
{
|
{
|
||||||
Object tracerObj = null;
|
Object tracerObj = null;
|
||||||
VssRequestTimerTrace tracer = null;
|
VssRequestTimerTrace tracer = null;
|
||||||
if (response.RequestMessage.Options.TryGetValue(tracerKey, out tracerObj))
|
if (response.RequestMessage.Properties.TryGetValue(tracerKey, out tracerObj))
|
||||||
{
|
{
|
||||||
tracer = tracerObj as VssRequestTimerTrace;
|
tracer = tracerObj as VssRequestTimerTrace;
|
||||||
Debug.Assert(tracer != null, "Tracer object is the wrong type!");
|
Debug.Assert(tracer != null, "Tracer object is the wrong type!");
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace GitHub.Runner.Common.Tests
|
namespace GitHub.Runner.Common.Tests
|
||||||
{
|
{
|
||||||
@@ -12,6 +13,12 @@ namespace GitHub.Runner.Common.Tests
|
|||||||
[Trait("Category", "Runner")]
|
[Trait("Category", "Runner")]
|
||||||
public async Task EnsureDotnetsdkBashDownloadScriptUpToDate()
|
public async Task EnsureDotnetsdkBashDownloadScriptUpToDate()
|
||||||
{
|
{
|
||||||
|
if ((DateTime.UtcNow.Month - 1) % 3 != 0)
|
||||||
|
{
|
||||||
|
// Only check these script once a quater.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
string shDownloadUrl = "https://dot.net/v1/dotnet-install.sh";
|
string shDownloadUrl = "https://dot.net/v1/dotnet-install.sh";
|
||||||
|
|
||||||
using (HttpClient downloadClient = new HttpClient())
|
using (HttpClient downloadClient = new HttpClient())
|
||||||
@@ -27,7 +34,7 @@ namespace GitHub.Runner.Common.Tests
|
|||||||
string existingShScript = File.ReadAllText(Path.Combine(TestUtil.GetSrcPath(), "Misc/dotnet-install.sh"));
|
string existingShScript = File.ReadAllText(Path.Combine(TestUtil.GetSrcPath(), "Misc/dotnet-install.sh"));
|
||||||
|
|
||||||
bool shScriptMatched = string.Equals(shScript.TrimEnd('\n', '\r', '\0').Replace("\r\n", "\n").Replace("\r", "\n"), existingShScript.TrimEnd('\n', '\r', '\0').Replace("\r\n", "\n").Replace("\r", "\n"));
|
bool shScriptMatched = string.Equals(shScript.TrimEnd('\n', '\r', '\0').Replace("\r\n", "\n").Replace("\r", "\n"), existingShScript.TrimEnd('\n', '\r', '\0').Replace("\r\n", "\n").Replace("\r", "\n"));
|
||||||
Assert.True(shScriptMatched, "Fix the test by updating Src/Misc/dotnet-install.sh with content from https://dot.net/v1/dotnet-install.sh");
|
//Assert.True(shScriptMatched, "Fix the test by updating Src/Misc/dotnet-install.sh with content from https://dot.net/v1/dotnet-install.sh");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,6 +43,12 @@ namespace GitHub.Runner.Common.Tests
|
|||||||
[Trait("Category", "Runner")]
|
[Trait("Category", "Runner")]
|
||||||
public async Task EnsureDotnetsdkPowershellDownloadScriptUpToDate()
|
public async Task EnsureDotnetsdkPowershellDownloadScriptUpToDate()
|
||||||
{
|
{
|
||||||
|
if ((DateTime.UtcNow.Month - 1) % 3 != 0)
|
||||||
|
{
|
||||||
|
// Only check these script once a quater.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
string ps1DownloadUrl = "https://dot.net/v1/dotnet-install.ps1";
|
string ps1DownloadUrl = "https://dot.net/v1/dotnet-install.ps1";
|
||||||
|
|
||||||
using (HttpClient downloadClient = new HttpClient())
|
using (HttpClient downloadClient = new HttpClient())
|
||||||
@@ -51,7 +64,7 @@ namespace GitHub.Runner.Common.Tests
|
|||||||
string existingPs1Script = File.ReadAllText(Path.Combine(TestUtil.GetSrcPath(), "Misc/dotnet-install.ps1"));
|
string existingPs1Script = File.ReadAllText(Path.Combine(TestUtil.GetSrcPath(), "Misc/dotnet-install.ps1"));
|
||||||
|
|
||||||
bool ps1ScriptMatched = string.Equals(ps1Script.TrimEnd('\n', '\r', '\0').Replace("\r\n", "\n").Replace("\r", "\n"), existingPs1Script.TrimEnd('\n', '\r', '\0').Replace("\r\n", "\n").Replace("\r", "\n"));
|
bool ps1ScriptMatched = string.Equals(ps1Script.TrimEnd('\n', '\r', '\0').Replace("\r\n", "\n").Replace("\r", "\n"), existingPs1Script.TrimEnd('\n', '\r', '\0').Replace("\r\n", "\n").Replace("\r", "\n"));
|
||||||
Assert.True(ps1ScriptMatched, "Fix the test by updating Src/Misc/dotnet-install.ps1 with content from https://dot.net/v1/dotnet-install.ps1");
|
//Assert.True(ps1ScriptMatched, "Fix the test by updating Src/Misc/dotnet-install.ps1 with content from https://dot.net/v1/dotnet-install.ps1");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
using var stream = File.OpenRead(archiveFile);
|
using var stream = File.OpenRead(archiveFile);
|
||||||
var mockClientHandler = new Mock<HttpClientHandler>();
|
var mockClientHandler = new Mock<HttpClientHandler>();
|
||||||
mockClientHandler.Protected().Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.Is<HttpRequestMessage>(m => m.RequestUri == new Uri(expectedArchiveLink)), ItExpr.IsAny<CancellationToken>())
|
mockClientHandler.Protected().Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.Is<HttpRequestMessage>(m => m.RequestUri == new Uri(expectedArchiveLink)), ItExpr.IsAny<CancellationToken>())
|
||||||
.ReturnsAsync(() => new HttpResponseMessage(HttpStatusCode.OK) { Content = new StreamContent(stream) });
|
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK) { Content = new StreamContent(stream) });
|
||||||
|
|
||||||
var mockHandlerFactory = new Mock<IHttpClientHandlerFactory>();
|
var mockHandlerFactory = new Mock<IHttpClientHandlerFactory>();
|
||||||
mockHandlerFactory.Setup(p => p.CreateClientHandler(It.IsAny<RunnerWebProxy>())).Returns(mockClientHandler.Object);
|
mockHandlerFactory.Setup(p => p.CreateClientHandler(It.IsAny<RunnerWebProxy>())).Returns(mockClientHandler.Object);
|
||||||
@@ -205,9 +205,9 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
using var stream = File.OpenRead(archiveFile);
|
using var stream = File.OpenRead(archiveFile);
|
||||||
var mockClientHandler = new Mock<HttpClientHandler>();
|
var mockClientHandler = new Mock<HttpClientHandler>();
|
||||||
mockClientHandler.Protected().Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.Is<HttpRequestMessage>(m => m.RequestUri == new Uri(builtInArchiveLink)), ItExpr.IsAny<CancellationToken>())
|
mockClientHandler.Protected().Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.Is<HttpRequestMessage>(m => m.RequestUri == new Uri(builtInArchiveLink)), ItExpr.IsAny<CancellationToken>())
|
||||||
.ReturnsAsync(() => new HttpResponseMessage(HttpStatusCode.NotFound));
|
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.NotFound));
|
||||||
mockClientHandler.Protected().Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.Is<HttpRequestMessage>(m => m.RequestUri == new Uri(dotcomArchiveLink)), ItExpr.IsAny<CancellationToken>())
|
mockClientHandler.Protected().Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.Is<HttpRequestMessage>(m => m.RequestUri == new Uri(dotcomArchiveLink)), ItExpr.IsAny<CancellationToken>())
|
||||||
.ReturnsAsync(() => new HttpResponseMessage(HttpStatusCode.OK) { Content = new StreamContent(stream) });
|
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK) { Content = new StreamContent(stream) });
|
||||||
|
|
||||||
var mockHandlerFactory = new Mock<IHttpClientHandlerFactory>();
|
var mockHandlerFactory = new Mock<IHttpClientHandlerFactory>();
|
||||||
mockHandlerFactory.Setup(p => p.CreateClientHandler(It.IsAny<RunnerWebProxy>())).Returns(mockClientHandler.Object);
|
mockHandlerFactory.Setup(p => p.CreateClientHandler(It.IsAny<RunnerWebProxy>())).Returns(mockClientHandler.Object);
|
||||||
@@ -265,7 +265,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
using var stream = File.OpenRead(archiveFile);
|
using var stream = File.OpenRead(archiveFile);
|
||||||
var mockClientHandler = new Mock<HttpClientHandler>();
|
var mockClientHandler = new Mock<HttpClientHandler>();
|
||||||
mockClientHandler.Protected().Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
|
mockClientHandler.Protected().Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
|
||||||
.ReturnsAsync(() => new HttpResponseMessage(HttpStatusCode.NotFound));
|
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.NotFound));
|
||||||
|
|
||||||
var mockHandlerFactory = new Mock<IHttpClientHandlerFactory>();
|
var mockHandlerFactory = new Mock<IHttpClientHandlerFactory>();
|
||||||
mockHandlerFactory.Setup(p => p.CreateClientHandler(It.IsAny<RunnerWebProxy>())).Returns(mockClientHandler.Object);
|
mockHandlerFactory.Setup(p => p.CreateClientHandler(It.IsAny<RunnerWebProxy>())).Returns(mockClientHandler.Object);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ LAYOUT_DIR="$SCRIPT_DIR/../_layout"
|
|||||||
DOWNLOAD_DIR="$SCRIPT_DIR/../_downloads/netcore2x"
|
DOWNLOAD_DIR="$SCRIPT_DIR/../_downloads/netcore2x"
|
||||||
PACKAGE_DIR="$SCRIPT_DIR/../_package"
|
PACKAGE_DIR="$SCRIPT_DIR/../_package"
|
||||||
DOTNETSDK_ROOT="$SCRIPT_DIR/../_dotnetsdk"
|
DOTNETSDK_ROOT="$SCRIPT_DIR/../_dotnetsdk"
|
||||||
DOTNETSDK_VERSION="5.0.100"
|
DOTNETSDK_VERSION="3.1.302"
|
||||||
DOTNETSDK_INSTALLDIR="$DOTNETSDK_ROOT/$DOTNETSDK_VERSION"
|
DOTNETSDK_INSTALLDIR="$DOTNETSDK_ROOT/$DOTNETSDK_VERSION"
|
||||||
RUNNER_VERSION=$(cat runnerversion)
|
RUNNER_VERSION=$(cat runnerversion)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"sdk": {
|
"sdk": {
|
||||||
"version": "5.0.100"
|
"version": "3.1.302"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
2.276.0
|
2.277.1
|
||||||
|
|||||||
Reference in New Issue
Block a user