Skip to content

Commit

Permalink
Add runner support for cache action. (#120)
Browse files Browse the repository at this point in the history
  • Loading branch information
TingluoHuang committed Oct 5, 2019
1 parent 10989fb commit 0dca481
Show file tree
Hide file tree
Showing 24 changed files with 630 additions and 56 deletions.
1 change: 1 addition & 0 deletions src/Runner.Worker/ActionCommandManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ public void ProcessCommand(IExecutionContext context, string line, ActionCommand
}

context.EnvironmentVariables[envName] = command.Data;
context.SetEnvContext(envName, command.Data);
context.Output(line);
context.Debug($"{envName}='{command.Data}'");
omitEcho = true;
Expand Down
8 changes: 8 additions & 0 deletions src/Runner.Worker/ActionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -797,9 +797,17 @@ public sealed class ScriptActionExecutionData : ActionExecutionData

public abstract class ActionExecutionData
{
private string _cleanupCondition = $"{Constants.Expressions.Always}()";

public abstract ActionExecutionType ExecutionType { get; }

public abstract bool HasCleanup { get; }

public string CleanupCondition
{
get { return _cleanupCondition; }
set { _cleanupCondition = value; }
}
}

public class ContainerSetupInfo
Expand Down
47 changes: 43 additions & 4 deletions src/Runner.Worker/ActionManifestManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public interface IActionManifestManager : IRunnerService
List<string> EvaluateContainerArguments(IExecutionContext executionContext, SequenceToken token, IDictionary<string, PipelineContextData> contextData);

Dictionary<string, string> EvaluateContainerEnvironment(IExecutionContext executionContext, MappingToken token, IDictionary<string, PipelineContextData> contextData);

string EvaluateDefaultInput(IExecutionContext executionContext, string inputName, TemplateToken token, IDictionary<string, PipelineContextData> contextData);
}

public sealed class ActionManifestManager : RunnerService, IActionManifestManager
Expand Down Expand Up @@ -207,6 +209,38 @@ public Dictionary<string, string> EvaluateContainerEnvironment(
return result;
}

public string EvaluateDefaultInput(
IExecutionContext executionContext,
string inputName,
TemplateToken token,
IDictionary<string, PipelineContextData> contextData)
{
string result = "";
if (token != null)
{
var context = CreateContext(executionContext, contextData);
try
{
var evaluateResult = TemplateEvaluator.Evaluate(context, "input-default-context", token, 0, null, omitHeader: true);
context.Errors.Check();

Trace.Info($"Input '{inputName}': default value evaluate result: {StringUtil.ConvertToJson(evaluateResult)}");

// String
result = evaluateResult.AssertString($"default value for input '{inputName}'").Value;
}
catch (Exception ex) when (!(ex is TemplateValidationException))
{
Trace.Error(ex);
context.Errors.Add(ex);
}

context.Errors.Check();
}

return result;
}

