mirror of
https://github.com/actions/runner.git
synced 2025-12-10 12:36:23 +00:00
Compare commits
10 Commits
v2.160.0
...
users/eric
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8770849c3b | ||
|
|
61f9d3f656 | ||
|
|
08b9f6e045 | ||
|
|
0129e8111f | ||
|
|
ccca13ac07 | ||
|
|
82e9857d4f | ||
|
|
afd233b735 | ||
|
|
83be145bfd | ||
|
|
6e20aceaff | ||
|
|
e89148e33e |
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
|||||||
- os: macOS-latest
|
- os: macOS-latest
|
||||||
devScript: ./dev.sh
|
devScript: ./dev.sh
|
||||||
- os: windows-latest
|
- os: windows-latest
|
||||||
devScript: dev.cmd
|
devScript: ./dev
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
|
|||||||
@@ -5,36 +5,55 @@
|
|||||||
## Supported Distributions and Versions
|
## Supported Distributions and Versions
|
||||||
|
|
||||||
x64
|
x64
|
||||||
- Red Hat Enterprise Linux 6 (see note 1), 7
|
- Red Hat Enterprise Linux 7
|
||||||
- CentOS 6 (see note 1), 7
|
- CentOS 7
|
||||||
- Oracle Linux 7
|
- Oracle Linux 7
|
||||||
- Fedora 28, 27
|
- Fedora 29+
|
||||||
- Debian 9, 8.7 or later versions
|
- Debian 9+
|
||||||
- Ubuntu 18.04, Ubuntu 16.04, Ubuntu 14.04
|
- Ubuntu 16.04+
|
||||||
- Linux Mint 18, 17
|
- Linux Mint 18+
|
||||||
- openSUSE 42.3 or later versions
|
- openSUSE 15+
|
||||||
- SUSE Enterprise Linux (SLES) 12 SP2 or later versions
|
- SUSE Enterprise Linux (SLES) 12 SP2+
|
||||||
|
|
||||||
ARM32 (see note 2)
|
## Install .Net Core 3.x Linux Dependencies
|
||||||
- Debian 9 or later versions
|
|
||||||
- Ubuntu 18.04 or later versions
|
|
||||||
|
|
||||||
> Note 1: Red Hat Enterprise Linux 6 and CentOS 6 require installing the specialized "rhel.6-x64" agent package
|
The `./config.sh` will check .Net Core 3.x dependencies during runner configuration.
|
||||||
> Note 2: ARM instruction set [ARMv7](https://en.wikipedia.org/wiki/List_of_ARM_microarchitectures) or above is required, you can get your device's information by executing `uname -a`
|
|
||||||
|
|
||||||
## Install .Net Core 2.x Linux Dependencies
|
|
||||||
|
|
||||||
The `./config.sh` will check .Net Core 2.x dependencies during agent configuration.
|
|
||||||
You might see something like this which indicate a dependency's missing.
|
You might see something like this which indicate a dependency's missing.
|
||||||
```bash
|
```bash
|
||||||
./config.sh
|
./config.sh
|
||||||
libunwind.so.8 => not found
|
libunwind.so.8 => not found
|
||||||
libunwind-x86_64.so.8 => not found
|
libunwind-x86_64.so.8 => not found
|
||||||
Dependencies is missing for Dotnet Core 2.1
|
Dependencies is missing for Dotnet Core 3.0
|
||||||
Execute ./bin/installdependencies.sh to install any missing Dotnet Core 2.1 dependencies.
|
Execute ./bin/installdependencies.sh to install any missing Dotnet Core 3.0 dependencies.
|
||||||
```
|
```
|
||||||
You can easily correct the problem by executing `./bin/installdependencies.sh`.
|
You can easily correct the problem by executing `./bin/installdependencies.sh`.
|
||||||
The `installdependencies.sh` script should install all required dependencies on all supported Linux versions
|
The `installdependencies.sh` script should install all required dependencies on all supported Linux versions
|
||||||
> Note: The `installdependencies.sh` script will try to use the default package management mechanism on your Linux flavor (ex. `yum`/`apt-get`/`apt`). You might need to deal with error coming from the package management mechanism related to your setup, like [#1353](https://github.com/Microsoft/vsts-agent/issues/1353)
|
> Note: The `installdependencies.sh` script will try to use the default package management mechanism on your Linux flavor (ex. `yum`/`apt-get`/`apt`). You might need to deal with error coming from the package management mechanism related to your setup, like [#1353](https://github.com/Microsoft/vsts-agent/issues/1353)
|
||||||
|
|
||||||
|
### Full dependencies list
|
||||||
|
|
||||||
|
Debian based OS (Debian, Ubuntu, Linux Mint)
|
||||||
|
|
||||||
|
- liblttng-ust0
|
||||||
|
- libkrb5-3
|
||||||
|
- zlib1g
|
||||||
|
- libssl1.1, libssl1.0.2 or libssl1.0.0
|
||||||
|
- libicu63, libicu60, libicu57 or libicu55
|
||||||
|
|
||||||
|
Fedora based OS (Fedora, Redhat, Centos, Oracle Linux 7)
|
||||||
|
|
||||||
|
- lttng-ust
|
||||||
|
- openssl-libs
|
||||||
|
- krb5-libs
|
||||||
|
- zlib
|
||||||
|
- libicu
|
||||||
|
|
||||||
|
SUSE based OS (OpenSUSE, SUSE Enterprise)
|
||||||
|
|
||||||
|
- lttng-ust
|
||||||
|
- libopenssl1_1
|
||||||
|
- krb5
|
||||||
|
- zlib
|
||||||
|
- libicu60_2
|
||||||
|
|
||||||
## [More .Net Core Prerequisites Information](https://docs.microsoft.com/en-us/dotnet/core/linux-prerequisites?tabs=netcore2x)
|
## [More .Net Core Prerequisites Information](https://docs.microsoft.com/en-us/dotnet/core/linux-prerequisites?tabs=netcore2x)
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
## Features
|
## Features
|
||||||
- Set Default shell to powershell for windows runners (#135)
|
- N/A
|
||||||
- Use Powershell as fallback if Powershell Core is not available for default shell on windows (#142)
|
|
||||||
|
|
||||||
## Bugs
|
## Bugs
|
||||||
- Removed unintended additional fields on error and warning commands (#137)
|
- Reverted removal of additional fields error and warning fields (#147)
|
||||||
|
- Actions cache would incorrectly cache the action if the tag was updated (#148)
|
||||||
|
|
||||||
## Misc
|
## Misc
|
||||||
- N/A
|
- Updated to .NET Core 3.0 (#127)
|
||||||
|
|
||||||
## Agent Downloads
|
## Agent Downloads
|
||||||
|
|
||||||
|
|||||||
91
src/Misc/dotnet-install.ps1
vendored
91
src/Misc/dotnet-install.ps1
vendored
@@ -37,10 +37,7 @@
|
|||||||
.PARAMETER SharedRuntime
|
.PARAMETER SharedRuntime
|
||||||
This parameter is obsolete and may be removed in a future version of this script.
|
This parameter is obsolete and may be removed in a future version of this script.
|
||||||
The recommended alternative is '-Runtime dotnet'.
|
The recommended alternative is '-Runtime dotnet'.
|
||||||
|
|
||||||
Default: false
|
|
||||||
Installs just the shared runtime bits, not the entire SDK.
|
Installs just the shared runtime bits, not the entire SDK.
|
||||||
This is equivalent to specifying `-Runtime dotnet`.
|
|
||||||
.PARAMETER Runtime
|
.PARAMETER Runtime
|
||||||
Installs just a shared runtime, not the entire SDK.
|
Installs just a shared runtime, not the entire SDK.
|
||||||
Possible values:
|
Possible values:
|
||||||
@@ -77,11 +74,15 @@
|
|||||||
Skips installing non-versioned files if they already exist, such as dotnet.exe.
|
Skips installing non-versioned files if they already exist, such as dotnet.exe.
|
||||||
.PARAMETER NoCdn
|
.PARAMETER NoCdn
|
||||||
Disable downloading from the Azure CDN, and use the uncached feed directly.
|
Disable downloading from the Azure CDN, and use the uncached feed directly.
|
||||||
|
.PARAMETER JSonFile
|
||||||
|
Determines the SDK version from a user specified global.json file
|
||||||
|
Note: global.json must have a value for 'SDK:Version'
|
||||||
#>
|
#>
|
||||||
[cmdletbinding()]
|
[cmdletbinding()]
|
||||||
param(
|
param(
|
||||||
[string]$Channel="LTS",
|
[string]$Channel="LTS",
|
||||||
[string]$Version="Latest",
|
[string]$Version="Latest",
|
||||||
|
[string]$JSonFile,
|
||||||
[string]$InstallDir="<auto>",
|
[string]$InstallDir="<auto>",
|
||||||
[string]$Architecture="<auto>",
|
[string]$Architecture="<auto>",
|
||||||
[ValidateSet("dotnet", "aspnetcore", "windowsdesktop", IgnoreCase = $false)]
|
[ValidateSet("dotnet", "aspnetcore", "windowsdesktop", IgnoreCase = $false)]
|
||||||
@@ -258,7 +259,6 @@ function GetHTTPResponse([Uri] $Uri)
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function Get-Latest-Version-Info([string]$AzureFeed, [string]$Channel, [bool]$Coherent) {
|
function Get-Latest-Version-Info([string]$AzureFeed, [string]$Channel, [bool]$Coherent) {
|
||||||
Say-Invocation $MyInvocation
|
Say-Invocation $MyInvocation
|
||||||
|
|
||||||
@@ -304,20 +304,64 @@ function Get-Latest-Version-Info([string]$AzureFeed, [string]$Channel, [bool]$Co
|
|||||||
return $VersionInfo
|
return $VersionInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Parse-Jsonfile-For-Version([string]$JSonFile) {
|
||||||
function Get-Specific-Version-From-Version([string]$AzureFeed, [string]$Channel, [string]$Version) {
|
|
||||||
Say-Invocation $MyInvocation
|
Say-Invocation $MyInvocation
|
||||||
|
|
||||||
switch ($Version.ToLower()) {
|
If (-Not (Test-Path $JSonFile)) {
|
||||||
{ $_ -eq "latest" } {
|
throw "Unable to find '$JSonFile'"
|
||||||
$LatestVersionInfo = Get-Latest-Version-Info -AzureFeed $AzureFeed -Channel $Channel -Coherent $False
|
exit 0
|
||||||
return $LatestVersionInfo.Version
|
}
|
||||||
|
try {
|
||||||
|
$JSonContent = Get-Content($JSonFile) -Raw | ConvertFrom-Json | Select-Object -expand "sdk" -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
throw "Json file unreadable: '$JSonFile'"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
if ($JSonContent) {
|
||||||
|
try {
|
||||||
|
$JSonContent.PSObject.Properties | ForEach-Object {
|
||||||
|
$PropertyName = $_.Name
|
||||||
|
if ($PropertyName -eq "version") {
|
||||||
|
$Version = $_.Value
|
||||||
|
Say-Verbose "Version = $Version"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
{ $_ -eq "coherent" } {
|
catch {
|
||||||
$LatestVersionInfo = Get-Latest-Version-Info -AzureFeed $AzureFeed -Channel $Channel -Coherent $True
|
throw "Unable to parse the SDK node in '$JSonFile'"
|
||||||
return $LatestVersionInfo.Version
|
exit 0
|
||||||
}
|
}
|
||||||
default { return $Version }
|
}
|
||||||
|
else {
|
||||||
|
throw "Unable to find the SDK node in '$JSonFile'"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
If ($Version -eq $null) {
|
||||||
|
throw "Unable to find the SDK:version node in '$JSonFile'"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
return $Version
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-Specific-Version-From-Version([string]$AzureFeed, [string]$Channel, [string]$Version, [string]$JSonFile) {
|
||||||
|
Say-Invocation $MyInvocation
|
||||||
|
|
||||||
|
if (-not $JSonFile) {
|
||||||
|
switch ($Version.ToLower()) {
|
||||||
|
{ $_ -eq "latest" } {
|
||||||
|
$LatestVersionInfo = Get-Latest-Version-Info -AzureFeed $AzureFeed -Channel $Channel -Coherent $False
|
||||||
|
return $LatestVersionInfo.Version
|
||||||
|
}
|
||||||
|
{ $_ -eq "coherent" } {
|
||||||
|
$LatestVersionInfo = Get-Latest-Version-Info -AzureFeed $AzureFeed -Channel $Channel -Coherent $True
|
||||||
|
return $LatestVersionInfo.Version
|
||||||
|
}
|
||||||
|
default { return $Version }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Parse-Jsonfile-For-Version $JSonFile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,23 +426,6 @@ function Resolve-Installation-Path([string]$InstallDir) {
|
|||||||
return $InstallDir
|
return $InstallDir
|
||||||
}
|
}
|
||||||
|
|
||||||
function Get-Version-Info-From-Version-File([string]$InstallRoot, [string]$RelativePathToVersionFile) {
|
|
||||||
Say-Invocation $MyInvocation
|
|
||||||
|
|
||||||
$VersionFile = Join-Path -Path $InstallRoot -ChildPath $RelativePathToVersionFile
|
|
||||||
Say-Verbose "Local version file: $VersionFile"
|
|
||||||
|
|
||||||
if (Test-Path $VersionFile) {
|
|
||||||
$VersionText = cat $VersionFile
|
|
||||||
Say-Verbose "Local version file text: $VersionText"
|
|
||||||
return Get-Version-Info-From-Version-Text $VersionText
|
|
||||||
}
|
|
||||||
|
|
||||||
Say-Verbose "Local version file not found."
|
|
||||||
|
|
||||||
return $null
|
|
||||||
}
|
|
||||||
|
|
||||||
function Is-Dotnet-Package-Installed([string]$InstallRoot, [string]$RelativePathToPackage, [string]$SpecificVersion) {
|
function Is-Dotnet-Package-Installed([string]$InstallRoot, [string]$RelativePathToPackage, [string]$SpecificVersion) {
|
||||||
Say-Invocation $MyInvocation
|
Say-Invocation $MyInvocation
|
||||||
|
|
||||||
@@ -534,7 +561,7 @@ function Prepend-Sdk-InstallRoot-To-Path([string]$InstallRoot, [string]$BinFolde
|
|||||||
}
|
}
|
||||||
|
|
||||||
$CLIArchitecture = Get-CLIArchitecture-From-Architecture $Architecture
|
$CLIArchitecture = Get-CLIArchitecture-From-Architecture $Architecture
|
||||||
$SpecificVersion = Get-Specific-Version-From-Version -AzureFeed $AzureFeed -Channel $Channel -Version $Version
|
$SpecificVersion = Get-Specific-Version-From-Version -AzureFeed $AzureFeed -Channel $Channel -Version $Version -JSonFile $JSonFile
|
||||||
$DownloadLink = Get-Download-Link -AzureFeed $AzureFeed -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture
|
$DownloadLink = Get-Download-Link -AzureFeed $AzureFeed -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture
|
||||||
$LegacyDownloadLink = Get-LegacyDownload-Link -AzureFeed $AzureFeed -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture
|
$LegacyDownloadLink = Get-LegacyDownload-Link -AzureFeed $AzureFeed -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture
|
||||||
|
|
||||||
|
|||||||
125
src/Misc/dotnet-install.sh
vendored
125
src/Misc/dotnet-install.sh
vendored
@@ -435,11 +435,52 @@ get_latest_version_info() {
|
|||||||
return $?
|
return $?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# args:
|
||||||
|
# json_file - $1
|
||||||
|
parse_jsonfile_for_version() {
|
||||||
|
eval $invocation
|
||||||
|
|
||||||
|
local json_file="$1"
|
||||||
|
if [ ! -f "$json_file" ]; then
|
||||||
|
say_err "Unable to find \`$json_file\`"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
sdk_section=$(cat $json_file | awk '/"sdk"/,/}/')
|
||||||
|
if [ -z "$sdk_section" ]; then
|
||||||
|
say_err "Unable to parse the SDK node in \`$json_file\`"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
sdk_list=$(echo $sdk_section | awk -F"[{}]" '{print $2}')
|
||||||
|
sdk_list=${sdk_list//[\" ]/}
|
||||||
|
sdk_list=${sdk_list//,/$'\n'}
|
||||||
|
sdk_list="$(echo -e "${sdk_list}" | tr -d '[[:space:]]')"
|
||||||
|
|
||||||
|
local version_info=""
|
||||||
|
while read -r line; do
|
||||||
|
IFS=:
|
||||||
|
while read -r key value; do
|
||||||
|
if [[ "$key" == "version" ]]; then
|
||||||
|
version_info=$value
|
||||||
|
fi
|
||||||
|
done <<< "$line"
|
||||||
|
done <<< "$sdk_list"
|
||||||
|
if [ -z "$version_info" ]; then
|
||||||
|
say_err "Unable to find the SDK:version node in \`$json_file\`"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$version_info"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
# args:
|
# args:
|
||||||
# azure_feed - $1
|
# azure_feed - $1
|
||||||
# channel - $2
|
# channel - $2
|
||||||
# normalized_architecture - $3
|
# normalized_architecture - $3
|
||||||
# version - $4
|
# version - $4
|
||||||
|
# json_file - $5
|
||||||
get_specific_version_from_version() {
|
get_specific_version_from_version() {
|
||||||
eval $invocation
|
eval $invocation
|
||||||
|
|
||||||
@@ -447,27 +488,35 @@ get_specific_version_from_version() {
|
|||||||
local channel="$2"
|
local channel="$2"
|
||||||
local normalized_architecture="$3"
|
local normalized_architecture="$3"
|
||||||
local version="$(to_lowercase "$4")"
|
local version="$(to_lowercase "$4")"
|
||||||
|
local json_file="$5"
|
||||||
|
|
||||||
case "$version" in
|
if [ -z "$json_file" ]; then
|
||||||
latest)
|
case "$version" in
|
||||||
local version_info
|
latest)
|
||||||
version_info="$(get_latest_version_info "$azure_feed" "$channel" "$normalized_architecture" false)" || return 1
|
local version_info
|
||||||
say_verbose "get_specific_version_from_version: version_info=$version_info"
|
version_info="$(get_latest_version_info "$azure_feed" "$channel" "$normalized_architecture" false)" || return 1
|
||||||
echo "$version_info" | get_version_from_version_info
|
say_verbose "get_specific_version_from_version: version_info=$version_info"
|
||||||
return 0
|
echo "$version_info" | get_version_from_version_info
|
||||||
;;
|
return 0
|
||||||
coherent)
|
;;
|
||||||
local version_info
|
coherent)
|
||||||
version_info="$(get_latest_version_info "$azure_feed" "$channel" "$normalized_architecture" true)" || return 1
|
local version_info
|
||||||
say_verbose "get_specific_version_from_version: version_info=$version_info"
|
version_info="$(get_latest_version_info "$azure_feed" "$channel" "$normalized_architecture" true)" || return 1
|
||||||
echo "$version_info" | get_version_from_version_info
|
say_verbose "get_specific_version_from_version: version_info=$version_info"
|
||||||
return 0
|
echo "$version_info" | get_version_from_version_info
|
||||||
;;
|
return 0
|
||||||
*)
|
;;
|
||||||
echo "$version"
|
*)
|
||||||
return 0
|
echo "$version"
|
||||||
;;
|
return 0
|
||||||
esac
|
;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
local version_info
|
||||||
|
version_info="$(parse_jsonfile_for_version "$json_file")" || return 1
|
||||||
|
echo "$version_info"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# args:
|
# args:
|
||||||
@@ -558,24 +607,6 @@ resolve_installation_path() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# args:
|
|
||||||
# install_root - $1
|
|
||||||
get_installed_version_info() {
|
|
||||||
eval $invocation
|
|
||||||
|
|
||||||
local install_root="$1"
|
|
||||||
local version_file="$(combine_paths "$install_root" "$local_version_file_relative_path")"
|
|
||||||
say_verbose "Local version file: $version_file"
|
|
||||||
if [ ! -z "$version_file" ] | [ -r "$version_file" ]; then
|
|
||||||
local version_info="$(cat "$version_file")"
|
|
||||||
echo "$version_info"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
say_verbose "Local version file not found."
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# args:
|
# args:
|
||||||
# relative_or_absolute_path - $1
|
# relative_or_absolute_path - $1
|
||||||
get_absolute_path() {
|
get_absolute_path() {
|
||||||
@@ -724,7 +755,7 @@ 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"
|
||||||
|
|
||||||
specific_version="$(get_specific_version_from_version "$azure_feed" "$channel" "$normalized_architecture" "$version")"
|
specific_version="$(get_specific_version_from_version "$azure_feed" "$channel" "$normalized_architecture" "$version" "$json_file")"
|
||||||
say_verbose "specific_version=$specific_version"
|
say_verbose "specific_version=$specific_version"
|
||||||
if [ -z "$specific_version" ]; then
|
if [ -z "$specific_version" ]; then
|
||||||
say_err "Could not resolve version information."
|
say_err "Could not resolve version information."
|
||||||
@@ -826,6 +857,7 @@ temporary_file_template="${TMPDIR:-/tmp}/dotnet.XXXXXXXXX"
|
|||||||
|
|
||||||
channel="LTS"
|
channel="LTS"
|
||||||
version="Latest"
|
version="Latest"
|
||||||
|
json_file=""
|
||||||
install_dir="<auto>"
|
install_dir="<auto>"
|
||||||
architecture="<auto>"
|
architecture="<auto>"
|
||||||
dry_run=false
|
dry_run=false
|
||||||
@@ -912,6 +944,10 @@ do
|
|||||||
runtime_id="$1"
|
runtime_id="$1"
|
||||||
non_dynamic_parameters+=" $name "\""$1"\"""
|
non_dynamic_parameters+=" $name "\""$1"\"""
|
||||||
;;
|
;;
|
||||||
|
--jsonfile|-[Jj][Ss]on[Ff]ile)
|
||||||
|
shift
|
||||||
|
json_file="$1"
|
||||||
|
;;
|
||||||
--skip-non-versioned-files|-[Ss]kip[Nn]on[Vv]ersioned[Ff]iles)
|
--skip-non-versioned-files|-[Ss]kip[Nn]on[Vv]ersioned[Ff]iles)
|
||||||
override_non_versioned_files=false
|
override_non_versioned_files=false
|
||||||
non_dynamic_parameters+=" $name"
|
non_dynamic_parameters+=" $name"
|
||||||
@@ -953,22 +989,25 @@ do
|
|||||||
echo " Possible values:"
|
echo " Possible values:"
|
||||||
echo " - dotnet - the Microsoft.NETCore.App shared runtime"
|
echo " - dotnet - the Microsoft.NETCore.App shared runtime"
|
||||||
echo " - aspnetcore - the Microsoft.AspNetCore.App shared runtime"
|
echo " - aspnetcore - the Microsoft.AspNetCore.App shared runtime"
|
||||||
echo " --skip-non-versioned-files Skips non-versioned files if they already exist, such as the dotnet executable."
|
|
||||||
echo " -SkipNonVersionedFiles"
|
|
||||||
echo " --dry-run,-DryRun Do not perform installation. Display download link."
|
echo " --dry-run,-DryRun Do not perform installation. Display download link."
|
||||||
echo " --no-path, -NoPath Do not set PATH for the current process."
|
echo " --no-path, -NoPath Do not set PATH for the current process."
|
||||||
echo " --verbose,-Verbose Display diagnostics information."
|
echo " --verbose,-Verbose Display diagnostics information."
|
||||||
echo " --azure-feed,-AzureFeed Azure feed location. Defaults to $azure_feed, This parameter typically is not changed by the user."
|
echo " --azure-feed,-AzureFeed Azure feed location. Defaults to $azure_feed, This parameter typically is not changed by the user."
|
||||||
echo " --uncached-feed,-UncachedFeed Uncached feed location. This parameter typically is not changed by the user."
|
echo " --uncached-feed,-UncachedFeed Uncached feed location. This parameter typically is not changed by the user."
|
||||||
echo " --no-cdn,-NoCdn Disable downloading from the Azure CDN, and use the uncached feed directly."
|
|
||||||
echo " --feed-credential,-FeedCredential Azure feed shared access token. This parameter typically is not specified."
|
echo " --feed-credential,-FeedCredential Azure feed shared access token. This parameter typically is not specified."
|
||||||
|
echo " --skip-non-versioned-files Skips non-versioned files if they already exist, such as the dotnet executable."
|
||||||
|
echo " -SkipNonVersionedFiles"
|
||||||
|
echo " --no-cdn,-NoCdn Disable downloading from the Azure CDN, and use the uncached feed directly."
|
||||||
|
echo " --jsonfile <JSONFILE> Determines the SDK version from a user specified global.json file."
|
||||||
|
echo " Note: global.json must have a value for 'SDK:Version'"
|
||||||
echo " --runtime-id Installs the .NET Tools for the given platform (use linux-x64 for portable linux)."
|
echo " --runtime-id Installs the .NET Tools for the given platform (use linux-x64 for portable linux)."
|
||||||
echo " -RuntimeId"
|
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 " -SharedRuntime Installs just the shared runtime bits, not the entire SDK."
|
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 ""
|
echo ""
|
||||||
echo "Install Location:"
|
echo "Install Location:"
|
||||||
echo " Location is chosen in following order:"
|
echo " Location is chosen in following order:"
|
||||||
|
|||||||
@@ -60,10 +60,9 @@ then
|
|||||||
print_errormessage
|
print_errormessage
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ubuntu 18 uses libcurl4
|
# libissl version prefer: libssl1.1 -> libssl1.0.2 -> libssl1.0.0
|
||||||
# ubuntu 14, 16 and other linux use libcurl3
|
apt install -y libssl1.1$ || apt install -y libssl1.0.2$ || apt install -y libssl1.0.0$
|
||||||
apt install -y libcurl3 || apt install -y libcurl4
|
|
||||||
if [ $? -ne 0 ]
|
if [ $? -ne 0 ]
|
||||||
then
|
then
|
||||||
echo "'apt' failed with exit code '$?'"
|
echo "'apt' failed with exit code '$?'"
|
||||||
@@ -71,18 +70,8 @@ then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# debian 9 use libssl1.0.2
|
# libicu version prefer: libicu63 -> libicu60 -> libicu57 -> libicu55 -> libicu52
|
||||||
# other debian linux use libssl1.0.0
|
apt install -y libicu63 || apt install -y libicu60 || apt install -y libicu57 || apt install -y libicu55 || apt install -y libicu52
|
||||||
apt install -y libssl1.0.0 || apt install -y libssl1.0.2
|
|
||||||
if [ $? -ne 0 ]
|
|
||||||
then
|
|
||||||
echo "'apt' failed with exit code '$?'"
|
|
||||||
print_errormessage
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# libicu version prefer: libicu52 -> libicu55 -> libicu57 -> libicu60
|
|
||||||
apt install -y libicu52 || apt install -y libicu55 || apt install -y libicu57 || apt install -y libicu60
|
|
||||||
if [ $? -ne 0 ]
|
if [ $? -ne 0 ]
|
||||||
then
|
then
|
||||||
echo "'apt' failed with exit code '$?'"
|
echo "'apt' failed with exit code '$?'"
|
||||||
@@ -101,9 +90,8 @@ then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ubuntu 18 uses libcurl4
|
# libissl version prefer: libssl1.1 -> libssl1.0.2 -> libssl1.0.0
|
||||||
# ubuntu 14, 16 and other linux use libcurl3
|
apt-get install -y libssl1.1$ || apt-get install -y libssl1.0.2$ || apt install -y libssl1.0.0$
|
||||||
apt-get install -y libcurl3 || apt-get install -y libcurl4
|
|
||||||
if [ $? -ne 0 ]
|
if [ $? -ne 0 ]
|
||||||
then
|
then
|
||||||
echo "'apt-get' failed with exit code '$?'"
|
echo "'apt-get' failed with exit code '$?'"
|
||||||
@@ -111,18 +99,8 @@ then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# debian 9 use libssl1.0.2
|
# libicu version prefer: libicu63 -> libicu60 -> libicu57 -> libicu55 -> libicu52
|
||||||
# other debian linux use libssl1.0.0
|
apt-get install -y libicu63 || apt-get install -y libicu60 || apt install -y libicu57 || apt install -y libicu55 || apt install -y libicu52
|
||||||
apt-get install -y libssl1.0.0 || apt install -y libssl1.0.2
|
|
||||||
if [ $? -ne 0 ]
|
|
||||||
then
|
|
||||||
echo "'apt-get' failed with exit code '$?'"
|
|
||||||
print_errormessage
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# libicu version prefer: libicu52 -> libicu55 -> libicu57 -> libicu60
|
|
||||||
apt-get install -y libicu52 || apt install -y libicu55 || apt install -y libicu57 || apt install -y libicu60
|
|
||||||
if [ $? -ne 0 ]
|
if [ $? -ne 0 ]
|
||||||
then
|
then
|
||||||
echo "'apt-get' failed with exit code '$?'"
|
echo "'apt-get' failed with exit code '$?'"
|
||||||
@@ -149,46 +127,7 @@ then
|
|||||||
command -v dnf
|
command -v dnf
|
||||||
if [ $? -eq 0 ]
|
if [ $? -eq 0 ]
|
||||||
then
|
then
|
||||||
useCompatSsl=0
|
dnf install -y lttng-ust openssl-libs krb5-libs zlib libicu
|
||||||
grep -i 'fedora release 28' /etc/fedora-release
|
|
||||||
if [ $? -eq 0 ]
|
|
||||||
then
|
|
||||||
useCompatSsl=1
|
|
||||||
else
|
|
||||||
grep -i 'fedora release 27' /etc/fedora-release
|
|
||||||
if [ $? -eq 0 ]
|
|
||||||
then
|
|
||||||
useCompatSsl=1
|
|
||||||
else
|
|
||||||
grep -i 'fedora release 26' /etc/fedora-release
|
|
||||||
if [ $? -eq 0 ]
|
|
||||||
then
|
|
||||||
useCompatSsl=1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ $useCompatSsl -eq 1 ]
|
|
||||||
then
|
|
||||||
echo "Use compat-openssl10-devel instead of openssl-devel for Fedora 27/28 (dotnet core requires openssl 1.0.x)"
|
|
||||||
dnf install -y compat-openssl10
|
|
||||||
if [ $? -ne 0 ]
|
|
||||||
then
|
|
||||||
echo "'dnf' failed with exit code '$?'"
|
|
||||||
print_errormessage
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
dnf install -y openssl-libs
|
|
||||||
if [ $? -ne 0 ]
|
|
||||||
then
|
|
||||||
echo "'dnf' failed with exit code '$?'"
|
|
||||||
print_errormessage
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnf install -y lttng-ust libcurl krb5-libs zlib libicu
|
|
||||||
if [ $? -ne 0 ]
|
if [ $? -ne 0 ]
|
||||||
then
|
then
|
||||||
echo "'dnf' failed with exit code '$?'"
|
echo "'dnf' failed with exit code '$?'"
|
||||||
@@ -204,22 +143,13 @@ then
|
|||||||
command -v yum
|
command -v yum
|
||||||
if [ $? -eq 0 ]
|
if [ $? -eq 0 ]
|
||||||
then
|
then
|
||||||
yum install -y openssl-libs libcurl krb5-libs zlib libicu
|
yum install -y lttng-ust openssl-libs krb5-libs zlib libicu
|
||||||
if [ $? -ne 0 ]
|
if [ $? -ne 0 ]
|
||||||
then
|
then
|
||||||
echo "'yum' failed with exit code '$?'"
|
echo "'yum' failed with exit code '$?'"
|
||||||
print_errormessage
|
print_errormessage
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# install lttng-ust separately since it's not part of offical package repository
|
|
||||||
yum install -y wget && wget -P /etc/yum.repos.d/ https://packages.efficios.com/repo.files/EfficiOS-RHEL7-x86-64.repo && rpmkeys --import https://packages.efficios.com/rhel/repo.key && yum updateinfo && yum install -y lttng-ust
|
|
||||||
if [ $? -ne 0 ]
|
|
||||||
then
|
|
||||||
echo "'lttng-ust' installation failed with exit code '$?'"
|
|
||||||
print_errormessage
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
echo "Can not find 'yum'"
|
echo "Can not find 'yum'"
|
||||||
print_errormessage
|
print_errormessage
|
||||||
@@ -230,13 +160,14 @@ then
|
|||||||
# we might on OpenSUSE
|
# we might on OpenSUSE
|
||||||
OSTYPE=$(grep ID_LIKE /etc/os-release | cut -f2 -d=)
|
OSTYPE=$(grep ID_LIKE /etc/os-release | cut -f2 -d=)
|
||||||
echo $OSTYPE
|
echo $OSTYPE
|
||||||
if [ $OSTYPE == '"suse"' ]
|
echo $OSTYPE | grep "suse"
|
||||||
|
if [ $? -eq 0 ]
|
||||||
then
|
then
|
||||||
echo "The current OS is SUSE based"
|
echo "The current OS is SUSE based"
|
||||||
command -v zypper
|
command -v zypper
|
||||||
if [ $? -eq 0 ]
|
if [ $? -eq 0 ]
|
||||||
then
|
then
|
||||||
zypper -n install lttng-ust libopenssl1_0_0 libcurl4 krb5 zlib libicu52_1
|
zypper -n install lttng-ust libopenssl1_1 krb5 zlib libicu60_2
|
||||||
if [ $? -ne 0 ]
|
if [ $? -ne 0 ]
|
||||||
then
|
then
|
||||||
echo "'zypper' failed with exit code '$?'"
|
echo "'zypper' failed with exit code '$?'"
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ if [ $user_id -eq 0 -a -z "$AGENT_ALLOW_RUNASROOT" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check dotnet core 2.1 dependencies for Linux
|
# Check dotnet core 3.0 dependencies for Linux
|
||||||
if [[ (`uname` == "Linux") ]]
|
if [[ (`uname` == "Linux") ]]
|
||||||
then
|
then
|
||||||
command -v ldd > /dev/null
|
command -v ldd > /dev/null
|
||||||
@@ -20,29 +20,22 @@ then
|
|||||||
|
|
||||||
ldd ./bin/libcoreclr.so | grep 'not found'
|
ldd ./bin/libcoreclr.so | grep 'not found'
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
echo "Dependencies is missing for Dotnet Core 2.1"
|
echo "Dependencies is missing for Dotnet Core 3.0"
|
||||||
echo "Execute ./bin/installdependencies.sh to install any missing Dotnet Core 2.1 dependencies."
|
echo "Execute ./bin/installdependencies.sh to install any missing Dotnet Core 3.0 dependencies."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ldd ./bin/System.Security.Cryptography.Native.OpenSsl.so | grep 'not found'
|
ldd ./bin/System.Security.Cryptography.Native.OpenSsl.so | grep 'not found'
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
echo "Dependencies is missing for Dotnet Core 2.1"
|
echo "Dependencies is missing for Dotnet Core 3.0"
|
||||||
echo "Execute ./bin/installdependencies.sh to install any missing Dotnet Core 2.1 dependencies."
|
echo "Execute ./bin/installdependencies.sh to install any missing Dotnet Core 3.0 dependencies."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ldd ./bin/System.IO.Compression.Native.so | grep 'not found'
|
ldd ./bin/System.IO.Compression.Native.so | grep 'not found'
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
echo "Dependencies is missing for Dotnet Core 2.1"
|
echo "Dependencies is missing for Dotnet Core 3.0"
|
||||||
echo "Execute ./bin/installdependencies.sh to install any missing Dotnet Core 2.1 dependencies."
|
echo "Execute ./bin/installdependencies.sh to install any missing Dotnet Core 3.0 dependencies."
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
ldd ./bin/System.Net.Http.Native.so | grep 'not found'
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
echo "Dependencies is missing for Dotnet Core 2.1"
|
|
||||||
echo "Execute ./bin/installdependencies.sh to install any missing Dotnet Core 2.1 dependencies."
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -59,8 +52,8 @@ then
|
|||||||
libpath=${LD_LIBRARY_PATH:-}
|
libpath=${LD_LIBRARY_PATH:-}
|
||||||
$LDCONFIG_COMMAND -NXv ${libpath//:/} 2>&1 | grep libicu >/dev/null 2>&1
|
$LDCONFIG_COMMAND -NXv ${libpath//:/} 2>&1 | grep libicu >/dev/null 2>&1
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo "Libicu's dependencies is missing for Dotnet Core 2.1"
|
echo "Libicu's dependencies is missing for Dotnet Core 3.0"
|
||||||
echo "Execute ./bin/installdependencies.sh to install any missing Dotnet Core 2.1 dependencies."
|
echo "Execute ./bin/installdependencies.sh to install any missing Dotnet Core 3.0 dependencies."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ namespace GitHub.Runner.Common
|
|||||||
// Action command extensions.
|
// Action command extensions.
|
||||||
case "GitHub.Runner.Worker.IActionCommandExtension":
|
case "GitHub.Runner.Worker.IActionCommandExtension":
|
||||||
Add<T>(extensions, "GitHub.Runner.Worker.InternalPluginSetRepoPathCommandExtension, Runner.Worker");
|
Add<T>(extensions, "GitHub.Runner.Worker.InternalPluginSetRepoPathCommandExtension, Runner.Worker");
|
||||||
|
Add<T>(extensions, "GitHub.Runner.Worker.SetWorkspaceCommandExtension, Runner.Worker");
|
||||||
Add<T>(extensions, "GitHub.Runner.Worker.SetEnvCommandExtension, Runner.Worker");
|
Add<T>(extensions, "GitHub.Runner.Worker.SetEnvCommandExtension, Runner.Worker");
|
||||||
Add<T>(extensions, "GitHub.Runner.Worker.SetOutputCommandExtension, Runner.Worker");
|
Add<T>(extensions, "GitHub.Runner.Worker.SetOutputCommandExtension, Runner.Worker");
|
||||||
Add<T>(extensions, "GitHub.Runner.Worker.SaveStateCommandExtension, Runner.Worker");
|
Add<T>(extensions, "GitHub.Runner.Worker.SaveStateCommandExtension, Runner.Worker");
|
||||||
@@ -54,6 +55,7 @@ namespace GitHub.Runner.Common
|
|||||||
Add<T>(extensions, "GitHub.Runner.Worker.DebugCommandExtension, Runner.Worker");
|
Add<T>(extensions, "GitHub.Runner.Worker.DebugCommandExtension, Runner.Worker");
|
||||||
Add<T>(extensions, "GitHub.Runner.Worker.GroupCommandExtension, Runner.Worker");
|
Add<T>(extensions, "GitHub.Runner.Worker.GroupCommandExtension, Runner.Worker");
|
||||||
Add<T>(extensions, "GitHub.Runner.Worker.EndGroupCommandExtension, Runner.Worker");
|
Add<T>(extensions, "GitHub.Runner.Worker.EndGroupCommandExtension, Runner.Worker");
|
||||||
|
Add<T>(extensions, "GitHub.Runner.Worker.EchoCommandExtension, Runner.Worker");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// This should never happen.
|
// This should never happen.
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
||||||
<NoWarn>NU1701;NU1603</NoWarn>
|
<NoWarn>NU1701;NU1603</NoWarn>
|
||||||
<Version>$(Version)</Version>
|
<Version>$(Version)</Version>
|
||||||
|
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
||||||
<NoWarn>NU1701;NU1603</NoWarn>
|
<NoWarn>NU1701;NU1603</NoWarn>
|
||||||
<Version>$(Version)</Version>
|
<Version>$(Version)</Version>
|
||||||
|
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
||||||
|
<PublishReadyToRun>true</PublishReadyToRun>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
||||||
<NoWarn>NU1701;NU1603</NoWarn>
|
<NoWarn>NU1701;NU1603</NoWarn>
|
||||||
<Version>$(Version)</Version>
|
<Version>$(Version)</Version>
|
||||||
|
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
||||||
|
<PublishReadyToRun>true</PublishReadyToRun>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -236,15 +236,15 @@ namespace GitHub.Runner.Plugins.Artifact
|
|||||||
// try upload all files for the first time.
|
// try upload all files for the first time.
|
||||||
UploadResult uploadResult = await ParallelUploadAsync(context, files, maxConcurrentUploads, _uploadCancellationTokenSource.Token);
|
UploadResult uploadResult = await ParallelUploadAsync(context, files, maxConcurrentUploads, _uploadCancellationTokenSource.Token);
|
||||||
|
|
||||||
if (uploadResult.FailedFiles.Count == 0)
|
if (uploadResult.RetryFiles.Count == 0)
|
||||||
{
|
{
|
||||||
// all files have been upload succeed.
|
// all files have been upload succeed.
|
||||||
context.Output("File upload succeed.");
|
context.Output("File upload complete.");
|
||||||
return uploadResult.TotalFileSizeUploaded;
|
return uploadResult.TotalFileSizeUploaded;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
context.Output($"{uploadResult.FailedFiles.Count} files failed to upload, retry these files after a minute.");
|
context.Output($"{uploadResult.RetryFiles.Count} files failed to upload, retry these files after a minute.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delay 1 min then retry failed files.
|
// Delay 1 min then retry failed files.
|
||||||
@@ -255,13 +255,13 @@ namespace GitHub.Runner.Plugins.Artifact
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Retry upload all failed files.
|
// Retry upload all failed files.
|
||||||
context.Output($"Start retry {uploadResult.FailedFiles.Count} failed files upload.");
|
context.Output($"Start retry {uploadResult.RetryFiles.Count} failed files upload.");
|
||||||
UploadResult retryUploadResult = await ParallelUploadAsync(context, uploadResult.FailedFiles, maxConcurrentUploads, _uploadCancellationTokenSource.Token);
|
UploadResult retryUploadResult = await ParallelUploadAsync(context, uploadResult.RetryFiles, maxConcurrentUploads, _uploadCancellationTokenSource.Token);
|
||||||
|
|
||||||
if (retryUploadResult.FailedFiles.Count == 0)
|
if (retryUploadResult.RetryFiles.Count == 0)
|
||||||
{
|
{
|
||||||
// all files have been upload succeed after retry.
|
// all files have been upload succeed after retry.
|
||||||
context.Output("File upload succeed after retry.");
|
context.Output("File upload complete after retry.");
|
||||||
return uploadResult.TotalFileSizeUploaded + retryUploadResult.TotalFileSizeUploaded;
|
return uploadResult.TotalFileSizeUploaded + retryUploadResult.TotalFileSizeUploaded;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -465,75 +465,61 @@ namespace GitHub.Runner.Plugins.Artifact
|
|||||||
using (FileStream fs = File.Open(fileToUpload, FileMode.Open, FileAccess.Read, FileShare.Read))
|
using (FileStream fs = File.Open(fileToUpload, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||||
{
|
{
|
||||||
string itemPath = (_containerPath.TrimEnd('/') + "/" + fileToUpload.Remove(0, _sourceParentDirectory.Length + 1)).Replace('\\', '/');
|
string itemPath = (_containerPath.TrimEnd('/') + "/" + fileToUpload.Remove(0, _sourceParentDirectory.Length + 1)).Replace('\\', '/');
|
||||||
uploadTimer.Restart();
|
bool failAndExit = false;
|
||||||
bool catchExceptionDuringUpload = false;
|
|
||||||
HttpResponseMessage response = null;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
response = await _fileContainerHttpClient.UploadFileAsync(_containerId, itemPath, fs, _projectId, cancellationToken: token, chunkSize: 4 * 1024 * 1024);
|
uploadTimer.Restart();
|
||||||
|
using (HttpResponseMessage response = await _fileContainerHttpClient.UploadFileAsync(_containerId, itemPath, fs, _projectId, cancellationToken: token, chunkSize: 4 * 1024 * 1024))
|
||||||
|
{
|
||||||
|
if (response == null || response.StatusCode != HttpStatusCode.Created)
|
||||||
|
{
|
||||||
|
context.Output($"Unable to copy file to server StatusCode={response?.StatusCode}: {response?.ReasonPhrase}. Source file path: {fileToUpload}. Target server path: {itemPath}");
|
||||||
|
|
||||||
|
if (response?.StatusCode == HttpStatusCode.Conflict)
|
||||||
|
{
|
||||||
|
// fail upload task but continue with any other files
|
||||||
|
context.Error($"Error '{fileToUpload}' has already been uploaded.");
|
||||||
|
}
|
||||||
|
else if (_fileContainerHttpClient.IsFastFailResponse(response))
|
||||||
|
{
|
||||||
|
// Fast fail: we received an http status code where we should abandon our efforts
|
||||||
|
context.Output($"Cannot continue uploading files, so draining upload queue of {_fileUploadQueue.Count} items.");
|
||||||
|
DrainUploadQueue(context);
|
||||||
|
failedFiles.Clear();
|
||||||
|
failAndExit = true;
|
||||||
|
throw new UploadFailedException($"Critical failure uploading '{fileToUpload}'");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context.Debug($"Adding '{fileToUpload}' to retry list.");
|
||||||
|
failedFiles.Add(fileToUpload);
|
||||||
|
}
|
||||||
|
throw new UploadFailedException($"Http failure response '{response?.StatusCode}': '{response?.ReasonPhrase}' while uploading '{fileToUpload}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadTimer.Stop();
|
||||||
|
context.Debug($"File: '{fileToUpload}' took {uploadTimer.ElapsedMilliseconds} milliseconds to finish upload");
|
||||||
|
uploadedSize += fs.Length;
|
||||||
|
OutputLogForFile(context, fileToUpload, $"Detail upload trace for file: {itemPath}", context.Debug);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException) when (token.IsCancellationRequested)
|
catch (OperationCanceledException) when (token.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
context.Output($"File upload has been cancelled during upload file: '{fileToUpload}'.");
|
context.Output($"File upload has been cancelled during upload file: '{fileToUpload}'.");
|
||||||
if (response != null)
|
|
||||||
{
|
|
||||||
response.Dispose();
|
|
||||||
response = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
catchExceptionDuringUpload = true;
|
|
||||||
context.Output($"Fail to upload '{fileToUpload}' due to '{ex.Message}'.");
|
context.Output($"Fail to upload '{fileToUpload}' due to '{ex.Message}'.");
|
||||||
context.Output(ex.ToString());
|
context.Output(ex.ToString());
|
||||||
}
|
|
||||||
|
|
||||||
uploadTimer.Stop();
|
OutputLogForFile(context, fileToUpload, $"Detail upload trace for file that fail to upload: {itemPath}", context.Output);
|
||||||
if (catchExceptionDuringUpload || (response != null && response.StatusCode != HttpStatusCode.Created))
|
|
||||||
{
|
if (failAndExit)
|
||||||
if (response != null)
|
|
||||||
{
|
{
|
||||||
context.Output($"Unable to copy file to server StatusCode={response.StatusCode}: {response.ReasonPhrase}. Source file path: {fileToUpload}. Target server path: {itemPath}");
|
context.Debug("Exiting upload.");
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
// output detail upload trace for the file.
|
|
||||||
ConcurrentQueue<string> logQueue;
|
|
||||||
if (_fileUploadTraceLog.TryGetValue(itemPath, out logQueue))
|
|
||||||
{
|
|
||||||
context.Output($"Detail upload trace for file that fail to upload: {itemPath}");
|
|
||||||
string message;
|
|
||||||
while (logQueue.TryDequeue(out message))
|
|
||||||
{
|
|
||||||
context.Output(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// tracking file that failed to upload.
|
|
||||||
failedFiles.Add(fileToUpload);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
context.Debug($"File: '{fileToUpload}' took {uploadTimer.ElapsedMilliseconds} milliseconds to finish upload");
|
|
||||||
uploadedSize += fs.Length;
|
|
||||||
// debug detail upload trace for the file.
|
|
||||||
ConcurrentQueue<string> logQueue;
|
|
||||||
if (_fileUploadTraceLog.TryGetValue(itemPath, out logQueue))
|
|
||||||
{
|
|
||||||
context.Debug($"Detail upload trace for file: {itemPath}");
|
|
||||||
string message;
|
|
||||||
while (logQueue.TryDequeue(out message))
|
|
||||||
{
|
|
||||||
context.Debug(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response != null)
|
|
||||||
{
|
|
||||||
response.Dispose();
|
|
||||||
response = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -590,6 +576,30 @@ namespace GitHub.Runner.Plugins.Artifact
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DrainUploadQueue(RunnerActionPluginExecutionContext context)
|
||||||
|
{
|
||||||
|
while (_fileUploadQueue.TryDequeue(out string fileToUpload))
|
||||||
|
{
|
||||||
|
context.Debug($"Clearing upload queue: '{fileToUpload}'");
|
||||||
|
Interlocked.Increment(ref _uploadFilesProcessed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OutputLogForFile(RunnerActionPluginExecutionContext context, string itemPath, string logDescription, Action<string> log)
|
||||||
|
{
|
||||||
|
// output detail upload trace for the file.
|
||||||
|
ConcurrentQueue<string> logQueue;
|
||||||
|
if (_fileUploadTraceLog.TryGetValue(itemPath, out logQueue))
|
||||||
|
{
|
||||||
|
log(logDescription);
|
||||||
|
string message;
|
||||||
|
while (logQueue.TryDequeue(out message))
|
||||||
|
{
|
||||||
|
log(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void UploadFileTraceReportReceived(object sender, ReportTraceEventArgs e)
|
private void UploadFileTraceReportReceived(object sender, ReportTraceEventArgs e)
|
||||||
{
|
{
|
||||||
ConcurrentQueue<string> logQueue = _fileUploadTraceLog.GetOrAdd(e.File, new ConcurrentQueue<string>());
|
ConcurrentQueue<string> logQueue = _fileUploadTraceLog.GetOrAdd(e.File, new ConcurrentQueue<string>());
|
||||||
@@ -607,22 +617,22 @@ namespace GitHub.Runner.Plugins.Artifact
|
|||||||
{
|
{
|
||||||
public UploadResult()
|
public UploadResult()
|
||||||
{
|
{
|
||||||
FailedFiles = new List<string>();
|
RetryFiles = new List<string>();
|
||||||
TotalFileSizeUploaded = 0;
|
TotalFileSizeUploaded = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UploadResult(List<string> failedFiles, long totalFileSizeUploaded)
|
public UploadResult(List<string> retryFiles, long totalFileSizeUploaded)
|
||||||
{
|
{
|
||||||
FailedFiles = failedFiles;
|
RetryFiles = retryFiles ?? new List<string>();
|
||||||
TotalFileSizeUploaded = totalFileSizeUploaded;
|
TotalFileSizeUploaded = totalFileSizeUploaded;
|
||||||
}
|
}
|
||||||
public List<string> FailedFiles { get; set; }
|
public List<string> RetryFiles { get; set; }
|
||||||
|
|
||||||
public long TotalFileSizeUploaded { get; set; }
|
public long TotalFileSizeUploaded { get; set; }
|
||||||
|
|
||||||
public void AddUploadResult(UploadResult resultToAdd)
|
public void AddUploadResult(UploadResult resultToAdd)
|
||||||
{
|
{
|
||||||
this.FailedFiles.AddRange(resultToAdd.FailedFiles);
|
this.RetryFiles.AddRange(resultToAdd.RetryFiles);
|
||||||
this.TotalFileSizeUploaded += resultToAdd.TotalFileSizeUploaded;
|
this.TotalFileSizeUploaded += resultToAdd.TotalFileSizeUploaded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -657,4 +667,19 @@ namespace GitHub.Runner.Plugins.Artifact
|
|||||||
this.FailedFiles.AddRange(resultToAdd.FailedFiles);
|
this.FailedFiles.AddRange(resultToAdd.FailedFiles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class UploadFailedException : Exception
|
||||||
|
{
|
||||||
|
public UploadFailedException()
|
||||||
|
: base()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public UploadFailedException(string message)
|
||||||
|
: base(message)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public UploadFailedException(string message, Exception inner)
|
||||||
|
: base(message, inner)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -74,17 +74,22 @@ namespace GitHub.Runner.Plugins.Artifact
|
|||||||
context.Output($"Uploading artifact '{artifactName}' from '{fullPath}' for run #{buildId}");
|
context.Output($"Uploading artifact '{artifactName}' from '{fullPath}' for run #{buildId}");
|
||||||
|
|
||||||
FileContainerServer fileContainerHelper = new FileContainerServer(context.VssConnection, projectId, containerId, artifactName);
|
FileContainerServer fileContainerHelper = new FileContainerServer(context.VssConnection, projectId, containerId, artifactName);
|
||||||
long size = await fileContainerHelper.CopyToContainerAsync(context, fullPath, token);
|
|
||||||
var propertiesDictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
var propertiesDictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
propertiesDictionary.Add("artifactsize", size.ToString());
|
try
|
||||||
|
{
|
||||||
string fileContainerFullPath = StringUtil.Format($"#/{containerId}/{artifactName}");
|
long size = await fileContainerHelper.CopyToContainerAsync(context, fullPath, token);
|
||||||
context.Output($"Uploaded '{fullPath}' to server");
|
propertiesDictionary.Add("artifactsize", size.ToString());
|
||||||
|
context.Output($"Uploaded '{size}' bytes from '{fullPath}' to server");
|
||||||
BuildServer buildHelper = new BuildServer(context.VssConnection);
|
}
|
||||||
string jobId = context.Variables.GetValueOrDefault(WellKnownDistributedTaskVariables.JobId).Value ?? string.Empty;
|
// if any of the results were successful, make sure to attach them to the build
|
||||||
var artifact = await buildHelper.AssociateArtifact(projectId, buildId, jobId, artifactName, ArtifactResourceTypes.Container, fileContainerFullPath, propertiesDictionary, token);
|
finally
|
||||||
context.Output($"Associated artifact {artifactName} ({artifact.Id}) with run #{buildId}");
|
{
|
||||||
|
string fileContainerFullPath = StringUtil.Format($"#/{containerId}/{artifactName}");
|
||||||
|
BuildServer buildHelper = new BuildServer(context.VssConnection);
|
||||||
|
string jobId = context.Variables.GetValueOrDefault(WellKnownDistributedTaskVariables.JobId).Value ?? string.Empty;
|
||||||
|
var artifact = await buildHelper.AssociateArtifact(projectId, buildId, jobId, artifactName, ArtifactResourceTypes.Container, fileContainerFullPath, propertiesDictionary, token);
|
||||||
|
context.Output($"Associated artifact {artifactName} ({artifact.Id}) with run #{buildId}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
||||||
<NoWarn>NU1701;NU1603</NoWarn>
|
<NoWarn>NU1701;NU1603</NoWarn>
|
||||||
<Version>$(Version)</Version>
|
<Version>$(Version)</Version>
|
||||||
|
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -70,13 +70,6 @@ namespace GitHub.Runner.Sdk
|
|||||||
|
|
||||||
VssClientHttpRequestSettings.Default.UserAgent = headerValues;
|
VssClientHttpRequestSettings.Default.UserAgent = headerValues;
|
||||||
|
|
||||||
#if OS_LINUX || OS_OSX
|
|
||||||
// The .NET Core 2.1 runtime switched its HTTP default from HTTP 1.1 to HTTP 2.
|
|
||||||
// This causes problems with some versions of the Curl handler.
|
|
||||||
// See GitHub issue https://github.com/dotnet/corefx/issues/32376
|
|
||||||
VssClientHttpRequestSettings.Default.UseHttp11 = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var certSetting = GetCertConfiguration();
|
var certSetting = GetCertConfiguration();
|
||||||
if (certSetting != null)
|
if (certSetting != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
||||||
<NoWarn>NU1701;NU1603</NoWarn>
|
<NoWarn>NU1701;NU1603</NoWarn>
|
||||||
<Version>$(Version)</Version>
|
<Version>$(Version)</Version>
|
||||||
|
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -27,13 +27,6 @@ namespace GitHub.Runner.Sdk
|
|||||||
|
|
||||||
VssClientHttpRequestSettings.Default.UserAgent = headerValues;
|
VssClientHttpRequestSettings.Default.UserAgent = headerValues;
|
||||||
VssClientHttpRequestSettings.Default.ClientCertificateManager = clientCert;
|
VssClientHttpRequestSettings.Default.ClientCertificateManager = clientCert;
|
||||||
#if OS_LINUX || OS_OSX
|
|
||||||
// The .NET Core 2.1 runtime switched its HTTP default from HTTP 1.1 to HTTP 2.
|
|
||||||
// This causes problems with some versions of the Curl handler.
|
|
||||||
// See GitHub issue https://github.com/dotnet/corefx/issues/32376
|
|
||||||
VssClientHttpRequestSettings.Default.UseHttp11 = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
VssHttpMessageHandler.DefaultWebProxy = proxy;
|
VssHttpMessageHandler.DefaultWebProxy = proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -107,26 +107,35 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
else if (_commandExtensions.TryGetValue(actionCommand.Command, out IActionCommandExtension extension))
|
else if (_commandExtensions.TryGetValue(actionCommand.Command, out IActionCommandExtension extension))
|
||||||
{
|
{
|
||||||
bool omitEcho;
|
bool commandHasBeenOutput = false;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
extension.ProcessCommand(context, input, actionCommand, out omitEcho);
|
if (context.EchoOnActionCommand)
|
||||||
|
{
|
||||||
|
context.Output(input);
|
||||||
|
context.Debug($"Processing command '{actionCommand.Command}'");
|
||||||
|
commandHasBeenOutput = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
extension.ProcessCommand(context, input, actionCommand);
|
||||||
|
|
||||||
|
if (context.EchoOnActionCommand)
|
||||||
|
{
|
||||||
|
context.Debug($"Processed command '{actionCommand.Command}' successfully");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
omitEcho = true;
|
if (!commandHasBeenOutput)
|
||||||
context.Output(input);
|
{
|
||||||
|
context.Output(input);
|
||||||
|
}
|
||||||
|
|
||||||
context.Error($"Unable to process command '{input}' successfully.");
|
context.Error($"Unable to process command '{input}' successfully.");
|
||||||
context.Error(ex);
|
context.Error(ex);
|
||||||
context.CommandResult = TaskResult.Failed;
|
context.CommandResult = TaskResult.Failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!omitEcho)
|
|
||||||
{
|
|
||||||
context.Output(input);
|
|
||||||
context.Debug($"Processed command");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -143,7 +152,7 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
string Command { get; }
|
string Command { get; }
|
||||||
|
|
||||||
void ProcessCommand(IExecutionContext context, string line, ActionCommand command, out bool omitEcho);
|
void ProcessCommand(IExecutionContext context, string line, ActionCommand command);
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class InternalPluginSetRepoPathCommandExtension : RunnerService, IActionCommandExtension
|
public sealed class InternalPluginSetRepoPathCommandExtension : RunnerService, IActionCommandExtension
|
||||||
@@ -152,7 +161,7 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, out bool omitEcho)
|
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
|
||||||
{
|
{
|
||||||
if (!command.Properties.TryGetValue(SetRepoPathCommandProperties.repoFullName, out string repoFullName) || string.IsNullOrEmpty(repoFullName))
|
if (!command.Properties.TryGetValue(SetRepoPathCommandProperties.repoFullName, out string repoFullName) || string.IsNullOrEmpty(repoFullName))
|
||||||
{
|
{
|
||||||
@@ -166,8 +175,6 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
var directoryManager = HostContext.GetService<IPipelineDirectoryManager>();
|
var directoryManager = HostContext.GetService<IPipelineDirectoryManager>();
|
||||||
var trackingConfig = directoryManager.UpdateRepositoryDirectory(context, repoFullName, command.Data, StringUtil.ConvertToBoolean(workspaceRepo));
|
var trackingConfig = directoryManager.UpdateRepositoryDirectory(context, repoFullName, command.Data, StringUtil.ConvertToBoolean(workspaceRepo));
|
||||||
|
|
||||||
omitEcho = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class SetRepoPathCommandProperties
|
private static class SetRepoPathCommandProperties
|
||||||
@@ -177,13 +184,47 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sealed class SetWorkspaceCommandExtension : RunnerService, IActionCommandExtension
|
||||||
|
{
|
||||||
|
public string Command => "set-workspace";
|
||||||
|
|
||||||
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
|
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
|
||||||
|
{
|
||||||
|
string path = command.Data;
|
||||||
|
if (string.IsNullOrWhiteSpace(path))
|
||||||
|
{
|
||||||
|
throw new Exception("Path not specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Path.IsPathRooted(path))
|
||||||
|
{
|
||||||
|
throw new Exception("Expected a rooted path");
|
||||||
|
}
|
||||||
|
|
||||||
|
string runnerWorkspace = context.GetRunnerContext("workspace");
|
||||||
|
ArgUtil.Directory(runnerWorkspace, nameof(runnerWorkspace));
|
||||||
|
|
||||||
|
// Must be under runner workspace
|
||||||
|
path = Path.GetFullPath(path); // remove relative pathing and normalize slashes
|
||||||
|
if (!path.StartsWith(runnerWorkspace + Path.DirectorySeparatorChar, IOUtil.FilePathStringComparison))
|
||||||
|
{
|
||||||
|
throw new Exception($"Expected path to be under {runnerWorkspace}");
|
||||||
|
}
|
||||||
|
|
||||||
|
Trace.Info($"Setting GitHub workspace to '{path}'");
|
||||||
|
context.SetGitHubContext("workspace", path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public sealed class SetEnvCommandExtension : RunnerService, IActionCommandExtension
|
public sealed class SetEnvCommandExtension : RunnerService, IActionCommandExtension
|
||||||
{
|
{
|
||||||
public string Command => "set-env";
|
public string Command => "set-env";
|
||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, out bool omitEcho)
|
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
|
||||||
{
|
{
|
||||||
if (!command.Properties.TryGetValue(SetEnvCommandProperties.Name, out string envName) || string.IsNullOrEmpty(envName))
|
if (!command.Properties.TryGetValue(SetEnvCommandProperties.Name, out string envName) || string.IsNullOrEmpty(envName))
|
||||||
{
|
{
|
||||||
@@ -192,9 +233,7 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
context.EnvironmentVariables[envName] = command.Data;
|
context.EnvironmentVariables[envName] = command.Data;
|
||||||
context.SetEnvContext(envName, command.Data);
|
context.SetEnvContext(envName, command.Data);
|
||||||
context.Output(line);
|
|
||||||
context.Debug($"{envName}='{command.Data}'");
|
context.Debug($"{envName}='{command.Data}'");
|
||||||
omitEcho = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class SetEnvCommandProperties
|
private static class SetEnvCommandProperties
|
||||||
@@ -209,7 +248,7 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, out bool omitEcho)
|
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
|
||||||
{
|
{
|
||||||
if (!command.Properties.TryGetValue(SetOutputCommandProperties.Name, out string outputName) || string.IsNullOrEmpty(outputName))
|
if (!command.Properties.TryGetValue(SetOutputCommandProperties.Name, out string outputName) || string.IsNullOrEmpty(outputName))
|
||||||
{
|
{
|
||||||
@@ -217,9 +256,7 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
|
|
||||||
context.SetOutput(outputName, command.Data, out var reference);
|
context.SetOutput(outputName, command.Data, out var reference);
|
||||||
context.Output(line);
|
|
||||||
context.Debug($"{reference}='{command.Data}'");
|
context.Debug($"{reference}='{command.Data}'");
|
||||||
omitEcho = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class SetOutputCommandProperties
|
private static class SetOutputCommandProperties
|
||||||
@@ -234,7 +271,7 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, out bool omitEcho)
|
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
|
||||||
{
|
{
|
||||||
if (!command.Properties.TryGetValue(SaveStateCommandProperties.Name, out string stateName) || string.IsNullOrEmpty(stateName))
|
if (!command.Properties.TryGetValue(SaveStateCommandProperties.Name, out string stateName) || string.IsNullOrEmpty(stateName))
|
||||||
{
|
{
|
||||||
@@ -243,7 +280,6 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
context.IntraActionState[stateName] = command.Data;
|
context.IntraActionState[stateName] = command.Data;
|
||||||
context.Debug($"Save intra-action state {stateName} = {command.Data}");
|
context.Debug($"Save intra-action state {stateName} = {command.Data}");
|
||||||
omitEcho = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class SaveStateCommandProperties
|
private static class SaveStateCommandProperties
|
||||||
@@ -258,19 +294,17 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, out bool omitEcho)
|
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(command.Data))
|
if (string.IsNullOrWhiteSpace(command.Data))
|
||||||
{
|
{
|
||||||
context.Warning("Can't add secret mask for empty string.");
|
context.Warning("Can't add secret mask for empty string in ##[add-mask] command.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
HostContext.SecretMasker.AddValue(command.Data);
|
HostContext.SecretMasker.AddValue(command.Data);
|
||||||
Trace.Info($"Add new secret mask with length of {command.Data.Length}");
|
Trace.Info($"Add new secret mask with length of {command.Data.Length}");
|
||||||
}
|
}
|
||||||
|
|
||||||
omitEcho = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,12 +314,11 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, out bool omitEcho)
|
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
|
||||||
{
|
{
|
||||||
ArgUtil.NotNullOrEmpty(command.Data, "path");
|
ArgUtil.NotNullOrEmpty(command.Data, "path");
|
||||||
context.PrependPath.RemoveAll(x => string.Equals(x, command.Data, StringComparison.CurrentCulture));
|
context.PrependPath.RemoveAll(x => string.Equals(x, command.Data, StringComparison.CurrentCulture));
|
||||||
context.PrependPath.Add(command.Data);
|
context.PrependPath.Add(command.Data);
|
||||||
omitEcho = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,9 +328,8 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, out bool omitEcho)
|
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
|
||||||
{
|
{
|
||||||
omitEcho = false;
|
|
||||||
var file = command.Data;
|
var file = command.Data;
|
||||||
|
|
||||||
// File is required
|
// File is required
|
||||||
@@ -342,23 +374,22 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, out bool omitEcho)
|
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
|
||||||
{
|
{
|
||||||
omitEcho = false;
|
|
||||||
command.Properties.TryGetValue(RemoveMatcherCommandProperties.Owner, out string owner);
|
command.Properties.TryGetValue(RemoveMatcherCommandProperties.Owner, out string owner);
|
||||||
var file = command.Data;
|
var file = command.Data;
|
||||||
|
|
||||||
// Owner and file are mutually exclusive
|
// Owner and file are mutually exclusive
|
||||||
if (!string.IsNullOrEmpty(owner) && !string.IsNullOrEmpty(file))
|
if (!string.IsNullOrEmpty(owner) && !string.IsNullOrEmpty(file))
|
||||||
{
|
{
|
||||||
context.Warning("Either specify a matcher owner name or a file path. Both values cannot be set.");
|
context.Warning("Either specify an owner name or a file path in ##[remove-matcher] command. Both values cannot be set.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Owner or file is required
|
// Owner or file is required
|
||||||
if (string.IsNullOrEmpty(owner) && string.IsNullOrEmpty(file))
|
if (string.IsNullOrEmpty(owner) && string.IsNullOrEmpty(file))
|
||||||
{
|
{
|
||||||
context.Warning("Either a matcher owner name or a file path must be specified.");
|
context.Warning("Either an owner name or a file path must be specified in ##[remove-matcher] command.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,9 +441,8 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string inputLine, ActionCommand command, out bool omitEcho)
|
public void ProcessCommand(IExecutionContext context, string inputLine, ActionCommand command)
|
||||||
{
|
{
|
||||||
omitEcho = true;
|
|
||||||
context.Debug(command.Data);
|
context.Debug(command.Data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -438,9 +468,11 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string inputLine, ActionCommand command, out bool omitEcho)
|
public void ProcessCommand(IExecutionContext context, string inputLine, ActionCommand command)
|
||||||
{
|
{
|
||||||
omitEcho = true;
|
command.Properties.TryGetValue(IssueCommandProperties.File, out string file);
|
||||||
|
command.Properties.TryGetValue(IssueCommandProperties.Line, out string line);
|
||||||
|
command.Properties.TryGetValue(IssueCommandProperties.Column, out string column);
|
||||||
|
|
||||||
Issue issue = new Issue()
|
Issue issue = new Issue()
|
||||||
{
|
{
|
||||||
@@ -449,8 +481,54 @@ namespace GitHub.Runner.Worker
|
|||||||
Message = command.Data
|
Message = command.Data
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(file))
|
||||||
|
{
|
||||||
|
issue.Category = "Code";
|
||||||
|
|
||||||
|
if (context.Container != null)
|
||||||
|
{
|
||||||
|
// Translate file path back from container path
|
||||||
|
file = context.Container.TranslateToHostPath(file);
|
||||||
|
command.Properties[IssueCommandProperties.File] = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the values that represent the server path given a local path
|
||||||
|
string repoName = context.GetGitHubContext("repository");
|
||||||
|
var repoPath = context.GetGitHubContext("workspace");
|
||||||
|
|
||||||
|
string relativeSourcePath = IOUtil.MakeRelative(file, repoPath);
|
||||||
|
if (!string.Equals(relativeSourcePath, file, IOUtil.FilePathStringComparison))
|
||||||
|
{
|
||||||
|
// add repo info
|
||||||
|
if (!string.IsNullOrEmpty(repoName))
|
||||||
|
{
|
||||||
|
command.Properties["repo"] = repoName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(relativeSourcePath))
|
||||||
|
{
|
||||||
|
// replace sourcePath with the new relative path
|
||||||
|
// prefer `/` on all platforms
|
||||||
|
command.Properties[IssueCommandProperties.File] = relativeSourcePath.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var property in command.Properties)
|
||||||
|
{
|
||||||
|
issue.Data[property.Key] = property.Value;
|
||||||
|
}
|
||||||
|
|
||||||
context.AddIssue(issue);
|
context.AddIssue(issue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class IssueCommandProperties
|
||||||
|
{
|
||||||
|
public const String File = "file";
|
||||||
|
public const String Line = "line";
|
||||||
|
public const String Column = "col";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class GroupCommandExtension : GroupingCommandExtension
|
public sealed class GroupCommandExtension : GroupingCommandExtension
|
||||||
@@ -468,11 +546,37 @@ namespace GitHub.Runner.Worker
|
|||||||
public abstract string Command { get; }
|
public abstract string Command { get; }
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, out bool omitEcho)
|
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
|
||||||
{
|
{
|
||||||
var data = this is GroupCommandExtension ? command.Data : string.Empty;
|
var data = this is GroupCommandExtension ? command.Data : string.Empty;
|
||||||
context.Output($"##[{Command}]{data}");
|
context.Output($"##[{Command}]{data}");
|
||||||
omitEcho = true;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class EchoCommandExtension : RunnerService, IActionCommandExtension
|
||||||
|
{
|
||||||
|
public string Command => "echo";
|
||||||
|
|
||||||
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
|
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
|
||||||
|
{
|
||||||
|
ArgUtil.NotNullOrEmpty(command.Data, "value");
|
||||||
|
|
||||||
|
switch (command.Data.Trim().ToUpperInvariant())
|
||||||
|
{
|
||||||
|
case "ON":
|
||||||
|
context.EchoOnActionCommand = true;
|
||||||
|
context.Debug("Setting echo command value to 'on'");
|
||||||
|
break;
|
||||||
|
case "OFF":
|
||||||
|
context.EchoOnActionCommand = false;
|
||||||
|
context.Debug("Setting echo command value to 'off'");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception($"Invalid echo command value. Possible values can be: 'on', 'off'. Current value is: '{command.Data}'.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,9 @@ namespace GitHub.Runner.Worker
|
|||||||
executionContext.Warning("The 'PREVIEW_ACTION_TOKEN' secret is depreciated. Please remove it from the repository's secrets");
|
executionContext.Warning("The 'PREVIEW_ACTION_TOKEN' secret is depreciated. Please remove it from the repository's secrets");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear the cache (local runner)
|
||||||
|
IOUtil.DeleteDirectory(HostContext.GetDirectory(WellKnownDirectory.Actions), executionContext.CancellationToken);
|
||||||
|
|
||||||
foreach (var action in actions)
|
foreach (var action in actions)
|
||||||
{
|
{
|
||||||
if (action.Reference.Type == Pipelines.ActionSourceType.ContainerRegistry)
|
if (action.Reference.Type == Pipelines.ActionSourceType.ContainerRegistry)
|
||||||
@@ -445,7 +448,7 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// make sure we get an clean folder ready to use.
|
// make sure we get a clean folder ready to use.
|
||||||
IOUtil.DeleteDirectory(destDirectory, executionContext.CancellationToken);
|
IOUtil.DeleteDirectory(destDirectory, executionContext.CancellationToken);
|
||||||
Directory.CreateDirectory(destDirectory);
|
Directory.CreateDirectory(destDirectory);
|
||||||
executionContext.Output($"Download action repository '{repositoryReference.Name}@{repositoryReference.Ref}'");
|
executionContext.Output($"Download action repository '{repositoryReference.Name}@{repositoryReference.Ref}'");
|
||||||
|
|||||||
@@ -12,14 +12,14 @@ using GitHub.Services.WebApi;
|
|||||||
using GitHub.DistributedTask.Pipelines;
|
using GitHub.DistributedTask.Pipelines;
|
||||||
using GitHub.DistributedTask.Pipelines.ContextData;
|
using GitHub.DistributedTask.Pipelines.ContextData;
|
||||||
using GitHub.DistributedTask.WebApi;
|
using GitHub.DistributedTask.WebApi;
|
||||||
using Pipelines = GitHub.DistributedTask.Pipelines;
|
|
||||||
using ObjectTemplating = GitHub.DistributedTask.ObjectTemplating;
|
|
||||||
using GitHub.Runner.Common.Util;
|
using GitHub.Runner.Common.Util;
|
||||||
using GitHub.Runner.Common;
|
using GitHub.Runner.Common;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using ObjectTemplating = GitHub.DistributedTask.ObjectTemplating;
|
||||||
|
using Pipelines = GitHub.DistributedTask.Pipelines;
|
||||||
|
|
||||||
namespace GitHub.Runner.Worker
|
namespace GitHub.Runner.Worker
|
||||||
{
|
{
|
||||||
@@ -62,6 +62,8 @@ namespace GitHub.Runner.Worker
|
|||||||
// Only job level ExecutionContext has PostJobSteps
|
// Only job level ExecutionContext has PostJobSteps
|
||||||
Stack<IStep> PostJobSteps { get; }
|
Stack<IStep> PostJobSteps { get; }
|
||||||
|
|
||||||
|
bool EchoOnActionCommand { get; set; }
|
||||||
|
|
||||||
// Initialize
|
// Initialize
|
||||||
void InitializeJob(Pipelines.AgentJobRequestMessage message, CancellationToken token);
|
void InitializeJob(Pipelines.AgentJobRequestMessage message, CancellationToken token);
|
||||||
void CancelToken();
|
void CancelToken();
|
||||||
@@ -76,6 +78,7 @@ namespace GitHub.Runner.Worker
|
|||||||
void Start(string currentOperation = null);
|
void Start(string currentOperation = null);
|
||||||
TaskResult Complete(TaskResult? result = null, string currentOperation = null, string resultCode = null);
|
TaskResult Complete(TaskResult? result = null, string currentOperation = null, string resultCode = null);
|
||||||
void SetEnvContext(string name, string value);
|
void SetEnvContext(string name, string value);
|
||||||
|
string GetRunnerContext(string name);
|
||||||
void SetRunnerContext(string name, string value);
|
void SetRunnerContext(string name, string value);
|
||||||
string GetGitHubContext(string name);
|
string GetGitHubContext(string name);
|
||||||
void SetGitHubContext(string name, string value);
|
void SetGitHubContext(string name, string value);
|
||||||
@@ -153,6 +156,8 @@ namespace GitHub.Runner.Worker
|
|||||||
// Only job level ExecutionContext has PostJobSteps
|
// Only job level ExecutionContext has PostJobSteps
|
||||||
public Stack<IStep> PostJobSteps { get; private set; }
|
public Stack<IStep> PostJobSteps { get; private set; }
|
||||||
|
|
||||||
|
public bool EchoOnActionCommand { get; set; }
|
||||||
|
|
||||||
|
|
||||||
public TaskResult? Result
|
public TaskResult? Result
|
||||||
{
|
{
|
||||||
@@ -292,6 +297,7 @@ namespace GitHub.Runner.Worker
|
|||||||
child.PrependPath = PrependPath;
|
child.PrependPath = PrependPath;
|
||||||
child.Container = Container;
|
child.Container = Container;
|
||||||
child.ServiceContainers = ServiceContainers;
|
child.ServiceContainers = ServiceContainers;
|
||||||
|
child.EchoOnActionCommand = EchoOnActionCommand;
|
||||||
|
|
||||||
if (recordOrder != null)
|
if (recordOrder != null)
|
||||||
{
|
{
|
||||||
@@ -360,6 +366,13 @@ namespace GitHub.Runner.Worker
|
|||||||
return Result.Value;
|
return Result.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetRunnerContext(string name)
|
||||||
|
{
|
||||||
|
ArgUtil.NotNullOrEmpty(name, nameof(name));
|
||||||
|
var runnerContext = ExpressionValues["runner"] as RunnerContext;
|
||||||
|
return runnerContext[name].AssertString($"runner[{name}]");
|
||||||
|
}
|
||||||
|
|
||||||
public void SetRunnerContext(string name, string value)
|
public void SetRunnerContext(string name, string value)
|
||||||
{
|
{
|
||||||
ArgUtil.NotNullOrEmpty(name, nameof(name));
|
ArgUtil.NotNullOrEmpty(name, nameof(name));
|
||||||
@@ -704,6 +717,9 @@ namespace GitHub.Runner.Worker
|
|||||||
_logger = HostContext.CreateService<IPagingLogger>();
|
_logger = HostContext.CreateService<IPagingLogger>();
|
||||||
_logger.Setup(_mainTimelineId, _record.Id);
|
_logger.Setup(_mainTimelineId, _record.Id);
|
||||||
|
|
||||||
|
// Initialize 'echo on action command success' property, default to false, unless Step_Debug is set
|
||||||
|
EchoOnActionCommand = Variables.Step_Debug ?? false;
|
||||||
|
|
||||||
// Verbosity (from GitHub.Step_Debug).
|
// Verbosity (from GitHub.Step_Debug).
|
||||||
WriteDebug = Variables.Step_Debug ?? false;
|
WriteDebug = Variables.Step_Debug ?? false;
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
||||||
<NoWarn>NU1701;NU1603</NoWarn>
|
<NoWarn>NU1701;NU1603</NoWarn>
|
||||||
<Version>$(Version)</Version>
|
<Version>$(Version)</Version>
|
||||||
|
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
||||||
|
<PublishReadyToRun>true</PublishReadyToRun>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ namespace GitHub.DistributedTask.Expressions2
|
|||||||
|
|
||||||
// Attempt to match a named-value or index operator.
|
// Attempt to match a named-value or index operator.
|
||||||
// Note, do not push children of the index operator.
|
// Note, do not push children of the index operator.
|
||||||
if (node is NamedValue || node is Index)
|
if (node is NamedValue || node is Sdk.Operators.Index)
|
||||||
{
|
{
|
||||||
// Lazy initialize the pattern segments
|
// Lazy initialize the pattern segments
|
||||||
if (segmentedPatterns is null)
|
if (segmentedPatterns is null)
|
||||||
@@ -201,7 +201,7 @@ namespace GitHub.DistributedTask.Expressions2
|
|||||||
result.Push(node);
|
result.Push(node);
|
||||||
}
|
}
|
||||||
// Node is an index
|
// Node is an index
|
||||||
else if (node is Index index)
|
else if (node is Sdk.Operators.Index index)
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
@@ -218,7 +218,7 @@ namespace GitHub.DistributedTask.Expressions2
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Parameter 0 is an index
|
// Parameter 0 is an index
|
||||||
else if (parameter0 is Index index2)
|
else if (parameter0 is Sdk.Operators.Index index2)
|
||||||
{
|
{
|
||||||
index = index2;
|
index = index2;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using System.Text;
|
|||||||
using Minimatch;
|
using Minimatch;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
using GitHub.DistributedTask.Expressions2.Sdk;
|
||||||
using GitHub.DistributedTask.Pipelines.ContextData;
|
using GitHub.DistributedTask.Pipelines.ContextData;
|
||||||
using GitHub.DistributedTask.Pipelines.ObjectTemplating;
|
using GitHub.DistributedTask.Pipelines.ObjectTemplating;
|
||||||
namespace GitHub.DistributedTask.Expressions2.Sdk.Functions
|
namespace GitHub.DistributedTask.Expressions2.Sdk.Functions
|
||||||
@@ -28,29 +29,50 @@ namespace GitHub.DistributedTask.Expressions2.Sdk.Functions
|
|||||||
string searchRoot = workspaceData.Value;
|
string searchRoot = workspaceData.Value;
|
||||||
string pattern = Parameters[0].Evaluate(context).ConvertToString();
|
string pattern = Parameters[0].Evaluate(context).ConvertToString();
|
||||||
|
|
||||||
|
// Convert slashes on Windows
|
||||||
|
if (s_isWindows)
|
||||||
|
{
|
||||||
|
pattern = pattern.Replace('\\', '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Root the pattern
|
||||||
|
if (!Path.IsPathRooted(pattern))
|
||||||
|
{
|
||||||
|
var patternRoot = s_isWindows ? searchRoot.Replace('\\', '/').TrimEnd('/') : searchRoot.TrimEnd('/');
|
||||||
|
pattern = string.Concat(patternRoot, "/", pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all files
|
||||||
context.Trace.Info($"Search root directory: '{searchRoot}'");
|
context.Trace.Info($"Search root directory: '{searchRoot}'");
|
||||||
context.Trace.Info($"Search pattern: '{pattern}'");
|
context.Trace.Info($"Search pattern: '{pattern}'");
|
||||||
var files = Directory.GetFiles(searchRoot, "*", SearchOption.AllDirectories).OrderBy(x => x).ToList();
|
var files = Directory.GetFiles(searchRoot, "*", SearchOption.AllDirectories)
|
||||||
|
.Select(x => s_isWindows ? x.Replace('\\', '/') : x)
|
||||||
|
.OrderBy(x => x, StringComparer.Ordinal)
|
||||||
|
.ToList();
|
||||||
if (files.Count == 0)
|
if (files.Count == 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"'hashFiles({pattern})' failed. Directory '{searchRoot}' is empty");
|
throw new ArgumentException($"hashFiles('{ExpressionUtility.StringEscape(pattern)}') failed. Directory '{searchRoot}' is empty");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
context.Trace.Info($"Found {files.Count} files");
|
context.Trace.Info($"Found {files.Count} files");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Match
|
||||||
var matcher = new Minimatcher(pattern, s_minimatchOptions);
|
var matcher = new Minimatcher(pattern, s_minimatchOptions);
|
||||||
files = matcher.Filter(files).ToList();
|
files = matcher.Filter(files)
|
||||||
|
.Select(x => s_isWindows ? x.Replace('/', '\\') : x)
|
||||||
|
.ToList();
|
||||||
if (files.Count == 0)
|
if (files.Count == 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"'hashFiles({pattern})' failed. Search pattern '{pattern}' doesn't match any file under '{searchRoot}'");
|
throw new ArgumentException($"hashFiles('{ExpressionUtility.StringEscape(pattern)}') failed. Search pattern '{pattern}' doesn't match any file under '{searchRoot}'");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
context.Trace.Info($"{files.Count} matches to hash");
|
context.Trace.Info($"{files.Count} matches to hash");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hash each file
|
||||||
List<byte> filesSha256 = new List<byte>();
|
List<byte> filesSha256 = new List<byte>();
|
||||||
foreach (var file in files)
|
foreach (var file in files)
|
||||||
{
|
{
|
||||||
@@ -64,6 +86,7 @@ namespace GitHub.DistributedTask.Expressions2.Sdk.Functions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hash the hashes
|
||||||
using (SHA256 sha256hash = SHA256.Create())
|
using (SHA256 sha256hash = SHA256.Create())
|
||||||
{
|
{
|
||||||
var hashBytes = sha256hash.ComputeHash(filesSha256.ToArray());
|
var hashBytes = sha256hash.ComputeHash(filesSha256.ToArray());
|
||||||
@@ -83,11 +106,17 @@ namespace GitHub.DistributedTask.Expressions2.Sdk.Functions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static readonly bool s_isWindows = Environment.OSVersion.Platform != PlatformID.Unix && Environment.OSVersion.Platform != PlatformID.MacOSX;
|
||||||
|
|
||||||
|
// Only support basic globbing (* ? and []) and globstar (**)
|
||||||
private static readonly Options s_minimatchOptions = new Options
|
private static readonly Options s_minimatchOptions = new Options
|
||||||
{
|
{
|
||||||
Dot = true,
|
Dot = true,
|
||||||
NoBrace = true,
|
NoBrace = true,
|
||||||
NoCase = Environment.OSVersion.Platform != PlatformID.Unix && Environment.OSVersion.Platform != PlatformID.MacOSX
|
NoCase = s_isWindows,
|
||||||
|
NoComment = true,
|
||||||
|
NoExt = true,
|
||||||
|
NoNegate = true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,7 +154,7 @@ namespace GitHub.DistributedTask.Expressions2.Tokens
|
|||||||
{
|
{
|
||||||
case TokenKind.StartIndex: // "["
|
case TokenKind.StartIndex: // "["
|
||||||
case TokenKind.Dereference: // "."
|
case TokenKind.Dereference: // "."
|
||||||
return new Index();
|
return new Sdk.Operators.Index();
|
||||||
|
|
||||||
case TokenKind.LogicalOperator:
|
case TokenKind.LogicalOperator:
|
||||||
switch (RawValue)
|
switch (RawValue)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
<DefineConstants>NETSTANDARD;NET_STANDARD;TRACE</DefineConstants>
|
<DefineConstants>NETSTANDARD;NET_STANDARD;TRACE</DefineConstants>
|
||||||
<LangVersion>7.3</LangVersion>
|
<LangVersion>7.3</LangVersion>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -21,11 +22,7 @@
|
|||||||
<PackageReference Include="System.Security.Cryptography.Cng" Version="4.4.0" />
|
<PackageReference Include="System.Security.Cryptography.Cng" Version="4.4.0" />
|
||||||
<PackageReference Include="System.Security.Cryptography.Pkcs" Version="4.4.0" />
|
<PackageReference Include="System.Security.Cryptography.Pkcs" Version="4.4.0" />
|
||||||
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.4.0" />
|
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.4.0" />
|
||||||
<PackageReference Include="System.Data.SqlClient" Version="4.4.0" />
|
|
||||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="4.4.0" />
|
|
||||||
<PackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" Version="3.19.4" />
|
<PackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" Version="3.19.4" />
|
||||||
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.9.1" />
|
|
||||||
<PackageReference Include="WindowsAzure.Storage" Version="8.7.0" />
|
|
||||||
<PackageReference Include="Minimatch" Version="2.0.0" />
|
<PackageReference Include="Minimatch" Version="2.0.0" />
|
||||||
<PackageReference Include="YamlDotNet.Signed" Version="5.3.0" />
|
<PackageReference Include="YamlDotNet.Signed" Version="5.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -397,6 +397,11 @@ namespace GitHub.Services.FileContainer.Client
|
|||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else if (IsFastFailResponse(response))
|
||||||
|
{
|
||||||
|
FileUploadTrace(itemPath, $"Chunk '{currentChunk}' attempt '{attempt}' of file '{itemPath}' received non-success status code {response.StatusCode} for sending request and cannot continue.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FileUploadTrace(itemPath, $"Chunk '{currentChunk}' attempt '{attempt}' of file '{itemPath}' received non-success status code {response.StatusCode} for sending request.");
|
FileUploadTrace(itemPath, $"Chunk '{currentChunk}' attempt '{attempt}' of file '{itemPath}' received non-success status code {response.StatusCode} for sending request.");
|
||||||
@@ -538,6 +543,17 @@ namespace GitHub.Services.FileContainer.Client
|
|||||||
cancellationToken);
|
cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsFastFailResponse(HttpResponseMessage response)
|
||||||
|
{
|
||||||
|
int statusCode = (int)response?.StatusCode;
|
||||||
|
return statusCode >= 400 && statusCode <= 499;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool ShouldThrowError(HttpResponseMessage response)
|
||||||
|
{
|
||||||
|
return !response.IsSuccessStatusCode && !IsFastFailResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<HttpResponseMessage> ContainerGetRequestAsync(
|
private async Task<HttpResponseMessage> ContainerGetRequestAsync(
|
||||||
Int64 containerId,
|
Int64 containerId,
|
||||||
String itemPath,
|
String itemPath,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using GitHub.DistributedTask.WebApi;
|
|||||||
using GitHub.Runner.Worker;
|
using GitHub.Runner.Worker;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
using Pipelines = GitHub.DistributedTask.Pipelines;
|
||||||
|
|
||||||
namespace GitHub.Runner.Common.Tests.Worker
|
namespace GitHub.Runner.Common.Tests.Worker
|
||||||
{
|
{
|
||||||
@@ -146,5 +147,159 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
Assert.True(commandManager.TryProcessCommand(_ec.Object, "##[set-env name=foo]bar"));
|
Assert.True(commandManager.TryProcessCommand(_ec.Object, "##[set-env name=foo]bar"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Worker")]
|
||||||
|
public void EchoProcessCommand()
|
||||||
|
{
|
||||||
|
using (TestHostContext _hc = new TestHostContext(this))
|
||||||
|
{
|
||||||
|
var extensionManager = new Mock<IExtensionManager>();
|
||||||
|
var echoCommand = new EchoCommandExtension();
|
||||||
|
echoCommand.Initialize(_hc);
|
||||||
|
|
||||||
|
extensionManager.Setup(x => x.GetExtensions<IActionCommandExtension>())
|
||||||
|
.Returns(new List<IActionCommandExtension>() { echoCommand });
|
||||||
|
_hc.SetSingleton<IExtensionManager>(extensionManager.Object);
|
||||||
|
|
||||||
|
Mock<IExecutionContext> _ec = new Mock<IExecutionContext>();
|
||||||
|
_ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>()))
|
||||||
|
.Returns((string tag, string line) =>
|
||||||
|
{
|
||||||
|
_hc.GetTrace().Info($"{tag} {line}");
|
||||||
|
return 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
_ec.SetupAllProperties();
|
||||||
|
|
||||||
|
ActionCommandManager commandManager = new ActionCommandManager();
|
||||||
|
commandManager.Initialize(_hc);
|
||||||
|
|
||||||
|
Assert.False(_ec.Object.EchoOnActionCommand);
|
||||||
|
|
||||||
|
Assert.True(commandManager.TryProcessCommand(_ec.Object, "::echo::on"));
|
||||||
|
Assert.True(_ec.Object.EchoOnActionCommand);
|
||||||
|
|
||||||
|
Assert.True(commandManager.TryProcessCommand(_ec.Object, "::echo::off"));
|
||||||
|
Assert.False(_ec.Object.EchoOnActionCommand);
|
||||||
|
|
||||||
|
Assert.True(commandManager.TryProcessCommand(_ec.Object, "::echo::ON"));
|
||||||
|
Assert.True(_ec.Object.EchoOnActionCommand);
|
||||||
|
|
||||||
|
Assert.True(commandManager.TryProcessCommand(_ec.Object, "::echo::Off "));
|
||||||
|
Assert.False(_ec.Object.EchoOnActionCommand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Worker")]
|
||||||
|
public void EchoProcessCommandDebugOn()
|
||||||
|
{
|
||||||
|
using (TestHostContext _hc = new TestHostContext(this))
|
||||||
|
{
|
||||||
|
// Set up a few things
|
||||||
|
// 1. Job request message (with ACTIONS_STEP_DEBUG = true)
|
||||||
|
TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
|
||||||
|
TimelineReference timeline = new TimelineReference();
|
||||||
|
JobEnvironment environment = new JobEnvironment();
|
||||||
|
environment.SystemConnection = new ServiceEndpoint();
|
||||||
|
List<TaskInstance> tasks = new List<TaskInstance>();
|
||||||
|
Guid JobId = Guid.NewGuid();
|
||||||
|
string jobName = "some job name";
|
||||||
|
var jobRequest = Pipelines.AgentJobRequestMessageUtil.Convert(new AgentJobRequestMessage(plan, timeline, JobId, jobName, jobName, environment, tasks));
|
||||||
|
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
|
||||||
|
{
|
||||||
|
Alias = Pipelines.PipelineConstants.SelfAlias,
|
||||||
|
Id = "github",
|
||||||
|
Version = "sha1"
|
||||||
|
});
|
||||||
|
jobRequest.ContextData["github"] = new Pipelines.ContextData.DictionaryContextData();
|
||||||
|
jobRequest.Variables["ACTIONS_STEP_DEBUG"] = "true";
|
||||||
|
|
||||||
|
// Some service dependencies
|
||||||
|
var jobServerQueue = new Mock<IJobServerQueue>();
|
||||||
|
jobServerQueue.Setup(x => x.QueueTimelineRecordUpdate(It.IsAny<Guid>(), It.IsAny<TimelineRecord>()));
|
||||||
|
|
||||||
|
_hc.SetSingleton(jobServerQueue.Object);
|
||||||
|
|
||||||
|
var extensionManager = new Mock<IExtensionManager>();
|
||||||
|
var echoCommand = new EchoCommandExtension();
|
||||||
|
echoCommand.Initialize(_hc);
|
||||||
|
|
||||||
|
extensionManager.Setup(x => x.GetExtensions<IActionCommandExtension>())
|
||||||
|
.Returns(new List<IActionCommandExtension>() { echoCommand });
|
||||||
|
_hc.SetSingleton<IExtensionManager>(extensionManager.Object);
|
||||||
|
|
||||||
|
var configurationStore = new Mock<IConfigurationStore>();
|
||||||
|
configurationStore.Setup(x => x.GetSettings()).Returns(new RunnerSettings());
|
||||||
|
_hc.SetSingleton(configurationStore.Object);
|
||||||
|
|
||||||
|
var pagingLogger = new Mock<IPagingLogger>();
|
||||||
|
_hc.EnqueueInstance(pagingLogger.Object);
|
||||||
|
|
||||||
|
ActionCommandManager commandManager = new ActionCommandManager();
|
||||||
|
commandManager.Initialize(_hc);
|
||||||
|
|
||||||
|
var _ec = new Runner.Worker.ExecutionContext();
|
||||||
|
_ec.Initialize(_hc);
|
||||||
|
|
||||||
|
// Initialize the job (to exercise logic that sets EchoOnActionCommand)
|
||||||
|
_ec.InitializeJob(jobRequest, System.Threading.CancellationToken.None);
|
||||||
|
|
||||||
|
_ec.Complete();
|
||||||
|
|
||||||
|
Assert.True(_ec.EchoOnActionCommand);
|
||||||
|
|
||||||
|
Assert.True(commandManager.TryProcessCommand(_ec, "::echo::off"));
|
||||||
|
Assert.False(_ec.EchoOnActionCommand);
|
||||||
|
|
||||||
|
Assert.True(commandManager.TryProcessCommand(_ec, "::echo::on"));
|
||||||
|
Assert.True(_ec.EchoOnActionCommand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Worker")]
|
||||||
|
public void EchoProcessCommandInvalid()
|
||||||
|
{
|
||||||
|
using (TestHostContext _hc = new TestHostContext(this))
|
||||||
|
{
|
||||||
|
var extensionManager = new Mock<IExtensionManager>();
|
||||||
|
var echoCommand = new EchoCommandExtension();
|
||||||
|
echoCommand.Initialize(_hc);
|
||||||
|
|
||||||
|
extensionManager.Setup(x => x.GetExtensions<IActionCommandExtension>())
|
||||||
|
.Returns(new List<IActionCommandExtension>() { echoCommand });
|
||||||
|
_hc.SetSingleton<IExtensionManager>(extensionManager.Object);
|
||||||
|
|
||||||
|
Mock<IExecutionContext> _ec = new Mock<IExecutionContext>();
|
||||||
|
_ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>()))
|
||||||
|
.Returns((string tag, string line) =>
|
||||||
|
{
|
||||||
|
_hc.GetTrace().Info($"{tag} {line}");
|
||||||
|
return 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
_ec.SetupAllProperties();
|
||||||
|
|
||||||
|
ActionCommandManager commandManager = new ActionCommandManager();
|
||||||
|
commandManager.Initialize(_hc);
|
||||||
|
|
||||||
|
// Echo commands below are considered "processed", but are invalid
|
||||||
|
// 1. Invalid echo value
|
||||||
|
Assert.True(commandManager.TryProcessCommand(_ec.Object, "::echo::invalid"));
|
||||||
|
Assert.Equal(TaskResult.Failed, _ec.Object.CommandResult);
|
||||||
|
Assert.False(_ec.Object.EchoOnActionCommand);
|
||||||
|
|
||||||
|
// 2. No value
|
||||||
|
Assert.True(commandManager.TryProcessCommand(_ec.Object, "::echo::"));
|
||||||
|
Assert.Equal(TaskResult.Failed, _ec.Object.CommandResult);
|
||||||
|
Assert.False(_ec.Object.EchoOnActionCommand);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -233,6 +233,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
@@ -272,6 +273,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
Teardown();
|
Teardown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
@@ -306,6 +308,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
#if OS_LINUX
|
#if OS_LINUX
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
@@ -772,6 +775,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
Teardown();
|
Teardown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
||||||
|
|||||||
@@ -16,7 +16,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="2.2.300"
|
DOTNETSDK_VERSION="3.0.100"
|
||||||
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": "2.2.300"
|
"version": "3.0.100"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1 +1 @@
|
|||||||
2.159.2
|
2.160.0
|
||||||
Reference in New Issue
Block a user