Compare commits

..

4 Commits

Author SHA1 Message Date
Julio Barba
f9ce10da6d Release 2.282.1 runner 2021-09-15 14:00:06 -04:00
Julio Barba
c3649406e8 Prepare 2.282.1 release (#1345)
* Revert "Recreate VssConnection on retry (#1316)" (#1343)

This reverts commit 4359dd605b.

* Prepare 2.282.1 release
2021-09-15 13:49:24 -04:00
Patrick Ellis
f954835f54 Update releaseVersion to 2.282.0 2021-09-13 14:12:48 -04:00
Patrick Ellis
512cd2b4f8 Release 2.282.0 2021-09-13 14:08:46 -04:00
86 changed files with 379 additions and 1219 deletions

View File

@@ -1,8 +0,0 @@
# https://editorconfig.org/
[*]
insert_final_newline = true # ensure all files end with a single newline
trim_trailing_whitespace = true # attempt to remove trailing whitespace on save
[*.md]
trim_trailing_whitespace = false # in markdown, "two trailing spaces" is unfortunately meaningful; it means `<br>`

View File

@@ -5,7 +5,7 @@
# GitHub Actions Runner # GitHub Actions Runner
[![Actions Status](https://github.com/actions/runner/workflows/Runner%20CI/badge.svg)](https://github.com/actions/runner/actions) [![Actions Status](https://github.com/actions/runner/workflows/Runner%20CI/badge.svg)](https://github.com/actions/runner/actions)
[![Runner E2E Test](https://github.com/actions-canary/actions-runner-e2e/actions/workflows/runner_e2etest.yml/badge.svg)](https://github.com/actions-canary/actions-runner-e2e/actions/workflows/runner_e2etest.yml) [![Runner E2E Test](https://github.com/actions/runner/workflows/Runner%20E2E%20Test/badge.svg)](https://github.com/actions/runner/actions)
The runner is the application that runs a job from a GitHub Actions workflow. It is used by GitHub Actions in the [hosted virtual environments](https://github.com/actions/virtual-environments), or you can [self-host the runner](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/about-self-hosted-runners) in your own environment. The runner is the application that runs a job from a GitHub Actions workflow. It is used by GitHub Actions in the [hosted virtual environments](https://github.com/actions/virtual-environments), or you can [self-host the runner](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/about-self-hosted-runners) in your own environment.

View File

@@ -1,71 +0,0 @@
# ADR 1438: Support Conditionals In Composite Actions
**Date**: 2021-10-13
**Status**: Accepted
## Context
We recently shipped composite actions, which allows you to reuse individual steps inside an action.
However, one of the [most requested features](https://github.com/actions/runner/issues/834) has been a way to support the `if` keyword.
### Goals
- We want to keep consistent with current behavior
- We want to support conditionals via the `if` keyword
- Our built in functions like `success` should be implementable without calling them, for example you can do `job.status == success` rather then `success()` currently.
### How does composite currently work?
Currently, we have limited conditional support in composite actions for `pre` and `post` steps.
These are based on the `job status`, and support keywords like `always()`, `failed()`, `success()` and `cancelled()`.
However, generic or main steps do **not** support conditionals.
By default, in a regular workflow, a step runs on the `success()` condition. Which looks at the **job** **status**, sees if it is successful and runs.
By default, in a composite action, main steps run until a single step fails in that composite action, then the composite action is halted early. It does **not** care about the job status.
Pre, and post steps in composite actions use the job status to determine if they should run.
### How do we go forward?
Well, if we think about what composite actions are currently doing when invoking main steps, they are checking if the current composite action is successful.
Lets formalize that concept into a "real" idea.
- We will add an `action_status` field to the github context to mimic the [job's context status](https://docs.github.com/en/actions/learn-github-actions/contexts#job-context).
- We have an existing concept that does this `action_path` which is only set for composite actions on the github context.
- In a composite action during a main step, the `success()` function will check if `action_status == success`, rather then `job_status == success`. Failure will work the same way.
- Pre and post steps in composite actions will not change, they will continue to check the job status.
### Nested Scenario
For nested composite actions, we will follow the existing behavior, you only care about your current composite action, not any parents.
For example, lets imagine a scenario with a simple nested composite action
```
- Job
- Regular Step
- Composite Action
- runs: exit 1
- if: always()
uses: A child composite action
- if: success()
runs: echo "this should print"
- runs: echo "this should also print"
- if: success()
runs: echo "this will not print as the current composite action has failed already"
```
The child composite actions steps should run in this example, the child composite action has not yet failed, so it should run all steps until a step fails. This is consistent with how a composite action currently works in production if the main job fails but a composite action is invoked with `if:always()` or `if: failure()`
### Other options explored
We could add the `current_step_status` to the job context rather then `__status` to the steps context, however this comes with two major downsides:
- We need to support the field for every type of step, because its non trivial to remove a field from the job context once it has been added (its readonly)
- For all actions besides composite it would only every be `success`
- Its weird to have a `current_step` value on the job context
- We also explored a `__status` on the steps context.
- The `__` is required to prevent us from colliding with a step with id: status
- This felt wrong because the naming was not smooth, and did not fit into current conventions.
### Consequences
- github context has a new field for the status of the current composite action.
- We support conditional's in composite actions
- We keep the existing behavior for all users, but allow them to expand that functionality.

View File

@@ -55,7 +55,6 @@ If you are having trouble connecting, try these steps:
- You may need to configure your TLS settings to use the correct version - You may need to configure your TLS settings to use the correct version
- You should support TLS version 1.2 or later - You should support TLS version 1.2 or later
- You may need to configure your TLS settings to have up to date cipher suites, this may be solved by system updates and patches. - You may need to configure your TLS settings to have up to date cipher suites, this may be solved by system updates and patches.
- Most notably, on windows server 2012 make sure [the tls cipher suite update](https://support.microsoft.com/en-us/topic/update-adds-new-tls-cipher-suites-and-changes-cipher-suite-priorities-in-windows-8-1-and-windows-server-2012-r2-8e395e43-c8ef-27d8-b60c-0fc57d526d94) is installed
- Your firewall, proxy or network configuration may be blocking the connection - Your firewall, proxy or network configuration may be blocking the connection
- You will want to reach out to whoever is in charge of your network with these pcap files to further troubleshoot - You will want to reach out to whoever is in charge of your network with these pcap files to further troubleshoot
- If you see a failure later in the handshake: - If you see a failure later in the handshake:

View File

@@ -1,19 +1,14 @@
## Features ## Features
- Expose GITHUB_REF_* as environment variable (#1314) N/A
- Add arch to runner context (#1372)
- Support Conditional Steps in Composite Actions (#1438)
- Log current runner version in terminal (#1441)
## Bugs ## Bugs
- Makes the user keychains available to the service (#847) - Revert "More resilient VssConnection client retries in JobServer" (#1343)
- Use Actions Service health and api.github.com endpoints after connection failure on Actions Server and Hosted (#1385)
- Fix an issue where nested local composite actions did not correctly register post steps (#1433)
## Misc ## Misc
- Cleanup Older versions on MacOS now that we recreate node versions as needed (#1410) N/A
## Windows x64 ## Windows x64
We recommend configuring the runner in a root folder of the Windows drive (e.g. "C:\actions-runner"). This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows. We recommend configuring the runner in a root folder of the Windows drive (e.g. "C:\actions-runner"). This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows.

View File

@@ -1 +1 @@
<Update to ./src/runnerversion when creating release> 2.282.1

View File

@@ -25,7 +25,5 @@
</dict> </dict>
<key>ProcessType</key> <key>ProcessType</key>
<string>Interactive</string> <string>Interactive</string>
<key>SessionCreate</key>
<true/>
</dict> </dict>
</plist> </plist>

View File

@@ -18,8 +18,6 @@ downloadrunnerversion=_DOWNLOAD_RUNNER_VERSION_
logfile="_UPDATE_LOG_" logfile="_UPDATE_LOG_"
restartinteractiverunner=_RESTART_INTERACTIVE_RUNNER_ restartinteractiverunner=_RESTART_INTERACTIVE_RUNNER_
telemetryfile="$rootfolder/_diag/.telemetry"
# log user who run the script # log user who run the script
date "+[%F %T-%4N] --------whoami--------" >> "$logfile" 2>&1 date "+[%F %T-%4N] --------whoami--------" >> "$logfile" 2>&1
whoami >> "$logfile" 2>&1 whoami >> "$logfile" 2>&1
@@ -120,55 +118,40 @@ then
exit 1 exit 1
fi fi
# fix upgrade issue with macOS when running as a service # fix upgrade issue with macOS
attemptedtargetedfix=0
currentplatform=$(uname | awk '{print tolower($0)}') currentplatform=$(uname | awk '{print tolower($0)}')
if [[ "$currentplatform" == 'darwin' && restartinteractiverunner -eq 0 ]]; then if [[ "$currentplatform" == 'darwin' ]]; then
# We needed a fix for https://github.com/actions/runner/issues/743 # need a short-term fix for https://github.com/actions/runner/issues/743
# We will recreate the ./externals/node12/bin/node of the past runner version that launched the runnerlistener service # we will recreate all the ./externals/node12/bin/node of the past 5 versions
# Otherwise mac gatekeeper kills the processes we spawn on creation as we are running a process with no backing file # v2.280.3 v2.280.2 v2.280.1 v2.279.0 v2.278.0
if [[ ! -e "$rootfolder/externals.2.280.3/node12/bin/node" ]]
# We need the pid for the nodejs loop, get that here, its the parent of the runner C# pid
# assumption here is only one process is invoking rootfolder/runsvc.sh
procgroup=$(ps x -o pgid,command | grep "$rootfolder/runsvc.sh" | grep -v grep | awk '{print $1}')
if [[ $? -eq 0 && -n "$procgroup" ]]
then then
# inspect the open file handles to find the node process mkdir -p "$rootfolder/externals.2.280.3/node12/bin"
# we can't actually inspect the process using ps because it uses relative paths and doesn't follow symlinks cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.280.3/node12/bin/node"
path=$(lsof -a -g "$procgroup" -F n | grep node12/bin/node | grep externals | tail -1 | cut -c2-) fi
if [[ $? -eq 0 && -n "$path" ]]
then if [[ ! -e "$rootfolder/externals.2.280.2/node12/bin/node" ]]
# trim the last 5 characters of the path '/node' then
trimmedpath=$(dirname "$path") mkdir -p "$rootfolder/externals.2.280.2/node12/bin"
if [[ $? -eq 0 && -n "$trimmedpath" ]] cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.280.2/node12/bin/node"
then fi
attemptedtargetedfix=1
# Create the path if it does not exist if [[ ! -e "$rootfolder/externals.2.280.1/node12/bin/node" ]]
if [[ ! -e "$path" ]] then
then mkdir -p "$rootfolder/externals.2.280.1/node12/bin"
date "+[%F %T-%4N] Creating fallback node at path $path" >> "$logfile" 2>&1 cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.280.1/node12/bin/node"
mkdir -p "$trimmedpath" fi
cp "$rootfolder/externals/node12/bin/node" "$path"
else if [[ ! -e "$rootfolder/externals.2.279.0/node12/bin/node" ]]
date "+[%F %T-%4N] Path for fallback node exists, skipping creating $path" >> "$logfile" 2>&1 then
fi mkdir -p "$rootfolder/externals.2.279.0/node12/bin"
else cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.279.0/node12/bin/node"
date "+[%F %T-%4N] DarwinRunnerUpgrade: Failed to trim runner path. TrimmedPath: $trimmedpath, path: $path, pgid: $procgroup, root: $rootfolder" >> "$logfile" 2>&1 fi
date "+[%F %T-%4N] DarwinRunnerUpgrade: Failed to trim runner path. TrimmedPath: $trimmedpath, path: $path, pgid: $procgroup, root: $rootfolder" >> "$telemetryfile" 2>&1
fi if [[ ! -e "$rootfolder/externals.2.278.0/node12/bin/node" ]]
else then
date "+[%F %T-%4N] DarwinRunnerUpgrade: Failed to find runner path. Path: $path, pgid: $procgroup, root: $rootfolder" >> "$logfile" 2>&1 mkdir -p "$rootfolder/externals.2.278.0/node12/bin"
date "+[%F %T-%4N] DarwinRunnerUpgrade: Failed to find runner path. Path: $path, pgid: $procgroup, root: $rootfolder" >> "$telemetryfile" 2>&1 cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.278.0/node12/bin/node"
fi
else
runproc=$(ps x -o pgid,command | grep "run.sh" | grep -v grep | awk '{print $1}')
if [[ $? -eq 0 && -n "$runproc" ]]
then
date "+[%F %T-%4N] Running as ephemeral using run.sh, no need to recreate node folder" >> "$logfile" 2>&1
else
date "+[%F %T-%4N] DarwinRunnerUpgrade: Failed to find runner pgid. pgid: $procgroup, root: $rootfolder" >> "$logfile" 2>&1
date "+[%F %T-%4N] DarwinRunnerUpgrade: Failed to find runner pgid. pgid: $procgroup, root: $rootfolder" >> "$telemetryfile" 2>&1
fi
fi fi
fi fi

View File

@@ -43,21 +43,6 @@ else
else else
sleep 5 sleep 5
fi fi
elif [[ $returnCode == 4 ]]; then
if [ ! -x "$(command -v sleep)" ]; then
if [ ! -x "$(command -v ping)" ]; then
COUNT="0"
while [[ $COUNT != 5000 ]]; do
echo "SLEEP" > /dev/null
COUNT=$[$COUNT+1]
done
else
ping -c 5 127.0.0.1 > /dev/null
fi
else
sleep 5
fi
"$DIR"/bin/Runner.Listener run $*
else else
exit $returnCode exit $returnCode
fi fi

View File

@@ -26,7 +26,6 @@ namespace GitHub.Runner.Common
Certificates, Certificates,
Options, Options,
SetupInfo, SetupInfo,
Telemetry
} }
public static class Constants public static class Constants
@@ -129,7 +128,7 @@ namespace GitHub.Runner.Common
public static readonly string Ephemeral = "ephemeral"; public static readonly string Ephemeral = "ephemeral";
public static readonly string Help = "help"; public static readonly string Help = "help";
public static readonly string Replace = "replace"; public static readonly string Replace = "replace";
public static readonly string Once = "once"; // Keep this around since customers still relies on it public static readonly string Once = "once"; // TODO: Remove in 10/2021
public static readonly string RunAsService = "runasservice"; public static readonly string RunAsService = "runasservice";
public static readonly string Unattended = "unattended"; public static readonly string Unattended = "unattended";
public static readonly string Version = "version"; public static readonly string Version = "version";
@@ -155,7 +154,6 @@ namespace GitHub.Runner.Common
public static readonly string LowDiskSpace = "LOW_DISK_SPACE"; public static readonly string LowDiskSpace = "LOW_DISK_SPACE";
public static readonly string UnsupportedCommand = "UNSUPPORTED_COMMAND"; public static readonly string UnsupportedCommand = "UNSUPPORTED_COMMAND";
public static readonly string UnsupportedCommandMessageDisabled = "The `{0}` command is disabled. Please upgrade to using Environment Files or opt into unsecure command execution by setting the `ACTIONS_ALLOW_UNSECURE_COMMANDS` environment variable to `true`. For more information see: https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/"; public static readonly string UnsupportedCommandMessageDisabled = "The `{0}` command is disabled. Please upgrade to using Environment Files or opt into unsecure command execution by setting the `ACTIONS_ALLOW_UNSECURE_COMMANDS` environment variable to `true`. For more information see: https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/";
public static readonly string UnsupportedStopCommandTokenDisabled = "You cannot use a endToken that is an empty string, the string 'pause-logging', or another workflow command. For more information see: https://docs.github.com/en/actions/learn-github-actions/workflow-commands-for-github-actions#example-stopping-and-starting-workflow-commands or opt into insecure command execution by setting the `ACTIONS_ALLOW_UNSECURE_STOPCOMMAND_TOKENS` environment variable to `true`.";
} }
public static class RunnerEvent public static class RunnerEvent
@@ -215,7 +213,6 @@ namespace GitHub.Runner.Common
// Keep alphabetical // Keep alphabetical
// //
public static readonly string AllowUnsupportedCommands = "ACTIONS_ALLOW_UNSECURE_COMMANDS"; public static readonly string AllowUnsupportedCommands = "ACTIONS_ALLOW_UNSECURE_COMMANDS";
public static readonly string AllowUnsupportedStopCommandTokens = "ACTIONS_ALLOW_UNSECURE_STOPCOMMAND_TOKENS";
public static readonly string RunnerDebug = "ACTIONS_RUNNER_DEBUG"; public static readonly string RunnerDebug = "ACTIONS_RUNNER_DEBUG";
public static readonly string StepDebug = "ACTIONS_STEP_DEBUG"; public static readonly string StepDebug = "ACTIONS_STEP_DEBUG";
} }

View File

@@ -343,12 +343,6 @@ namespace GitHub.Runner.Common
".setup_info"); ".setup_info");
break; break;
case WellKnownConfigFile.Telemetry:
path = Path.Combine(
GetDirectory(WellKnownDirectory.Diag),
".telemetry");
break;
default: default:
throw new NotSupportedException($"Unexpected well known config file: '{configFile}'"); throw new NotSupportedException($"Unexpected well known config file: '{configFile}'");
} }

View File

@@ -2,11 +2,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Net.Http;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GitHub.Runner.Sdk;
using GitHub.Services.Common;
using GitHub.Services.WebApi; using GitHub.Services.WebApi;
namespace GitHub.Runner.Common namespace GitHub.Runner.Common
@@ -38,11 +35,7 @@ namespace GitHub.Runner.Common
public async Task ConnectAsync(VssConnection jobConnection) public async Task ConnectAsync(VssConnection jobConnection)
{ {
_connection = jobConnection; _connection = jobConnection;
int totalAttempts = 5; int attemptCount = 5;
int attemptCount = totalAttempts;
var configurationStore = HostContext.GetService<IConfigurationStore>();
var runnerSettings = configurationStore.GetSettings();
while (!_connection.HasAuthenticated && attemptCount-- > 0) while (!_connection.HasAuthenticated && attemptCount-- > 0)
{ {
try try
@@ -52,71 +45,17 @@ namespace GitHub.Runner.Common
} }
catch (Exception ex) when (attemptCount > 0) catch (Exception ex) when (attemptCount > 0)
{ {
Trace.Info($"Catch exception during connect. {attemptCount} attempts left."); Trace.Info($"Catch exception during connect. {attemptCount} attemp left.");
Trace.Error(ex); Trace.Error(ex);
if (runnerSettings.IsHostedServer)
{
await CheckNetworkEndpointsAsync(attemptCount);
}
} }
int attempt = totalAttempts - attemptCount; await Task.Delay(100);
TimeSpan backoff = BackoffTimerHelper.GetExponentialBackoff(attempt, TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(3.2), TimeSpan.FromMilliseconds(100));
await Task.Delay(backoff);
} }
_taskClient = _connection.GetClient<TaskHttpClient>(); _taskClient = _connection.GetClient<TaskHttpClient>();
_hasConnection = true; _hasConnection = true;
} }
private async Task CheckNetworkEndpointsAsync(int attemptsLeft)
{
try
{
Trace.Info("Requesting Actions Service health endpoint status");
using (var httpClientHandler = HostContext.CreateHttpClientHandler())
using (var actionsClient = new HttpClient(httpClientHandler))
{
var baseUri = new Uri(_connection.Uri.GetLeftPart(UriPartial.Authority));
actionsClient.DefaultRequestHeaders.UserAgent.AddRange(HostContext.UserAgents);
// Call the _apis/health endpoint, and include how many attempts are left as a URL query for easy tracking
var response = await actionsClient.GetAsync(new Uri(baseUri, $"_apis/health?_internalRunnerAttemptsLeft={attemptsLeft}"));
Trace.Info($"Actions health status code: {response.StatusCode}");
}
}
catch (Exception ex)
{
// Log error, but continue as this call is best-effort
Trace.Info($"Actions Service health endpoint failed due to {ex.GetType().Name}");
Trace.Error(ex);
}
try
{
Trace.Info("Requesting Github API endpoint status");
// This is a dotcom public API... just call it directly
using (var httpClientHandler = HostContext.CreateHttpClientHandler())
using (var gitHubClient = new HttpClient(httpClientHandler))
{
gitHubClient.DefaultRequestHeaders.UserAgent.AddRange(HostContext.UserAgents);
// Call the api.github.com endpoint, and include how many attempts are left as a URL query for easy tracking
var response = await gitHubClient.GetAsync($"https://api.github.com?_internalRunnerAttemptsLeft={attemptsLeft}");
Trace.Info($"api.github.com status code: {response.StatusCode}");
}
}
catch (Exception ex)
{
// Log error, but continue as this call is best-effort
Trace.Info($"Github API endpoint failed due to {ex.GetType().Name}");
Trace.Error(ex);
}
}
private void CheckConnection() private void CheckConnection()
{ {
if (!_hasConnection) if (!_hasConnection)

View File

@@ -1,10 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
<NoWarn>NU1701;NU1603</NoWarn> <NoWarn>NU1701;NU1603</NoWarn>
<Version>$(Version)</Version> <Version>$(Version)</Version>
<TieredCompilationQuickJit>true</TieredCompilationQuickJit> <TieredCompilationQuickJit>true</TieredCompilationQuickJit>

View File

@@ -29,10 +29,8 @@ namespace GitHub.Runner.Common
// Configuration // Configuration
Task<TaskAgent> AddAgentAsync(Int32 agentPoolId, TaskAgent agent); Task<TaskAgent> AddAgentAsync(Int32 agentPoolId, TaskAgent agent);
Task DeleteAgentAsync(int agentPoolId, int agentId); Task DeleteAgentAsync(int agentPoolId, int agentId);
Task DeleteAgentAsync(int agentId);
Task<List<TaskAgentPool>> GetAgentPoolsAsync(string agentPoolName = null, TaskAgentPoolType poolType = TaskAgentPoolType.Automation); Task<List<TaskAgentPool>> GetAgentPoolsAsync(string agentPoolName = null, TaskAgentPoolType poolType = TaskAgentPoolType.Automation);
Task<List<TaskAgent>> GetAgentsAsync(int agentPoolId, string agentName = null); Task<List<TaskAgent>> GetAgentsAsync(int agentPoolId, string agentName = null);
Task<List<TaskAgent>> GetAgentsAsync(string agentName);
Task<TaskAgent> ReplaceAgentAsync(int agentPoolId, TaskAgent agent); Task<TaskAgent> ReplaceAgentAsync(int agentPoolId, TaskAgent agent);
// messagequeue // messagequeue
@@ -254,11 +252,6 @@ namespace GitHub.Runner.Common
return _genericTaskAgentClient.GetAgentsAsync(agentPoolId, agentName, false); return _genericTaskAgentClient.GetAgentsAsync(agentPoolId, agentName, false);
} }
public Task<List<TaskAgent>> GetAgentsAsync(string agentName)
{
return GetAgentsAsync(0, agentName); // search in all all agentPools
}
public Task<TaskAgent> ReplaceAgentAsync(int agentPoolId, TaskAgent agent) public Task<TaskAgent> ReplaceAgentAsync(int agentPoolId, TaskAgent agent)
{ {
CheckConnection(RunnerConnectionType.Generic); CheckConnection(RunnerConnectionType.Generic);
@@ -271,11 +264,6 @@ namespace GitHub.Runner.Common
return _genericTaskAgentClient.DeleteAgentAsync(agentPoolId, agentId); return _genericTaskAgentClient.DeleteAgentAsync(agentPoolId, agentId);
} }
public Task DeleteAgentAsync(int agentId)
{
return DeleteAgentAsync(0, agentId); // agentPool is ignored server side
}
//----------------------------------------------------------------- //-----------------------------------------------------------------
// MessageQueue // MessageQueue
//----------------------------------------------------------------- //-----------------------------------------------------------------

View File

@@ -31,7 +31,6 @@ namespace GitHub.Runner.Listener
Constants.Runner.CommandLine.Flags.Commit, Constants.Runner.CommandLine.Flags.Commit,
Constants.Runner.CommandLine.Flags.Ephemeral, Constants.Runner.CommandLine.Flags.Ephemeral,
Constants.Runner.CommandLine.Flags.Help, Constants.Runner.CommandLine.Flags.Help,
Constants.Runner.CommandLine.Flags.Once,
Constants.Runner.CommandLine.Flags.Replace, Constants.Runner.CommandLine.Flags.Replace,
Constants.Runner.CommandLine.Flags.RunAsService, Constants.Runner.CommandLine.Flags.RunAsService,
Constants.Runner.CommandLine.Flags.Unattended, Constants.Runner.CommandLine.Flags.Unattended,
@@ -69,7 +68,7 @@ namespace GitHub.Runner.Listener
public bool Version => TestFlag(Constants.Runner.CommandLine.Flags.Version); public bool Version => TestFlag(Constants.Runner.CommandLine.Flags.Version);
public bool Ephemeral => TestFlag(Constants.Runner.CommandLine.Flags.Ephemeral); public bool Ephemeral => TestFlag(Constants.Runner.CommandLine.Flags.Ephemeral);
// Keep this around since customers still relies on it // TODO: Remove in 10/2021
public bool RunOnce => TestFlag(Constants.Runner.CommandLine.Flags.Once); public bool RunOnce => TestFlag(Constants.Runner.CommandLine.Flags.Once);
// Constructor. // Constructor.
@@ -243,7 +242,6 @@ namespace GitHub.Runner.Listener
validator: Validators.ServerUrlValidator); validator: Validators.ServerUrlValidator);
} }
#if OS_WINDOWS
public string GetWindowsLogonAccount(string defaultValue, string descriptionMsg) public string GetWindowsLogonAccount(string defaultValue, string descriptionMsg)
{ {
return GetArgOrPrompt( return GetArgOrPrompt(
@@ -252,7 +250,6 @@ namespace GitHub.Runner.Listener
defaultValue: defaultValue, defaultValue: defaultValue,
validator: Validators.NTAccountValidator); validator: Validators.NTAccountValidator);
} }
#endif
public string GetWindowsLogonPassword(string accountName) public string GetWindowsLogonPassword(string accountName)
{ {

View File

@@ -22,7 +22,6 @@ namespace GitHub.Runner.Listener.Configuration
bool IsConfigured(); bool IsConfigured();
Task ConfigureAsync(CommandSettings command); Task ConfigureAsync(CommandSettings command);
Task UnconfigureAsync(CommandSettings command); Task UnconfigureAsync(CommandSettings command);
void DeleteLocalRunnerConfig();
RunnerSettings LoadSettings(); RunnerSettings LoadSettings();
} }
@@ -330,38 +329,6 @@ namespace GitHub.Runner.Listener.Configuration
#endif #endif
} }
// Delete .runner and .credentials files
public void DeleteLocalRunnerConfig()
{
bool isConfigured = _store.IsConfigured();
bool hasCredentials = _store.HasCredentials();
//delete credential config files
var currentAction = "Removing .credentials";
if (hasCredentials)
{
_store.DeleteCredential();
var keyManager = HostContext.GetService<IRSAKeyManager>();
keyManager.DeleteKey();
_term.WriteSuccessMessage("Removed .credentials");
}
else
{
_term.WriteLine("Does not exist. Skipping " + currentAction);
}
//delete settings config file
currentAction = "Removing .runner";
if (isConfigured)
{
_store.DeleteSettings();
_term.WriteSuccessMessage("Removed .runner");
}
else
{
_term.WriteLine("Does not exist. Skipping " + currentAction);
}
}
public async Task UnconfigureAsync(CommandSettings command) public async Task UnconfigureAsync(CommandSettings command)
{ {
string currentAction = string.Empty; string currentAction = string.Empty;
@@ -415,7 +382,7 @@ namespace GitHub.Runner.Listener.Configuration
// Determine the service deployment type based on connection data. (Hosted/OnPremises) // Determine the service deployment type based on connection data. (Hosted/OnPremises)
await _runnerServer.ConnectAsync(new Uri(settings.ServerUrl), creds); await _runnerServer.ConnectAsync(new Uri(settings.ServerUrl), creds);
var agents = await _runnerServer.GetAgentsAsync(settings.AgentName); var agents = await _runnerServer.GetAgentsAsync(settings.PoolId, settings.AgentName);
Trace.Verbose("Returns {0} agents", agents.Count); Trace.Verbose("Returns {0} agents", agents.Count);
TaskAgent agent = agents.FirstOrDefault(); TaskAgent agent = agents.FirstOrDefault();
if (agent == null) if (agent == null)
@@ -424,7 +391,7 @@ namespace GitHub.Runner.Listener.Configuration
} }
else else
{ {
await _runnerServer.DeleteAgentAsync(settings.AgentId); await _runnerServer.DeleteAgentAsync(settings.PoolId, settings.AgentId);
_term.WriteLine(); _term.WriteLine();
_term.WriteSuccessMessage("Runner removed successfully"); _term.WriteSuccessMessage("Runner removed successfully");
@@ -435,7 +402,31 @@ namespace GitHub.Runner.Listener.Configuration
_term.WriteLine("Cannot connect to server, because config files are missing. Skipping removing runner from the server."); _term.WriteLine("Cannot connect to server, because config files are missing. Skipping removing runner from the server.");
} }
DeleteLocalRunnerConfig(); //delete credential config files
currentAction = "Removing .credentials";
if (hasCredentials)
{
_store.DeleteCredential();
var keyManager = HostContext.GetService<IRSAKeyManager>();
keyManager.DeleteKey();
_term.WriteSuccessMessage("Removed .credentials");
}
else
{
_term.WriteLine("Does not exist. Skipping " + currentAction);
}
//delete settings config file
currentAction = "Removing .runner";
if (isConfigured)
{
_store.DeleteSettings();
_term.WriteSuccessMessage("Removed .runner");
}
else
{
_term.WriteLine("Does not exist. Skipping " + currentAction);
}
} }
catch (Exception) catch (Exception)
{ {

View File

@@ -67,7 +67,6 @@ namespace GitHub.Runner.Listener.Configuration
return !string.IsNullOrEmpty(value); return !string.IsNullOrEmpty(value);
} }
#if OS_WINDOWS
public static bool NTAccountValidator(string arg) public static bool NTAccountValidator(string arg)
{ {
if (string.IsNullOrEmpty(arg) || String.IsNullOrEmpty(arg.TrimStart('.', '\\'))) if (string.IsNullOrEmpty(arg) || String.IsNullOrEmpty(arg.TrimStart('.', '\\')))
@@ -88,6 +87,5 @@ namespace GitHub.Runner.Listener.Configuration
return true; return true;
} }
#endif
} }
} }

