Compare commits

...

22 Commits

Author SHA1 Message Date
Thomas Boop
85b072ae28 test release 2019-11-08 08:27:17 -05:00
Thomas Boop
022fddf73d Remove Unused Public Keys from Runner Service 2019-11-08 08:25:38 -05:00
Thomas Boop
222af415c6 Reverse test release changes 2019-11-07 16:32:54 -05:00
Thomas Boop
7dec45247d test release 2019-11-07 12:54:12 -05:00
eric sciple
8911283cdb fix problem matcher to treat fromPath as a file path (#183) 2019-11-07 11:26:29 -05:00
Eilon Lipton
76078b5c44 Add SLN file and make projects build in VS (#173)
* Add SLN file and make projects build in VS

- Added new ActionsRunner.sln file with all the CSPROJ's in it
- Added Directory.Build.props that gets auto-included in all CSPROJ files under it
- Made default runtime platforms for Windows and Linux (to be 64bit) so that you don't have to specify it in order to build

* Remove extra invalid parens
2019-11-06 16:57:46 -05:00
Eilon Lipton
ec9cb6c68d Fix build warnings in Test project (#178)
The build warnings were of these type (mostly reported by xUnit's Code Analyzers):
- Fixed wrong parameter order in xUnit assertions (can lead to poor error reporting in test failures)
- Unused code was removed
- Correct assertions were used (e.g. Assert.True/.Contains/.EndsWith)
- Public non-test methods on test classes were made private
2019-11-06 08:52:51 -05:00
Eilon Lipton
bcac4557a0 Fix Runner.Worker build warnings (#174)
Most of these warnings show up on only certain build OSes because of #ifdefs in the code. The fix is to suppress these warnings.
2019-11-06 08:47:56 -05:00
Eilon Lipton
19580bdaf8 Update contribute.md (#175)
Small cleanup of contribution guide
2019-11-05 17:21:50 -05:00
Eilon Lipton
96d3288553 Remove unused dreamlifter section (#177) 2019-11-05 17:21:00 -05:00
Tingluo Huang
5b6f9d3b93 Stop job container after all post actions. (#165)
* stop job container after all post actions.

* c

* c
2019-11-04 13:19:21 -05:00
eric sciple
51581ac865 root search pattern for hashfiles and allow forward slash on windows (#151) 2019-10-29 13:23:30 -04:00
eric sciple
e7dd2c6cc2 Update dotnet install script (#155) 2019-10-29 13:13:58 -04:00
Thomas Boop
08b9f6e045 Merge release 160.0 into master (#153)
* Update to Version 2.160.0 (#144)

* Revert "remove issue generation on warning/error commands (#137)" (#147)

* Revert "remove issue generation on warning/error commands (#137)"

This reverts commit 53da198867.

* Updated Release notes

* Users/thboop/port directory changes (#152)

* Clear action cache for local runner

* update release notes for actions directory cache changes
2019-10-28 15:45:27 -04:00
eric sciple
0129e8111f Clear action cache for local runner (#148) 2019-10-28 11:56:12 -04:00
eric sciple
ccca13ac07 restrict hashFiles to basic globbing and globstar (#150) 2019-10-28 11:52:22 -04:00
Julio Barba
82e9857d4f Implement new echo behavior and command (#139)
* Remove controlling echoing by command

* Add 'echo on' and 'echo off' action commands

* PR feedback and add L0 tests

* Register new command

* Eric's PR feedback

* Tweak logging a bit

* Rename EchoOnActionCommandSuccess -> EchoOnActionCommand

* More PR reaction

* Make warning messages in Action Commands not rely on context from echo commands
2019-10-25 10:38:56 -04:00
Tingluo Huang
afd233b735 consume dotnet core 3.0 (#127)
* consume dotnet core 3.0

* update linux dependency doc.
2019-10-24 16:52:29 -04:00
Thomas Boop
83be145bfd Update build.yml 2019-10-24 14:05:10 -04:00
Thomas Boop
6e20aceaff Update build.yml 2019-10-24 14:00:56 -04:00
Lucas Killgore
e89148e33e Don't retry uploads when the http status code response from the server is in the 400's (#131)
* Don't retry uploads when the http status code
response from the server is in the 400's

* Don't retry on fast-fail

* Feedback from code review

* Always try to attach any uploaded files to the build
Don't fast-fail on 'Conflict'

* Add dispose

* Refactored upload code.
Called out specialized 'Conflict' logic.

* Added typed exception.
2019-10-23 12:48:10 -04:00
Thomas Boop
f1c58c33b6 Default to pwsh with powershell as a fallback (#142)
* Default to pwsh with powershell as a fallback

* Update releaseNote.md

* clean up code
2019-10-23 11:24:02 -04:00
58 changed files with 1242 additions and 875 deletions

View File

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

1
.gitignore vendored
View File

@@ -3,7 +3,6 @@
**/libs **/libs
**/*.xproj **/*.xproj
**/*.xproj.user **/*.xproj.user
**/*.sln
**/.vs **/.vs
**/.vscode **/.vscode
**/*.error **/*.error

73
ActionsRunner.sln Normal file
View File

@@ -0,0 +1,73 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29411.138
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Runner.Common", "src\Runner.Common\Runner.Common.csproj", "{084289A3-CD7A-42E0-9219-4348B4B7E19B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Runner.Listener", "src\Runner.Listener\Runner.Listener.csproj", "{7D461AEE-BF2A-4855-BD96-56921160B36A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Runner.PluginHost", "src\Runner.PluginHost\Runner.PluginHost.csproj", "{D0320EB1-CB6D-4179-BFDC-2F2B664A370C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Runner.Plugins", "src\Runner.Plugins\Runner.Plugins.csproj", "{C23AFD6F-4DCD-4243-BC61-865BE31B9168}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Runner.Sdk", "src\Runner.Sdk\Runner.Sdk.csproj", "{D0484633-DA97-4C34-8E47-1DADE212A57A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RunnerService", "src\Runner.Service\Windows\RunnerService.csproj", "{D12EBD71-0464-46D0-8394-40BCFBA0A6F2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Runner.Worker", "src\Runner.Worker\Runner.Worker.csproj", "{C2F5B9FA-2621-411F-8EB2-273ED276F503}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sdk", "src\Sdk\Sdk.csproj", "{D2EE812B-E4DF-49BB-AE87-12BC49949B5F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "src\Test\Test.csproj", "{C932061F-F6A1-4F1E-B854-A6C6B30DC3EF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{084289A3-CD7A-42E0-9219-4348B4B7E19B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{084289A3-CD7A-42E0-9219-4348B4B7E19B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{084289A3-CD7A-42E0-9219-4348B4B7E19B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{084289A3-CD7A-42E0-9219-4348B4B7E19B}.Release|Any CPU.Build.0 = Release|Any CPU
{7D461AEE-BF2A-4855-BD96-56921160B36A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7D461AEE-BF2A-4855-BD96-56921160B36A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7D461AEE-BF2A-4855-BD96-56921160B36A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7D461AEE-BF2A-4855-BD96-56921160B36A}.Release|Any CPU.Build.0 = Release|Any CPU
{D0320EB1-CB6D-4179-BFDC-2F2B664A370C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D0320EB1-CB6D-4179-BFDC-2F2B664A370C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D0320EB1-CB6D-4179-BFDC-2F2B664A370C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D0320EB1-CB6D-4179-BFDC-2F2B664A370C}.Release|Any CPU.Build.0 = Release|Any CPU
{C23AFD6F-4DCD-4243-BC61-865BE31B9168}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C23AFD6F-4DCD-4243-BC61-865BE31B9168}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C23AFD6F-4DCD-4243-BC61-865BE31B9168}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C23AFD6F-4DCD-4243-BC61-865BE31B9168}.Release|Any CPU.Build.0 = Release|Any CPU
{D0484633-DA97-4C34-8E47-1DADE212A57A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D0484633-DA97-4C34-8E47-1DADE212A57A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D0484633-DA97-4C34-8E47-1DADE212A57A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D0484633-DA97-4C34-8E47-1DADE212A57A}.Release|Any CPU.Build.0 = Release|Any CPU
{D12EBD71-0464-46D0-8394-40BCFBA0A6F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D12EBD71-0464-46D0-8394-40BCFBA0A6F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D12EBD71-0464-46D0-8394-40BCFBA0A6F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D12EBD71-0464-46D0-8394-40BCFBA0A6F2}.Release|Any CPU.Build.0 = Release|Any CPU
{C2F5B9FA-2621-411F-8EB2-273ED276F503}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C2F5B9FA-2621-411F-8EB2-273ED276F503}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C2F5B9FA-2621-411F-8EB2-273ED276F503}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C2F5B9FA-2621-411F-8EB2-273ED276F503}.Release|Any CPU.Build.0 = Release|Any CPU
{D2EE812B-E4DF-49BB-AE87-12BC49949B5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D2EE812B-E4DF-49BB-AE87-12BC49949B5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D2EE812B-E4DF-49BB-AE87-12BC49949B5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D2EE812B-E4DF-49BB-AE87-12BC49949B5F}.Release|Any CPU.Build.0 = Release|Any CPU
{C932061F-F6A1-4F1E-B854-A6C6B30DC3EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C932061F-F6A1-4F1E-B854-A6C6B30DC3EF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C932061F-F6A1-4F1E-B854-A6C6B30DC3EF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C932061F-F6A1-4F1E-B854-A6C6B30DC3EF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4A831DDA-3860-45E5-930E-BB3A7833AE80}
EndGlobalSection
EndGlobal

View File

@@ -1,12 +1,12 @@
# Contribute (Dev) # Contribution guide for developers
## Dev Dependencies ## Required Dev Dependencies
![Win](res/win_sm.png) Git for Windows [Install Here](https://git-scm.com/downloads) (needed for dev sh script) ![Win](res/win_sm.png) Git for Windows [Install Here](https://git-scm.com/downloads) (needed for dev sh script)
## Build, Test, Layout ## To Build, Test, Layout
From src: Navigate to the `src` directory and run the following command:
![Win](res/win_sm.png) `dev {command}` ![Win](res/win_sm.png) `dev {command}`
@@ -14,13 +14,12 @@ From src:
**Commands:** **Commands:**
`layout` (`l`): Run first time to create a full agent layout in {root}/_layout * `layout` (`l`): Run first time to create a full agent layout in `{root}/_layout`
* `build` (`b`): Build everything and update agent layout folder
* `test` (`t`): Build agent binaries and run unit tests
`build` (`b`): build everything and update agent layout folder Sample developer flow:
`test` (`t`): build agent binaries and run unit tests
Normal dev flow:
```bash ```bash
git clone https://github.com/actions/runner git clone https://github.com/actions/runner
cd ./src cd ./src
@@ -37,5 +36,5 @@ cd ./src
## Styling ## Styling
We use the dotnet foundation and CoreCLR style guidelines [located here]( We use the .NET Foundation and CoreCLR style guidelines [located here](
https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/coding-style.md) https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/coding-style.md)

View File

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

View File

@@ -1,11 +1,11 @@
## Features ## Features
- Set Default shell to powershell for windows runners (#135) - N/A
## Bugs ## Bugs
- Removed unintended additional fields on error and warning commands (#137) - Test Release please ignore
## Misc ## Misc
- N/A - Updated to .NET Core 3.0 (#127)
## Agent Downloads ## Agent Downloads

52
src/Directory.Build.props Normal file
View File

@@ -0,0 +1,52 @@
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Detect OS for build -->
<PropertyGroup>
<BUILD_OS Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">Windows</BUILD_OS>
<BUILD_OS Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">OSX</BUILD_OS>
<BUILD_OS Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">Linux</BUILD_OS>
</PropertyGroup>
<!-- Set OS vars -->
<PropertyGroup Condition="'$(BUILD_OS)' == 'Windows'">
<DefineConstants>$(DefineConstants);OS_WINDOWS</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(BUILD_OS)' == 'OSX'">
<DefineConstants>$(DefineConstants);OS_OSX</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(BUILD_OS)' == 'Linux'">
<DefineConstants>$(DefineConstants);OS_LINUX</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(BUILD_OS)' == 'Linux' AND '$(PackageRuntime)' == 'rhel.6-x64'">
<DefineConstants>$(DefineConstants);OS_RHEL6</DefineConstants>
</PropertyGroup>
<!-- Set Platform/bitness vars -->
<PropertyGroup Condition="'$(BUILD_OS)' == 'Windows' AND ('$(PackageRuntime)' == 'win-x64' OR '$(PackageRuntime)' == '')">
<DefineConstants>$(DefineConstants);X64</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(BUILD_OS)' == 'Windows' AND '$(PackageRuntime)' == 'win-x86'">
<DefineConstants>$(DefineConstants);X86</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(BUILD_OS)' == 'OSX'">
<DefineConstants>$(DefineConstants);X64</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(BUILD_OS)' == 'Linux' AND ('$(PackageRuntime)' == 'linux-x64' OR '$(PackageRuntime)' == '')">
<DefineConstants>$(DefineConstants);X64</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(BUILD_OS)' == 'Linux' AND '$(PackageRuntime)' == 'rhel.6-x64'">
<DefineConstants>$(DefineConstants);X64</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(BUILD_OS)' == 'Linux' AND '$(PackageRuntime)' == 'linux-arm'">
<DefineConstants>$(DefineConstants);ARM</DefineConstants>
</PropertyGroup>
<!-- Set TRACE/DEBUG vars -->
<PropertyGroup>
<DefineConstants>$(DefineConstants);TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<DefineConstants>$(DefineConstants);DEBUG</DefineConstants>
</PropertyGroup>
</Project>

View File

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

View File

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

View File

@@ -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 '$?'"

View File

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

View File

@@ -54,6 +54,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.

View File

@@ -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>
@@ -26,43 +27,5 @@
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugType>portable</DebugType> <DebugType>portable</DebugType>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x64'">
<DefineConstants>OS_WINDOWS;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x86'">
<DefineConstants>OS_WINDOWS;X86;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x64'">
<DefineConstants>OS_WINDOWS;X64;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x86'">
<DefineConstants>OS_WINDOWS;X86;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">
<DefineConstants>OS_OSX;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true' AND '$(Configuration)' == 'Debug'">
<DefineConstants>OS_OSX;DEBUG;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-x64'">
<DefineConstants>OS_LINUX;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'rhel.6-x64'">
<DefineConstants>OS_LINUX;OS_RHEL6;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-arm'">
<DefineConstants>OS_LINUX;ARM;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-x64'">
<DefineConstants>OS_LINUX;X64;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'rhel.6-x64'">
<DefineConstants>OS_LINUX;OS_RHEL6;X64;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-arm'">
<DefineConstants>OS_LINUX;ARM;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
</Project> </Project>

View File

@@ -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>
@@ -28,43 +30,5 @@
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugType>portable</DebugType> <DebugType>portable</DebugType>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x64'">
<DefineConstants>OS_WINDOWS;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x86'">
<DefineConstants>OS_WINDOWS;X86;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x64'">
<DefineConstants>OS_WINDOWS;X64;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x86'">
<DefineConstants>OS_WINDOWS;X86;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">
<DefineConstants>OS_OSX;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true' AND '$(Configuration)' == 'Debug'">
<DefineConstants>OS_OSX;DEBUG;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-x64'">
<DefineConstants>OS_LINUX;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'rhel.6-x64'">
<DefineConstants>OS_LINUX;OS_RHEL6;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-arm'">
<DefineConstants>OS_LINUX;ARM;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-x64'">
<DefineConstants>OS_LINUX;X64;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'rhel.6-x64'">
<DefineConstants>OS_LINUX;OS_RHEL6;X64;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-arm'">
<DefineConstants>OS_LINUX;ARM;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
</Project> </Project>

View File

@@ -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>
@@ -22,42 +24,4 @@
<DebugType>portable</DebugType> <DebugType>portable</DebugType>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x64'">
<DefineConstants>OS_WINDOWS;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x86'">
<DefineConstants>OS_WINDOWS;X86;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x64'">
<DefineConstants>OS_WINDOWS;X64;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x86'">
<DefineConstants>OS_WINDOWS;X86;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">
<DefineConstants>OS_OSX;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true' AND '$(Configuration)' == 'Debug'">
<DefineConstants>OS_OSX;DEBUG;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-x64'">
<DefineConstants>OS_LINUX;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'rhel.6-x64'">
<DefineConstants>OS_LINUX;OS_RHEL6;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-arm'">
<DefineConstants>OS_LINUX;ARM;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-x64'">
<DefineConstants>OS_LINUX;X64;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'rhel.6-x64'">
<DefineConstants>OS_LINUX;OS_RHEL6;X64;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-arm'">
<DefineConstants>OS_LINUX;ARM;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
</Project> </Project>

View File

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

View File

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

View File

@@ -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>
@@ -18,43 +19,5 @@
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugType>portable</DebugType> <DebugType>portable</DebugType>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x64'">
<DefineConstants>OS_WINDOWS;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x86'">
<DefineConstants>OS_WINDOWS;X86;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x64'">
<DefineConstants>OS_WINDOWS;X64;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x86'">
<DefineConstants>OS_WINDOWS;X86;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">
<DefineConstants>OS_OSX;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true' AND '$(Configuration)' == 'Debug'">
<DefineConstants>OS_OSX;DEBUG;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-x64'">
<DefineConstants>OS_LINUX;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'rhel.6-x64'">
<DefineConstants>OS_LINUX;OS_RHEL6;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-arm'">
<DefineConstants>OS_LINUX;ARM;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-x64'">
<DefineConstants>OS_LINUX;X64;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'rhel.6-x64'">
<DefineConstants>OS_LINUX;OS_RHEL6;X64;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-arm'">
<DefineConstants>OS_LINUX;ARM;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
</Project> </Project>

View File

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

View File

@@ -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>
@@ -23,43 +24,5 @@
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugType>portable</DebugType> <DebugType>portable</DebugType>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x64'">
<DefineConstants>OS_WINDOWS;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x86'">
<DefineConstants>OS_WINDOWS;X86;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x64'">
<DefineConstants>OS_WINDOWS;X64;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x86'">
<DefineConstants>OS_WINDOWS;X86;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">
<DefineConstants>OS_OSX;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true' AND '$(Configuration)' == 'Debug'">
<DefineConstants>OS_OSX;DEBUG;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-x64'">
<DefineConstants>OS_LINUX;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'rhel.6-x64'">
<DefineConstants>OS_LINUX;OS_RHEL6;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-arm'">
<DefineConstants>OS_LINUX;ARM;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-x64'">
<DefineConstants>OS_LINUX;X64;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'rhel.6-x64'">
<DefineConstants>OS_LINUX;OS_RHEL6;X64;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-arm'">
<DefineConstants>OS_LINUX;ARM;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
</Project> </Project>

View File

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

View File

@@ -9,9 +9,8 @@
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>RunnerService</RootNamespace> <RootNamespace>RunnerService</RootNamespace>
<AssemblyName>RunnerService</AssemblyName> <AssemblyName>RunnerService</AssemblyName>
<SignAssembly>true</SignAssembly> <SignAssembly>false</SignAssembly>
<AssemblyOriginatorKeyFile>FinalPublicKey.snk</AssemblyOriginatorKeyFile> <DelaySign>false</DelaySign>
<DelaySign>true</DelaySign>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
@@ -64,7 +63,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="App.config" /> <None Include="App.config" />
<None Include="FinalPublicKey.snk" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Resource.resx"> <EmbeddedResource Include="Resource.resx">

View File

@@ -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
@@ -183,7 +190,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(SetEnvCommandProperties.Name, out string envName) || string.IsNullOrEmpty(envName)) if (!command.Properties.TryGetValue(SetEnvCommandProperties.Name, out string envName) || string.IsNullOrEmpty(envName))
{ {
@@ -192,9 +199,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 +214,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 +222,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 +237,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 +246,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 +260,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 +280,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 +294,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 +340,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 +407,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 +434,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 +447,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 +512,36 @@ 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}'.");
}
} }
} }
} }

View File

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

View File

@@ -94,7 +94,21 @@ namespace GitHub.Runner.Worker
{ {
postDisplayName = $"Post {this.DisplayName}"; postDisplayName = $"Post {this.DisplayName}";
} }
ExecutionContext.RegisterPostJobAction(postDisplayName, handlerData.CleanupCondition, Action);
var repositoryReference = Action.Reference as RepositoryPathReference;
var pathString = string.IsNullOrEmpty(repositoryReference.Path) ? string.Empty : $"/{repositoryReference.Path}";
var repoString = string.IsNullOrEmpty(repositoryReference.Ref) ? $"{repositoryReference.Name}{pathString}" :
$"{repositoryReference.Name}{pathString}@{repositoryReference.Ref}";
ExecutionContext.Debug($"Register post job cleanup for action: {repoString}");
var actionRunner = HostContext.CreateService<IActionRunner>();
actionRunner.Action = Action;
actionRunner.Stage = ActionRunStage.Post;
actionRunner.Condition = handlerData.CleanupCondition;
actionRunner.DisplayName = postDisplayName;
ExecutionContext.RegisterPostJobStep($"{actionRunner.Action.Name}_post", actionRunner);
} }
IStepHost stepHost = HostContext.CreateService<IDefaultStepHost>(); IStepHost stepHost = HostContext.CreateService<IDefaultStepHost>();

View File

@@ -276,7 +276,9 @@ namespace GitHub.Runner.Worker.Container
return await ExecuteDockerCommandAsync(context, "exec", $"{options} {containerId} {command}", context.CancellationToken); return await ExecuteDockerCommandAsync(context, "exec", $"{options} {containerId} {command}", context.CancellationToken);
} }
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously (method has async logic on only certain platforms)
public async Task<int> DockerExec(IExecutionContext context, string containerId, string options, string command, List<string> output) public async Task<int> DockerExec(IExecutionContext context, string containerId, string options, string command, List<string> output)
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
{ {
ArgUtil.NotNull(output, nameof(output)); ArgUtil.NotNull(output, nameof(output));
@@ -337,7 +339,9 @@ namespace GitHub.Runner.Worker.Container
return ExecuteDockerCommandAsync(context, command, options, null, cancellationToken); return ExecuteDockerCommandAsync(context, command, options, null, cancellationToken);
} }
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously (method has async logic on only certain platforms)
private async Task<int> ExecuteDockerCommandAsync(IExecutionContext context, string command, string options, IDictionary<string, string> environment, EventHandler<ProcessDataReceivedEventArgs> stdoutDataReceived, EventHandler<ProcessDataReceivedEventArgs> stderrDataReceived, CancellationToken cancellationToken = default(CancellationToken)) private async Task<int> ExecuteDockerCommandAsync(IExecutionContext context, string command, string options, IDictionary<string, string> environment, EventHandler<ProcessDataReceivedEventArgs> stdoutDataReceived, EventHandler<ProcessDataReceivedEventArgs> stderrDataReceived, CancellationToken cancellationToken = default(CancellationToken))
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
{ {
string arg = $"{command} {options}".Trim(); string arg = $"{command} {options}".Trim();
context.Command($"{DockerPath} {arg}"); context.Command($"{DockerPath} {arg}");
@@ -362,7 +366,9 @@ namespace GitHub.Runner.Worker.Container
#endif #endif
} }
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously (method has async logic on only certain platforms)
private async Task<int> ExecuteDockerCommandAsync(IExecutionContext context, string command, string options, string workingDirectory, CancellationToken cancellationToken = default(CancellationToken)) private async Task<int> ExecuteDockerCommandAsync(IExecutionContext context, string command, string options, string workingDirectory, CancellationToken cancellationToken = default(CancellationToken))
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
{ {
string arg = $"{command} {options}".Trim(); string arg = $"{command} {options}".Trim();
context.Command($"{DockerPath} {arg}"); context.Command($"{DockerPath} {arg}");

View File

@@ -11,6 +11,7 @@ using GitHub.Runner.Common;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using GitHub.DistributedTask.Pipelines.ContextData; using GitHub.DistributedTask.Pipelines.ContextData;
using Microsoft.Win32; using Microsoft.Win32;
using GitHub.DistributedTask.Pipelines.ObjectTemplating;
namespace GitHub.Runner.Worker namespace GitHub.Runner.Worker
{ {
@@ -38,6 +39,14 @@ namespace GitHub.Runner.Worker
List<ContainerInfo> containers = data as List<ContainerInfo>; List<ContainerInfo> containers = data as List<ContainerInfo>;
ArgUtil.NotNull(containers, nameof(containers)); ArgUtil.NotNull(containers, nameof(containers));
var postJobStep = new JobExtensionRunner(runAsync: this.StopContainersAsync,
condition: $"{PipelineTemplateConstants.Always}()",
displayName: "Stop containers",
data: data);
executionContext.Debug($"Register post job cleanup for stoping/deleting containers.");
executionContext.RegisterPostJobStep(nameof(StopContainersAsync), postJobStep);
// Check whether we are inside a container. // Check whether we are inside a container.
// Our container feature requires to map working directory from host to the container. // Our container feature requires to map working directory from host to the container.
// If we are already inside a container, we will not able to find out the real working direcotry path on the host. // If we are already inside a container, we will not able to find out the real working direcotry path on the host.

View File

@@ -31,7 +31,9 @@ namespace GitHub.Runner.Worker
public sealed class DiagnosticLogManager : RunnerService, IDiagnosticLogManager public sealed class DiagnosticLogManager : RunnerService, IDiagnosticLogManager
{ {
private static string DateTimeFormat = "yyyyMMdd-HHmmss"; private static string DateTimeFormat = "yyyyMMdd-HHmmss";
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously (method has async logic on only certain platforms)
public async Task UploadDiagnosticLogsAsync(IExecutionContext executionContext, public async Task UploadDiagnosticLogsAsync(IExecutionContext executionContext,
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
IExecutionContext parentContext, IExecutionContext parentContext,
Pipelines.AgentJobRequestMessage message, Pipelines.AgentJobRequestMessage message,
DateTime jobStartTimeUtc) DateTime jobStartTimeUtc)

View File

@@ -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();
@@ -96,7 +98,7 @@ namespace GitHub.Runner.Worker
// others // others
void ForceTaskComplete(); void ForceTaskComplete();
void RegisterPostJobAction(string displayName, string condition, Pipelines.ActionStep action); void RegisterPostJobStep(string refName, IStep step);
} }
public sealed class ExecutionContext : RunnerService, IExecutionContext public sealed class ExecutionContext : RunnerService, IExecutionContext
@@ -153,6 +155,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
{ {
@@ -236,27 +240,10 @@ namespace GitHub.Runner.Worker
}); });
} }
public void RegisterPostJobAction(string displayName, string condition, Pipelines.ActionStep action) public void RegisterPostJobStep(string refName, IStep step)
{ {
if (action.Reference.Type != ActionSourceType.Repository) step.ExecutionContext = Root.CreatePostChild(step.DisplayName, refName, IntraActionState);
{ Root.PostJobSteps.Push(step);
throw new NotSupportedException("Only action that has `action.yml` can define post job execution.");
}
var repositoryReference = action.Reference as RepositoryPathReference;
var pathString = string.IsNullOrEmpty(repositoryReference.Path) ? string.Empty : $"/{repositoryReference.Path}";
var repoString = string.IsNullOrEmpty(repositoryReference.Ref) ? $"{repositoryReference.Name}{pathString}" :
$"{repositoryReference.Name}{pathString}@{repositoryReference.Ref}";
this.Debug($"Register post job cleanup for action: {repoString}");
var actionRunner = HostContext.CreateService<IActionRunner>();
actionRunner.Action = action;
actionRunner.Stage = ActionRunStage.Post;
actionRunner.Condition = condition;
actionRunner.DisplayName = displayName;
actionRunner.ExecutionContext = Root.CreatePostChild(displayName, $"{actionRunner.Action.Name}_post", IntraActionState);
Root.PostJobSteps.Push(actionRunner);
} }
public IExecutionContext CreateChild(Guid recordId, string displayName, string refName, string scopeName, string contextName, Dictionary<string, string> intraActionState = null, int? recordOrder = null) public IExecutionContext CreateChild(Guid recordId, string displayName, string refName, string scopeName, string contextName, Dictionary<string, string> intraActionState = null, int? recordOrder = null)
@@ -292,6 +279,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)
{ {
@@ -704,6 +692,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;

View File

@@ -22,7 +22,9 @@ namespace GitHub.Runner.Worker.Handlers
{ {
public ContainerActionExecutionData Data { get; set; } public ContainerActionExecutionData Data { get; set; }
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously (method has async logic on only certain platforms)
public async Task RunAsync(ActionRunStage stage) public async Task RunAsync(ActionRunStage stage)
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
{ {
// Validate args. // Validate args.
Trace.Entering(); Trace.Entering();

View File

@@ -263,15 +263,17 @@ namespace GitHub.Runner.Worker.Handlers
// Root using fromPath // Root using fromPath
if (!string.IsNullOrWhiteSpace(match.FromPath) && !Path.IsPathRooted(file)) if (!string.IsNullOrWhiteSpace(match.FromPath) && !Path.IsPathRooted(file))
{ {
file = Path.Combine(match.FromPath, file); var fromDirectory = Path.GetDirectoryName(match.FromPath);
if (!string.IsNullOrWhiteSpace(fromDirectory))
{
file = Path.Combine(fromDirectory, file);
}
} }
// Root using system.defaultWorkingDirectory // Root using workspace
if (!Path.IsPathRooted(file)) if (!Path.IsPathRooted(file))
{ {
var githubContext = _executionContext.ExpressionValues["github"] as GitHubContext; var workspace = _executionContext.GetGitHubContext("workspace");
ArgUtil.NotNull(githubContext, nameof(githubContext));
var workspace = githubContext["workspace"].ToString();
ArgUtil.NotNullOrEmpty(workspace, "workspace"); ArgUtil.NotNullOrEmpty(workspace, "workspace");
file = Path.Combine(workspace, file); file = Path.Combine(workspace, file);
@@ -297,7 +299,7 @@ namespace GitHub.Runner.Worker.Handlers
} }
else else
{ {
// prefer `/` on all platforms // Prefer `/` on all platforms
issue.Data["file"] = file.Substring(repositoryPath.Length).TrimStart(Path.DirectorySeparatorChar).Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); issue.Data["file"] = file.Substring(repositoryPath.Length).TrimStart(Path.DirectorySeparatorChar).Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
} }
} }

View File

@@ -60,10 +60,16 @@ namespace GitHub.Runner.Worker.Handlers
if (string.IsNullOrEmpty(shell)) if (string.IsNullOrEmpty(shell))
{ {
#if OS_WINDOWS #if OS_WINDOWS
shellCommand = "powershell"; shellCommand = "pwsh";
if(validateShellOnHost) if(validateShellOnHost)
{ {
shellCommandPath = WhichUtil.Which(shellCommand, true, Trace); shellCommandPath = WhichUtil.Which(shellCommand, require: false, Trace);
if (string.IsNullOrEmpty(shellCommandPath))
{
shellCommand = "powershell";
Trace.Info($"Defaulting to {shellCommand}");
shellCommandPath = WhichUtil.Which(shellCommand, require: true, Trace);
}
} }
#else #else
shellCommand = "sh"; shellCommand = "sh";
@@ -143,8 +149,14 @@ namespace GitHub.Runner.Worker.Handlers
if (string.IsNullOrEmpty(shell)) if (string.IsNullOrEmpty(shell))
{ {
#if OS_WINDOWS #if OS_WINDOWS
shellCommand = "powershell"; shellCommand = "pwsh";
commandPath = WhichUtil.Which(shellCommand, true, Trace); commandPath = WhichUtil.Which(shellCommand, require: false, Trace);
if (string.IsNullOrEmpty(commandPath))
{
shellCommand = "powershell";
Trace.Info($"Defaulting to {shellCommand}");
commandPath = WhichUtil.Which(shellCommand, require: true, Trace);
}
ArgUtil.NotNullOrEmpty(commandPath, "Default Shell"); ArgUtil.NotNullOrEmpty(commandPath, "Default Shell");
#else #else
shellCommand = "sh"; shellCommand = "sh";

View File

@@ -110,9 +110,7 @@ namespace GitHub.Runner.Worker
} }
} }
// Build up 3 lists of steps, pre-job, job, post-job // Build up 2 lists of steps, pre-job, job
var postJobStepsBuilder = new Stack<IStep>();
// Download actions not already in the cache // Download actions not already in the cache
Trace.Info("Downloading actions"); Trace.Info("Downloading actions");
var actionManager = HostContext.GetService<IActionManager>(); var actionManager = HostContext.GetService<IActionManager>();
@@ -134,10 +132,6 @@ namespace GitHub.Runner.Worker
condition: $"{PipelineTemplateConstants.Success}()", condition: $"{PipelineTemplateConstants.Success}()",
displayName: "Initialize containers", displayName: "Initialize containers",
data: (object)containers)); data: (object)containers));
postJobStepsBuilder.Push(new JobExtensionRunner(runAsync: containerProvider.StopContainersAsync,
condition: $"{PipelineTemplateConstants.Always}()",
displayName: "Stop containers",
data: (object)containers));
} }
// Add action steps // Add action steps
@@ -187,33 +181,9 @@ namespace GitHub.Runner.Worker
} }
} }
// Add post-job steps
Trace.Info("Adding post-job steps");
while (postJobStepsBuilder.Count > 0)
{
postJobSteps.Add(postJobStepsBuilder.Pop());
}
// Create execution context for post-job steps
foreach (var step in postJobSteps)
{
if (step is JobExtensionRunner)
{
JobExtensionRunner extensionStep = step as JobExtensionRunner;
ArgUtil.NotNull(extensionStep, extensionStep.DisplayName);
Guid stepId = Guid.NewGuid();
extensionStep.ExecutionContext = jobContext.CreateChild(stepId, extensionStep.DisplayName, stepId.ToString("N"), null, null);
}
}
List<IStep> steps = new List<IStep>(); List<IStep> steps = new List<IStep>();
steps.AddRange(preJobSteps); steps.AddRange(preJobSteps);
steps.AddRange(jobSteps); steps.AddRange(jobSteps);
steps.AddRange(postJobSteps);
// Start agent log plugin host process
// var logPlugin = HostContext.GetService<IAgentLogPlugin>();
// await logPlugin.StartAsync(context, steps, jobContext.CancellationToken);
// Prepare for orphan process cleanup // Prepare for orphan process cleanup
_processCleanup = jobContext.Variables.GetBoolean("process.clean") ?? true; _processCleanup = jobContext.Variables.GetBoolean("process.clean") ?? true;

View File

@@ -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>
@@ -33,42 +35,4 @@
<DebugType>portable</DebugType> <DebugType>portable</DebugType>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x64'">
<DefineConstants>OS_WINDOWS;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x86'">
<DefineConstants>OS_WINDOWS;X86;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x64'">
<DefineConstants>OS_WINDOWS;X64;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x86'">
<DefineConstants>OS_WINDOWS;X86;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">
<DefineConstants>OS_OSX;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true' AND '$(Configuration)' == 'Debug'">
<DefineConstants>OS_OSX;DEBUG;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-x64'">
<DefineConstants>OS_LINUX;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'rhel.6-x64'">
<DefineConstants>OS_LINUX;OS_RHEL6;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-arm'">
<DefineConstants>OS_LINUX;ARM;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-x64'">
<DefineConstants>OS_LINUX;X64;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'rhel.6-x64'">
<DefineConstants>OS_LINUX;OS_RHEL6;X64;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-arm'">
<DefineConstants>OS_LINUX;ARM;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
</Project> </Project>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -47,8 +47,8 @@ namespace GitHub.Runner.Common.Tests
}); });
// Assert. // Assert.
Assert.Equal(hc.SecretMasker.MaskSecrets("secret value 1"), "***"); Assert.Equal("***", hc.SecretMasker.MaskSecrets("secret value 1"));
Assert.Equal(hc.SecretMasker.MaskSecrets("secret value 2"), "***"); Assert.Equal("***", hc.SecretMasker.MaskSecrets("secret value 2"));
} }
} }
@@ -90,9 +90,9 @@ namespace GitHub.Runner.Common.Tests
trace.Info("Args: {0}", clp.Args.Count); trace.Info("Args: {0}", clp.Args.Count);
Assert.True(clp.Args.Count == 2); Assert.True(clp.Args.Count == 2);
Assert.True(clp.Args.ContainsKey("arg1")); Assert.True(clp.Args.ContainsKey("arg1"));
Assert.Equal(clp.Args["arg1"], "arg1val"); Assert.Equal("arg1val", clp.Args["arg1"]);
Assert.True(clp.Args.ContainsKey("arg2")); Assert.True(clp.Args.ContainsKey("arg2"));
Assert.Equal(clp.Args["arg2"], "arg2val"); Assert.Equal("arg2val", clp.Args["arg2"]);
} }
} }
@@ -113,8 +113,8 @@ namespace GitHub.Runner.Common.Tests
trace.Info("Args: {0}", clp.Flags.Count); trace.Info("Args: {0}", clp.Flags.Count);
Assert.True(clp.Flags.Count == 2); Assert.True(clp.Flags.Count == 2);
Assert.True(clp.Flags.Contains("flag1")); Assert.Contains("flag1", clp.Flags);
Assert.True(clp.Flags.Contains("flag2")); Assert.Contains("flag2", clp.Flags);
} }
} }

