Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use StepHost when evaluating inputs to actions #1762

Merged
merged 15 commits into from
Apr 11, 2022
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Runner.Common/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ public static class Features
{
public static readonly string DiskSpaceWarning = "runner.diskspace.warning";
public static readonly string Node12Warning = "DistributedTask.AddWarningToNode12Action";
public static readonly string UseContainerPathForTemplate = "DistributedTask.UseContainerPathForTemplate";
}

public static readonly string InternalTelemetryIssueDataKey = "_internal_telemetry";
Expand Down
27 changes: 24 additions & 3 deletions src/Runner.Worker/ActionRunner.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using GitHub.DistributedTask.ObjectTemplating;
using GitHub.DistributedTask.ObjectTemplating.Tokens;
Expand All @@ -9,7 +10,6 @@
using GitHub.Runner.Common;
using GitHub.Runner.Common.Util;
using GitHub.Runner.Sdk;
using GitHub.Runner.Worker;
using GitHub.Runner.Worker.Handlers;
using Pipelines = GitHub.DistributedTask.Pipelines;

Expand Down Expand Up @@ -165,14 +165,23 @@ Action.Reference is Pipelines.RepositoryPathReference repoAction &&
stepHost = containerStepHost;
}


// Setup File Command Manager
var fileCommandManager = HostContext.CreateService<IFileCommandManager>();
fileCommandManager.InitializeFiles(ExecutionContext, null);

// Load the inputs.
ExecutionContext.Debug("Loading inputs");
var templateEvaluator = ExecutionContext.ToPipelineTemplateEvaluator();
var inputs = templateEvaluator.EvaluateStepInputs(Action.Inputs, ExecutionContext.ExpressionValues, ExecutionContext.ExpressionFunctions);
Dictionary<string, string> inputs;
if (ExecutionContext.Global.Variables.GetBoolean(Constants.Runner.Features.UseContainerPathForTemplate) ?? false)
{
inputs = EvaluateStepInputs(stepHost);
}
else
{
var templateEvaluator = ExecutionContext.ToPipelineTemplateEvaluator();
inputs = templateEvaluator.EvaluateStepInputs(Action.Inputs, ExecutionContext.ExpressionValues, ExecutionContext.ExpressionFunctions);
}

var userInputs = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (KeyValuePair<string, string> input in inputs)
Expand Down Expand Up @@ -299,6 +308,18 @@ public bool TryEvaluateDisplayName(DictionaryContextData contextData, IExecution
return didFullyEvaluate;
}

private Dictionary<String, String> EvaluateStepInputs(
fhammerl marked this conversation as resolved.
Show resolved Hide resolved
IStepHost stepHost
)
{
DictionaryContextData expressionValues = stepHost.GetExpressionValues(ExecutionContext);
// expression values of github = github dictionary
var templateEvaluator = ExecutionContext.ToPipelineTemplateEvaluator();
var inputs = templateEvaluator.EvaluateStepInputs(Action.Inputs, expressionValues, ExecutionContext.ExpressionFunctions);

return inputs;
}