View File

@@ -36,10 +36,7 @@ namespace GitHub.Runner.Listener
{ {
private readonly Lazy<Dictionary<long, TaskResult>> _localRunJobResult = new Lazy<Dictionary<long, TaskResult>>(); private readonly Lazy<Dictionary<long, TaskResult>> _localRunJobResult = new Lazy<Dictionary<long, TaskResult>>();
private int _poolId; private int _poolId;
RunnerSettings _runnerSetting;
IConfigurationStore _configurationStore;
RunnerSettings _runnerSettings;
private static readonly string _workerProcessName = $"Runner.Worker{IOUtil.ExeExtension}"; private static readonly string _workerProcessName = $"Runner.Worker{IOUtil.ExeExtension}";
// this is not thread-safe // this is not thread-safe
@@ -57,9 +54,9 @@ namespace GitHub.Runner.Listener
base.Initialize(hostContext); base.Initialize(hostContext);
// get pool id from config // get pool id from config
_configurationStore = hostContext.GetService<IConfigurationStore>(); var configurationStore = hostContext.GetService<IConfigurationStore>();
_runnerSettings = _configurationStore.GetSettings(); _runnerSetting = configurationStore.GetSettings();
_poolId = _runnerSettings.PoolId; _poolId = _runnerSetting.PoolId;
int channelTimeoutSeconds; int channelTimeoutSeconds;
if (!int.TryParse(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_CHANNEL_TIMEOUT") ?? string.Empty, out channelTimeoutSeconds)) if (!int.TryParse(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_CHANNEL_TIMEOUT") ?? string.Empty, out channelTimeoutSeconds))
@@ -664,15 +661,13 @@ namespace GitHub.Runner.Listener
try try
{ {
request = await runnerServer.RenewAgentRequestAsync(poolId, requestId, lockToken, orchestrationId, token); request = await runnerServer.RenewAgentRequestAsync(poolId, requestId, lockToken, orchestrationId, token);
Trace.Info($"Successfully renew job request {requestId}, job is valid till {request.LockedUntil.Value}"); Trace.Info($"Successfully renew job request {requestId}, job is valid till {request.LockedUntil.Value}");
if (!firstJobRequestRenewed.Task.IsCompleted) if (!firstJobRequestRenewed.Task.IsCompleted)
{ {
// fire first renew succeed event. // fire first renew succeed event.
firstJobRequestRenewed.TrySetResult(0); firstJobRequestRenewed.TrySetResult(0);
// Update settings if the runner name has been changed server-side
UpdateAgentNameIfNeeded(request.ReservedAgent?.Name);
} }
if (encounteringError > 0) if (encounteringError > 0)
@@ -772,27 +767,6 @@ namespace GitHub.Runner.Listener
} }
} }
private void UpdateAgentNameIfNeeded(string agentName)
{
var isNewAgentName = !string.Equals(_runnerSettings.AgentName, agentName, StringComparison.Ordinal);
if (!isNewAgentName || string.IsNullOrEmpty(agentName))
{
return;
}
_runnerSettings.AgentName = agentName;
try
{
_configurationStore.SaveSettings(_runnerSettings);
}
catch (Exception ex)
{
Trace.Error("Cannot update the settings file:");
Trace.Error(ex);
}
}
// Best effort upload any logs for this job. // Best effort upload any logs for this job.
private async Task TryUploadUnfinishedLogs(Pipelines.AgentJobRequestMessage message) private async Task TryUploadUnfinishedLogs(Pipelines.AgentJobRequestMessage message)
{ {

View File

@@ -129,7 +129,7 @@ namespace GitHub.Runner.Listener
private static void LoadAndSetEnv() private static void LoadAndSetEnv()
{ {
var binDir = Path.GetDirectoryName(AppContext.BaseDirectory); var binDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
var rootDir = new DirectoryInfo(binDir).Parent.FullName; var rootDir = new DirectoryInfo(binDir).Parent.FullName;
string envFile = Path.Combine(rootDir, ".env"); string envFile = Path.Combine(rootDir, ".env");
if (File.Exists(envFile)) if (File.Exists(envFile))

View File

@@ -1,10 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
<NoWarn>NU1701;NU1603</NoWarn> <NoWarn>NU1701;NU1603</NoWarn>
<Version>$(Version)</Version> <Version>$(Version)</Version>
<TieredCompilationQuickJit>true</TieredCompilationQuickJit> <TieredCompilationQuickJit>true</TieredCompilationQuickJit>

View File

@@ -233,14 +233,8 @@ namespace GitHub.Runner.Listener
Trace.Info($"Set runner startup type - {startType}"); Trace.Info($"Set runner startup type - {startType}");
HostContext.StartupType = startType; HostContext.StartupType = startType;
if (command.RunOnce)
{
_term.WriteLine("Warning: '--once' is going to be deprecated in the future, please consider using '--ephemeral' during runner registration.", ConsoleColor.Yellow);
_term.WriteLine("https://docs.github.com/en/actions/hosting-your-own-runners/autoscaling-with-self-hosted-runners#using-ephemeral-runners-for-autoscaling", ConsoleColor.Yellow);
}
// Run the runner interactively or as service // Run the runner interactively or as service
return await RunAsync(settings, command.RunOnce || settings.Ephemeral); return await RunAsync(settings, command.RunOnce || settings.Ephemeral); // TODO: Remove RunOnce later.
} }
else else
{ {
@@ -312,15 +306,10 @@ namespace GitHub.Runner.Listener
} }
HostContext.WritePerfCounter("SessionCreated"); HostContext.WritePerfCounter("SessionCreated");
_term.WriteLine($"Current runner version: '{BuildConstants.RunnerPackage.Version}'");
_term.WriteLine($"{DateTime.UtcNow:u}: Listening for Jobs"); _term.WriteLine($"{DateTime.UtcNow:u}: Listening for Jobs");
IJobDispatcher jobDispatcher = null; IJobDispatcher jobDispatcher = null;
CancellationTokenSource messageQueueLoopTokenSource = CancellationTokenSource.CreateLinkedTokenSource(HostContext.RunnerShutdownToken); CancellationTokenSource messageQueueLoopTokenSource = CancellationTokenSource.CreateLinkedTokenSource(HostContext.RunnerShutdownToken);
// Should we try to cleanup ephemeral runners
bool runOnceJobCompleted = false;
try try
{ {
var notification = HostContext.GetService<IJobNotification>(); var notification = HostContext.GetService<IJobNotification>();
@@ -382,7 +371,6 @@ namespace GitHub.Runner.Listener
Task completeTask = await Task.WhenAny(getNextMessage, jobDispatcher.RunOnceJobCompleted.Task); Task completeTask = await Task.WhenAny(getNextMessage, jobDispatcher.RunOnceJobCompleted.Task);
if (completeTask == jobDispatcher.RunOnceJobCompleted.Task) if (completeTask == jobDispatcher.RunOnceJobCompleted.Task)
{ {
runOnceJobCompleted = true;
Trace.Info("Job has finished at backend, the runner will exit since it is running under onetime use mode."); Trace.Info("Job has finished at backend, the runner will exit since it is running under onetime use mode.");
Trace.Info("Stop message queue looping."); Trace.Info("Stop message queue looping.");
messageQueueLoopTokenSource.Cancel(); messageQueueLoopTokenSource.Cancel();
@@ -490,12 +478,6 @@ namespace GitHub.Runner.Listener
} }
messageQueueLoopTokenSource.Dispose(); messageQueueLoopTokenSource.Dispose();
if (settings.Ephemeral && runOnceJobCompleted)
{
var configManager = HostContext.GetService<IConfigurationManager>();
configManager.DeleteLocalRunnerConfig();
}
} }
} }
catch (TaskAgentAccessTokenExpiredException) catch (TaskAgentAccessTokenExpiredException)