private TemplateContext CreateContext(
IExecutionContext executionContext,
IDictionary<string, PipelineContextData> contextData)
Expand Down Expand Up @@ -248,6 +282,7 @@ private ActionExecutionData ConvertRuns(
var pluginToken = default(StringToken);
var postToken = default(StringToken);
var postEntrypointToken = default(StringToken);
var postIfToken = default(StringToken);
foreach (var run in runsMapping)
{
var runsKey = run.Key.AssertString("runs key").Value;
Expand Down Expand Up @@ -280,6 +315,9 @@ private ActionExecutionData ConvertRuns(
case "post-entrypoint":
postEntrypointToken = run.Value.AssertString("post-entrypoint");
break;
case "post-if":
postIfToken = run.Value.AssertString("post-if");
break;
default:
Trace.Info($"Ignore run property {runsKey}.");
break;
Expand All @@ -302,7 +340,8 @@ private ActionExecutionData ConvertRuns(
Arguments = argsToken,
EntryPoint = entrypointToken?.Value,
Environment = envToken,
Cleanup = postEntrypointToken?.Value
Cleanup = postEntrypointToken?.Value,
CleanupCondition = postIfToken?.Value
};
}
}
Expand All @@ -317,7 +356,8 @@ private ActionExecutionData ConvertRuns(
return new NodeJSActionExecutionData()
{
Script = mainToken.Value,
Cleanup = postToken?.Value
Cleanup = postToken?.Value,
CleanupCondition = postIfToken?.Value
};
}
}
Expand Down Expand Up @@ -355,8 +395,7 @@ private void ConvertInputs(
if (string.Equals(metadataName, "default", StringComparison.OrdinalIgnoreCase))
{
hasDefault = true;
var inputDefault = metadata.Value.AssertString("input default");
actionDefinition.Inputs.Add(inputName, inputDefault);
actionDefinition.Inputs.Add(inputName, metadata.Value);
}
else if (string.Equals(metadataName, "deprecationMessage", StringComparison.OrdinalIgnoreCase))
{
Expand Down
12 changes: 9 additions & 3 deletions src/Runner.Worker/ActionRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public async Task RunAsync()
{
postDisplayName = $"Post {this.DisplayName}";
}
ExecutionContext.RegisterPostJobAction(postDisplayName, Action);
ExecutionContext.RegisterPostJobAction(postDisplayName, handlerData.CleanupCondition, Action);
}

IStepHost stepHost = HostContext.CreateService<IDefaultStepHost>();
Expand Down Expand Up @@ -144,13 +144,19 @@ public async Task RunAsync()
// Merge the default inputs from the definition
if (definition.Data?.Inputs != null)
{
var manifestManager = HostContext.GetService<IActionManifestManager>();
foreach (var input in (definition.Data?.Inputs))
{
string key = input.Key.AssertString("action input name").Value;
string value = input.Value.AssertString("action input default value").Value;
if (!inputs.ContainsKey(key))
{
inputs[key] = value;
var evaluateContext = new Dictionary<string, PipelineContextData>(StringComparer.OrdinalIgnoreCase);
foreach (var data in ExecutionContext.ExpressionValues)
{
evaluateContext[data.Key] = data.Value;
}

inputs[key] = manifestManager.EvaluateDefaultInput(ExecutionContext, key, input.Value, evaluateContext);
}
}
}
Expand Down
37 changes: 23 additions & 14 deletions src/Runner.Worker/ExecutionContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using GitHub.Runner.Sdk;
using Newtonsoft.Json;
using System.Text;
using System.Collections;

namespace GitHub.Runner.Worker
{
Expand Down Expand Up @@ -74,7 +75,7 @@ public interface IExecutionContext : IRunnerService
// timeline record update methods
void Start(string currentOperation = null);
TaskResult Complete(TaskResult? result = null, string currentOperation = null, string resultCode = null);
string GetRunnerContext(string name);
void SetEnvContext(string name, string value);
void SetRunnerContext(string name, string value);
string GetGitHubContext(string name);
void SetGitHubContext(string name, string value);
Expand All @@ -95,7 +96,7 @@ public interface IExecutionContext : IRunnerService

// others
void ForceTaskComplete();
void RegisterPostJobAction(string displayName, Pipelines.ActionStep action);
void RegisterPostJobAction(string displayName, string condition, Pipelines.ActionStep action);
}

public sealed class ExecutionContext : RunnerService, IExecutionContext
Expand Down Expand Up @@ -235,7 +236,7 @@ public void ForceTaskComplete()
});
}

public void RegisterPostJobAction(string displayName, Pipelines.ActionStep action)
public void RegisterPostJobAction(string displayName, string condition, Pipelines.ActionStep action)
{
if (action.Reference.Type != ActionSourceType.Repository)
{
Expand All @@ -252,7 +253,7 @@ public void RegisterPostJobAction(string displayName, Pipelines.ActionStep actio
var actionRunner = HostContext.CreateService<IActionRunner>();
actionRunner.Action = action;
actionRunner.Stage = ActionRunStage.Post;
actionRunner.Condition = $"{Constants.Expressions.Always}()";
actionRunner.Condition = condition;
actionRunner.DisplayName = displayName;
actionRunner.ExecutionContext = Root.CreatePostChild(displayName, $"{actionRunner.Action.Name}_post", IntraActionState);
Root.PostJobSteps.Push(actionRunner);
Expand Down Expand Up @@ -366,18 +367,18 @@ public void SetRunnerContext(string name, string value)
runnerContext[name] = new StringContextData(value);
}

public string GetRunnerContext(string name)
public void SetEnvContext(string name, string value)
{
ArgUtil.NotNullOrEmpty(name, nameof(name));
var runnerContext = ExpressionValues["runner"] as RunnerContext;
if (runnerContext.TryGetValue(name, out var value))
{
return value as StringContextData;
}
else
{
return null;
}

#if OS_WINDOWS
var envContext = ExpressionValues["env"] as DictionaryContextData;
envContext[name] = new StringContextData(value);
#else
var envContext = ExpressionValues["env"] as CaseSensitiveDictionaryContextData;
envContext[name] = new StringContextData(value);
#endif

}

public void SetGitHubContext(string name, string value)
Expand Down Expand Up @@ -611,6 +612,14 @@ public void InitializeJob(Pipelines.AgentJobRequestMessage message, Cancellation
}
ExpressionValues["github"] = githubContext;

Trace.Info("Initialize Env context");
#if OS_WINDOWS
ExpressionValues["env"] = new DictionaryContextData();
#else

ExpressionValues["env"] = new CaseSensitiveDictionaryContextData();
#endif

// Prepend Path
PrependPath = new List<string>();

Expand Down
10 changes: 10 additions & 0 deletions src/Runner.Worker/Handlers/ContainerActionHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using GitHub.Runner.Sdk;
using GitHub.DistributedTask.WebApi;
using GitHub.DistributedTask.Pipelines.ContextData;
using System.Linq;

namespace GitHub.Runner.Worker.Handlers
{
Expand Down Expand Up @@ -172,6 +173,15 @@ public async Task RunAsync(ActionRunStage stage)
}
}

// Add Actions Runtime server info
var systemConnection = ExecutionContext.Endpoints.Single(x => string.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase));
Environment["ACTIONS_RUNTIME_URL"] = systemConnection.Url.AbsoluteUri;
Environment["ACTIONS_RUNTIME_TOKEN"] = systemConnection.Authorization.Parameters[EndpointAuthorizationParameters.AccessToken];
if (systemConnection.Data.TryGetValue("CacheServerUrl", out var cacheUrl) && !string.IsNullOrEmpty(cacheUrl))
{
Environment["ACTIONS_CACHE_URL"] = cacheUrl;
}