View File

@@ -36,10 +36,10 @@ namespace GitHub.Runner.Common.Tests.Worker.Container
// Assert // Assert
Assert.NotNull(result0); Assert.NotNull(result0);
Assert.Equal(result0.Count, 0); Assert.Equal(0, result0.Count);
Assert.NotNull(result1); Assert.NotNull(result1);
Assert.Equal(result1.Count, 1); Assert.Equal(1, result1.Count);
var result1Port80Mapping = result1.Find(pm => var result1Port80Mapping = result1.Find(pm =>
string.Equals(pm.ContainerPort, "80") && string.Equals(pm.ContainerPort, "80") &&
string.Equals(pm.HostPort, "32881") && string.Equals(pm.HostPort, "32881") &&
@@ -48,10 +48,10 @@ namespace GitHub.Runner.Common.Tests.Worker.Container
Assert.NotNull(result1Port80Mapping); Assert.NotNull(result1Port80Mapping);
Assert.NotNull(result1Empty); Assert.NotNull(result1Empty);
Assert.Equal(result1Empty.Count, 0); Assert.Equal(0, result1Empty.Count);
Assert.NotNull(result2); Assert.NotNull(result2);
Assert.Equal(result2.Count, 2); Assert.Equal(2, result2.Count);
var result2Port80Mapping = result2.Find(pm => var result2Port80Mapping = result2.Find(pm =>
string.Equals(pm.ContainerPort, "80") && string.Equals(pm.ContainerPort, "80") &&
string.Equals(pm.HostPort, "32881") && string.Equals(pm.HostPort, "32881") &&

View File

@@ -107,7 +107,7 @@ namespace GitHub.Runner.Common.Tests
} }
} }
public void Setup([CallerMemberName] string testName = "") private void Setup([CallerMemberName] string testName = "")
{ {
_tokenSource = new CancellationTokenSource(); _tokenSource = new CancellationTokenSource();
_hc = new HostContext( _hc = new HostContext(
@@ -115,7 +115,7 @@ namespace GitHub.Runner.Common.Tests
logFile: Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), $"trace_{nameof(HostContextL0)}_{testName}.log")); logFile: Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), $"trace_{nameof(HostContextL0)}_{testName}.log"));
} }
public void Teardown() private void Teardown()
{ {
_hc?.Dispose(); _hc?.Dispose();
_tokenSource?.Dispose(); _tokenSource?.Dispose();

View File

@@ -52,7 +52,7 @@ namespace GitHub.Runner.Common.Tests
// Assert. // Assert.
Assert.Equal("some agent", actual); Assert.Equal("some agent", actual);
Assert.Equal(string.Empty, Environment.GetEnvironmentVariable("ACTIONS_RUNNER_INPUT_AGENT") ?? string.Empty); // Should remove. Assert.Equal(string.Empty, Environment.GetEnvironmentVariable("ACTIONS_RUNNER_INPUT_AGENT") ?? string.Empty); // Should remove.
Assert.Equal(hc.SecretMasker.MaskSecrets("some agent"), "some agent"); Assert.Equal("some agent", hc.SecretMasker.MaskSecrets("some agent"));
} }
finally finally
{ {
@@ -80,7 +80,7 @@ namespace GitHub.Runner.Common.Tests
// Assert. // Assert.
Assert.Equal("some secret token value", actual); Assert.Equal("some secret token value", actual);
Assert.Equal(string.Empty, Environment.GetEnvironmentVariable("ACTIONS_RUNNER_INPUT_TOKEN") ?? string.Empty); // Should remove. Assert.Equal(string.Empty, Environment.GetEnvironmentVariable("ACTIONS_RUNNER_INPUT_TOKEN") ?? string.Empty); // Should remove.
Assert.Equal(hc.SecretMasker.MaskSecrets("some secret token value"), "***"); Assert.Equal("***", hc.SecretMasker.MaskSecrets("some secret token value"));
} }
finally finally
{ {
@@ -250,7 +250,7 @@ namespace GitHub.Runner.Common.Tests
bool actual = command.Unattended; bool actual = command.Unattended;
// Assert. // Assert.
Assert.Equal(true, actual); Assert.True(actual);
Assert.Equal(string.Empty, Environment.GetEnvironmentVariable("ACTIONS_RUNNER_INPUT_UNATTENDED") ?? string.Empty); // Should remove. Assert.Equal(string.Empty, Environment.GetEnvironmentVariable("ACTIONS_RUNNER_INPUT_UNATTENDED") ?? string.Empty); // Should remove.
} }
finally finally
@@ -720,7 +720,7 @@ namespace GitHub.Runner.Common.Tests
var command = new CommandSettings(hc, args: new string[] { "badcommand" }); var command = new CommandSettings(hc, args: new string[] { "badcommand" });
// Assert. // Assert.
Assert.True(command.Validate().Contains("badcommand")); Assert.Contains("badcommand", command.Validate());
} }
} }
@@ -735,7 +735,7 @@ namespace GitHub.Runner.Common.Tests
var command = new CommandSettings(hc, args: new string[] { "--badflag" }); var command = new CommandSettings(hc, args: new string[] { "--badflag" });
// Assert. // Assert.
Assert.True(command.Validate().Contains("badflag")); Assert.Contains("badflag", command.Validate());
} }
} }
@@ -750,7 +750,7 @@ namespace GitHub.Runner.Common.Tests
var command = new CommandSettings(hc, args: new string[] { "--badargname", "bad arg value" }); var command = new CommandSettings(hc, args: new string[] { "--badargname", "bad arg value" });
// Assert. // Assert.
Assert.True(command.Validate().Contains("badargname")); Assert.Contains("badargname", command.Validate());
} }
} }