View File

@@ -75,9 +75,11 @@ namespace GitHub.Runner.Listener
Trace.Info($"All running job has exited."); Trace.Info($"All running job has exited.");
// We need to keep runner backup around for macOS until we fixed https://github.com/actions/runner/issues/743 // We need to keep runner backup around for macOS until we fixed https://github.com/actions/runner/issues/743
#if !OS_OSX
// delete runner backup // delete runner backup
DeletePreviousVersionRunnerBackup(token); DeletePreviousVersionRunnerBackup(token);
Trace.Info($"Delete old version runner backup."); Trace.Info($"Delete old version runner backup.");
#endif
// generate update script from template // generate update script from template
await UpdateRunnerUpdateStateAsync("Generate and execute update script."); await UpdateRunnerUpdateStateAsync("Generate and execute update script.");

View File

@@ -95,7 +95,7 @@ namespace GitHub.Runner.PluginHost
string assemblyFilename = assembly.Name + ".dll"; string assemblyFilename = assembly.Name + ".dll";
if (string.IsNullOrEmpty(executingAssemblyLocation)) if (string.IsNullOrEmpty(executingAssemblyLocation))
{ {
executingAssemblyLocation = Path.GetDirectoryName(AppContext.BaseDirectory); executingAssemblyLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
} }
return context.LoadFromAssemblyPath(Path.Combine(executingAssemblyLocation, assemblyFilename)); return context.LoadFromAssemblyPath(Path.Combine(executingAssemblyLocation, assemblyFilename));
} }

View File

@@ -1,10 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
<NoWarn>NU1701;NU1603</NoWarn> <NoWarn>NU1701;NU1603</NoWarn>
<Version>$(Version)</Version> <Version>$(Version)</Version>
<TieredCompilationQuickJit>true</TieredCompilationQuickJit> <TieredCompilationQuickJit>true</TieredCompilationQuickJit>

View File

@@ -444,7 +444,7 @@ namespace GitHub.Runner.Plugins.Artifact
{ {
// We should never // We should never
context.Error($"Error '{ex.Message}' when downloading file '{fileToDownload}'. (Downloader {downloaderId})"); context.Error($"Error '{ex.Message}' when downloading file '{fileToDownload}'. (Downloader {downloaderId})");
throw; throw ex;
} }
} }
@@ -528,7 +528,7 @@ namespace GitHub.Runner.Plugins.Artifact
catch (Exception ex) catch (Exception ex)
{ {
context.Output($"File error '{ex.Message}' when uploading file '{fileToUpload}'."); context.Output($"File error '{ex.Message}' when uploading file '{fileToUpload}'.");
throw; throw ex;
} }
} }

View File

@@ -1,10 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
<NoWarn>NU1701;NU1603</NoWarn> <NoWarn>NU1701;NU1603</NoWarn>
<Version>$(Version)</Version> <Version>$(Version)</Version>
<TieredCompilationQuickJit>true</TieredCompilationQuickJit> <TieredCompilationQuickJit>true</TieredCompilationQuickJit>

View File

@@ -1,10 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
<NoWarn>NU1701;NU1603</NoWarn> <NoWarn>NU1701;NU1603</NoWarn>
<Version>$(Version)</Version> <Version>$(Version)</Version>
<TieredCompilationQuickJit>true</TieredCompilationQuickJit> <TieredCompilationQuickJit>true</TieredCompilationQuickJit>

View File

@@ -1,5 +1,7 @@
using GitHub.DistributedTask.Pipelines.ContextData; using GitHub.DistributedTask.Pipelines;
using GitHub.DistributedTask.Pipelines.ContextData;
using GitHub.DistributedTask.WebApi; using GitHub.DistributedTask.WebApi;
using GitHub.Runner.Common.Util;
using GitHub.Runner.Worker.Container; using GitHub.Runner.Worker.Container;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -108,18 +110,11 @@ namespace GitHub.Runner.Worker
// Stop command // Stop command
if (string.Equals(actionCommand.Command, _stopCommand, StringComparison.OrdinalIgnoreCase)) if (string.Equals(actionCommand.Command, _stopCommand, StringComparison.OrdinalIgnoreCase))
{ {
ValidateStopToken(context, actionCommand.Data); context.Output(input);
context.Debug("Paused processing commands until '##[{actionCommand.Data}]' is received");
_stopToken = actionCommand.Data; _stopToken = actionCommand.Data;
_stopProcessCommand = true; _stopProcessCommand = true;
_registeredCommands.Add(_stopToken); _registeredCommands.Add(_stopToken);
if (_stopToken.Length > 6)
{
HostContext.SecretMasker.AddValue(_stopToken);
}
context.Output(input);
context.Debug("Paused processing commands until the token you called ::stopCommands:: with is received");
return true; return true;
} }
// Found command // Found command
@@ -153,42 +148,7 @@ namespace GitHub.Runner.Worker
return true; return true;
} }
private void ValidateStopToken(IExecutionContext context, string stopToken) internal static bool EnhancedAnnotationsEnabled(IExecutionContext context) {
{
#if OS_WINDOWS
var envContext = context.ExpressionValues["env"] as DictionaryContextData;
#else
var envContext = context.ExpressionValues["env"] as CaseSensitiveDictionaryContextData;
#endif
var allowUnsecureStopCommandTokens = false;
allowUnsecureStopCommandTokens = StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable(Constants.Variables.Actions.AllowUnsupportedStopCommandTokens));
if (!allowUnsecureStopCommandTokens && envContext.ContainsKey(Constants.Variables.Actions.AllowUnsupportedStopCommandTokens))
{
allowUnsecureStopCommandTokens = StringUtil.ConvertToBoolean(envContext[Constants.Variables.Actions.AllowUnsupportedStopCommandTokens].ToString());
}
bool isTokenInvalid = _registeredCommands.Contains(stopToken)
|| string.IsNullOrEmpty(stopToken)
|| string.Equals(stopToken, "pause-logging", StringComparison.OrdinalIgnoreCase);
if (isTokenInvalid)
{
var telemetry = new JobTelemetry
{
Message = $"Invoked ::stopCommand:: with token: [{stopToken}]",
Type = JobTelemetryType.ActionCommand
};
context.JobTelemetry.Add(telemetry);
}
if (isTokenInvalid && !allowUnsecureStopCommandTokens)
{
throw new Exception(Constants.Runner.UnsupportedStopCommandTokenDisabled);
}
}
internal static bool EnhancedAnnotationsEnabled(IExecutionContext context)
{
return context.Global.Variables.GetBoolean("DistributedTask.EnhancedAnnotations") ?? false; return context.Global.Variables.GetBoolean("DistributedTask.EnhancedAnnotations") ?? false;
} }
} }

View File