private string GenerateDisplayName(ActionStep action, DictionaryContextData contextData, IExecutionContext context, out bool didFullyEvaluate)
{
ArgUtil.NotNull(context, nameof(context));
Expand Down
2 changes: 1 addition & 1 deletion src/Runner.Worker/Handlers/CompositeActionHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public async Task RunAsync(ActionRunStage stage)

ExecutionContext.StepTelemetry.HasPreStep = Data.HasPre;
ExecutionContext.StepTelemetry.HasPostStep = Data.HasPost;

ExecutionContext.StepTelemetry.HasRunsStep = hasRunsStep;
ExecutionContext.StepTelemetry.HasUsesStep = hasUsesStep;
ExecutionContext.StepTelemetry.StepCount = steps.Count;
Expand Down
36 changes: 30 additions & 6 deletions src/Runner.Worker/Handlers/StepHost.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks;
using GitHub.DistributedTask.WebApi;
using GitHub.Runner.Common.Util;
using GitHub.Runner.Worker.Container;
using GitHub.Services.WebApi;
using Newtonsoft.Json;
using GitHub.Runner.Common;
using GitHub.Runner.Sdk;
using System.Linq;
using GitHub.DistributedTask.Pipelines.ContextData;

namespace GitHub.Runner.Worker.Handlers
{
Expand All @@ -34,6 +29,8 @@ Task<int> ExecuteAsync(string workingDirectory,
bool killProcessOnCancel,
bool inheritConsoleHandler,
CancellationToken cancellationToken);

DictionaryContextData GetExpressionValues(IExecutionContext executionContext);
fhammerl marked this conversation as resolved.
Show resolved Hide resolved
}

[ServiceLocator(Default = typeof(ContainerStepHost))]
Expand Down Expand Up @@ -90,6 +87,11 @@ public async Task<int> ExecuteAsync(string workingDirectory,
cancellationToken: cancellationToken);
}
}

public DictionaryContextData GetExpressionValues(IExecutionContext executionContext)
{
return executionContext.ExpressionValues;
}
}

public sealed class ContainerStepHost : RunnerService, IContainerStepHost
Expand Down Expand Up @@ -239,5 +241,27 @@ public async Task<int> ExecuteAsync(string workingDirectory,
cancellationToken: cancellationToken);
}
}

public DictionaryContextData GetExpressionValues(IExecutionContext executionContext)
fhammerl marked this conversation as resolved.
Show resolved Hide resolved
{
var expressionValues = executionContext.ExpressionValues.Clone() as DictionaryContextData;
UpdatePathsInExpressionValues("github", expressionValues);
UpdatePathsInExpressionValues("runner", expressionValues);
return expressionValues;
}

private void UpdatePathsInExpressionValues(string contextName, DictionaryContextData expressionValues)
{
var dict = expressionValues[contextName].AssertDictionary($"expected context {contextName} to be a dictionary");
foreach (var key in dict.Keys.ToList())
{
var value = dict[key]?.ToString();
if (!string.IsNullOrEmpty(value))
fhammerl marked this conversation as resolved.
Show resolved Hide resolved
{
dict[key] = new StringContextData(ResolvePathForStepHost(value));
}
}
expressionValues[contextName] = dict;
}
}
}
95 changes: 94 additions & 1 deletion src/Test/L0/Worker/StepHostL0.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
using GitHub.Runner.Worker;
using GitHub.Runner.Worker.Handlers;
using GitHub.Runner.Worker.Container;

using GitHub.DistributedTask.Pipelines.ContextData;
using System.Linq;
using GitHub.DistributedTask.Pipelines;
namespace GitHub.Runner.Common.Tests.Worker
fhammerl marked this conversation as resolved.
Show resolved Hide resolved
{
public sealed class StepHostL0
Expand Down Expand Up @@ -52,6 +54,97 @@ public async Task DetermineNodeRuntimeVersionInContainerAsync()
}
}