View File

@@ -43,10 +43,6 @@ namespace GitHub.Runner.Common.Tests.Listener.Configuration
private string _expectedServerUrl = "https://localhost"; private string _expectedServerUrl = "https://localhost";
private string _expectedAgentName = "expectedAgentName"; private string _expectedAgentName = "expectedAgentName";
private string _expectedPoolName = "poolName"; private string _expectedPoolName = "poolName";
private string _expectedCollectionName = "testCollectionName";
private string _expectedProjectName = "testProjectName";
private string _expectedProjectId = "edf3f94e-d251-49df-bfce-602d6c967409";
private string _expectedMachineGroupName = "testMachineGroupName";
private string _expectedAuthType = "pat"; private string _expectedAuthType = "pat";
private string _expectedWorkFolder = "_work"; private string _expectedWorkFolder = "_work";
private int _expectedPoolId = 1; private int _expectedPoolId = 1;

View File

@@ -64,7 +64,7 @@ namespace GitHub.Runner.Common.Tests.Listener
string line; string line;
while ((line = freader.ReadLine()) != null) while ((line = freader.ReadLine()) != null)
{ {
Assert.True(line.EndsWith(LogData)); Assert.EndsWith(LogData, line);
bytesWritten += logDataSize; bytesWritten += logDataSize;
} }
} }