@@ -267,19 +267,6 @@ namespace GitHub.Runner.Worker
_cachedEmbeddedPostSteps[parentStepId].Push(clonedAction); _cachedEmbeddedPostSteps[parentStepId].Push(clonedAction);
} }
} }
else if (depth > 0)
{
// if we're in a composite action and haven't loaded the local action yet
// we assume it has a post step
if (!_cachedEmbeddedPostSteps.ContainsKey(parentStepId))
{
// If we haven't done so already, add the parent to the post steps
_cachedEmbeddedPostSteps[parentStepId] = new Stack<Pipelines.ActionStep>();
}
// Clone action so we can modify the condition without affecting the original
var clonedAction = action.Clone() as Pipelines.ActionStep;
_cachedEmbeddedPostSteps[parentStepId].Push(clonedAction);
}
} }
} }
@@ -646,12 +633,7 @@ namespace GitHub.Runner.Worker
} }
catch (Exception ex) when (!executionContext.CancellationToken.IsCancellationRequested) // Do not retry if the run is canceled. catch (Exception ex) when (!executionContext.CancellationToken.IsCancellationRequested) // Do not retry if the run is canceled.
{ {
// UnresolvableActionDownloadInfoException is a 422 client error, don't retry if (attempt < 3)
// Some possible cases are:
// * Repo is rate limited
// * Repo or tag doesn't exist, or isn't public
// * Policy validation failed
if (attempt < 3 && !(ex is WebApi.UnresolvableActionDownloadInfoException))
{ {
executionContext.Output($"Failed to resolve action download info. Error: {ex.Message}"); executionContext.Output($"Failed to resolve action download info. Error: {ex.Message}");
executionContext.Debug(ex.ToString()); executionContext.Debug(ex.ToString());
@@ -667,7 +649,6 @@ namespace GitHub.Runner.Worker
// Some possible cases are: // Some possible cases are:
// * Repo is rate limited // * Repo is rate limited
// * Repo or tag doesn't exist, or isn't public // * Repo or tag doesn't exist, or isn't public
// * Policy validation failed
if (ex is WebApi.UnresolvableActionDownloadInfoException) if (ex is WebApi.UnresolvableActionDownloadInfoException)
{ {
throw; throw;
@@ -1047,6 +1028,7 @@ namespace GitHub.Runner.Worker
} }
} }
// TODO: remove once we remove the DistributedTask.EnableCompositeActions FF
foreach (var step in compositeAction.Steps) foreach (var step in compositeAction.Steps)
{ {
if (string.IsNullOrEmpty(executionContext.Global.Variables.Get("DistributedTask.EnableCompositeActions")) && step.Reference.Type != Pipelines.ActionSourceType.Script) if (string.IsNullOrEmpty(executionContext.Global.Variables.Get("DistributedTask.EnableCompositeActions")) && step.Reference.Type != Pipelines.ActionSourceType.Script)

View File

@@ -40,7 +40,6 @@ namespace GitHub.Runner.Worker
string ScopeName { get; } string ScopeName { get; }
string SiblingScopeName { get; } string SiblingScopeName { get; }
string ContextName { get; } string ContextName { get; }
ActionRunStage Stage { get; }
Task ForceCompleted { get; } Task ForceCompleted { get; }
TaskResult? Result { get; set; } TaskResult? Result { get; set; }
TaskResult? Outcome { get; set; } TaskResult? Outcome { get; set; }
@@ -53,7 +52,6 @@ namespace GitHub.Runner.Worker
Dictionary<string, VariableValue> JobOutputs { get; } Dictionary<string, VariableValue> JobOutputs { get; }
ActionsEnvironmentReference ActionsEnvironment { get; } ActionsEnvironmentReference ActionsEnvironment { get; }
List<ActionsStepTelemetry> ActionsStepsTelemetry { get; } List<ActionsStepTelemetry> ActionsStepsTelemetry { get; }
List<JobTelemetry> JobTelemetry { get; }
DictionaryContextData ExpressionValues { get; } DictionaryContextData ExpressionValues { get; }
IList<IFunctionInfo> ExpressionFunctions { get; } IList<IFunctionInfo> ExpressionFunctions { get; }
JobContext JobContext { get; } JobContext JobContext { get; }
@@ -63,7 +61,7 @@ namespace GitHub.Runner.Worker
// Only job level ExecutionContext has PostJobSteps // Only job level ExecutionContext has PostJobSteps
Stack<IStep> PostJobSteps { get; } Stack<IStep> PostJobSteps { get; }
Dictionary<Guid, string> EmbeddedStepsWithPostRegistered { get; } HashSet<Guid> EmbeddedStepsWithPostRegistered{ get; }
// Keep track of embedded steps states // Keep track of embedded steps states
Dictionary<Guid, Dictionary<string, string>> EmbeddedIntraActionState { get; } Dictionary<Guid, Dictionary<string, string>> EmbeddedIntraActionState { get; }
@@ -77,8 +75,8 @@ namespace GitHub.Runner.Worker
// Initialize // Initialize
void InitializeJob(Pipelines.AgentJobRequestMessage message, CancellationToken token); void InitializeJob(Pipelines.AgentJobRequestMessage message, CancellationToken token);
void CancelToken(); void CancelToken();
IExecutionContext CreateChild(Guid recordId, string displayName, string refName, string scopeName, string contextName, ActionRunStage stage, Dictionary<string, string> intraActionState = null, int? recordOrder = null, IPagingLogger logger = null, bool isEmbedded = false, CancellationTokenSource cancellationTokenSource = null, Guid embeddedId = default(Guid), string siblingScopeName = null); IExecutionContext CreateChild(Guid recordId, string displayName, string refName, string scopeName, string contextName, Dictionary<string, string> intraActionState = null, int? recordOrder = null, IPagingLogger logger = null, bool isEmbedded = false, CancellationTokenSource cancellationTokenSource = null, Guid embeddedId = default(Guid), string siblingScopeName = null);
IExecutionContext CreateEmbeddedChild(string scopeName, string contextName, Guid embeddedId, ActionRunStage stage, Dictionary<string, string> intraActionState = null, string siblingScopeName = null); IExecutionContext CreateEmbeddedChild(string scopeName, string contextName, Guid embeddedId, Dictionary<string, string> intraActionState = null, string siblingScopeName = null);
// logging // logging
long Write(string tag, string message); long Write(string tag, string message);
@@ -145,7 +143,6 @@ namespace GitHub.Runner.Worker
public string ScopeName { get; private set; } public string ScopeName { get; private set; }
public string SiblingScopeName { get; private set; } public string SiblingScopeName { get; private set; }
public string ContextName { get; private set; } public string ContextName { get; private set; }
public ActionRunStage Stage { get; private set; }
public Task ForceCompleted => _forceCompleted.Task; public Task ForceCompleted => _forceCompleted.Task;
public CancellationToken CancellationToken => _cancellationTokenSource.Token; public CancellationToken CancellationToken => _cancellationTokenSource.Token;
public Dictionary<string, string> IntraActionState { get; private set; } public Dictionary<string, string> IntraActionState { get; private set; }
@@ -153,7 +150,6 @@ namespace GitHub.Runner.Worker
public ActionsEnvironmentReference ActionsEnvironment { get; private set; } public ActionsEnvironmentReference ActionsEnvironment { get; private set; }
public List<ActionsStepTelemetry> ActionsStepsTelemetry { get; private set; } public List<ActionsStepTelemetry> ActionsStepsTelemetry { get; private set; }
public List<JobTelemetry> JobTelemetry { get; private set; }
public DictionaryContextData ExpressionValues { get; } = new DictionaryContextData(); public DictionaryContextData ExpressionValues { get; } = new DictionaryContextData();
public IList<IFunctionInfo> ExpressionFunctions { get; } = new List<IFunctionInfo>(); public IList<IFunctionInfo> ExpressionFunctions { get; } = new List<IFunctionInfo>();
@@ -170,7 +166,7 @@ namespace GitHub.Runner.Worker
public HashSet<Guid> StepsWithPostRegistered { get; private set; } public HashSet<Guid> StepsWithPostRegistered { get; private set; }
// Only job level ExecutionContext has EmbeddedStepsWithPostRegistered // Only job level ExecutionContext has EmbeddedStepsWithPostRegistered
public Dictionary<Guid, string> EmbeddedStepsWithPostRegistered { get; private set; } public HashSet<Guid> EmbeddedStepsWithPostRegistered { get; private set; }
public Dictionary<Guid, Dictionary<string, string>> EmbeddedIntraActionState { get; private set; } public Dictionary<Guid, Dictionary<string, string>> EmbeddedIntraActionState { get; private set; }
@@ -267,18 +263,11 @@ namespace GitHub.Runner.Worker
string siblingScopeName = null; string siblingScopeName = null;
if (this.IsEmbedded) if (this.IsEmbedded)
{ {
if (step is IActionRunner actionRunner) if (step is IActionRunner actionRunner && !Root.EmbeddedStepsWithPostRegistered.Add(actionRunner.Action.Id))
{ {
if (Root.EmbeddedStepsWithPostRegistered.ContainsKey(actionRunner.Action.Id)) Trace.Info($"'post' of '{actionRunner.DisplayName}' already push to child post step stack.");
{
Trace.Info($"'post' of '{actionRunner.DisplayName}' already push to child post step stack.");
}
else
{
Root.EmbeddedStepsWithPostRegistered[actionRunner.Action.Id] = actionRunner.Condition;
}
return;
} }
return;
} }
else if (step is IActionRunner actionRunner && !Root.StepsWithPostRegistered.Add(actionRunner.Action.Id)) else if (step is IActionRunner actionRunner && !Root.StepsWithPostRegistered.Add(actionRunner.Action.Id))
{ {
@@ -294,7 +283,7 @@ namespace GitHub.Runner.Worker
Root.PostJobSteps.Push(step); Root.PostJobSteps.Push(step);
} }
public IExecutionContext CreateChild(Guid recordId, string displayName, string refName, string scopeName, string contextName, ActionRunStage stage, Dictionary<string, string> intraActionState = null, int? recordOrder = null, IPagingLogger logger = null, bool isEmbedded = false, CancellationTokenSource cancellationTokenSource = null, Guid embeddedId = default(Guid), string siblingScopeName = null) public IExecutionContext CreateChild(Guid recordId, string displayName, string refName, string scopeName, string contextName, Dictionary<string, string> intraActionState = null, int? recordOrder = null, IPagingLogger logger = null, bool isEmbedded = false, CancellationTokenSource cancellationTokenSource = null, Guid embeddedId = default(Guid), string siblingScopeName = null)
{ {
Trace.Entering(); Trace.Entering();
@@ -303,10 +292,8 @@ namespace GitHub.Runner.Worker
child.Global = Global; child.Global = Global;
child.ScopeName = scopeName; child.ScopeName = scopeName;
child.ContextName = contextName; child.ContextName = contextName;
child.Stage = stage;
child.EmbeddedId = embeddedId; child.EmbeddedId = embeddedId;
child.SiblingScopeName = siblingScopeName; child.SiblingScopeName = siblingScopeName;
child.JobTelemetry = JobTelemetry;
if (intraActionState == null) if (intraActionState == null)
{ {
child.IntraActionState = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); child.IntraActionState = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
@@ -354,9 +341,9 @@ namespace GitHub.Runner.Worker
/// An embedded execution context shares the same record ID, record name, logger, /// An embedded execution context shares the same record ID, record name, logger,
/// and a linked cancellation token. /// and a linked cancellation token.
/// </summary> /// </summary>
public IExecutionContext CreateEmbeddedChild(string scopeName, string contextName, Guid embeddedId, ActionRunStage stage, Dictionary<string, string> intraActionState = null, string siblingScopeName = null) public IExecutionContext CreateEmbeddedChild(string scopeName, string contextName, Guid embeddedId, Dictionary<string, string> intraActionState = null, string siblingScopeName = null)
{ {
return Root.CreateChild(_record.Id, _record.Name, _record.Id.ToString("N"), scopeName, contextName, stage, logger: _logger, isEmbedded: true, cancellationTokenSource: CancellationTokenSource.CreateLinkedTokenSource(_cancellationTokenSource.Token), intraActionState: intraActionState, embeddedId: embeddedId, siblingScopeName: siblingScopeName); return Root.CreateChild(_record.Id, _record.Name, _record.Id.ToString("N"), scopeName, contextName, logger: _logger, isEmbedded: true, cancellationTokenSource: CancellationTokenSource.CreateLinkedTokenSource(_cancellationTokenSource.Token), intraActionState: intraActionState, embeddedId: embeddedId, siblingScopeName: siblingScopeName);
} }
public void Start(string currentOperation = null) public void Start(string currentOperation = null)
@@ -663,8 +650,6 @@ namespace GitHub.Runner.Worker
// ActionsStepTelemetry // ActionsStepTelemetry
ActionsStepsTelemetry = new List<ActionsStepTelemetry>(); ActionsStepsTelemetry = new List<ActionsStepTelemetry>();
JobTelemetry = new List<JobTelemetry>();
// Service container info // Service container info
Global.ServiceContainers = new List<ContainerInfo>(); Global.ServiceContainers = new List<ContainerInfo>();
@@ -726,10 +711,10 @@ namespace GitHub.Runner.Worker
StepsWithPostRegistered = new HashSet<Guid>(); StepsWithPostRegistered = new HashSet<Guid>();
// EmbeddedStepsWithPostRegistered for job ExecutionContext // EmbeddedStepsWithPostRegistered for job ExecutionContext
EmbeddedStepsWithPostRegistered = new Dictionary<Guid, string>(); EmbeddedStepsWithPostRegistered = new HashSet<Guid>();
// EmbeddedIntraActionState for job ExecutionContext // EmbeddedIntraActionState for job ExecutionContext
EmbeddedIntraActionState = new Dictionary<Guid, Dictionary<string, string>>(); EmbeddedIntraActionState = new Dictionary<Guid, Dictionary<string,string>>();
// Job timeline record. // Job timeline record.
InitializeTimelineRecord( InitializeTimelineRecord(
@@ -947,7 +932,7 @@ namespace GitHub.Runner.Worker
} }
var newGuid = Guid.NewGuid(); var newGuid = Guid.NewGuid();
return CreateChild(newGuid, displayName, newGuid.ToString("N"), null, null, ActionRunStage.Post, intraActionState, _childTimelineRecordOrder - Root.PostJobSteps.Count, siblingScopeName: siblingScopeName); return CreateChild(newGuid, displayName, newGuid.ToString("N"), null, null, intraActionState, _childTimelineRecordOrder - Root.PostJobSteps.Count, siblingScopeName: siblingScopeName);
} }
} }
@@ -980,7 +965,7 @@ namespace GitHub.Runner.Worker
// Do not add a format string overload. See comment on ExecutionContext.Write(). // Do not add a format string overload. See comment on ExecutionContext.Write().
public static void InfrastructureError(this IExecutionContext context, string message) public static void InfrastructureError(this IExecutionContext context, string message)
{ {
context.AddIssue(new Issue() { Type = IssueType.Error, Message = message, IsInfrastructureIssue = true }); context.AddIssue(new Issue() { Type = IssueType.Error, Message = message, IsInfrastructureIssue = true});
} }
// Do not add a format string overload. See comment on ExecutionContext.Write(). // Do not add a format string overload. See comment on ExecutionContext.Write().

View File

@@ -24,19 +24,8 @@ namespace GitHub.Runner.Worker.Expressions
ArgUtil.NotNull(templateContext, nameof(templateContext)); ArgUtil.NotNull(templateContext, nameof(templateContext));
var executionContext = templateContext.State[nameof(IExecutionContext)] as IExecutionContext; var executionContext = templateContext.State[nameof(IExecutionContext)] as IExecutionContext;
ArgUtil.NotNull(executionContext, nameof(executionContext)); ArgUtil.NotNull(executionContext, nameof(executionContext));
ActionResult jobStatus = executionContext.JobContext.Status ?? ActionResult.Success;
// Decide based on 'action_status' for composite MAIN steps and 'job.status' for pre, post and job-level steps return jobStatus == ActionResult.Failure;
var isCompositeMainStep = executionContext.IsEmbedded && executionContext.Stage == ActionRunStage.Main;
if (isCompositeMainStep)
{
ActionResult actionStatus = EnumUtil.TryParse<ActionResult>(executionContext.GetGitHubContext("action_status")) ?? ActionResult.Success;
return actionStatus == ActionResult.Failure;
}
else
{
ActionResult jobStatus = executionContext.JobContext.Status ?? ActionResult.Success;
return jobStatus == ActionResult.Failure;
}
} }
} }
} }

View File

@@ -59,7 +59,7 @@ namespace GitHub.Runner.Worker.Expressions
context.Trace.Info($"Search root directory: '{githubWorkspace}'"); context.Trace.Info($"Search root directory: '{githubWorkspace}'");
context.Trace.Info($"Search pattern: '{string.Join(", ", patterns)}'"); context.Trace.Info($"Search pattern: '{string.Join(", ", patterns)}'");
string binDir = Path.GetDirectoryName(AppContext.BaseDirectory); string binDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
string runnerRoot = new DirectoryInfo(binDir).Parent.FullName; string runnerRoot = new DirectoryInfo(binDir).Parent.FullName;
string node = Path.Combine(runnerRoot, "externals", "node12", "bin", $"node{IOUtil.ExeExtension}"); string node = Path.Combine(runnerRoot, "externals", "node12", "bin", $"node{IOUtil.ExeExtension}");

View File