foreach (var variable in this.Environment)
{
container.ContainerEnvironmentVariables[variable.Key] = container.TranslateToContainerPath(variable.Value);
Expand Down
10 changes: 10 additions & 0 deletions src/Runner.Worker/Handlers/NodeScriptActionHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using GitHub.DistributedTask.WebApi;
using Pipelines = GitHub.DistributedTask.Pipelines;
using System;
using System.Linq;

namespace GitHub.Runner.Worker.Handlers
{
Expand Down Expand Up @@ -44,6 +45,15 @@ public async Task RunAsync(ActionRunStage stage)
}
}

// Add Actions Runtime server info
var systemConnection = ExecutionContext.Endpoints.Single(x => string.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase));
Environment["ACTIONS_RUNTIME_URL"] = systemConnection.Url.AbsoluteUri;
Environment["ACTIONS_RUNTIME_TOKEN"] = systemConnection.Authorization.Parameters[EndpointAuthorizationParameters.AccessToken];
if (systemConnection.Data.TryGetValue("CacheServerUrl", out var cacheUrl) && !string.IsNullOrEmpty(cacheUrl))
{
Environment["ACTIONS_CACHE_URL"] = cacheUrl;
}

// Resolve the target script.
string target = null;
if (stage == ActionRunStage.Main)
Expand Down
1 change: 1 addition & 0 deletions src/Runner.Worker/JobExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ public async Task<List<IStep>> InitializeJob(IExecutionContext jobContext, Pipel
foreach (var pair in environmentVariables)
{
context.EnvironmentVariables[pair.Key] = pair.Value ?? string.Empty;
context.SetEnvContext(pair.Key, pair.Value ?? string.Empty);
}
}

Expand Down
20 changes: 17 additions & 3 deletions src/Runner.Worker/action_yaml.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"input": {
"mapping": {
"properties": {
"default": "string"
"default": "input-default-context"
},
"loose-key-type": "non-empty-string",
"loose-value-type": "any"
Expand All @@ -43,7 +43,8 @@
"entrypoint": "non-empty-string",
"args": "container-runs-args",
"env": "container-runs-env",
"post-entrypoint": "non-empty-string"
"post-entrypoint": "non-empty-string",
"post-if": "non-empty-string"
}
}
},
Expand All @@ -66,7 +67,8 @@
"properties": {
"using": "non-empty-string",
"main": "non-empty-string",
"post": "non-empty-string"
"post": "non-empty-string",
"post-if": "non-empty-string"
}
}
},
Expand All @@ -83,6 +85,18 @@
],
"string": {}
},
"input-default-context": {
"context": [
"github",
"strategy",
"matrix",
"steps",
"job",
"runner",
"env"
],
"string": {}
},
"non-empty-string": {
"string": {
"require-non-empty": true
Expand Down
1 change: 1 addition & 0 deletions src/Sdk/DTExpressions2/Expressions2/ExpressionConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ static ExpressionConstants()
AddFunction<Join>("join", 1, 2);
AddFunction<StartsWith>("startsWith", 2, 2);
AddFunction<ToJson>("toJson", 1, 1);
AddFunction<HashFiles>("hashFiles", 1, 1);
}

private static void AddFunction<T>(String name, Int32 minParameters, Int32 maxParameters)
Expand Down
Loading

0 comments on commit 0dca481

Please sign in to comment.