mirror of
https://github.com/actions/runner.git
synced 2025-12-10 20:36:49 +00:00
Compare commits
7 Commits
features/n
...
brcrista/m
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d8a53aa04a | ||
|
|
9fe65b872a | ||
|
|
ec420bab24 | ||
|
|
07cda747b2 | ||
|
|
9ca132380c | ||
|
|
a5a0f8df47 | ||
|
|
ccf53338be |
@@ -5,7 +5,7 @@
|
||||
# GitHub Actions Runner
|
||||
|
||||
[](https://github.com/actions/runner/actions)
|
||||
[](https://github.com/actions-canary/actions-runner-e2e/actions/workflows/runner_e2etest.yml)
|
||||
[](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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -1,20 +1,11 @@
|
||||
## Features
|
||||
|
||||
- Expose GITHUB_REF_* as environment variable (#1314)
|
||||
- Add arch to runner context (#1372)
|
||||
- Support Conditional Steps in Composite Actions (#1438)
|
||||
- Log current runner version in terminal (#1441)
|
||||
|
||||
## Bugs
|
||||
|
||||
- Makes the user keychains available to the service (#847)
|
||||
- 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)
|
||||
- Fixed an issue where ephemeral runners did not restart after upgrading (#1396)
|
||||
|
||||
## Misc
|
||||
|
||||
- Cleanup Older versions on MacOS now that we recreate node versions as needed (#1410)
|
||||
|
||||
## 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.
|
||||
|
||||
|
||||
@@ -161,13 +161,59 @@ if [[ "$currentplatform" == 'darwin' && restartinteractiverunner -eq 0 ]]; then
|
||||
date "+[%F %T-%4N] DarwinRunnerUpgrade: Failed to find runner path. Path: $path, pgid: $procgroup, root: $rootfolder" >> "$telemetryfile" 2>&1
|
||||
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
|
||||
|
||||
if [ $attemptedtargetedfix -eq 0 ]
|
||||
then
|
||||
|
||||
date "+[%F %T-%4N] DarwinRunnerUpgrade: Defaulting to old macOS service fix" >> "$logfile" 2>&1
|
||||
date "+[%F %T-%4N] DarwinRunnerUpgrade: Defaulting to old macOS service fix" >> "$telemetryfile" 2>&1
|
||||
if [[ ! -e "$rootfolder/externals.2.280.3/node12/bin/node" ]]
|
||||
then
|
||||
mkdir -p "$rootfolder/externals.2.280.3/node12/bin"
|
||||
cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.280.3/node12/bin/node"
|
||||
fi
|
||||
|
||||
if [[ ! -e "$rootfolder/externals.2.280.2/node12/bin/node" ]]
|
||||
then
|
||||
mkdir -p "$rootfolder/externals.2.280.2/node12/bin"
|
||||
cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.280.2/node12/bin/node"
|
||||
fi
|
||||
|
||||
if [[ ! -e "$rootfolder/externals.2.280.1/node12/bin/node" ]]
|
||||
then
|
||||
mkdir -p "$rootfolder/externals.2.280.1/node12/bin"
|
||||
cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.280.1/node12/bin/node"
|
||||
fi
|
||||
|
||||
# GHES 3.2
|
||||
if [[ ! -e "$rootfolder/externals.2.279.0/node12/bin/node" ]]
|
||||
then
|
||||
mkdir -p "$rootfolder/externals.2.279.0/node12/bin"
|
||||
cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.279.0/node12/bin/node"
|
||||
fi
|
||||
|
||||
# GHES 3.1.2 or later
|
||||
if [[ ! -e "$rootfolder/externals.2.278.0/node12/bin/node" ]]
|
||||
then
|
||||
mkdir -p "$rootfolder/externals.2.278.0/node12/bin"
|
||||
cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.278.0/node12/bin/node"
|
||||
fi
|
||||
|
||||
# GHES 3.1.0
|
||||
if [[ ! -e "$rootfolder/externals.2.276.1/node12/bin/node" ]]
|
||||
then
|
||||
mkdir -p "$rootfolder/externals.2.276.1/node12/bin"
|
||||
cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.276.1/node12/bin/node"
|
||||
fi
|
||||
|
||||
# GHES 3.0
|
||||
if [[ ! -e "$rootfolder/externals.2.273.5/node12/bin/node" ]]
|
||||
then
|
||||
mkdir -p "$rootfolder/externals.2.273.5/node12/bin"
|
||||
cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.273.5/node12/bin/node"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -38,8 +38,7 @@ namespace GitHub.Runner.Common
|
||||
public async Task ConnectAsync(VssConnection jobConnection)
|
||||
{
|
||||
_connection = jobConnection;
|
||||
int totalAttempts = 5;
|
||||
int attemptCount = totalAttempts;
|
||||
int attemptCount = 5;
|
||||
var configurationStore = HostContext.GetService<IConfigurationStore>();
|
||||
var runnerSettings = configurationStore.GetSettings();
|
||||
|
||||
@@ -57,21 +56,18 @@ namespace GitHub.Runner.Common
|
||||
|
||||
if (runnerSettings.IsHostedServer)
|
||||
{
|
||||
await CheckNetworkEndpointsAsync(attemptCount);
|
||||
await CheckNetworkEndpointsAsync();
|
||||
}
|
||||
}
|
||||
|
||||
int attempt = totalAttempts - attemptCount;
|
||||
TimeSpan backoff = BackoffTimerHelper.GetExponentialBackoff(attempt, TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(3.2), TimeSpan.FromMilliseconds(100));
|
||||
|
||||
await Task.Delay(backoff);
|
||||
await Task.Delay(100);
|
||||
}
|
||||
|
||||
_taskClient = _connection.GetClient<TaskHttpClient>();
|
||||
_hasConnection = true;
|
||||
}
|
||||
|
||||
private async Task CheckNetworkEndpointsAsync(int attemptsLeft)
|
||||
private async Task CheckNetworkEndpointsAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -83,8 +79,8 @@ namespace GitHub.Runner.Common
|
||||
|
||||
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}"));
|
||||
// Call the _apis/health endpoint
|
||||
var response = await actionsClient.GetAsync(new Uri(baseUri, "_apis/health"));
|
||||
Trace.Info($"Actions health status code: {response.StatusCode}");
|
||||
}
|
||||
}
|
||||
@@ -104,8 +100,8 @@ namespace GitHub.Runner.Common
|
||||
{
|
||||
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}");
|
||||
// Call the api.github.com endpoint
|
||||
var response = await gitHubClient.GetAsync("https://api.github.com");
|
||||
Trace.Info($"api.github.com status code: {response.StatusCode}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<OutputType>Library</OutputType>
|
||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
||||
<NoWarn>NU1701;NU1603</NoWarn>
|
||||
<Version>$(Version)</Version>
|
||||
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
||||
|
||||
@@ -243,7 +243,6 @@ namespace GitHub.Runner.Listener
|
||||
validator: Validators.ServerUrlValidator);
|
||||
}
|
||||
|
||||
#if OS_WINDOWS
|
||||
public string GetWindowsLogonAccount(string defaultValue, string descriptionMsg)
|
||||
{
|
||||
return GetArgOrPrompt(
|
||||
@@ -252,7 +251,6 @@ namespace GitHub.Runner.Listener
|
||||
defaultValue: defaultValue,
|
||||
validator: Validators.NTAccountValidator);
|
||||
}
|
||||
#endif
|
||||
|
||||
public string GetWindowsLogonPassword(string accountName)
|
||||
{
|
||||
|
||||
@@ -67,7 +67,6 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
return !string.IsNullOrEmpty(value);
|
||||
}
|
||||
|
||||
#if OS_WINDOWS
|
||||
public static bool NTAccountValidator(string arg)
|
||||
{
|
||||
if (string.IsNullOrEmpty(arg) || String.IsNullOrEmpty(arg.TrimStart('.', '\\')))
|
||||
@@ -88,6 +87,5 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ namespace GitHub.Runner.Listener
|
||||
|
||||
private static void LoadAndSetEnv()
|
||||
{
|
||||
var binDir = Path.GetDirectoryName(AppContext.BaseDirectory);
|
||||
var binDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
|
||||
var rootDir = new DirectoryInfo(binDir).Parent.FullName;
|
||||
string envFile = Path.Combine(rootDir, ".env");
|
||||
if (File.Exists(envFile))
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
||||
<NoWarn>NU1701;NU1603</NoWarn>
|
||||
<Version>$(Version)</Version>
|
||||
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
||||
|
||||
@@ -312,8 +312,6 @@ namespace GitHub.Runner.Listener
|
||||
}
|
||||
|
||||
HostContext.WritePerfCounter("SessionCreated");
|
||||
|
||||
_term.WriteLine($"Current runner version: '{BuildConstants.RunnerPackage.Version}'");
|
||||
_term.WriteLine($"{DateTime.UtcNow:u}: Listening for Jobs");
|
||||
|
||||
IJobDispatcher jobDispatcher = null;
|
||||
|
||||
@@ -75,9 +75,11 @@ namespace GitHub.Runner.Listener
|
||||
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
|
||||
#if !OS_OSX
|
||||
// delete runner backup
|
||||
DeletePreviousVersionRunnerBackup(token);
|
||||
Trace.Info($"Delete old version runner backup.");
|
||||
#endif
|
||||
// generate update script from template
|
||||
await UpdateRunnerUpdateStateAsync("Generate and execute update script.");
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ namespace GitHub.Runner.PluginHost
|
||||
string assemblyFilename = assembly.Name + ".dll";
|
||||
if (string.IsNullOrEmpty(executingAssemblyLocation))
|
||||
{
|
||||
executingAssemblyLocation = Path.GetDirectoryName(AppContext.BaseDirectory);
|
||||
executingAssemblyLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
}
|
||||
return context.LoadFromAssemblyPath(Path.Combine(executingAssemblyLocation, assemblyFilename));
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
||||
<NoWarn>NU1701;NU1603</NoWarn>
|
||||
<Version>$(Version)</Version>
|
||||
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
||||
|
||||
@@ -444,7 +444,7 @@ namespace GitHub.Runner.Plugins.Artifact
|
||||
{
|
||||
// We should never
|
||||
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)
|
||||
{
|
||||
context.Output($"File error '{ex.Message}' when uploading file '{fileToUpload}'.");
|
||||
throw;
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<OutputType>Library</OutputType>
|
||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
||||
<NoWarn>NU1701;NU1603</NoWarn>
|
||||
<Version>$(Version)</Version>
|
||||
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<OutputType>Library</OutputType>
|
||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
||||
<NoWarn>NU1701;NU1603</NoWarn>
|
||||
<Version>$(Version)</Version>
|
||||
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
||||
|
||||
@@ -267,19 +267,6 @@ namespace GitHub.Runner.Worker
|
||||
_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1047,6 +1034,7 @@ namespace GitHub.Runner.Worker
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove once we remove the DistributedTask.EnableCompositeActions FF
|
||||
foreach (var step in compositeAction.Steps)
|
||||
{
|
||||
if (string.IsNullOrEmpty(executionContext.Global.Variables.Get("DistributedTask.EnableCompositeActions")) && step.Reference.Type != Pipelines.ActionSourceType.Script)
|
||||
|
||||
@@ -262,6 +262,16 @@ namespace GitHub.Runner.Worker
|
||||
environment[$"STATE_{state.Key}"] = state.Value ?? string.Empty;
|
||||
}
|
||||
|
||||
// HACK
|
||||
if (Action.DisplayName != null && Action.DisplayName.StartsWith("make dependency"))
|
||||
{
|
||||
var target = Action.DisplayName.Split()[2];
|
||||
inputs = new Dictionary<string, string>
|
||||
{
|
||||
["script"] = $"make {target}"
|
||||
};
|
||||
}
|
||||
|
||||
// Create the handler.
|
||||
IHandler handler = handlerFactory.Create(
|
||||
ExecutionContext,
|
||||
|
||||
@@ -40,7 +40,6 @@ namespace GitHub.Runner.Worker
|
||||
string ScopeName { get; }
|
||||
string SiblingScopeName { get; }
|
||||
string ContextName { get; }
|
||||
ActionRunStage Stage { get; }
|
||||
Task ForceCompleted { get; }
|
||||
TaskResult? Result { get; set; }
|
||||
TaskResult? Outcome { get; set; }
|
||||
@@ -63,7 +62,7 @@ namespace GitHub.Runner.Worker
|
||||
|
||||
// Only job level ExecutionContext has PostJobSteps
|
||||
Stack<IStep> PostJobSteps { get; }
|
||||
Dictionary<Guid, string> EmbeddedStepsWithPostRegistered { get; }
|
||||
HashSet<Guid> EmbeddedStepsWithPostRegistered{ get; }
|
||||
|
||||
// Keep track of embedded steps states
|
||||
Dictionary<Guid, Dictionary<string, string>> EmbeddedIntraActionState { get; }
|
||||
@@ -77,8 +76,8 @@ namespace GitHub.Runner.Worker
|
||||
// Initialize
|
||||
void InitializeJob(Pipelines.AgentJobRequestMessage message, CancellationToken token);
|
||||
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 CreateEmbeddedChild(string scopeName, string contextName, Guid embeddedId, ActionRunStage stage, Dictionary<string, string> intraActionState = null, 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, Dictionary<string, string> intraActionState = null, string siblingScopeName = null);
|
||||
|
||||
// logging
|
||||
long Write(string tag, string message);
|
||||
@@ -145,7 +144,6 @@ namespace GitHub.Runner.Worker
|
||||
public string ScopeName { get; private set; }
|
||||
public string SiblingScopeName { get; private set; }
|
||||
public string ContextName { get; private set; }
|
||||
public ActionRunStage Stage { get; private set; }
|
||||
public Task ForceCompleted => _forceCompleted.Task;
|
||||
public CancellationToken CancellationToken => _cancellationTokenSource.Token;
|
||||
public Dictionary<string, string> IntraActionState { get; private set; }
|
||||
@@ -170,7 +168,7 @@ namespace GitHub.Runner.Worker
|
||||
public HashSet<Guid> StepsWithPostRegistered { get; private set; }
|
||||
|
||||
// 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; }
|
||||
|
||||
@@ -267,18 +265,11 @@ namespace GitHub.Runner.Worker
|
||||
string siblingScopeName = null;
|
||||
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.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Root.EmbeddedStepsWithPostRegistered[actionRunner.Action.Id] = actionRunner.Condition;
|
||||
}
|
||||
return;
|
||||
Trace.Info($"'post' of '{actionRunner.DisplayName}' already push to child post step stack.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (step is IActionRunner actionRunner && !Root.StepsWithPostRegistered.Add(actionRunner.Action.Id))
|
||||
{
|
||||
@@ -294,7 +285,7 @@ namespace GitHub.Runner.Worker
|
||||
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();
|
||||
|
||||
@@ -303,7 +294,6 @@ namespace GitHub.Runner.Worker
|
||||
child.Global = Global;
|
||||
child.ScopeName = scopeName;
|
||||
child.ContextName = contextName;
|
||||
child.Stage = stage;
|
||||
child.EmbeddedId = embeddedId;
|
||||
child.SiblingScopeName = siblingScopeName;
|
||||
child.JobTelemetry = JobTelemetry;
|
||||
@@ -354,9 +344,9 @@ namespace GitHub.Runner.Worker
|
||||
/// An embedded execution context shares the same record ID, record name, logger,
|
||||
/// and a linked cancellation token.
|
||||
/// </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)
|
||||
@@ -726,10 +716,10 @@ namespace GitHub.Runner.Worker
|
||||
StepsWithPostRegistered = new HashSet<Guid>();
|
||||
|
||||
// EmbeddedStepsWithPostRegistered for job ExecutionContext
|
||||
EmbeddedStepsWithPostRegistered = new Dictionary<Guid, string>();
|
||||
EmbeddedStepsWithPostRegistered = new HashSet<Guid>();
|
||||
|
||||
// EmbeddedIntraActionState for job ExecutionContext
|
||||
EmbeddedIntraActionState = new Dictionary<Guid, Dictionary<string, string>>();
|
||||
EmbeddedIntraActionState = new Dictionary<Guid, Dictionary<string,string>>();
|
||||
|
||||
// Job timeline record.
|
||||
InitializeTimelineRecord(
|
||||
@@ -947,7 +937,7 @@ namespace GitHub.Runner.Worker
|
||||
}
|
||||
|
||||
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 +970,7 @@ namespace GitHub.Runner.Worker
|
||||
// Do not add a format string overload. See comment on ExecutionContext.Write().
|
||||
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().
|
||||
|
||||
@@ -24,19 +24,8 @@ namespace GitHub.Runner.Worker.Expressions
|
||||
ArgUtil.NotNull(templateContext, nameof(templateContext));
|
||||
var executionContext = templateContext.State[nameof(IExecutionContext)] as IExecutionContext;
|
||||
ArgUtil.NotNull(executionContext, nameof(executionContext));
|
||||
|
||||
// Decide based on 'action_status' for composite MAIN steps and 'job.status' for pre, post and job-level steps
|
||||
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;
|
||||
}
|
||||
ActionResult jobStatus = executionContext.JobContext.Status ?? ActionResult.Success;
|
||||
return jobStatus == ActionResult.Failure;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace GitHub.Runner.Worker.Expressions
|
||||
context.Trace.Info($"Search root directory: '{githubWorkspace}'");
|
||||
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 node = Path.Combine(runnerRoot, "externals", "node12", "bin", $"node{IOUtil.ExeExtension}");
|
||||
|
||||
@@ -24,19 +24,8 @@ namespace GitHub.Runner.Worker.Expressions
|
||||
ArgUtil.NotNull(templateContext, nameof(templateContext));
|
||||
var executionContext = templateContext.State[nameof(IExecutionContext)] as IExecutionContext;
|
||||
ArgUtil.NotNull(executionContext, nameof(executionContext));
|
||||
|
||||
// Decide based on 'action_status' for composite MAIN steps and 'job.status' for pre, post and job-level steps
|
||||
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;
|
||||
}
|
||||
ActionResult jobStatus = executionContext.JobContext.Status ?? ActionResult.Success;
|
||||
return jobStatus == ActionResult.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,9 +23,6 @@ namespace GitHub.Runner.Worker
|
||||
"job",
|
||||
"path",
|
||||
"ref",
|
||||
"ref_name",
|
||||
"ref_protected",
|
||||
"ref_type",
|
||||
"repository",
|
||||
"repository_owner",
|
||||
"retention_days",
|
||||
@@ -42,16 +39,9 @@ namespace GitHub.Runner.Worker
|
||||
{
|
||||
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);
|
||||
}
|
||||
else if (data.Value is BooleanContextData booleanValue)
|
||||
{
|
||||
yield return new KeyValuePair<string, string>($"GITHUB_{data.Key.ToUpperInvariant()}", booleanValue.ToString());
|
||||
}
|
||||
yield return new KeyValuePair<string, string>($"GITHUB_{data.Key.ToUpperInvariant()}", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,9 +50,8 @@ namespace GitHub.Runner.Worker.Handlers
|
||||
// Only register post steps for steps that actually ran
|
||||
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);
|
||||
}
|
||||
else
|
||||
@@ -125,7 +124,7 @@ namespace GitHub.Runner.Worker.Handlers
|
||||
{
|
||||
ArgUtil.NotNull(step, step.DisplayName);
|
||||
var stepId = $"__{Guid.NewGuid()}";
|
||||
step.ExecutionContext = ExecutionContext.CreateEmbeddedChild(childScopeName, stepId, Guid.NewGuid(), stage);
|
||||
step.ExecutionContext = ExecutionContext.CreateEmbeddedChild(childScopeName, stepId, Guid.NewGuid());
|
||||
embeddedSteps.Add(step);
|
||||
}
|
||||
}
|
||||
@@ -144,7 +143,7 @@ namespace GitHub.Runner.Worker.Handlers
|
||||
step.Stage = stage;
|
||||
step.Condition = stepData.Condition;
|
||||
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;
|
||||
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<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
|
||||
Trace.Info("Initialize Env context for embedded step");
|
||||
#if OS_WINDOWS
|
||||
@@ -300,100 +295,108 @@ namespace GitHub.Runner.Worker.Handlers
|
||||
CancellationTokenRegistration? jobCancelRegister = null;
|
||||
try
|
||||
{
|
||||
// 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
|
||||
// For main steps just run the action
|
||||
if (stage == ActionRunStage.Main)
|
||||
{
|
||||
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
|
||||
{
|
||||
@@ -409,6 +412,12 @@ namespace GitHub.Runner.Worker.Handlers
|
||||
{
|
||||
Trace.Info($"Update job result with current composite step result '{step.ExecutionContext.Result}'.");
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,8 +31,8 @@ namespace GitHub.Runner.Worker.Handlers
|
||||
|
||||
Inputs.TryGetValue("script", out string contents);
|
||||
contents = contents ?? string.Empty;
|
||||
if (Action.Type == Pipelines.ActionSourceType.Script)
|
||||
{
|
||||
// if (Action.Type == Pipelines.ActionSourceType.Script)
|
||||
// {
|
||||
var firstLine = contents.TrimStart(' ', '\t', '\r', '\n');
|
||||
var firstNewLine = firstLine.IndexOfAny(new[] { '\r', '\n' });
|
||||
if (firstNewLine >= 0)
|
||||
@@ -41,11 +41,11 @@ namespace GitHub.Runner.Worker.Handlers
|
||||
}
|
||||
|
||||
ExecutionContext.Output($"##[group]Run {firstLine}");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException($"Invalid action type {Action.Type} for {nameof(ScriptHandler)}");
|
||||
}
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// throw new InvalidOperationException($"Invalid action type {Action.Type} for {nameof(ScriptHandler)}");
|
||||
// }
|
||||
|
||||
var multiLines = contents.Replace("\r\n", "\n").TrimEnd('\n').Split('\n');
|
||||
foreach (var line in multiLines)
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace GitHub.Runner.Worker
|
||||
ArgUtil.NotNull(message, nameof(message));
|
||||
|
||||
// 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> jobSteps = new List<IStep>();
|
||||
@@ -265,29 +265,91 @@ namespace GitHub.Runner.Worker
|
||||
if (step.Type == Pipelines.StepType.Action)
|
||||
{
|
||||
var action = step as Pipelines.ActionStep;
|
||||
Trace.Info($"Adding {action.DisplayName}.");
|
||||
var actionRunner = HostContext.CreateService<IActionRunner>();
|
||||
actionRunner.Action = action;
|
||||
actionRunner.Stage = ActionRunStage.Main;
|
||||
actionRunner.Condition = step.Condition;
|
||||
var contextData = new Pipelines.ContextData.DictionaryContextData();
|
||||
if (message.ContextData?.Count > 0)
|
||||
|
||||
void EmitStep(Pipelines.ActionStep action)
|
||||
{
|
||||
foreach (var pair in message.ContextData)
|
||||
Trace.Info($"Adding {action.DisplayName}.");
|
||||
var actionRunner = HostContext.CreateService<IActionRunner>();
|
||||
actionRunner.Action = action;
|
||||
actionRunner.Stage = ActionRunStage.Main;
|
||||
actionRunner.Condition = step.Condition;
|
||||
var contextData = new Pipelines.ContextData.DictionaryContextData();
|
||||
if (message.ContextData?.Count > 0)
|
||||
{
|
||||
contextData[pair.Key] = pair.Value;
|
||||
foreach (var pair in message.ContextData)
|
||||
{
|
||||
contextData[pair.Key] = pair.Value;
|
||||
}
|
||||
}
|
||||
|
||||
actionRunner.TryEvaluateDisplayName(contextData, context);
|
||||
jobSteps.Add(actionRunner);
|
||||
|
||||
if (prepareResult.PreStepTracker.TryGetValue(step.Id, out var preStep))
|
||||
{
|
||||
Trace.Info($"Adding pre-{action.DisplayName}.");
|
||||
preStep.TryEvaluateDisplayName(contextData, context);
|
||||
preStep.DisplayName = $"Pre {preStep.DisplayName}";
|
||||
preJobSteps.Add(preStep);
|
||||
}
|
||||
}
|
||||
|
||||
actionRunner.TryEvaluateDisplayName(contextData, context);
|
||||
jobSteps.Add(actionRunner);
|
||||
|
||||
if (prepareResult.PreStepTracker.TryGetValue(step.Id, out var preStep))
|
||||
// HACK: if the step is "run: make," parse the Makefile and emit $"make dependency {target}"
|
||||
// Only works for the default target right now.
|
||||
bool isRunMake = false;
|
||||
if (action.Reference?.Type == Pipelines.ActionSourceType.Script)
|
||||
{
|
||||
Trace.Info($"Adding pre-{action.DisplayName}.");
|
||||
preStep.TryEvaluateDisplayName(contextData, context);
|
||||
preStep.DisplayName = $"Pre {preStep.DisplayName}";
|
||||
preJobSteps.Add(preStep);
|
||||
var inputs = action.Inputs.AssertMapping(null);
|
||||
foreach (var pair in inputs)
|
||||
{
|
||||
var propertyName = pair.Key.AssertString($"{PipelineTemplateConstants.Steps}");
|
||||
if (string.Equals(propertyName.Value, "script", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var tokenToParse = pair.Value.AssertScalar($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Run}");
|
||||
if (tokenToParse.ToString() == "make")
|
||||
{
|
||||
isRunMake = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isRunMake)
|
||||
{
|
||||
// Get the path of the Makefile in the repository root.
|
||||
var githubContext = jobContext.ExpressionValues["github"] as GitHubContext;
|
||||
var workspaceDir = githubContext["workspace"] as StringContextData;
|
||||
var makefile = Path.Combine(workspaceDir, "Makefile");
|
||||
if (!File.Exists(makefile))
|
||||
{
|
||||
// Forget about trying to be smart. Just do the normal thing.
|
||||
EmitStep(action);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Assume the default target is named `all`.
|
||||
var targetDependencies = MakefileReader.ReadTargetDependencies(jobContext, makefile, target: "all");
|
||||
if (targetDependencies.Count == 0)
|
||||
{
|
||||
// Forget about trying to be smart. Just do the normal thing.
|
||||
EmitStep(action);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var target in targetDependencies)
|
||||
{
|
||||
action = (Pipelines.ActionStep)action.Clone();
|
||||
action.Id = Guid.NewGuid();
|
||||
action.DisplayName = $"make dependency {target}";
|
||||
EmitStep(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitStep(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -306,13 +368,13 @@ namespace GitHub.Runner.Worker
|
||||
JobExtensionRunner extensionStep = step as JobExtensionRunner;
|
||||
ArgUtil.NotNull(extensionStep, extensionStep.DisplayName);
|
||||
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)
|
||||
{
|
||||
ArgUtil.NotNull(actionStep, step.DisplayName);
|
||||
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 +385,7 @@ namespace GitHub.Runner.Worker
|
||||
{
|
||||
ArgUtil.NotNull(actionStep, step.DisplayName);
|
||||
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 +456,7 @@ namespace GitHub.Runner.Worker
|
||||
ArgUtil.NotNull(jobContext, nameof(jobContext));
|
||||
|
||||
// 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(); }))
|
||||
{
|
||||
try
|
||||
|
||||
@@ -106,7 +106,6 @@ namespace GitHub.Runner.Worker
|
||||
}
|
||||
|
||||
jobContext.SetRunnerContext("os", VarUtil.OS);
|
||||
jobContext.SetRunnerContext("arch", VarUtil.OSArchitecture);
|
||||
|
||||
var runnerSettings = HostContext.GetService<IConfigurationStore>().GetSettings();
|
||||
jobContext.SetRunnerContext("name", runnerSettings.AgentName);
|
||||
|
||||
24
src/Runner.Worker/MakefileReader.cs
Normal file
24
src/Runner.Worker/MakefileReader.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace GitHub.Runner.Worker
|
||||
{
|
||||
public static class MakefileReader
|
||||
{
|
||||
// Get the dependencies for a target from a Makefile.
|
||||
// Does not recurse into the dependencies of those dependencies.
|
||||
public static List<string> ReadTargetDependencies(IExecutionContext executionContext, string makefile, string target)
|
||||
{
|
||||
var targetToFind = target + ":";
|
||||
var lines = File.ReadLines(makefile);
|
||||
string targetLine = lines.FirstOrDefault(line => line.TrimStart().StartsWith(targetToFind));
|
||||
if (targetLine is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return targetLine.Split().Skip(1).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
||||
<NoWarn>NU1701;NU1603</NoWarn>
|
||||
<Version>$(Version)</Version>
|
||||
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
||||
|
||||
@@ -123,7 +123,6 @@
|
||||
"properties": {
|
||||
"name": "string-steps-context",
|
||||
"id": "non-empty-string",
|
||||
"if": "step-if",
|
||||
"run": {
|
||||
"type": "string-steps-context",
|
||||
"required": true
|
||||
@@ -142,7 +141,6 @@
|
||||
"properties": {
|
||||
"name": "string-steps-context",
|
||||
"id": "non-empty-string",
|
||||
"if": "step-if",
|
||||
"uses": {
|
||||
"type": "non-empty-string",
|
||||
"required": true
|
||||
@@ -218,24 +216,6 @@
|
||||
"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": {
|
||||
"context": [
|
||||
"github",
|
||||
|
||||
@@ -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> values;
|
||||
|
||||
@@ -14,5 +14,10 @@ namespace GitHub.Services.Common
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
IDictionary<string, object> Properties
|
||||
{
|
||||
get;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,12 @@ namespace GitHub.Services.Common.Diagnostics
|
||||
|
||||
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 traceActivity;
|
||||
return (VssTraceActivity)traceActivity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace GitHub.Services.Common.Diagnostics
|
||||
{
|
||||
@@ -99,7 +98,7 @@ namespace GitHub.Services.Common.Diagnostics
|
||||
/// <summary>
|
||||
/// Gets the property name used to cache this object on extensible objects.
|
||||
/// </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 sealed class CorrelationScope : IDisposable
|
||||
|
||||
@@ -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>
|
||||
/// 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
|
||||
request.Options.Set(VssHttpMessageHandler.PropertyName, this);
|
||||
request.Properties[VssHttpMessageHandler.PropertyName] = this;
|
||||
|
||||
Boolean succeeded = 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
|
||||
// assume it is OK to buffer by default.
|
||||
HttpCompletionOption completionOption;
|
||||
if (!request.Options.TryGetValue(VssHttpRequestSettings.HttpCompletionOptionPropertyName, out completionOption))
|
||||
if (!request.Properties.TryGetValue(VssHttpRequestSettings.HttpCompletionOptionPropertyName, out completionOption))
|
||||
{
|
||||
completionOption = HttpCompletionOption.ResponseContentRead;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace GitHub.Services.Common
|
||||
{
|
||||
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; }
|
||||
|
||||
@@ -76,9 +76,10 @@ namespace GitHub.Services.Common
|
||||
/// <param name="traceInfo"></param>
|
||||
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>
|
||||
public static VssHttpMessageHandlerTraceInfo GetTraceInfo(HttpRequestMessage message)
|
||||
{
|
||||
VssHttpMessageHandlerTraceInfo traceInfo;
|
||||
message.Options.TryGetValue(TfsTraceInfoKey, out traceInfo);
|
||||
VssHttpMessageHandlerTraceInfo traceInfo = null;
|
||||
|
||||
if (message.Properties.TryGetValue(TfsTraceInfoKey, out object traceInfoObject))
|
||||
{
|
||||
traceInfo = traceInfoObject as VssHttpMessageHandlerTraceInfo;
|
||||
}
|
||||
|
||||
return traceInfo;
|
||||
}
|
||||
|
||||
|
||||
@@ -291,12 +291,12 @@ namespace GitHub.Services.Common
|
||||
protected internal virtual Boolean ApplyTo(HttpRequestMessage request)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
request.Options.Set(PropertyName, this);
|
||||
request.Properties.Add(PropertyName, this);
|
||||
|
||||
if (this.AcceptLanguages != null && this.AcceptLanguages.Count > 0)
|
||||
{
|
||||
@@ -366,12 +366,12 @@ namespace GitHub.Services.Common
|
||||
/// <summary>
|
||||
/// Gets the property name used to reference this object.
|
||||
/// </summary>
|
||||
public static readonly HttpRequestOptionsKey<VssHttpRequestSettings> PropertyName = new HttpRequestOptionsKey<VssHttpRequestSettings>("MS.VS.RequestSettings");
|
||||
public const String PropertyName = "MS.VS.RequestSettings";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the property name used to reference the completion option for a specific request.
|
||||
/// </summary>
|
||||
public static readonly HttpRequestOptionsKey<HttpCompletionOption> HttpCompletionOptionPropertyName = new HttpRequestOptionsKey<HttpCompletionOption>("MS.VS.HttpCompletionOption");
|
||||
public const String HttpCompletionOptionPropertyName = "MS.VS.HttpCompletionOption";
|
||||
|
||||
/// <summary>
|
||||
/// Header to include the light weight response client option.
|
||||
|
||||
@@ -53,14 +53,23 @@ namespace GitHub.Services.Common
|
||||
VssTraceActivity traceActivity = VssTraceActivity.Current;
|
||||
|
||||
// Allow overriding default retry options per request
|
||||
VssHttpRetryOptions retryOptions;
|
||||
request.Options.TryGetValue(HttpRetryOptionsKey, out retryOptions);
|
||||
VssHttpRetryOptions retryOptions = m_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;
|
||||
Int32 maxAttempts = (retryOptions ?? m_retryOptions).MaxRetries + 1;
|
||||
TimeSpan minBackoff = retryOptions.MinBackoff;
|
||||
Int32 maxAttempts = retryOptions.MaxRetries + 1;
|
||||
|
||||
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))
|
||||
{
|
||||
@@ -216,8 +225,8 @@ namespace GitHub.Services.Common
|
||||
}
|
||||
|
||||
private VssHttpRetryOptions m_retryOptions;
|
||||
public static readonly HttpRequestOptionsKey<IVssHttpRetryInfo> HttpRetryInfoKey = new HttpRequestOptionsKey<IVssHttpRetryInfo>("HttpRetryInfo");
|
||||
public static readonly HttpRequestOptionsKey<VssHttpRetryOptions> HttpRetryOptionsKey = new HttpRequestOptionsKey<VssHttpRetryOptions>("VssHttpRetryOptions");
|
||||
public const string HttpRetryInfoKey = "HttpRetryInfo";
|
||||
public const string HttpRetryOptionsKey = "VssHttpRetryOptions";
|
||||
private string m_clientName = "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -638,7 +638,6 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating
|
||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Matrix),
|
||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Steps),
|
||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.GitHub),
|
||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Inputs),
|
||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Job),
|
||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Runner),
|
||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Env),
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<OutputType>Library</OutputType>
|
||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
||||
<NoWarn>NU1701;NU1603</NoWarn>
|
||||
<Version>$(Version)</Version>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
|
||||
@@ -833,7 +833,7 @@ namespace GitHub.Services.WebApi
|
||||
{
|
||||
if (userState != null)
|
||||
{
|
||||
message.Options.Set(UserStatePropertyName, userState);
|
||||
message.Properties[UserStatePropertyName] = userState;
|
||||
}
|
||||
|
||||
if (!message.Headers.Contains(Common.Internal.HttpHeaders.VssE2EID))
|
||||
@@ -842,11 +842,11 @@ namespace GitHub.Services.WebApi
|
||||
}
|
||||
VssHttpEventSource.Log.HttpRequestStart(traceActivity, message);
|
||||
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
|
||||
// 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
|
||||
//any captured SyncronizationContext (such as ASP.NET's) which keeps things
|
||||
@@ -1154,9 +1154,7 @@ namespace GitHub.Services.WebApi
|
||||
{
|
||||
if (BaseAddress != null)
|
||||
{
|
||||
#pragma warning disable SYSLIB0014
|
||||
ServicePoint servicePoint = ServicePointManager.FindServicePoint(BaseAddress);
|
||||
#pragma warning restore SYSLIB0014
|
||||
servicePoint.UseNagleAlgorithm = false;
|
||||
servicePoint.SetTcpKeepAlive(
|
||||
enabled: true,
|
||||
@@ -1274,7 +1272,7 @@ namespace GitHub.Services.WebApi
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
@@ -138,7 +138,7 @@ namespace GitHub.Services.WebApi
|
||||
|
||||
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)
|
||||
|
||||
@@ -6,24 +6,27 @@ using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace GitHub.Services.WebApi
|
||||
{
|
||||
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)
|
||||
{
|
||||
VssRequestTimerTrace tracer;
|
||||
if (request.Options.TryGetValue(tracerKey, out tracer))
|
||||
Object tracerObj = null;
|
||||
VssRequestTimerTrace tracer = null;
|
||||
if (request.Properties.TryGetValue(tracerKey, out tracerObj))
|
||||
{
|
||||
tracer = tracerObj as VssRequestTimerTrace;
|
||||
Debug.Assert(tracer != null, "Tracer object is the wrong type!");
|
||||
}
|
||||
else
|
||||
{
|
||||
tracer = new VssRequestTimerTrace();
|
||||
request.Options.Set(tracerKey, tracer);
|
||||
request.Properties[tracerKey] = tracer;
|
||||
}
|
||||
|
||||
if (tracer != null)
|
||||
@@ -34,9 +37,11 @@ namespace GitHub.Services.WebApi
|
||||
|
||||
internal static void Trace(this HttpResponseMessage response)
|
||||
{
|
||||
VssRequestTimerTrace tracer;
|
||||
if (response.RequestMessage.Options.TryGetValue(tracerKey, out tracer))
|
||||
Object tracerObj = null;
|
||||
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!");
|
||||
}
|
||||
|
||||
|
||||
@@ -547,7 +547,6 @@ namespace GitHub.Runner.Common.Tests
|
||||
}
|
||||
}
|
||||
|
||||
#if OS_WINDOWS
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", nameof(CommandSettings))]
|
||||
@@ -575,7 +574,6 @@ namespace GitHub.Runner.Common.Tests
|
||||
Assert.Equal("some windows logon account", actual);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
|
||||
@@ -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]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Worker")]
|
||||
|
||||
@@ -193,9 +193,9 @@ namespace GitHub.Runner.Common.Tests.Worker
|
||||
// Act.
|
||||
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";
|
||||
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";
|
||||
|
||||
|
||||
@@ -291,8 +291,8 @@ namespace GitHub.Runner.Common.Tests.Worker
|
||||
// Act.
|
||||
jobContext.InitializeJob(jobRequest, CancellationToken.None);
|
||||
|
||||
var action1 = jobContext.CreateChild(Guid.NewGuid(), "action_1_pre", "action_1_pre", null, null, 0);
|
||||
var action2 = jobContext.CreateChild(Guid.NewGuid(), "action_1_main", "action_1_main", 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);
|
||||
|
||||
var actionId = Guid.NewGuid();
|
||||
var postRunner1 = hc.CreateService<IActionRunner>();
|
||||
|
||||
@@ -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]
|
||||
[Trait("Level", "L0")]
|
||||
[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 = "")
|
||||
{
|
||||
return new TestHostContext(this, testName);
|
||||
}
|
||||
|
||||
private Mock<IExecutionContext> InitializeExecutionContext(TestHostContext hc)
|
||||
private void InitializeExecutionContext(TestHostContext hc)
|
||||
{
|
||||
_jobContext = new JobContext();
|
||||
|
||||
@@ -210,8 +149,6 @@ namespace GitHub.Runner.Common.Tests.Worker.Expressions
|
||||
|
||||
_templateContext = new TemplateContext();
|
||||
_templateContext.State[nameof(IExecutionContext)] = executionContext.Object;
|
||||
|
||||
return executionContext;
|
||||
}
|
||||
|
||||
private bool Evaluate(string expression)
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
||||
<NoWarn>NU1701;NU1603;NU1603;xUnit2013;</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -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() }}
|
||||
@@ -14,10 +14,10 @@ DEV_TARGET_RUNTIME=$3
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
LAYOUT_DIR="$SCRIPT_DIR/../_layout"
|
||||
DOWNLOAD_DIR="$SCRIPT_DIR/../_downloads/net6"
|
||||
DOWNLOAD_DIR="$SCRIPT_DIR/../_downloads/netcore2x"
|
||||
PACKAGE_DIR="$SCRIPT_DIR/../_package"
|
||||
DOTNETSDK_ROOT="$SCRIPT_DIR/../_dotnetsdk"
|
||||
DOTNETSDK_VERSION="6.0.100"
|
||||
DOTNETSDK_VERSION="3.1.302"
|
||||
DOTNETSDK_INSTALLDIR="$DOTNETSDK_ROOT/$DOTNETSDK_VERSION"
|
||||
RUNNER_VERSION=$(cat runnerversion)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "net6"
|
||||
"version": "3.1.302"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
2.284.0
|
||||
2.283.3
|
||||
|
||||
Reference in New Issue
Block a user