@@ -24,19 +24,8 @@ namespace GitHub.Runner.Worker.Expressions
ArgUtil.NotNull(templateContext, nameof(templateContext)); ArgUtil.NotNull(templateContext, nameof(templateContext));
var executionContext = templateContext.State[nameof(IExecutionContext)] as IExecutionContext; var executionContext = templateContext.State[nameof(IExecutionContext)] as IExecutionContext;
ArgUtil.NotNull(executionContext, nameof(executionContext)); ArgUtil.NotNull(executionContext, nameof(executionContext));
ActionResult jobStatus = executionContext.JobContext.Status ?? ActionResult.Success;
// Decide based on 'action_status' for composite MAIN steps and 'job.status' for pre, post and job-level steps return jobStatus == ActionResult.Success;
var isCompositeMainStep = executionContext.IsEmbedded && executionContext.Stage == ActionRunStage.Main;
if (isCompositeMainStep)
{
ActionResult actionStatus = EnumUtil.TryParse<ActionResult>(executionContext.GetGitHubContext("action_status")) ?? ActionResult.Success;
return actionStatus == ActionResult.Success;
}
else
{
ActionResult jobStatus = executionContext.JobContext.Status ?? ActionResult.Success;
return jobStatus == ActionResult.Success;
}
} }
} }
} }

View File

@@ -23,13 +23,9 @@ namespace GitHub.Runner.Worker
"job", "job",
"path", "path",
"ref", "ref",
"ref_name",
"ref_protected",
"ref_type",
"repository", "repository",
"repository_owner", "repository_owner",
"retention_days", "retention_days",
"run_attempt",
"run_id", "run_id",
"run_number", "run_number",
"server_url", "server_url",
@@ -42,16 +38,9 @@ namespace GitHub.Runner.Worker
{ {
foreach (var data in this) foreach (var data in this)
{ {
if (_contextEnvAllowlist.Contains(data.Key)) if (_contextEnvAllowlist.Contains(data.Key) && data.Value is StringContextData value)
{ {
if (data.Value is StringContextData value) yield return new KeyValuePair<string, string>($"GITHUB_{data.Key.ToUpperInvariant()}", value);
{
yield return new KeyValuePair<string, string>($"GITHUB_{data.Key.ToUpperInvariant()}", value);
}
else if (data.Value is BooleanContextData booleanValue)
{
yield return new KeyValuePair<string, string>($"GITHUB_{data.Key.ToUpperInvariant()}", booleanValue.ToString());
}
} }
} }
} }

View File

@@ -50,9 +50,8 @@ namespace GitHub.Runner.Worker.Handlers
// Only register post steps for steps that actually ran // Only register post steps for steps that actually ran
foreach (var step in Data.PostSteps.ToList()) foreach (var step in Data.PostSteps.ToList())
{ {
if (ExecutionContext.Root.EmbeddedStepsWithPostRegistered.ContainsKey(step.Id)) if (ExecutionContext.Root.EmbeddedStepsWithPostRegistered.Contains(step.Id))
{ {
step.Condition = ExecutionContext.Root.EmbeddedStepsWithPostRegistered[step.Id];
steps.Add(step); steps.Add(step);
} }
else else
@@ -125,7 +124,7 @@ namespace GitHub.Runner.Worker.Handlers
{ {
ArgUtil.NotNull(step, step.DisplayName); ArgUtil.NotNull(step, step.DisplayName);
var stepId = $"__{Guid.NewGuid()}"; var stepId = $"__{Guid.NewGuid()}";
step.ExecutionContext = ExecutionContext.CreateEmbeddedChild(childScopeName, stepId, Guid.NewGuid(), stage); step.ExecutionContext = ExecutionContext.CreateEmbeddedChild(childScopeName, stepId, Guid.NewGuid());
embeddedSteps.Add(step); embeddedSteps.Add(step);
} }
} }
@@ -144,7 +143,7 @@ namespace GitHub.Runner.Worker.Handlers
step.Stage = stage; step.Stage = stage;
step.Condition = stepData.Condition; step.Condition = stepData.Condition;
ExecutionContext.Root.EmbeddedIntraActionState.TryGetValue(step.Action.Id, out var intraActionState); ExecutionContext.Root.EmbeddedIntraActionState.TryGetValue(step.Action.Id, out var intraActionState);
step.ExecutionContext = ExecutionContext.CreateEmbeddedChild(childScopeName, stepData.ContextName, step.Action.Id, stage, intraActionState: intraActionState, siblingScopeName: siblingScopeName); step.ExecutionContext = ExecutionContext.CreateEmbeddedChild(childScopeName, stepData.ContextName, step.Action.Id, intraActionState: intraActionState, siblingScopeName: siblingScopeName);
step.ExecutionContext.ExpressionValues["inputs"] = inputsData; step.ExecutionContext.ExpressionValues["inputs"] = inputsData;
if (!String.IsNullOrEmpty(ExecutionContext.SiblingScopeName)) if (!String.IsNullOrEmpty(ExecutionContext.SiblingScopeName))
{ {
@@ -242,10 +241,6 @@ namespace GitHub.Runner.Worker.Handlers
step.ExecutionContext.ExpressionFunctions.Add(new FunctionInfo<FailureFunction>(PipelineTemplateConstants.Failure, 0, 0)); step.ExecutionContext.ExpressionFunctions.Add(new FunctionInfo<FailureFunction>(PipelineTemplateConstants.Failure, 0, 0));
step.ExecutionContext.ExpressionFunctions.Add(new FunctionInfo<SuccessFunction>(PipelineTemplateConstants.Success, 0, 0)); step.ExecutionContext.ExpressionFunctions.Add(new FunctionInfo<SuccessFunction>(PipelineTemplateConstants.Success, 0, 0));
// Set action_status to the success of the current composite action
var actionResult = ExecutionContext.Result?.ToActionResult() ?? ActionResult.Success;
step.ExecutionContext.SetGitHubContext("action_status", actionResult.ToString());
// Initialize env context // Initialize env context
Trace.Info("Initialize Env context for embedded step"); Trace.Info("Initialize Env context for embedded step");
#if OS_WINDOWS #if OS_WINDOWS
@@ -300,100 +295,108 @@ namespace GitHub.Runner.Worker.Handlers
CancellationTokenRegistration? jobCancelRegister = null; CancellationTokenRegistration? jobCancelRegister = null;
try try
{ {
// Register job cancellation call back only if job cancellation token not been fire before each step run // For main steps just run the action
if (!ExecutionContext.Root.CancellationToken.IsCancellationRequested) if (stage == ActionRunStage.Main)
{
// Test the condition again. The job was canceled after the condition was originally evaluated.
jobCancelRegister = ExecutionContext.Root.CancellationToken.Register(() =>
{
// Mark job as cancelled
ExecutionContext.Root.Result = TaskResult.Canceled;
ExecutionContext.Root.JobContext.Status = ExecutionContext.Root.Result?.ToActionResult();
step.ExecutionContext.Debug($"Re-evaluate condition on job cancellation for step: '{step.DisplayName}'.");
var conditionReTestTraceWriter = new ConditionTraceWriter(Trace, null); // host tracing only
var conditionReTestResult = false;
if (HostContext.RunnerShutdownToken.IsCancellationRequested)
{
step.ExecutionContext.Debug($"Skip Re-evaluate condition on runner shutdown.");
}
else
{
try
{
var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator(conditionReTestTraceWriter);
var condition = new BasicExpressionToken(null, null, null, step.Condition);
conditionReTestResult = templateEvaluator.EvaluateStepIf(condition, step.ExecutionContext.ExpressionValues, step.ExecutionContext.ExpressionFunctions, step.ExecutionContext.ToExpressionState());
}
catch (Exception ex)
{
// Cancel the step since we get exception while re-evaluate step condition
Trace.Info("Caught exception from expression when re-test condition on job cancellation.");
step.ExecutionContext.Error(ex);
}
}
if (!conditionReTestResult)
{
// Cancel the step
Trace.Info("Cancel current running step.");
step.ExecutionContext.CancelToken();
}
});
}
else
{
if (ExecutionContext.Root.Result != TaskResult.Canceled)
{
// Mark job as cancelled
ExecutionContext.Root.Result = TaskResult.Canceled;
ExecutionContext.Root.JobContext.Status = ExecutionContext.Root.Result?.ToActionResult();
}
}
// Evaluate condition
step.ExecutionContext.Debug($"Evaluating condition for step: '{step.DisplayName}'");
var conditionTraceWriter = new ConditionTraceWriter(Trace, step.ExecutionContext);
var conditionResult = false;
var conditionEvaluateError = default(Exception);
if (HostContext.RunnerShutdownToken.IsCancellationRequested)
{
step.ExecutionContext.Debug($"Skip evaluate condition on runner shutdown.");
}
else
{
try
{
var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator(conditionTraceWriter);
var condition = new BasicExpressionToken(null, null, null, step.Condition);
conditionResult = templateEvaluator.EvaluateStepIf(condition, step.ExecutionContext.ExpressionValues, step.ExecutionContext.ExpressionFunctions, step.ExecutionContext.ToExpressionState());
}
catch (Exception ex)
{
Trace.Info("Caught exception from expression.");
Trace.Error(ex);
conditionEvaluateError = ex;
}
}
if (!conditionResult && conditionEvaluateError == null)
{
// Condition is false
Trace.Info("Skipping step due to condition evaluation.");
step.ExecutionContext.Result = TaskResult.Skipped;
continue;
}
else if (conditionEvaluateError != null)
{
// Condition error
step.ExecutionContext.Error(conditionEvaluateError);
step.ExecutionContext.Result = TaskResult.Failed;
ExecutionContext.Result = TaskResult.Failed;
break;
}
else
{ {
await RunStepAsync(step); await RunStepAsync(step);
} }
// We need to evaluate conditions for pre/post steps
else
{
// Register job cancellation call back only if job cancellation token not been fire before each step run
if (!ExecutionContext.Root.CancellationToken.IsCancellationRequested)
{
// Test the condition again. The job was canceled after the condition was originally evaluated.
jobCancelRegister = ExecutionContext.Root.CancellationToken.Register(() =>
{
// Mark job as cancelled
ExecutionContext.Root.Result = TaskResult.Canceled;
ExecutionContext.Root.JobContext.Status = ExecutionContext.Root.Result?.ToActionResult();
step.ExecutionContext.Debug($"Re-evaluate condition on job cancellation for step: '{step.DisplayName}'.");
var conditionReTestTraceWriter = new ConditionTraceWriter(Trace, null); // host tracing only
var conditionReTestResult = false;
if (HostContext.RunnerShutdownToken.IsCancellationRequested)
{
step.ExecutionContext.Debug($"Skip Re-evaluate condition on runner shutdown.");
}
else
{
try
{
var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator(conditionReTestTraceWriter);
var condition = new BasicExpressionToken(null, null, null, step.Condition);
conditionReTestResult = templateEvaluator.EvaluateStepIf(condition, step.ExecutionContext.ExpressionValues, step.ExecutionContext.ExpressionFunctions, step.ExecutionContext.ToExpressionState());
}
catch (Exception ex)
{
// Cancel the step since we get exception while re-evaluate step condition
Trace.Info("Caught exception from expression when re-test condition on job cancellation.");
step.ExecutionContext.Error(ex);
}
}
if (!conditionReTestResult)
{
// Cancel the step
Trace.Info("Cancel current running step.");
step.ExecutionContext.CancelToken();
}
});
}
else
{
if (ExecutionContext.Root.Result != TaskResult.Canceled)
{
// Mark job as cancelled
ExecutionContext.Root.Result = TaskResult.Canceled;
ExecutionContext.Root.JobContext.Status = ExecutionContext.Root.Result?.ToActionResult();
}
}
// Evaluate condition
step.ExecutionContext.Debug($"Evaluating condition for step: '{step.DisplayName}'");
var conditionTraceWriter = new ConditionTraceWriter(Trace, step.ExecutionContext);
var conditionResult = false;
var conditionEvaluateError = default(Exception);
if (HostContext.RunnerShutdownToken.IsCancellationRequested)
{
step.ExecutionContext.Debug($"Skip evaluate condition on runner shutdown.");
}
else
{
try
{
var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator(conditionTraceWriter);
var condition = new BasicExpressionToken(null, null, null, step.Condition);
conditionResult = templateEvaluator.EvaluateStepIf(condition, step.ExecutionContext.ExpressionValues, step.ExecutionContext.ExpressionFunctions, step.ExecutionContext.ToExpressionState());
}
catch (Exception ex)
{
Trace.Info("Caught exception from expression.");
Trace.Error(ex);
conditionEvaluateError = ex;
}
}
if (!conditionResult && conditionEvaluateError == null)
{
// Condition is false
Trace.Info("Skipping step due to condition evaluation.");
step.ExecutionContext.Result = TaskResult.Skipped;
continue;
}
else if (conditionEvaluateError != null)
{
// Condition error
step.ExecutionContext.Error(conditionEvaluateError);
step.ExecutionContext.Result = TaskResult.Failed;
ExecutionContext.Result = TaskResult.Failed;
break;
}
else
{
await RunStepAsync(step);
}
}
} }
finally finally
{ {
@@ -409,6 +412,12 @@ namespace GitHub.Runner.Worker.Handlers
{ {
Trace.Info($"Update job result with current composite step result '{step.ExecutionContext.Result}'."); Trace.Info($"Update job result with current composite step result '{step.ExecutionContext.Result}'.");
ExecutionContext.Result = TaskResultUtil.MergeTaskResults(ExecutionContext.Result, step.ExecutionContext.Result.Value); ExecutionContext.Result = TaskResultUtil.MergeTaskResults(ExecutionContext.Result, step.ExecutionContext.Result.Value);
// We should run cleanup even if one of the cleanup step fails
if (stage != ActionRunStage.Post)
{
break;
}
} }
} }
} }

View File