[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public void ContainerStepHost_GetExpressionValues()
{
using (TestHostContext hc = CreateTestContext())
{
const string source = "/home/username/Projects/work/runner/_layout";
var containerInfo = new ContainerInfo();
containerInfo.ContainerId = "test";

containerInfo.AddPathTranslateMapping($"{source}/_work", "/__w");
containerInfo.AddPathTranslateMapping($"{source}/_temp", "/__t");
containerInfo.AddPathTranslateMapping($"{source}/externals", "/__e");

containerInfo.AddPathTranslateMapping($"{source}/_work/_temp/_github_home", "/github/home");
containerInfo.AddPathTranslateMapping($"{source}/_work/_temp/_github_workflow", "/github/workflow");


foreach (var v in new List<string>() {
$"{source}/_work",
$"{source}/externals",
$"{source}/_work/_temp",
$"{source}/_work/_actions",
$"{source}/_work/_tool",
})
{
containerInfo.MountVolumes.Add(new MountVolume(v, containerInfo.TranslateToContainerPath(v)));
};


var sh = new ContainerStepHost();
sh.Container = containerInfo;

var expressionValues = new DictionaryContextData();

var inputGithubContext = new GitHubContext();
var inputeRunnerContext = new RunnerContext();
expressionValues["github"] = inputGithubContext;
expressionValues["runner"] = inputeRunnerContext;
inputGithubContext["action_path"] = new StringContextData("/home/username/Projects/work/runner/_layout/_work/_actions/owner/composite/main");
inputGithubContext["action"] = new StringContextData("__owner_composite");
inputGithubContext["api_url"] = new StringContextData("https://api.github.com/custom/path");
inputGithubContext["env"] = new StringContextData("/home/username/Projects/work/runner/_layout/_work/_temp/_runner_file_commands/set_env_265698aa-7f38-40f5-9316-5c01a3153672");
inputGithubContext["path"] = new StringContextData("/home/username/Projects/work/runner/_layout/_work/_temp/_runner_file_commands/add_path_265698aa-7f38-40f5-9316-5c01a3153672");
inputGithubContext["event_path"] = new StringContextData("/home/username/Projects/work/runner/_layout/_work/_temp/_github_workflow/event.json");
inputGithubContext["repository"] = new StringContextData("owner/repo-name");
inputGithubContext["run_id"] = new StringContextData("2033211332");
inputGithubContext["workflow"] = new StringContextData("Name of Workflow");
inputGithubContext["workspace"] = new StringContextData("/home/username/Projects/work/runner/_layout/_work/step-order/step-order");
inputeRunnerContext["temp"] = new StringContextData("/home/username/Projects/work/runner/_layout/_work/_temp");
inputeRunnerContext["tool_cache"] = new StringContextData("/home/username/Projects/work/runner/_layout/_work/_tool");


var expectedGithubContext = new GitHubContext();
var expectedRunnerContext = new RunnerContext();
expectedGithubContext["action_path"] = new StringContextData("/__w/_actions/owner/composite/main");
expectedGithubContext["action"] = new StringContextData("__owner_composite");
expectedGithubContext["api_url"] = new StringContextData("https://api.github.com/custom/path");
expectedGithubContext["env"] = new StringContextData("/__w/_temp/_runner_file_commands/set_env_265698aa-7f38-40f5-9316-5c01a3153672");
expectedGithubContext["path"] = new StringContextData("/__w/_temp/_runner_file_commands/add_path_265698aa-7f38-40f5-9316-5c01a3153672");
expectedGithubContext["event_path"] = new StringContextData("/github/workflow/event.json");
expectedGithubContext["repository"] = new StringContextData("owner/repo-name");
expectedGithubContext["run_id"] = new StringContextData("2033211332");
expectedGithubContext["workflow"] = new StringContextData("Name of Workflow");
expectedGithubContext["workspace"] = new StringContextData("/__w/step-order/step-order");
expectedRunnerContext["temp"] = new StringContextData("/__w/_temp");
expectedRunnerContext["tool_cache"] = new StringContextData("/__w/_tool");

_ec.Setup(x => x.ExpressionValues).Returns(expressionValues);

var translatedExpressionValues = sh.GetExpressionValues(_ec.Object);

var dict = translatedExpressionValues["github"].AssertDictionary($"expected context github to be a dictionary");
foreach (var key in dict.Keys.ToList())
{
var expect = dict[key].AssertString("expect string");
var outcome = expectedGithubContext[key].AssertString("expect string");
Assert.Equal(expect.Value, outcome.Value);
}

dict = translatedExpressionValues["runner"].AssertDictionary($"expected context runner to be a dictionary");
foreach (var key in dict.Keys.ToList())
{
var expect = dict[key].AssertString("expect string");
var outcome = expectedRunnerContext[key].AssertString("expect string");
Assert.Equal(expect.Value, outcome.Value);
}
}
}

[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
Expand Down