View File

@@ -31,8 +31,8 @@ namespace GitHub.Runner.Common.Tests.Util
var connect = VssUtil.CreateConnection(new Uri("https://github.com/actions/runner"), new VssCredentials()); var connect = VssUtil.CreateConnection(new Uri("https://github.com/actions/runner"), new VssCredentials());
// Assert. // Assert.
Assert.Equal(connect.Settings.MaxRetryRequest.ToString(), "10"); Assert.Equal("10", connect.Settings.MaxRetryRequest.ToString());
Assert.Equal(connect.Settings.SendTimeout.TotalSeconds.ToString(), "360"); Assert.Equal("360", connect.Settings.SendTimeout.TotalSeconds.ToString());
trace.Info("Set httpretry to 100."); trace.Info("Set httpretry to 100.");
Environment.SetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_HTTP_RETRY", "100"); Environment.SetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_HTTP_RETRY", "100");
@@ -42,8 +42,8 @@ namespace GitHub.Runner.Common.Tests.Util
connect = VssUtil.CreateConnection(new Uri("https://github.com/actions/runner"), new VssCredentials()); connect = VssUtil.CreateConnection(new Uri("https://github.com/actions/runner"), new VssCredentials());
// Assert. // Assert.
Assert.Equal(connect.Settings.MaxRetryRequest.ToString(), "10"); Assert.Equal("10", connect.Settings.MaxRetryRequest.ToString());
Assert.Equal(connect.Settings.SendTimeout.TotalSeconds.ToString(), "1200"); Assert.Equal("1200", connect.Settings.SendTimeout.TotalSeconds.ToString());
} }
finally finally
{ {

View File

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

View File

@@ -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")]

View File

@@ -37,25 +37,25 @@ namespace GitHub.Runner.Common.Tests.Worker
//Assert //Assert
Assert.Equal(result.Name, "Hello World"); Assert.Equal("Hello World", result.Name);
Assert.Equal(result.Description, "Greet the world and record the time"); Assert.Equal("Greet the world and record the time", result.Description);
Assert.Equal(result.Inputs.Count, 2); Assert.Equal(2, result.Inputs.Count);
Assert.Equal(result.Inputs[0].Key.AssertString("key").Value, "greeting"); Assert.Equal("greeting", result.Inputs[0].Key.AssertString("key").Value);
Assert.Equal(result.Inputs[0].Value.AssertString("value").Value, "Hello"); Assert.Equal("Hello", result.Inputs[0].Value.AssertString("value").Value);
Assert.Equal(result.Inputs[1].Key.AssertString("key").Value, "entryPoint"); Assert.Equal("entryPoint", result.Inputs[1].Key.AssertString("key").Value);
Assert.Equal(result.Inputs[1].Value.AssertString("value").Value, ""); Assert.Equal("", result.Inputs[1].Value.AssertString("value").Value);
Assert.Equal(result.Execution.ExecutionType, ActionExecutionType.Container); Assert.Equal(ActionExecutionType.Container, result.Execution.ExecutionType);
var containerAction = result.Execution as ContainerActionExecutionData; var containerAction = result.Execution as ContainerActionExecutionData;
Assert.Equal(containerAction.Image, "Dockerfile"); Assert.Equal("Dockerfile", containerAction.Image);
Assert.Equal(containerAction.EntryPoint, "main.sh"); Assert.Equal("main.sh", containerAction.EntryPoint);
Assert.Equal(containerAction.Arguments[0].ToString(), "bzz"); Assert.Equal("bzz", containerAction.Arguments[0].ToString());
Assert.Equal(containerAction.Environment[0].Key.ToString(), "Token"); Assert.Equal("Token", containerAction.Environment[0].Key.ToString());
Assert.Equal(containerAction.Environment[0].Value.ToString(), "foo"); Assert.Equal("foo", containerAction.Environment[0].Value.ToString());
Assert.Equal(containerAction.Environment[1].Key.ToString(), "Url"); Assert.Equal("Url", containerAction.Environment[1].Key.ToString());
Assert.Equal(containerAction.Environment[1].Value.ToString(), "bar"); Assert.Equal("bar", containerAction.Environment[1].Value.ToString());
} }
finally finally
{ {
@@ -81,27 +81,27 @@ namespace GitHub.Runner.Common.Tests.Worker
//Assert //Assert
Assert.Equal(result.Name, "Hello World"); Assert.Equal("Hello World", result.Name);
Assert.Equal(result.Description, "Greet the world and record the time"); Assert.Equal("Greet the world and record the time", result.Description);
Assert.Equal(result.Inputs.Count, 2); Assert.Equal(2, result.Inputs.Count);
Assert.Equal(result.Inputs[0].Key.AssertString("key").Value, "greeting"); Assert.Equal("greeting", result.Inputs[0].Key.AssertString("key").Value);
Assert.Equal(result.Inputs[0].Value.AssertString("value").Value, "Hello"); Assert.Equal("Hello", result.Inputs[0].Value.AssertString("value").Value);
Assert.Equal(result.Inputs[1].Key.AssertString("key").Value, "entryPoint"); Assert.Equal("entryPoint", result.Inputs[1].Key.AssertString("key").Value);
Assert.Equal(result.Inputs[1].Value.AssertString("value").Value, ""); Assert.Equal("", result.Inputs[1].Value.AssertString("value").Value);
Assert.Equal(result.Execution.ExecutionType, ActionExecutionType.Container); Assert.Equal(ActionExecutionType.Container, result.Execution.ExecutionType);
var containerAction = result.Execution as ContainerActionExecutionData; var containerAction = result.Execution as ContainerActionExecutionData;
Assert.Equal(containerAction.Image, "Dockerfile"); Assert.Equal("Dockerfile", containerAction.Image);
Assert.Equal(containerAction.EntryPoint, "main.sh"); Assert.Equal("main.sh", containerAction.EntryPoint);
Assert.Equal(containerAction.Cleanup, "cleanup.sh"); Assert.Equal("cleanup.sh", containerAction.Cleanup);
Assert.Equal(containerAction.CleanupCondition, "failure()"); Assert.Equal("failure()", containerAction.CleanupCondition);
Assert.Equal(containerAction.Arguments[0].ToString(), "bzz"); Assert.Equal("bzz", containerAction.Arguments[0].ToString());
Assert.Equal(containerAction.Environment[0].Key.ToString(), "Token"); Assert.Equal("Token", containerAction.Environment[0].Key.ToString());
Assert.Equal(containerAction.Environment[0].Value.ToString(), "foo"); Assert.Equal("foo", containerAction.Environment[0].Value.ToString());
Assert.Equal(containerAction.Environment[1].Key.ToString(), "Url"); Assert.Equal("Url", containerAction.Environment[1].Key.ToString());
Assert.Equal(containerAction.Environment[1].Value.ToString(), "bar"); Assert.Equal("bar", containerAction.Environment[1].Value.ToString());
} }
finally finally
{ {
@@ -126,19 +126,19 @@ namespace GitHub.Runner.Common.Tests.Worker
var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "dockerfileaction_noargs_noenv_noentrypoint.yml")); var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "dockerfileaction_noargs_noenv_noentrypoint.yml"));
//Assert //Assert
Assert.Equal(result.Name, "Hello World"); Assert.Equal("Hello World", result.Name);
Assert.Equal(result.Description, "Greet the world and record the time"); Assert.Equal("Greet the world and record the time", result.Description);
Assert.Equal(result.Inputs.Count, 2); Assert.Equal(2, result.Inputs.Count);
Assert.Equal(result.Inputs[0].Key.AssertString("key").Value, "greeting"); Assert.Equal("greeting", result.Inputs[0].Key.AssertString("key").Value);
Assert.Equal(result.Inputs[0].Value.AssertString("value").Value, "Hello"); Assert.Equal("Hello", result.Inputs[0].Value.AssertString("value").Value);
Assert.Equal(result.Inputs[1].Key.AssertString("key").Value, "entryPoint"); Assert.Equal("entryPoint", result.Inputs[1].Key.AssertString("key").Value);
Assert.Equal(result.Inputs[1].Value.AssertString("value").Value, ""); Assert.Equal("", result.Inputs[1].Value.AssertString("value").Value);
Assert.Equal(result.Execution.ExecutionType, ActionExecutionType.Container); Assert.Equal(ActionExecutionType.Container, result.Execution.ExecutionType);
var containerAction = result.Execution as ContainerActionExecutionData; var containerAction = result.Execution as ContainerActionExecutionData;
Assert.Equal(containerAction.Image, "Dockerfile"); Assert.Equal("Dockerfile", containerAction.Image);
} }
finally finally
{ {
@@ -164,25 +164,25 @@ namespace GitHub.Runner.Common.Tests.Worker
//Assert //Assert
Assert.Equal(result.Name, "Hello World"); Assert.Equal("Hello World", result.Name);
Assert.Equal(result.Description, "Greet the world and record the time"); Assert.Equal("Greet the world and record the time", result.Description);
Assert.Equal(result.Inputs.Count, 2); Assert.Equal(2, result.Inputs.Count);
Assert.Equal(result.Inputs[0].Key.AssertString("key").Value, "greeting"); Assert.Equal("greeting", result.Inputs[0].Key.AssertString("key").Value);
Assert.Equal(result.Inputs[0].Value.AssertString("value").Value, "Hello"); Assert.Equal("Hello", result.Inputs[0].Value.AssertString("value").Value);
Assert.Equal(result.Inputs[1].Key.AssertString("key").Value, "entryPoint"); Assert.Equal("entryPoint", result.Inputs[1].Key.AssertString("key").Value);
Assert.Equal(result.Inputs[1].Value.AssertString("value").Value, ""); Assert.Equal("", result.Inputs[1].Value.AssertString("value").Value);
Assert.Equal(result.Execution.ExecutionType, ActionExecutionType.Container); Assert.Equal(ActionExecutionType.Container, result.Execution.ExecutionType);
var containerAction = result.Execution as ContainerActionExecutionData; var containerAction = result.Execution as ContainerActionExecutionData;
Assert.Equal(containerAction.Image, "Dockerfile"); Assert.Equal("Dockerfile", containerAction.Image);
Assert.Equal(containerAction.EntryPoint, "main.sh"); Assert.Equal("main.sh", containerAction.EntryPoint);
Assert.Equal(containerAction.Arguments[0].ToString(), "${{ inputs.greeting }}"); Assert.Equal("${{ inputs.greeting }}", containerAction.Arguments[0].ToString());
Assert.Equal(containerAction.Environment[0].Key.ToString(), "Token"); Assert.Equal("Token", containerAction.Environment[0].Key.ToString());
Assert.Equal(containerAction.Environment[0].Value.ToString(), "foo"); Assert.Equal("foo", containerAction.Environment[0].Value.ToString());
Assert.Equal(containerAction.Environment[1].Key.ToString(), "Url"); Assert.Equal("Url", containerAction.Environment[1].Key.ToString());
Assert.Equal(containerAction.Environment[1].Value.ToString(), "${{ inputs.entryPoint }}"); Assert.Equal("${{ inputs.entryPoint }}", containerAction.Environment[1].Value.ToString());
} }
finally finally
{ {
@@ -207,25 +207,25 @@ namespace GitHub.Runner.Common.Tests.Worker
var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "dockerhubaction.yml")); var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "dockerhubaction.yml"));
//Assert //Assert
Assert.Equal(result.Name, "Hello World"); Assert.Equal("Hello World", result.Name);
Assert.Equal(result.Description, "Greet the world and record the time"); Assert.Equal("Greet the world and record the time", result.Description);
Assert.Equal(result.Inputs.Count, 2); Assert.Equal(2, result.Inputs.Count);
Assert.Equal(result.Inputs[0].Key.AssertString("key").Value, "greeting"); Assert.Equal("greeting", result.Inputs[0].Key.AssertString("key").Value);
Assert.Equal(result.Inputs[0].Value.AssertString("value").Value, "Hello"); Assert.Equal("Hello", result.Inputs[0].Value.AssertString("value").Value);
Assert.Equal(result.Inputs[1].Key.AssertString("key").Value, "entryPoint"); Assert.Equal("entryPoint", result.Inputs[1].Key.AssertString("key").Value);
Assert.Equal(result.Inputs[1].Value.AssertString("value").Value, ""); Assert.Equal("", result.Inputs[1].Value.AssertString("value").Value);
Assert.Equal(result.Execution.ExecutionType, ActionExecutionType.Container); Assert.Equal(ActionExecutionType.Container, result.Execution.ExecutionType);
var containerAction = result.Execution as ContainerActionExecutionData; var containerAction = result.Execution as ContainerActionExecutionData;
Assert.Equal(containerAction.Image, "docker://ubuntu:18.04"); Assert.Equal("docker://ubuntu:18.04", containerAction.Image);
Assert.Equal(containerAction.EntryPoint, "main.sh"); Assert.Equal("main.sh", containerAction.EntryPoint);
Assert.Equal(containerAction.Arguments[0].ToString(), "bzz"); Assert.Equal("bzz", containerAction.Arguments[0].ToString());
Assert.Equal(containerAction.Environment[0].Key.ToString(), "Token"); Assert.Equal("Token", containerAction.Environment[0].Key.ToString());
Assert.Equal(containerAction.Environment[0].Value.ToString(), "foo"); Assert.Equal("foo", containerAction.Environment[0].Value.ToString());
Assert.Equal(containerAction.Environment[1].Key.ToString(), "Url"); Assert.Equal("Url", containerAction.Environment[1].Key.ToString());
Assert.Equal(containerAction.Environment[1].Value.ToString(), "bar"); Assert.Equal("bar", containerAction.Environment[1].Value.ToString());
} }
finally finally
{ {
@@ -250,24 +250,24 @@ namespace GitHub.Runner.Common.Tests.Worker
var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "nodeaction.yml")); var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "nodeaction.yml"));
//Assert //Assert
Assert.Equal(result.Name, "Hello World"); Assert.Equal("Hello World", result.Name);
Assert.Equal(result.Description, "Greet the world and record the time"); Assert.Equal("Greet the world and record the time", result.Description);
Assert.Equal(result.Inputs.Count, 2); Assert.Equal(2, result.Inputs.Count);
Assert.Equal(result.Inputs[0].Key.AssertString("key").Value, "greeting"); Assert.Equal("greeting", result.Inputs[0].Key.AssertString("key").Value);
Assert.Equal(result.Inputs[0].Value.AssertString("value").Value, "Hello"); Assert.Equal("Hello", result.Inputs[0].Value.AssertString("value").Value);
Assert.Equal(result.Inputs[1].Key.AssertString("key").Value, "entryPoint"); Assert.Equal("entryPoint", result.Inputs[1].Key.AssertString("key").Value);
Assert.Equal(result.Inputs[1].Value.AssertString("value").Value, ""); Assert.Equal("", result.Inputs[1].Value.AssertString("value").Value);
Assert.Equal(result.Deprecated.Count, 1); Assert.Equal(1, result.Deprecated.Count);
Assert.True(result.Deprecated.ContainsKey("greeting")); Assert.True(result.Deprecated.ContainsKey("greeting"));
result.Deprecated.TryGetValue("greeting", out string value); result.Deprecated.TryGetValue("greeting", out string value);
Assert.Equal(value, "This property has been deprecated"); Assert.Equal("This property has been deprecated", value);
Assert.Equal(result.Execution.ExecutionType, ActionExecutionType.NodeJS); Assert.Equal(ActionExecutionType.NodeJS, result.Execution.ExecutionType);
var nodeAction = result.Execution as NodeJSActionExecutionData; var nodeAction = result.Execution as NodeJSActionExecutionData;
Assert.Equal(nodeAction.Script, "main.js"); Assert.Equal("main.js", nodeAction.Script);
} }
finally finally
{ {
@@ -292,26 +292,26 @@ namespace GitHub.Runner.Common.Tests.Worker
var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "nodeaction_cleanup.yml")); var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "nodeaction_cleanup.yml"));
//Assert //Assert
Assert.Equal(result.Name, "Hello World"); Assert.Equal("Hello World", result.Name);
Assert.Equal(result.Description, "Greet the world and record the time"); Assert.Equal("Greet the world and record the time", result.Description);
Assert.Equal(result.Inputs.Count, 2); Assert.Equal(2, result.Inputs.Count);
Assert.Equal(result.Inputs[0].Key.AssertString("key").Value, "greeting"); Assert.Equal("greeting", result.Inputs[0].Key.AssertString("key").Value);
Assert.Equal(result.Inputs[0].Value.AssertString("value").Value, "Hello"); Assert.Equal("Hello", result.Inputs[0].Value.AssertString("value").Value);
Assert.Equal(result.Inputs[1].Key.AssertString("key").Value, "entryPoint"); Assert.Equal("entryPoint", result.Inputs[1].Key.AssertString("key").Value);
Assert.Equal(result.Inputs[1].Value.AssertString("value").Value, ""); Assert.Equal("", result.Inputs[1].Value.AssertString("value").Value);
Assert.Equal(result.Deprecated.Count, 1); Assert.Equal(1, result.Deprecated.Count);
Assert.True(result.Deprecated.ContainsKey("greeting")); Assert.True(result.Deprecated.ContainsKey("greeting"));
result.Deprecated.TryGetValue("greeting", out string value); result.Deprecated.TryGetValue("greeting", out string value);
Assert.Equal(value, "This property has been deprecated"); Assert.Equal("This property has been deprecated", value);
Assert.Equal(result.Execution.ExecutionType, ActionExecutionType.NodeJS); Assert.Equal(ActionExecutionType.NodeJS, result.Execution.ExecutionType);
var nodeAction = result.Execution as NodeJSActionExecutionData; var nodeAction = result.Execution as NodeJSActionExecutionData;
Assert.Equal(nodeAction.Script, "main.js"); Assert.Equal("main.js", nodeAction.Script);
Assert.Equal(nodeAction.Cleanup, "cleanup.js"); Assert.Equal("cleanup.js", nodeAction.Cleanup);
Assert.Equal(nodeAction.CleanupCondition, "cancelled()"); Assert.Equal("cancelled()", nodeAction.CleanupCondition);
} }
finally finally
{ {
@@ -336,19 +336,19 @@ namespace GitHub.Runner.Common.Tests.Worker
var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "pluginaction.yml")); var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "pluginaction.yml"));
//Assert //Assert
Assert.Equal(result.Name, "Hello World"); Assert.Equal("Hello World", result.Name);
Assert.Equal(result.Description, "Greet the world and record the time"); Assert.Equal("Greet the world and record the time", result.Description);
Assert.Equal(result.Inputs.Count, 2); Assert.Equal(2, result.Inputs.Count);
Assert.Equal(result.Inputs[0].Key.AssertString("key").Value, "greeting"); Assert.Equal("greeting", result.Inputs[0].Key.AssertString("key").Value);
Assert.Equal(result.Inputs[0].Value.AssertString("value").Value, "Hello"); Assert.Equal("Hello", result.Inputs[0].Value.AssertString("value").Value);
Assert.Equal(result.Inputs[1].Key.AssertString("key").Value, "entryPoint"); Assert.Equal("entryPoint", result.Inputs[1].Key.AssertString("key").Value);
Assert.Equal(result.Inputs[1].Value.AssertString("value").Value, ""); Assert.Equal("", result.Inputs[1].Value.AssertString("value").Value);
Assert.Equal(result.Execution.ExecutionType, ActionExecutionType.Plugin); Assert.Equal(ActionExecutionType.Plugin, result.Execution.ExecutionType);
var pluginAction = result.Execution as PluginActionExecutionData; var pluginAction = result.Execution as PluginActionExecutionData;
Assert.Equal(pluginAction.Plugin, "someplugin"); Assert.Equal("someplugin", pluginAction.Plugin);
} }
finally finally
{ {
@@ -383,9 +383,9 @@ namespace GitHub.Runner.Common.Tests.Worker
var result = actionManifest.EvaluateContainerArguments(_ec.Object, arguments, evaluateContext); var result = actionManifest.EvaluateContainerArguments(_ec.Object, arguments, evaluateContext);
//Assert //Assert
Assert.Equal(result[0], "hello"); Assert.Equal("hello", result[0]);
Assert.Equal(result[1], "test"); Assert.Equal("test", result[1]);
Assert.Equal(result.Count, 2); Assert.Equal(2, result.Count);
} }
finally finally
{ {
@@ -420,9 +420,9 @@ namespace GitHub.Runner.Common.Tests.Worker
var result = actionManifest.EvaluateContainerEnvironment(_ec.Object, environment, evaluateContext); var result = actionManifest.EvaluateContainerEnvironment(_ec.Object, environment, evaluateContext);
//Assert //Assert
Assert.Equal(result["hello"], "hello"); Assert.Equal("hello", result["hello"]);
Assert.Equal(result["test"], "test"); Assert.Equal("test", result["test"]);
Assert.Equal(result.Count, 2); Assert.Equal(2, result.Count);
} }
finally finally
{ {
@@ -459,13 +459,13 @@ namespace GitHub.Runner.Common.Tests.Worker
var result = actionManifest.EvaluateDefaultInput(_ec.Object, "testInput", new StringToken(null, null, null, "defaultValue"), evaluateContext); var result = actionManifest.EvaluateDefaultInput(_ec.Object, "testInput", new StringToken(null, null, null, "defaultValue"), evaluateContext);
//Assert //Assert
Assert.Equal(result, "defaultValue"); Assert.Equal("defaultValue", result);
//Act //Act
result = actionManifest.EvaluateDefaultInput(_ec.Object, "testInput", new BasicExpressionToken(null, null, null, "github.ref"), evaluateContext); result = actionManifest.EvaluateDefaultInput(_ec.Object, "testInput", new BasicExpressionToken(null, null, null, "github.ref"), evaluateContext);
//Assert //Assert
Assert.Equal(result, "refs/heads/master"); Assert.Equal("refs/heads/master", result);
} }
finally finally
{ {

View File

@@ -31,7 +31,6 @@ namespace GitHub.Runner.Common.Tests.Worker
private TestHostContext _hc; private TestHostContext _hc;
private ActionRunner _actionRunner; private ActionRunner _actionRunner;
private IActionManifestManager _actionManifestManager; private IActionManifestManager _actionManifestManager;
private string _workFolder;
private DictionaryContextData _context = new DictionaryContextData(); private DictionaryContextData _context = new DictionaryContextData();
[Fact] [Fact]
@@ -75,9 +74,9 @@ namespace GitHub.Runner.Common.Tests.Worker
} }
//Assert //Assert
Assert.Equal(finialInputs["input1"], "test1"); Assert.Equal("test1", finialInputs["input1"]);
Assert.Equal(finialInputs["input2"], "test2"); Assert.Equal("test2", finialInputs["input2"]);
Assert.Equal(finialInputs["input3"], "github"); Assert.Equal("github", finialInputs["input3"]);
} }
[Fact] [Fact]
@@ -278,24 +277,6 @@ namespace GitHub.Runner.Common.Tests.Worker
Assert.Equal("${{ matrix.node }}", _actionRunner.DisplayName); Assert.Equal("${{ matrix.node }}", _actionRunner.DisplayName);
} }
private void CreateAction(string yamlContent, out Pipelines.ActionStep instance, out string directory)
{
directory = Path.Combine(_workFolder, Constants.Path.ActionsDirectory, "GitHub/actions".Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar), "master");
string file = Path.Combine(directory, Constants.Path.ActionManifestFile);
Directory.CreateDirectory(Path.GetDirectoryName(file));
File.WriteAllText(file, yamlContent);
instance = new Pipelines.ActionStep()
{
Id = Guid.NewGuid(),
Reference = new Pipelines.RepositoryPathReference()
{
Name = "GitHub/actions",
Ref = "master",
RepositoryType = Pipelines.RepositoryTypes.GitHub
}
};
}
private void Setup([CallerMemberName] string name = "") private void Setup([CallerMemberName] string name = "")
{ {
_ecTokenSource?.Dispose(); _ecTokenSource?.Dispose();

View File

@@ -206,8 +206,22 @@ namespace GitHub.Runner.Common.Tests.Worker
var action2 = jobContext.CreateChild(Guid.NewGuid(), "action_2", "action_2", null, null); var action2 = jobContext.CreateChild(Guid.NewGuid(), "action_2", "action_2", null, null);
action2.IntraActionState["state"] = "2"; action2.IntraActionState["state"] = "2";
action1.RegisterPostJobAction("post1", "always()", new Pipelines.ActionStep() { Name = "post1", DisplayName = "Test 1", Reference = new Pipelines.RepositoryPathReference() { Name = "actions/action" } });
action2.RegisterPostJobAction("post2", "always()", new Pipelines.ActionStep() { Name = "post2", DisplayName = "Test 2", Reference = new Pipelines.RepositoryPathReference() { Name = "actions/action" } }); var postRunner1 = hc.CreateService<IActionRunner>();
postRunner1.Action = new Pipelines.ActionStep() { Name = "post1", DisplayName = "Test 1", Reference = new Pipelines.RepositoryPathReference() { Name = "actions/action" } };
postRunner1.Stage = ActionRunStage.Post;
postRunner1.Condition = "always()";
postRunner1.DisplayName = "post1";
var postRunner2 = hc.CreateService<IActionRunner>();
postRunner2.Action = new Pipelines.ActionStep() { Name = "post2", DisplayName = "Test 2", Reference = new Pipelines.RepositoryPathReference() { Name = "actions/action" } };
postRunner2.Stage = ActionRunStage.Post;
postRunner2.Condition = "always()";
postRunner2.DisplayName = "post2";
action1.RegisterPostJobStep("post1", postRunner1);
action2.RegisterPostJobStep("post2", postRunner2);
Assert.NotNull(jobContext.JobSteps); Assert.NotNull(jobContext.JobSteps);
Assert.NotNull(jobContext.PostJobSteps); Assert.NotNull(jobContext.PostJobSteps);

View File

@@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
@@ -158,7 +159,7 @@ namespace GitHub.Runner.Common.Tests.Worker
[Fact] [Fact]
[Trait("Level", "L0")] [Trait("Level", "L0")]
[Trait("Category", "Worker")] [Trait("Category", "Worker")]
public void Code() public void MatcherCode()
{ {
var matchers = new IssueMatchersConfig var matchers = new IssueMatchersConfig
{ {
@@ -300,7 +301,7 @@ namespace GitHub.Runner.Common.Tests.Worker
[Fact] [Fact]
[Trait("Level", "L0")] [Trait("Level", "L0")]
[Trait("Category", "Worker")] [Trait("Category", "Worker")]
public void LineColumn() public void MatcherLineColumn()
{ {
var matchers = new IssueMatchersConfig var matchers = new IssueMatchersConfig
{ {
@@ -348,7 +349,7 @@ namespace GitHub.Runner.Common.Tests.Worker
[Fact] [Fact]
[Trait("Level", "L0")] [Trait("Level", "L0")]
[Trait("Category", "Worker")] [Trait("Category", "Worker")]
public void ProcessCommand() public void MatcherDoesNotReceiveCommand()
{ {
using (Setup()) using (Setup())
using (_outputManager) using (_outputManager)
@@ -382,7 +383,7 @@ namespace GitHub.Runner.Common.Tests.Worker
[Fact] [Fact]
[Trait("Level", "L0")] [Trait("Level", "L0")]
[Trait("Category", "Worker")] [Trait("Category", "Worker")]
public void RemoveColorCodes() public void MatcherRemoveColorCodes()
{ {
using (Setup()) using (Setup())
using (_outputManager) using (_outputManager)
@@ -528,7 +529,7 @@ namespace GitHub.Runner.Common.Tests.Worker
[Fact] [Fact]
[Trait("Level", "L0")] [Trait("Level", "L0")]
[Trait("Category", "Worker")] [Trait("Category", "Worker")]
public void Severity() public void MatcherSeverity()
{ {
var matchers = new IssueMatchersConfig var matchers = new IssueMatchersConfig
{ {
@@ -589,7 +590,7 @@ namespace GitHub.Runner.Common.Tests.Worker
[Fact] [Fact]
[Trait("Level", "L0")] [Trait("Level", "L0")]
[Trait("Category", "Worker")] [Trait("Category", "Worker")]
public void Timeout() public void MatcherTimeout()
{ {
Environment.SetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_ISSUE_MATCHER_TIMEOUT", "0:0:0.01"); Environment.SetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_ISSUE_MATCHER_TIMEOUT", "0:0:0.01");
var matchers = new IssueMatchersConfig var matchers = new IssueMatchersConfig
@@ -640,10 +641,216 @@ namespace GitHub.Runner.Common.Tests.Worker
} }
} }
// todo: roots file against fromPath [Fact]
// todo: roots file against system.defaultWorkingDirectory [Trait("Level", "L0")]
// todo: matches repository [Trait("Category", "Worker")]
// todo: checks file exists public void MatcherFile()
{
var matchers = new IssueMatchersConfig
{
Matchers =
{
new IssueMatcherConfig
{
Owner = "my-matcher-1",
Patterns = new[]
{
new IssuePatternConfig
{
Pattern = @"(.+): (.+)",
File = 1,
Message = 2,
},
},
},
},
};
using (var hostContext = Setup(matchers: matchers))
using (_outputManager)
{
// Setup github.workspace
var workDirectory = hostContext.GetDirectory(WellKnownDirectory.Work);
ArgUtil.NotNullOrEmpty(workDirectory, nameof(workDirectory));
Directory.CreateDirectory(workDirectory);
var workspaceDirectory = Path.Combine(workDirectory, "workspace");
Directory.CreateDirectory(workspaceDirectory);
_executionContext.Setup(x => x.GetGitHubContext("workspace")).Returns(workspaceDirectory);
// Create a test file
Directory.CreateDirectory(Path.Combine(workspaceDirectory, "some-directory"));
var filePath = Path.Combine(workspaceDirectory, "some-directory", "some-file.txt");
File.WriteAllText(filePath, "");
// Process
Process("some-directory/some-file.txt: some error");
Assert.Equal(1, _issues.Count);
Assert.Equal("some error", _issues[0].Item1.Message);
Assert.Equal("some-directory/some-file.txt", _issues[0].Item1.Data["file"]);
Assert.Equal(0, _commands.Count);
Assert.Equal(0, _messages.Count);
}
}
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public void MatcherFileExists()
{
var matchers = new IssueMatchersConfig
{
Matchers =
{
new IssueMatcherConfig
{
Owner = "my-matcher-1",
Patterns = new[]
{
new IssuePatternConfig
{
Pattern = @"(.+): (.+)",
File = 1,
Message = 2,
},
},
},
},
};
using (var hostContext = Setup(matchers: matchers))
using (_outputManager)
{
// Setup github.workspace
var workDirectory = hostContext.GetDirectory(WellKnownDirectory.Work);
ArgUtil.NotNullOrEmpty(workDirectory, nameof(workDirectory));
Directory.CreateDirectory(workDirectory);
var workspaceDirectory = Path.Combine(workDirectory, "workspace");
Directory.CreateDirectory(workspaceDirectory);
_executionContext.Setup(x => x.GetGitHubContext("workspace")).Returns(workspaceDirectory);
// Create a test file
File.WriteAllText(Path.Combine(workspaceDirectory, "some-file-1.txt"), "");
// Process
Process("some-file-1.txt: some error 1"); // file exists
Process("some-file-2.txt: some error 2"); // file does not exist
Assert.Equal(2, _issues.Count);
Assert.Equal("some error 1", _issues[0].Item1.Message);
Assert.Equal("some-file-1.txt", _issues[0].Item1.Data["file"]);
Assert.Equal("some error 2", _issues[1].Item1.Message);
Assert.False(_issues[1].Item1.Data.ContainsKey("file")); // does not contain file key
Assert.Equal(0, _commands.Count);
Assert.Equal(0, _messages.Where(x => !x.StartsWith("##[debug]")).Count());
}
}
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public void MatcherFileOutsideRepository()
{
var matchers = new IssueMatchersConfig
{
Matchers =
{
new IssueMatcherConfig
{
Owner = "my-matcher-1",
Patterns = new[]
{
new IssuePatternConfig
{
Pattern = @"(.+): (.+)",
File = 1,
Message = 2,
},
},
},
},
};
using (var hostContext = Setup(matchers: matchers))
using (_outputManager)
{
// Setup github.workspace
var workDirectory = hostContext.GetDirectory(WellKnownDirectory.Work);
ArgUtil.NotNullOrEmpty(workDirectory, nameof(workDirectory));
Directory.CreateDirectory(workDirectory);
var workspaceDirectory = Path.Combine(workDirectory, "workspace");
Directory.CreateDirectory(workspaceDirectory);
_executionContext.Setup(x => x.GetGitHubContext("workspace")).Returns(workspaceDirectory);
// Create test files
var filePath1 = Path.Combine(workspaceDirectory, "some-file-1.txt");
File.WriteAllText(filePath1, "");
var workspaceSiblingDirectory = Path.Combine(Path.GetDirectoryName(workspaceDirectory), "workspace-sibling");
Directory.CreateDirectory(workspaceSiblingDirectory);
var filePath2 = Path.Combine(workspaceSiblingDirectory, "some-file-2.txt");
File.WriteAllText(filePath2, "");
// Process
Process($"{filePath1}: some error 1"); // file exists inside workspace
Process($"{filePath2}: some error 2"); // file exists outside workspace
Assert.Equal(2, _issues.Count);
Assert.Equal("some error 1", _issues[0].Item1.Message);
Assert.Equal("some-file-1.txt", _issues[0].Item1.Data["file"]);
Assert.Equal("some error 2", _issues[1].Item1.Message);
Assert.False(_issues[1].Item1.Data.ContainsKey("file")); // does not contain file key
Assert.Equal(0, _commands.Count);
Assert.Equal(0, _messages.Where(x => !x.StartsWith("##[debug]")).Count());
}
}
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public void MatcherFromPath()
{
var matchers = new IssueMatchersConfig
{
Matchers =
{
new IssueMatcherConfig
{
Owner = "my-matcher-1",
Patterns = new[]
{
new IssuePatternConfig
{
Pattern = @"(.+): (.+) \[(.+)\]",
File = 1,
Message = 2,
FromPath = 3,
},
},
},
},
};
using (var hostContext = Setup(matchers: matchers))
using (_outputManager)
{
// Setup github.workspace
var workDirectory = hostContext.GetDirectory(WellKnownDirectory.Work);
ArgUtil.NotNullOrEmpty(workDirectory, nameof(workDirectory));
Directory.CreateDirectory(workDirectory);
var workspaceDirectory = Path.Combine(workDirectory, "workspace");
Directory.CreateDirectory(workspaceDirectory);
_executionContext.Setup(x => x.GetGitHubContext("workspace")).Returns(workspaceDirectory);
// Create a test file
Directory.CreateDirectory(Path.Combine(workspaceDirectory, "some-directory"));
Directory.CreateDirectory(Path.Combine(workspaceDirectory, "some-project", "some-directory"));
var filePath = Path.Combine(workspaceDirectory, "some-project", "some-directory", "some-file.txt");
File.WriteAllText(filePath, "");
// Process
Process("some-directory/some-file.txt: some error [some-project/some-project.proj]");
Assert.Equal(1, _issues.Count);
Assert.Equal("some error", _issues[0].Item1.Message);
Assert.Equal("some-project/some-directory/some-file.txt", _issues[0].Item1.Data["file"]);
Assert.Equal(0, _commands.Count);
Assert.Equal(0, _messages.Count);
}
}
private TestHostContext Setup( private TestHostContext Setup(
[CallerMemberName] string name = "", [CallerMemberName] string name = "",

View File

@@ -150,7 +150,7 @@ namespace GitHub.Runner.Common.Tests.Worker
string actual = variables.Get("no such"); string actual = variables.Get("no such");
// Assert. // Assert.
Assert.Equal(null, actual); Assert.Null(actual);
} }
} }

View File

@@ -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>
@@ -29,42 +29,4 @@
<DebugType>portable</DebugType> <DebugType>portable</DebugType>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x64'">
<DefineConstants>OS_WINDOWS;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x86'">
<DefineConstants>OS_WINDOWS;X86;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x64'">
<DefineConstants>OS_WINDOWS;X64;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x86'">
<DefineConstants>OS_WINDOWS;X86;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">
<DefineConstants>OS_OSX;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true' AND '$(Configuration)' == 'Debug'">
<DefineConstants>OS_OSX;DEBUG;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-x64'">
<DefineConstants>OS_LINUX;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'rhel.6-x64'">
<DefineConstants>OS_LINUX;OS_RHEL6;X64;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-arm'">
<DefineConstants>OS_LINUX;ARM;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-x64'">
<DefineConstants>OS_LINUX;X64;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'rhel.6-x64'">
<DefineConstants>OS_LINUX;OS_RHEL6;X64;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-arm'">
<DefineConstants>OS_LINUX;ARM;DEBUG;TRACE</DefineConstants>
</PropertyGroup>
</Project> </Project>

View File

@@ -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)
@@ -208,8 +208,6 @@ fi
echo "Prepend ${DOTNETSDK_INSTALLDIR} to %PATH%" echo "Prepend ${DOTNETSDK_INSTALLDIR} to %PATH%"
export PATH=${DOTNETSDK_INSTALLDIR}:$PATH export PATH=${DOTNETSDK_INSTALLDIR}:$PATH
heading "Github Dreamlifter Runner"
heading "Dotnet SDK Version" heading "Dotnet SDK Version"
dotnet --version dotnet --version

View File

@@ -1,5 +1,5 @@
{ {
"sdk": { "sdk": {
"version": "2.2.300" "version": "3.0.100"
} }
} }

View File

@@ -1 +1 @@
2.159.2 2.159.9