@@ -55,7 +55,7 @@ namespace GitHub.Runner.Worker
ArgUtil.NotNull(message, nameof(message)); ArgUtil.NotNull(message, nameof(message));
// Create a new timeline record for 'Set up job' // Create a new timeline record for 'Set up job'
IExecutionContext context = jobContext.CreateChild(Guid.NewGuid(), "Set up job", $"{nameof(JobExtension)}_Init", null, null, ActionRunStage.Pre); IExecutionContext context = jobContext.CreateChild(Guid.NewGuid(), "Set up job", $"{nameof(JobExtension)}_Init", null, null);
List<IStep> preJobSteps = new List<IStep>(); List<IStep> preJobSteps = new List<IStep>();
List<IStep> jobSteps = new List<IStep>(); List<IStep> jobSteps = new List<IStep>();
@@ -306,13 +306,13 @@ namespace GitHub.Runner.Worker
JobExtensionRunner extensionStep = step as JobExtensionRunner; JobExtensionRunner extensionStep = step as JobExtensionRunner;
ArgUtil.NotNull(extensionStep, extensionStep.DisplayName); ArgUtil.NotNull(extensionStep, extensionStep.DisplayName);
Guid stepId = Guid.NewGuid(); Guid stepId = Guid.NewGuid();
extensionStep.ExecutionContext = jobContext.CreateChild(stepId, extensionStep.DisplayName, null, null, stepId.ToString("N"), ActionRunStage.Pre); extensionStep.ExecutionContext = jobContext.CreateChild(stepId, extensionStep.DisplayName, null, null, stepId.ToString("N"));
} }
else if (step is IActionRunner actionStep) else if (step is IActionRunner actionStep)
{ {
ArgUtil.NotNull(actionStep, step.DisplayName); ArgUtil.NotNull(actionStep, step.DisplayName);
Guid stepId = Guid.NewGuid(); Guid stepId = Guid.NewGuid();
actionStep.ExecutionContext = jobContext.CreateChild(stepId, actionStep.DisplayName, stepId.ToString("N"), null, null, ActionRunStage.Pre, intraActionStates[actionStep.Action.Id]); actionStep.ExecutionContext = jobContext.CreateChild(stepId, actionStep.DisplayName, stepId.ToString("N"), null, null, intraActionStates[actionStep.Action.Id]);
} }
} }
@@ -323,7 +323,7 @@ namespace GitHub.Runner.Worker
{ {
ArgUtil.NotNull(actionStep, step.DisplayName); ArgUtil.NotNull(actionStep, step.DisplayName);
intraActionStates.TryGetValue(actionStep.Action.Id, out var intraActionState); intraActionStates.TryGetValue(actionStep.Action.Id, out var intraActionState);
actionStep.ExecutionContext = jobContext.CreateChild(actionStep.Action.Id, actionStep.DisplayName, actionStep.Action.Name, null, actionStep.Action.ContextName, ActionRunStage.Main, intraActionState); actionStep.ExecutionContext = jobContext.CreateChild(actionStep.Action.Id, actionStep.DisplayName, actionStep.Action.Name, null, actionStep.Action.ContextName, intraActionState);
} }
} }
@@ -394,7 +394,7 @@ namespace GitHub.Runner.Worker
ArgUtil.NotNull(jobContext, nameof(jobContext)); ArgUtil.NotNull(jobContext, nameof(jobContext));
// create a new timeline record node for 'Finalize job' // create a new timeline record node for 'Finalize job'
IExecutionContext context = jobContext.CreateChild(Guid.NewGuid(), "Complete job", $"{nameof(JobExtension)}_Final", null, null, ActionRunStage.Post); IExecutionContext context = jobContext.CreateChild(Guid.NewGuid(), "Complete job", $"{nameof(JobExtension)}_Final", null, null);
using (var register = jobContext.CancellationToken.Register(() => { context.CancelToken(); })) using (var register = jobContext.CancellationToken.Register(() => { context.CancelToken(); }))
{ {
try try

View File

@@ -7,7 +7,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Net.Http; using System.Net.Http;
@@ -106,10 +105,6 @@ namespace GitHub.Runner.Worker
} }
jobContext.SetRunnerContext("os", VarUtil.OS); jobContext.SetRunnerContext("os", VarUtil.OS);
jobContext.SetRunnerContext("arch", VarUtil.OSArchitecture);
var runnerSettings = HostContext.GetService<IConfigurationStore>().GetSettings();
jobContext.SetRunnerContext("name", runnerSettings.AgentName);
string toolsDirectory = HostContext.GetDirectory(WellKnownDirectory.Tools); string toolsDirectory = HostContext.GetDirectory(WellKnownDirectory.Tools);
Directory.CreateDirectory(toolsDirectory); Directory.CreateDirectory(toolsDirectory);
@@ -230,15 +225,8 @@ namespace GitHub.Runner.Worker
return result; return result;
} }
// Load any upgrade telemetry
LoadFromTelemetryFile(jobContext.JobTelemetry);
// Make sure we don't submit secrets as telemetry
MaskTelemetrySecrets(jobContext.JobTelemetry);
Trace.Info("Raising job completed event."); Trace.Info("Raising job completed event.");
var jobCompletedEvent = new JobCompletedEvent(message.RequestId, message.JobId, result, jobContext.JobOutputs, jobContext.ActionsEnvironment, jobContext.ActionsStepsTelemetry, jobContext.JobTelemetry); var jobCompletedEvent = new JobCompletedEvent(message.RequestId, message.JobId, result, jobContext.JobOutputs, jobContext.ActionsEnvironment, jobContext.ActionsStepsTelemetry);
var completeJobRetryLimit = 5; var completeJobRetryLimit = 5;
var exceptions = new List<Exception>(); var exceptions = new List<Exception>();
@@ -282,38 +270,6 @@ namespace GitHub.Runner.Worker
throw new AggregateException(exceptions); throw new AggregateException(exceptions);
} }
private void MaskTelemetrySecrets(List<JobTelemetry> jobTelemetry)
{
foreach (var telemetryItem in jobTelemetry)
{
telemetryItem.Message = HostContext.SecretMasker.MaskSecrets(telemetryItem.Message);
}
}
private void LoadFromTelemetryFile(List<JobTelemetry> jobTelemetry)
{
try
{
var telemetryFilePath = HostContext.GetConfigFile(WellKnownConfigFile.Telemetry);
if (File.Exists(telemetryFilePath))
{
var telemetryData = File.ReadAllText(telemetryFilePath, Encoding.UTF8);
var telemetry = new JobTelemetry
{
Message = $"Runner File Telemetry:\n{telemetryData}",
Type = JobTelemetryType.General
};
jobTelemetry.Add(telemetry);
IOUtil.DeleteFile(telemetryFilePath);
}
}
catch (Exception e)
{
Trace.Error("Error when trying to load telemetry from telemetry file");
Trace.Error(e);
}
}
private async Task ShutdownQueue(bool throwOnFailure) private async Task ShutdownQueue(bool throwOnFailure)
{ {
if (_jobServerQueue != null) if (_jobServerQueue != null)

View File

@@ -1,10 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
<NoWarn>NU1701;NU1603</NoWarn> <NoWarn>NU1701;NU1603</NoWarn>
<Version>$(Version)</Version> <Version>$(Version)</Version>
<TieredCompilationQuickJit>true</TieredCompilationQuickJit> <TieredCompilationQuickJit>true</TieredCompilationQuickJit>

View File

@@ -123,7 +123,6 @@
"properties": { "properties": {
"name": "string-steps-context", "name": "string-steps-context",
"id": "non-empty-string", "id": "non-empty-string",
"if": "step-if",
"run": { "run": {
"type": "string-steps-context", "type": "string-steps-context",
"required": true "required": true
@@ -142,7 +141,6 @@
"properties": { "properties": {
"name": "string-steps-context", "name": "string-steps-context",
"id": "non-empty-string", "id": "non-empty-string",
"if": "step-if",
"uses": { "uses": {
"type": "non-empty-string", "type": "non-empty-string",
"required": true "required": true
@@ -218,24 +216,6 @@
"loose-value-type": "string" "loose-value-type": "string"
} }
}, },
"step-if": {
"context": [
"github",
"inputs",
"strategy",
"matrix",
"steps",
"job",
"runner",
"env",
"always(0,0)",
"failure(0,0)",
"cancelled(0,0)",
"success(0,0)",
"hashFiles(1,255)"
],
"string": {}
},
"step-with": { "step-with": {
"context": [ "context": [
"github", "github",

View File

@@ -28,6 +28,14 @@ namespace GitHub.Services.Common
} }
} }
public IDictionary<string, object> Properties
{
get
{
return m_request.Properties;
}
}
IEnumerable<String> IHttpHeaders.GetValues(String name) IEnumerable<String> IHttpHeaders.GetValues(String name)
{ {
IEnumerable<String> values; IEnumerable<String> values;

View File

@@ -14,5 +14,10 @@ namespace GitHub.Services.Common
{ {
get; get;
} }
IDictionary<string, object> Properties
{
get;
}
} }
} }

View File

@@ -20,11 +20,12 @@ namespace GitHub.Services.Common.Diagnostics
public static VssTraceActivity GetActivity(this HttpRequestMessage message) public static VssTraceActivity GetActivity(this HttpRequestMessage message)
{ {
if (!message.Options.TryGetValue(VssTraceActivity.PropertyName, out VssTraceActivity traceActivity)) Object traceActivity;
if (!message.Properties.TryGetValue(VssTraceActivity.PropertyName, out traceActivity))
{ {
return VssTraceActivity.Empty; return VssTraceActivity.Empty;
} }
return traceActivity; return (VssTraceActivity)traceActivity;
} }
} }
} }

View File

@@ -1,7 +1,6 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Net.Http;
namespace GitHub.Services.Common.Diagnostics namespace GitHub.Services.Common.Diagnostics
{ {
@@ -99,7 +98,7 @@ namespace GitHub.Services.Common.Diagnostics
/// <summary> /// <summary>
/// Gets the property name used to cache this object on extensible objects. /// Gets the property name used to cache this object on extensible objects.
/// </summary> /// </summary>
public static readonly HttpRequestOptionsKey<VssTraceActivity> PropertyName = new HttpRequestOptionsKey<VssTraceActivity>("MS.VSS.Diagnostics.TraceActivity"); public const String PropertyName = "MS.VSS.Diagnostics.TraceActivity";
private static Lazy<VssTraceActivity> s_empty = new Lazy<VssTraceActivity>(() => new VssTraceActivity(Guid.Empty)); private static Lazy<VssTraceActivity> s_empty = new Lazy<VssTraceActivity>(() => new VssTraceActivity(Guid.Empty));
private sealed class CorrelationScope : IDisposable private sealed class CorrelationScope : IDisposable

View File

@@ -110,7 +110,7 @@ namespace GitHub.Services.Common
} }
} }
internal static readonly HttpRequestOptionsKey<VssHttpMessageHandler> PropertyName = new HttpRequestOptionsKey<VssHttpMessageHandler>("MS.VS.MessageHandler"); internal static readonly String PropertyName = "MS.VS.MessageHandler";
/// <summary> /// <summary>
/// Handles the authentication hand-shake for a Visual Studio service. /// Handles the authentication hand-shake for a Visual Studio service.
@@ -169,7 +169,7 @@ namespace GitHub.Services.Common
} }
// Add ourselves to the message so the underlying token issuers may use it if necessary // Add ourselves to the message so the underlying token issuers may use it if necessary
request.Options.Set(VssHttpMessageHandler.PropertyName, this); request.Properties[VssHttpMessageHandler.PropertyName] = this;
Boolean succeeded = false; Boolean succeeded = false;
Boolean lastResponseDemandedProxyAuth = false; Boolean lastResponseDemandedProxyAuth = false;
@@ -409,7 +409,7 @@ namespace GitHub.Services.Common
// Read the completion option provided by the caller. If we don't find the property then we // Read the completion option provided by the caller. If we don't find the property then we
// assume it is OK to buffer by default. // assume it is OK to buffer by default.
HttpCompletionOption completionOption; HttpCompletionOption completionOption;
if (!request.Options.TryGetValue(VssHttpRequestSettings.HttpCompletionOptionPropertyName, out completionOption)) if (!request.Properties.TryGetValue(VssHttpRequestSettings.HttpCompletionOptionPropertyName, out completionOption))
{ {
completionOption = HttpCompletionOption.ResponseContentRead; completionOption = HttpCompletionOption.ResponseContentRead;
} }

View File

@@ -11,7 +11,7 @@ namespace GitHub.Services.Common
{ {
DateTime _lastTime; DateTime _lastTime;
private static readonly HttpRequestOptionsKey<VssHttpMessageHandlerTraceInfo> TfsTraceInfoKey = new HttpRequestOptionsKey<VssHttpMessageHandlerTraceInfo>("TFS_TraceInfo"); static readonly String TfsTraceInfoKey = "TFS_TraceInfo";
public int TokenRetries { get; internal set; } public int TokenRetries { get; internal set; }
@@ -76,9 +76,10 @@ namespace GitHub.Services.Common
/// <param name="traceInfo"></param> /// <param name="traceInfo"></param>
public static void SetTraceInfo(HttpRequestMessage message, VssHttpMessageHandlerTraceInfo traceInfo) public static void SetTraceInfo(HttpRequestMessage message, VssHttpMessageHandlerTraceInfo traceInfo)
{ {
if (!message.Options.TryGetValue(TfsTraceInfoKey, out var _)) object existingTraceInfo;
if (!message.Properties.TryGetValue(TfsTraceInfoKey, out existingTraceInfo))
{ {
message.Options.Set(TfsTraceInfoKey, traceInfo); message.Properties.Add(TfsTraceInfoKey, traceInfo);
} }
} }
@@ -89,8 +90,13 @@ namespace GitHub.Services.Common
/// <returns></returns> /// <returns></returns>
public static VssHttpMessageHandlerTraceInfo GetTraceInfo(HttpRequestMessage message) public static VssHttpMessageHandlerTraceInfo GetTraceInfo(HttpRequestMessage message)
{ {
VssHttpMessageHandlerTraceInfo traceInfo; VssHttpMessageHandlerTraceInfo traceInfo = null;
message.Options.TryGetValue(TfsTraceInfoKey, out traceInfo);
if (message.Properties.TryGetValue(TfsTraceInfoKey, out object traceInfoObject))
{
traceInfo = traceInfoObject as VssHttpMessageHandlerTraceInfo;
}
return traceInfo; return traceInfo;
} }

View File

@@ -291,12 +291,12 @@ namespace GitHub.Services.Common
protected internal virtual Boolean ApplyTo(HttpRequestMessage request) protected internal virtual Boolean ApplyTo(HttpRequestMessage request)
{ {
// Make sure we only apply the settings to the request once // Make sure we only apply the settings to the request once
if (request.Options.TryGetValue(PropertyName, out var _)) if (request.Properties.ContainsKey(PropertyName))
{ {
return false; return false;
} }
request.Options.Set(PropertyName, this); request.Properties.Add(PropertyName, this);
if (this.AcceptLanguages != null && this.AcceptLanguages.Count > 0) if (this.AcceptLanguages != null && this.AcceptLanguages.Count > 0)
{ {
@@ -366,12 +366,12 @@ namespace GitHub.Services.Common
/// <summary> /// <summary>
/// Gets the property name used to reference this object. /// Gets the property name used to reference this object.
/// </summary> /// </summary>
public static readonly HttpRequestOptionsKey<VssHttpRequestSettings> PropertyName = new HttpRequestOptionsKey<VssHttpRequestSettings>("MS.VS.RequestSettings"); public const String PropertyName = "MS.VS.RequestSettings";
/// <summary> /// <summary>
/// Gets the property name used to reference the completion option for a specific request. /// Gets the property name used to reference the completion option for a specific request.
/// </summary> /// </summary>
public static readonly HttpRequestOptionsKey<HttpCompletionOption> HttpCompletionOptionPropertyName = new HttpRequestOptionsKey<HttpCompletionOption>("MS.VS.HttpCompletionOption"); public const String HttpCompletionOptionPropertyName = "MS.VS.HttpCompletionOption";
/// <summary> /// <summary>
/// Header to include the light weight response client option. /// Header to include the light weight response client option.

View File

@@ -53,14 +53,23 @@ namespace GitHub.Services.Common
VssTraceActivity traceActivity = VssTraceActivity.Current; VssTraceActivity traceActivity = VssTraceActivity.Current;
// Allow overriding default retry options per request // Allow overriding default retry options per request
VssHttpRetryOptions retryOptions; VssHttpRetryOptions retryOptions = m_retryOptions;
request.Options.TryGetValue(HttpRetryOptionsKey, out retryOptions); object retryOptionsObject;
if (request.Properties.TryGetValue(HttpRetryOptionsKey, out retryOptionsObject)) // NETSTANDARD compliant, TryGetValue<T> is not
{
// Fallback to default options if object of unexpected type was passed
retryOptions = retryOptionsObject as VssHttpRetryOptions ?? m_retryOptions;
}
TimeSpan minBackoff = (retryOptions ?? m_retryOptions).MinBackoff; TimeSpan minBackoff = retryOptions.MinBackoff;
Int32 maxAttempts = (retryOptions ?? m_retryOptions).MaxRetries + 1; Int32 maxAttempts = retryOptions.MaxRetries + 1;
IVssHttpRetryInfo retryInfo = null; IVssHttpRetryInfo retryInfo = null;
request.Options.TryGetValue(HttpRetryInfoKey, out retryInfo); object retryInfoObject;
if (request.Properties.TryGetValue(HttpRetryInfoKey, out retryInfoObject)) // NETSTANDARD compliant, TryGetValue<T> is not
{
retryInfo = retryInfoObject as IVssHttpRetryInfo;
}
if (IsLowPriority(request)) if (IsLowPriority(request))
{ {
@@ -216,8 +225,8 @@ namespace GitHub.Services.Common
} }
private VssHttpRetryOptions m_retryOptions; private VssHttpRetryOptions m_retryOptions;
public static readonly HttpRequestOptionsKey<IVssHttpRetryInfo> HttpRetryInfoKey = new HttpRequestOptionsKey<IVssHttpRetryInfo>("HttpRetryInfo"); public const string HttpRetryInfoKey = "HttpRetryInfo";
public static readonly HttpRequestOptionsKey<VssHttpRetryOptions> HttpRetryOptionsKey = new HttpRequestOptionsKey<VssHttpRetryOptions>("VssHttpRetryOptions"); public const string HttpRetryOptionsKey = "VssHttpRetryOptions";
private string m_clientName = ""; private string m_clientName = "";
} }
} }

View File

@@ -638,7 +638,6 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Matrix), new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Matrix),
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Steps), new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Steps),
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.GitHub), new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.GitHub),
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Inputs),
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Job), new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Job),
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Runner), new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Runner),
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Env), new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Env),

View File

@@ -155,19 +155,6 @@ namespace GitHub.DistributedTask.WebApi
this.ActionsStepsTelemetry = actionsStepsTelemetry; this.ActionsStepsTelemetry = actionsStepsTelemetry;
} }
public JobCompletedEvent(
Int64 requestId,
Guid jobId,
TaskResult result,
Dictionary<String, VariableValue> outputs,
ActionsEnvironmentReference actionsEnvironment,
List<ActionsStepTelemetry> actionsStepsTelemetry,
List<JobTelemetry> jobTelemetry)
: this(requestId, jobId, result, outputs, actionsEnvironment, actionsStepsTelemetry)
{
this.JobTelemetry = jobTelemetry;
}
[DataMember(EmitDefaultValue = false)] [DataMember(EmitDefaultValue = false)]
public Int64 RequestId public Int64 RequestId
{ {
@@ -202,13 +189,6 @@ namespace GitHub.DistributedTask.WebApi
get; get;
set; set;
} }
[DataMember(EmitDefaultValue = false)]
public List<JobTelemetry> JobTelemetry
{
get;
set;
}
} }
[DataContract] [DataContract]

View File

@@ -1,17 +0,0 @@
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Information about a job run on the runner
/// </summary>
[DataContract]
public class JobTelemetry
{
[DataMember(EmitDefaultValue = false)]
public string Message { get; set; }
[DataMember(EmitDefaultValue = false)]
public JobTelemetryType Type { get; set; }
}
}

View File

@@ -1,13 +0,0 @@
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
public enum JobTelemetryType
{
[EnumMember]
General = 0,
[EnumMember]
ActionCommand = 1,
}
}

View File

@@ -1,10 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
<NoWarn>NU1701;NU1603</NoWarn> <NoWarn>NU1701;NU1603</NoWarn>
<Version>$(Version)</Version> <Version>$(Version)</Version>
<DefineConstants>TRACE</DefineConstants> <DefineConstants>TRACE</DefineConstants>

View File

@@ -833,7 +833,7 @@ namespace GitHub.Services.WebApi
{ {
if (userState != null) if (userState != null)
{ {
message.Options.Set(UserStatePropertyName, userState); message.Properties[UserStatePropertyName] = userState;
} }
if (!message.Headers.Contains(Common.Internal.HttpHeaders.VssE2EID)) if (!message.Headers.Contains(Common.Internal.HttpHeaders.VssE2EID))
@@ -842,11 +842,11 @@ namespace GitHub.Services.WebApi
} }
VssHttpEventSource.Log.HttpRequestStart(traceActivity, message); VssHttpEventSource.Log.HttpRequestStart(traceActivity, message);
message.Trace(); message.Trace();
message.Options.Set(VssTraceActivity.PropertyName, traceActivity); message.Properties[VssTraceActivity.PropertyName] = traceActivity;
// Send the completion option to the inner handler stack so we know when it's safe to buffer // Send the completion option to the inner handler stack so we know when it's safe to buffer
// and when we should avoid buffering. // and when we should avoid buffering.
message.Options.Set(VssHttpRequestSettings.HttpCompletionOptionPropertyName, completionOption); message.Properties[VssHttpRequestSettings.HttpCompletionOptionPropertyName] = completionOption;
//ConfigureAwait(false) enables the continuation to be run outside //ConfigureAwait(false) enables the continuation to be run outside
//any captured SyncronizationContext (such as ASP.NET's) which keeps things //any captured SyncronizationContext (such as ASP.NET's) which keeps things
@@ -1154,9 +1154,7 @@ namespace GitHub.Services.WebApi
{ {
if (BaseAddress != null) if (BaseAddress != null)
{ {
#pragma warning disable SYSLIB0014
ServicePoint servicePoint = ServicePointManager.FindServicePoint(BaseAddress); ServicePoint servicePoint = ServicePointManager.FindServicePoint(BaseAddress);
#pragma warning restore SYSLIB0014
servicePoint.UseNagleAlgorithm = false; servicePoint.UseNagleAlgorithm = false;
servicePoint.SetTcpKeepAlive( servicePoint.SetTcpKeepAlive(
enabled: true, enabled: true,
@@ -1274,7 +1272,7 @@ namespace GitHub.Services.WebApi
private const String c_jsonMediaType = "application/json"; private const String c_jsonMediaType = "application/json";
public static readonly HttpRequestOptionsKey<object> UserStatePropertyName = new HttpRequestOptionsKey<object>("VssClientBaseUserState"); public readonly static String UserStatePropertyName = "VssClientBaseUserState";
protected sealed class OperationScope : IDisposable protected sealed class OperationScope : IDisposable
{ {

View File

@@ -138,7 +138,7 @@ namespace GitHub.Services.WebApi
if (routeReplacementOptions.HasFlag(RouteReplacementOptions.EscapeUri)) if (routeReplacementOptions.HasFlag(RouteReplacementOptions.EscapeUri))
{ {
sbResult = new StringBuilder(Uri.EscapeDataString(sbResult.ToString())); sbResult = new StringBuilder(Uri.EscapeUriString(sbResult.ToString()));
} }
if (routeReplacementOptions.HasFlag(RouteReplacementOptions.AppendUnusedAsQueryParams) && unusedValues.Count > 0) if (routeReplacementOptions.HasFlag(RouteReplacementOptions.AppendUnusedAsQueryParams) && unusedValues.Count > 0)

View File

@@ -6,24 +6,27 @@ using System.Globalization;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Runtime.InteropServices;
namespace GitHub.Services.WebApi namespace GitHub.Services.WebApi
{ {
internal static class HttpMessageExtensions internal static class HttpMessageExtensions
{ {
private static readonly HttpRequestOptionsKey<VssRequestTimerTrace> tracerKey = new HttpRequestOptionsKey<VssRequestTimerTrace>("VSS_HTTP_TIMER_TRACE"); private const string tracerKey = "VSS_HTTP_TIMER_TRACE";
internal static void Trace(this HttpRequestMessage request) internal static void Trace(this HttpRequestMessage request)
{ {
VssRequestTimerTrace tracer; Object tracerObj = null;
if (request.Options.TryGetValue(tracerKey, out tracer)) VssRequestTimerTrace tracer = null;
if (request.Properties.TryGetValue(tracerKey, out tracerObj))
{ {
tracer = tracerObj as VssRequestTimerTrace;
Debug.Assert(tracer != null, "Tracer object is the wrong type!"); Debug.Assert(tracer != null, "Tracer object is the wrong type!");
} }
else else
{ {
tracer = new VssRequestTimerTrace(); tracer = new VssRequestTimerTrace();
request.Options.Set(tracerKey, tracer); request.Properties[tracerKey] = tracer;
} }
if (tracer != null) if (tracer != null)
@@ -34,9 +37,11 @@ namespace GitHub.Services.WebApi
internal static void Trace(this HttpResponseMessage response) internal static void Trace(this HttpResponseMessage response)
{ {
VssRequestTimerTrace tracer; Object tracerObj = null;
if (response.RequestMessage.Options.TryGetValue(tracerKey, out tracer)) VssRequestTimerTrace tracer = null;
if (response.RequestMessage.Properties.TryGetValue(tracerKey, out tracerObj))
{ {
tracer = tracerObj as VssRequestTimerTrace;
Debug.Assert(tracer != null, "Tracer object is the wrong type!"); Debug.Assert(tracer != null, "Tracer object is the wrong type!");
} }

View File

@@ -547,7 +547,6 @@ namespace GitHub.Runner.Common.Tests
} }
} }
#if OS_WINDOWS
[Fact] [Fact]
[Trait("Level", "L0")] [Trait("Level", "L0")]
[Trait("Category", nameof(CommandSettings))] [Trait("Category", nameof(CommandSettings))]
@@ -575,7 +574,6 @@ namespace GitHub.Runner.Common.Tests
Assert.Equal("some windows logon account", actual); Assert.Equal("some windows logon account", actual);
} }
} }
#endif
[Fact] [Fact]
[Trait("Level", "L0")] [Trait("Level", "L0")]

View File

@@ -161,8 +161,7 @@ namespace GitHub.Runner.Common.Tests.Listener.Configuration
"--work", _expectedWorkFolder, "--work", _expectedWorkFolder,
"--auth", _expectedAuthType, "--auth", _expectedAuthType,
"--token", _expectedToken, "--token", _expectedToken,
"--labels", userLabels, "--labels", userLabels
"--ephemeral",
}); });
trace.Info("Constructed."); trace.Info("Constructed.");
_store.Setup(x => x.IsConfigured()).Returns(false); _store.Setup(x => x.IsConfigured()).Returns(false);
@@ -180,7 +179,6 @@ namespace GitHub.Runner.Common.Tests.Listener.Configuration
Assert.True(s.AgentName.Equals(_expectedAgentName)); Assert.True(s.AgentName.Equals(_expectedAgentName));
Assert.True(s.PoolId.Equals(_secondRunnerGroupId)); Assert.True(s.PoolId.Equals(_secondRunnerGroupId));
Assert.True(s.WorkFolder.Equals(_expectedWorkFolder)); Assert.True(s.WorkFolder.Equals(_expectedWorkFolder));
Assert.True(s.Ephemeral.Equals(true));
// validate GetAgentPoolsAsync gets called twice with automation pool type // validate GetAgentPoolsAsync gets called twice with automation pool type
_runnerServer.Verify(x => x.GetAgentPoolsAsync(It.IsAny<string>(), It.Is<TaskAgentPoolType>(p => p == TaskAgentPoolType.Automation)), Times.Exactly(2)); _runnerServer.Verify(x => x.GetAgentPoolsAsync(It.IsAny<string>(), It.Is<TaskAgentPoolType>(p => p == TaskAgentPoolType.Automation)), Times.Exactly(2));

View File

@@ -264,170 +264,6 @@ namespace GitHub.Runner.Common.Tests.Listener
} }
} }
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Runner")]
public async void RenewJobRequestNewAgentNameUpdatesSettings()
{
//Arrange
using (var hc = new TestHostContext(this))
{
var count = 0;
var oldName = "OldName";
var newName = "NewName";
var oldSettings = new RunnerSettings { AgentName = oldName };
var reservedAgent = new TaskAgentReference { Name = newName };
var trace = hc.GetTrace(nameof(DispatcherRenewJobRequestStopOnJobTokenExpiredExceptions));
TaskCompletionSource<int> firstJobRequestRenewed = new TaskCompletionSource<int>();
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
var request = new Mock<TaskAgentJobRequest>();
request.Object.ReservedAgent = reservedAgent;
PropertyInfo lockUntilProperty = request.Object.GetType().GetProperty("LockedUntil", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
Assert.NotNull(lockUntilProperty);
lockUntilProperty.SetValue(request.Object, DateTime.UtcNow.AddMinutes(5));
hc.SetSingleton<IRunnerServer>(_runnerServer.Object);
hc.SetSingleton<IConfigurationStore>(_configurationStore.Object);
_configurationStore.Setup(x => x.GetSettings()).Returns(oldSettings);
_runnerServer.Setup(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
.Returns(() =>
{
count++;
if (count < 5)
{
return Task.FromResult<TaskAgentJobRequest>(request.Object);
}
else if (count == 5 || count == 6 || count == 7)
{
throw new TimeoutException("");
}
else
{
cancellationTokenSource.Cancel();
return Task.FromResult<TaskAgentJobRequest>(request.Object);
}
});
var jobDispatcher = new JobDispatcher();
jobDispatcher.Initialize(hc);
// Act
await jobDispatcher.RenewJobRequestAsync(0, 0, Guid.Empty, Guid.NewGuid().ToString(), firstJobRequestRenewed, cancellationTokenSource.Token);
// Assert
_configurationStore.Verify(x => x.SaveSettings(It.Is<RunnerSettings>(settings => settings.AgentName == newName)), Times.Once);
}
}
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Runner")]
public async void RenewJobRequestSameAgentNameIgnored()
{
//Arrange
using (var hc = new TestHostContext(this))
{
var count = 0;
var oldName = "OldName";
var newName = "OldName";
var oldSettings = new RunnerSettings { AgentName = oldName };
var reservedAgent = new TaskAgentReference { Name = newName };
var trace = hc.GetTrace(nameof(DispatcherRenewJobRequestStopOnJobTokenExpiredExceptions));
TaskCompletionSource<int> firstJobRequestRenewed = new TaskCompletionSource<int>();
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
var request = new Mock<TaskAgentJobRequest>();
request.Object.ReservedAgent = reservedAgent;
PropertyInfo lockUntilProperty = request.Object.GetType().GetProperty("LockedUntil", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
Assert.NotNull(lockUntilProperty);
lockUntilProperty.SetValue(request.Object, DateTime.UtcNow.AddMinutes(5));
hc.SetSingleton<IRunnerServer>(_runnerServer.Object);
hc.SetSingleton<IConfigurationStore>(_configurationStore.Object);
_configurationStore.Setup(x => x.GetSettings()).Returns(oldSettings);
_runnerServer.Setup(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
.Returns(() =>
{
count++;
if (count < 5)
{
return Task.FromResult<TaskAgentJobRequest>(request.Object);
}
else if (count == 5 || count == 6 || count == 7)
{
throw new TimeoutException("");
}
else
{
cancellationTokenSource.Cancel();
return Task.FromResult<TaskAgentJobRequest>(request.Object);
}
});
var jobDispatcher = new JobDispatcher();
jobDispatcher.Initialize(hc);
// Act
await jobDispatcher.RenewJobRequestAsync(0, 0, Guid.Empty, Guid.NewGuid().ToString(), firstJobRequestRenewed, cancellationTokenSource.Token);
// Assert
_configurationStore.Verify(x => x.SaveSettings(It.IsAny<RunnerSettings>()), Times.Never);
}
}
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Runner")]
public async void RenewJobRequestNullAgentNameIgnored()
{
//Arrange
using (var hc = new TestHostContext(this))
{
var count = 0;
var oldName = "OldName";
var oldSettings = new RunnerSettings { AgentName = oldName };
var trace = hc.GetTrace(nameof(DispatcherRenewJobRequestStopOnJobTokenExpiredExceptions));
TaskCompletionSource<int> firstJobRequestRenewed = new TaskCompletionSource<int>();
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
var request = new Mock<TaskAgentJobRequest>();
PropertyInfo lockUntilProperty = request.Object.GetType().GetProperty("LockedUntil", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
Assert.NotNull(lockUntilProperty);
lockUntilProperty.SetValue(request.Object, DateTime.UtcNow.AddMinutes(5));
hc.SetSingleton<IRunnerServer>(_runnerServer.Object);
hc.SetSingleton<IConfigurationStore>(_configurationStore.Object);
_configurationStore.Setup(x => x.GetSettings()).Returns(oldSettings);
_runnerServer.Setup(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
.Returns(() =>
{
count++;
if (count < 5)
{
return Task.FromResult<TaskAgentJobRequest>(request.Object);
}
else if (count == 5 || count == 6 || count == 7)
{
throw new TimeoutException("");
}
else
{
cancellationTokenSource.Cancel();
return Task.FromResult<TaskAgentJobRequest>(request.Object);
}
});
var jobDispatcher = new JobDispatcher();
jobDispatcher.Initialize(hc);
// Act
await jobDispatcher.RenewJobRequestAsync(0, 0, Guid.Empty, Guid.NewGuid().ToString(), firstJobRequestRenewed, cancellationTokenSource.Token);
// Assert
_configurationStore.Verify(x => x.SaveSettings(It.IsAny<RunnerSettings>()), Times.Never);
}
}
[Fact] [Fact]
[Trait("Level", "L0")] [Trait("Level", "L0")]
[Trait("Category", "Runner")] [Trait("Category", "Runner")]

View File

@@ -149,9 +149,6 @@ namespace GitHub.Runner.Common.Tests.Listener
_messageListener.Verify(x => x.CreateSessionAsync(It.IsAny<CancellationToken>()), Times.Once()); _messageListener.Verify(x => x.CreateSessionAsync(It.IsAny<CancellationToken>()), Times.Once());
_messageListener.Verify(x => x.DeleteSessionAsync(), Times.Once()); _messageListener.Verify(x => x.DeleteSessionAsync(), Times.Once());
_messageListener.Verify(x => x.DeleteMessageAsync(It.IsAny<TaskAgentMessage>()), Times.AtLeastOnce()); _messageListener.Verify(x => x.DeleteMessageAsync(It.IsAny<TaskAgentMessage>()), Times.AtLeastOnce());
// verify that we didn't try to delete local settings file (since we're not ephemeral)
_configurationManager.Verify(x => x.DeleteLocalRunnerConfig(), Times.Never());
} }
} }
} }
@@ -315,9 +312,6 @@ namespace GitHub.Runner.Common.Tests.Listener
_messageListener.Verify(x => x.CreateSessionAsync(It.IsAny<CancellationToken>()), Times.Once()); _messageListener.Verify(x => x.CreateSessionAsync(It.IsAny<CancellationToken>()), Times.Once());
_messageListener.Verify(x => x.DeleteSessionAsync(), Times.Once()); _messageListener.Verify(x => x.DeleteSessionAsync(), Times.Once());
_messageListener.Verify(x => x.DeleteMessageAsync(It.IsAny<TaskAgentMessage>()), Times.AtLeastOnce()); _messageListener.Verify(x => x.DeleteMessageAsync(It.IsAny<TaskAgentMessage>()), Times.AtLeastOnce());
// verify that we did try to delete local settings file (since we're ephemeral)
_configurationManager.Verify(x => x.DeleteLocalRunnerConfig(), Times.Once());
} }
} }

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using GitHub.DistributedTask.Pipelines.ContextData;
using GitHub.DistributedTask.WebApi; using GitHub.DistributedTask.WebApi;
using GitHub.Runner.Worker; using GitHub.Runner.Worker;
using GitHub.Runner.Worker.Container; using GitHub.Runner.Worker.Container;
@@ -84,7 +83,6 @@ namespace GitHub.Runner.Common.Tests.Worker
{ {
using (TestHostContext hc = CreateTestContext()) using (TestHostContext hc = CreateTestContext())
{ {
_ec.Setup(x => x.ExpressionValues).Returns(GetExpressionValues());
_ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>())) _ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>()))
.Returns((string tag, string line) => .Returns((string tag, string line) =>
{ {
@@ -107,88 +105,6 @@ namespace GitHub.Runner.Common.Tests.Worker
} }
} }
[Theory]
[InlineData("stop-commands", "1")]
[InlineData("", "1")]
[InlineData("set-env", "1")]
[InlineData("stop-commands", "true")]
[InlineData("", "true")]
[InlineData("set-env", "true")]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public void StopProcessCommand__AllowsInvalidStopTokens__IfEnvVarIsSet(string invalidToken, string allowUnsupportedStopCommandTokens)
{
using (TestHostContext hc = CreateTestContext())
{
_ec.Object.Global.EnvironmentVariables = new Dictionary<string, string>();
var expressionValues = new DictionaryContextData
{
["env"] =
#if OS_WINDOWS
new DictionaryContextData{ { Constants.Variables.Actions.AllowUnsupportedStopCommandTokens, new StringContextData(allowUnsupportedStopCommandTokens) }}
#else
new CaseSensitiveDictionaryContextData{ { Constants.Variables.Actions.AllowUnsupportedStopCommandTokens, new StringContextData(allowUnsupportedStopCommandTokens) }}
#endif
};
_ec.Setup(x => x.ExpressionValues).Returns(expressionValues);
_ec.Setup(x => x.JobTelemetry).Returns(new List<JobTelemetry>());
Assert.True(_commandManager.TryProcessCommand(_ec.Object, $"::stop-commands::{invalidToken}", null));
}
}
[Theory]
[InlineData("stop-commands")]
[InlineData("")]
[InlineData("set-env")]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public void StopProcessCommand__FailOnInvalidStopTokens(string invalidToken)
{
using (TestHostContext hc = CreateTestContext())
{
_ec.Object.Global.EnvironmentVariables = new Dictionary<string, string>();
_ec.Setup(x => x.ExpressionValues).Returns(GetExpressionValues());
_ec.Setup(x => x.JobTelemetry).Returns(new List<JobTelemetry>());
Assert.Throws<Exception>(() => _commandManager.TryProcessCommand(_ec.Object, $"::stop-commands::{invalidToken}", null));
}
}
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public void StopProcessCommandAcceptsValidToken()
{
var validToken = "randomToken";
using (TestHostContext hc = CreateTestContext())
{
_ec.Setup(x => x.ExpressionValues).Returns(GetExpressionValues());
Assert.True(_commandManager.TryProcessCommand(_ec.Object, $"::stop-commands::{validToken}", null));
Assert.False(_commandManager.TryProcessCommand(_ec.Object, "##[set-env name=foo]bar", null));
Assert.True(_commandManager.TryProcessCommand(_ec.Object, $"::{validToken}::", null));
Assert.True(_commandManager.TryProcessCommand(_ec.Object, "##[set-env name=foo]bar", null));
}
}
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public void StopProcessCommandMasksValidTokenForEntireRun()
{
var validToken = "randomToken";
using (TestHostContext hc = CreateTestContext())
{
_ec.Setup(x => x.ExpressionValues).Returns(GetExpressionValues());
Assert.True(_commandManager.TryProcessCommand(_ec.Object, $"::stop-commands::{validToken}", null));
Assert.False(_commandManager.TryProcessCommand(_ec.Object, "##[set-env name=foo]bar", null));
Assert.Equal("***", hc.SecretMasker.MaskSecrets(validToken));
Assert.True(_commandManager.TryProcessCommand(_ec.Object, $"::{validToken}::", null));
Assert.True(_commandManager.TryProcessCommand(_ec.Object, "##[set-env name=foo]bar", null));
Assert.Equal("***", hc.SecretMasker.MaskSecrets(validToken));
}
}
[Fact] [Fact]
[Trait("Level", "L0")] [Trait("Level", "L0")]
[Trait("Category", "Worker")] [Trait("Category", "Worker")]
@@ -286,7 +202,7 @@ namespace GitHub.Runner.Common.Tests.Worker
return 1; return 1;
}); });
var registeredCommands = new HashSet<string>(new string[1] { "warning" }); var registeredCommands = new HashSet<string>(new string[1]{ "warning" });
ActionCommand command; ActionCommand command;
// Columns when lines are different // Columns when lines are different
@@ -459,19 +375,5 @@ namespace GitHub.Runner.Common.Tests.Worker
return hostContext; return hostContext;
} }
private DictionaryContextData GetExpressionValues()
{
return new DictionaryContextData
{
["env"] =
#if OS_WINDOWS
new DictionaryContextData()
#else
new CaseSensitiveDictionaryContextData()
#endif
};
}
} }
} }

View File

@@ -628,32 +628,6 @@ namespace GitHub.Runner.Common.Tests.Worker
} }
} }
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public void Load_ConditionalCompositeAction()
{
try
{
//Arrange
Setup();
var actionManifest = new ActionManifestManager();
actionManifest.Initialize(_hc);
//Act
var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "conditional_composite_action.yml"));
//Assert
Assert.Equal("Conditional Composite", result.Name);
Assert.Equal(ActionExecutionType.Composite, result.Execution.ExecutionType);
}
finally
{
Teardown();
}
}
[Fact] [Fact]
[Trait("Level", "L0")] [Trait("Level", "L0")]
[Trait("Category", "Worker")] [Trait("Category", "Worker")]

View File

@@ -193,9 +193,9 @@ namespace GitHub.Runner.Common.Tests.Worker
// Act. // Act.
jobContext.InitializeJob(jobRequest, CancellationToken.None); jobContext.InitializeJob(jobRequest, CancellationToken.None);
var action1 = jobContext.CreateChild(Guid.NewGuid(), "action_1", "action_1", null, null, 0); var action1 = jobContext.CreateChild(Guid.NewGuid(), "action_1", "action_1", null, null);
action1.IntraActionState["state"] = "1"; action1.IntraActionState["state"] = "1";
var action2 = jobContext.CreateChild(Guid.NewGuid(), "action_2", "action_2", null, null, 0); var action2 = jobContext.CreateChild(Guid.NewGuid(), "action_2", "action_2", null, null);
action2.IntraActionState["state"] = "2"; action2.IntraActionState["state"] = "2";
@@ -291,8 +291,8 @@ namespace GitHub.Runner.Common.Tests.Worker
// Act. // Act.
jobContext.InitializeJob(jobRequest, CancellationToken.None); jobContext.InitializeJob(jobRequest, CancellationToken.None);
var action1 = jobContext.CreateChild(Guid.NewGuid(), "action_1_pre", "action_1_pre", null, null, 0); var action1 = jobContext.CreateChild(Guid.NewGuid(), "action_1_pre", "action_1_pre", null, null);
var action2 = jobContext.CreateChild(Guid.NewGuid(), "action_1_main", "action_1_main", null, null, 0); var action2 = jobContext.CreateChild(Guid.NewGuid(), "action_1_main", "action_1_main", null, null);
var actionId = Guid.NewGuid(); var actionId = Guid.NewGuid();
var postRunner1 = hc.CreateService<IActionRunner>(); var postRunner1 = hc.CreateService<IActionRunner>();

View File

@@ -105,36 +105,6 @@ namespace GitHub.Runner.Common.Tests.Worker.Expressions
} }
} }
[Theory]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
[InlineData(ActionResult.Failure, ActionResult.Failure, true)]
[InlineData(ActionResult.Failure, ActionResult.Success, false)]
[InlineData(ActionResult.Success, ActionResult.Failure, true)]
[InlineData(ActionResult.Success, ActionResult.Success, false)]
[InlineData(ActionResult.Success, null, false)]
public void FailureFunctionComposite(ActionResult jobStatus, ActionResult? actionStatus, bool expected)
{
using (TestHostContext hc = CreateTestContext())
{
// Arrange
var executionContext = InitializeExecutionContext(hc);
executionContext.Setup(x => x.GetGitHubContext("action_status")).Returns(actionStatus.ToString());
executionContext.Setup( x=> x.IsEmbedded).Returns(true);
executionContext.Setup( x=> x.Stage).Returns(ActionRunStage.Main);
_jobContext.Status = jobStatus;
// Act.
bool actual = Evaluate("failure()");
// Assert.
Assert.Equal(expected, actual);
}
}
[Fact] [Fact]
[Trait("Level", "L0")] [Trait("Level", "L0")]
[Trait("Category", "Worker")] [Trait("Category", "Worker")]
@@ -164,43 +134,12 @@ namespace GitHub.Runner.Common.Tests.Worker.Expressions
} }
} }
[Theory]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
[InlineData(ActionResult.Failure, ActionResult.Failure, false)]
[InlineData(ActionResult.Failure, ActionResult.Success, true)]
[InlineData(ActionResult.Success, ActionResult.Failure, false)]
[InlineData(ActionResult.Success, ActionResult.Success, true)]
[InlineData(ActionResult.Success, null, true)]
public void SuccessFunctionComposite(ActionResult jobStatus, ActionResult? actionStatus, bool expected)
{
using (TestHostContext hc = CreateTestContext())
{
// Arrange
var executionContext = InitializeExecutionContext(hc);
executionContext.Setup(x => x.GetGitHubContext("action_status")).Returns(actionStatus.ToString());
executionContext.Setup( x=> x.IsEmbedded).Returns(true);
executionContext.Setup( x=> x.Stage).Returns(ActionRunStage.Main);
_jobContext.Status = jobStatus;
// Act.
bool actual = Evaluate("success()");
// Assert.
Assert.Equal(expected, actual);
}
}
private TestHostContext CreateTestContext([CallerMemberName] String testName = "") private TestHostContext CreateTestContext([CallerMemberName] String testName = "")
{ {
return new TestHostContext(this, testName); return new TestHostContext(this, testName);
} }
private Mock<IExecutionContext> InitializeExecutionContext(TestHostContext hc) private void InitializeExecutionContext(TestHostContext hc)
{ {
_jobContext = new JobContext(); _jobContext = new JobContext();
@@ -210,8 +149,6 @@ namespace GitHub.Runner.Common.Tests.Worker.Expressions
_templateContext = new TemplateContext(); _templateContext = new TemplateContext();
_templateContext.State[nameof(IExecutionContext)] = executionContext.Object; _templateContext.State[nameof(IExecutionContext)] = executionContext.Object;
return executionContext;
} }
private bool Evaluate(string expression) private bool Evaluate(string expression)

View File

@@ -1,8 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
<NoWarn>NU1701;NU1603;NU1603;xUnit2013;</NoWarn> <NoWarn>NU1701;NU1603;NU1603;xUnit2013;</NoWarn>
</PropertyGroup> </PropertyGroup>

View File

@@ -1,49 +0,0 @@
name: 'Conditional Composite'
description: 'Test composite run step conditionals'
inputs:
exit-code:
description: 'Action fails if set to non-zero'
default: '0'
outputs:
default:
description: "Did step run with default?"
value: ${{ steps.default-conditional.outputs.default }}
success:
description: "Did step run with success?"
value: ${{ steps.success-conditional.outputs.success }}
failure:
description: "Did step run with failure?"
value: ${{ steps.failure-conditional.outputs.failure }}
always:
description: "Did step run with always?"
value: ${{ steps.always-conditional.outputs.always }}
runs:
using: "composite"
steps:
- run: exit ${{ inputs.exit-code }}
shell: bash
- run: echo "::set-output name=default::true"
id: default-conditional
shell: bash
- run: echo "::set-output name=success::true"
id: success-conditional
shell: bash
if: success()
- run: echo "::set-output name=failure::true"
id: failure-conditional
shell: bash
if: failure()
- run: echo "::set-output name=always::true"
id: always-conditional
shell: bash
if: always()
- run: echo "failed"
shell: bash
if: ${{ inputs.exit-code == 1 && failure() }}

View File

@@ -14,10 +14,10 @@ DEV_TARGET_RUNTIME=$3
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LAYOUT_DIR="$SCRIPT_DIR/../_layout" LAYOUT_DIR="$SCRIPT_DIR/../_layout"
DOWNLOAD_DIR="$SCRIPT_DIR/../_downloads/net6" 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="6.0.100" DOTNETSDK_VERSION="3.1.302"
DOTNETSDK_INSTALLDIR="$DOTNETSDK_ROOT/$DOTNETSDK_VERSION" DOTNETSDK_INSTALLDIR="$DOTNETSDK_ROOT/$DOTNETSDK_VERSION"
RUNNER_VERSION=$(cat runnerversion) RUNNER_VERSION=$(cat runnerversion)

View File

@@ -1,5 +1,5 @@
{ {
"sdk": { "sdk": {
"version": "net6" "version": "3.1.302"
} }
} }

View File

@@ -1 +1 @@
2.284.0 2.282.1