From 7cc689b0d9fda4dcc931cdb36acb4f9a190d1666 Mon Sep 17 00:00:00 2001 From: eric sciple Date: Fri, 30 Apr 2021 15:48:53 -0500 Subject: [PATCH] minor cleanup in composite (#1045) --- src/Runner.Worker/ExecutionContext.cs | 52 ++--- .../Handlers/CompositeActionHandler.cs | 190 ++++++++---------- src/Runner.Worker/Handlers/ScriptHandler.cs | 6 +- src/Runner.Worker/StepsContext.cs | 16 ++ src/Runner.Worker/StepsRunner.cs | 42 ++-- src/Runner.Worker/action_yaml.json | 4 +- 6 files changed, 136 insertions(+), 174 deletions(-) diff --git a/src/Runner.Worker/ExecutionContext.cs b/src/Runner.Worker/ExecutionContext.cs index baf5758fb..78226785c 100644 --- a/src/Runner.Worker/ExecutionContext.cs +++ b/src/Runner.Worker/ExecutionContext.cs @@ -61,14 +61,15 @@ namespace GitHub.Runner.Worker bool EchoOnActionCommand { get; set; } - bool InsideComposite { get; } + bool IsEmbedded { get; } ExecutionContext Root { get; } // Initialize void InitializeJob(Pipelines.AgentJobRequestMessage message, CancellationToken token); void CancelToken(); - IExecutionContext CreateChild(Guid recordId, string displayName, string refName, string scopeName, string contextName, Dictionary intraActionState = null, int? recordOrder = null, IPagingLogger logger = null, bool insideComposite = false, CancellationTokenSource cancellationTokenSource = null); + IExecutionContext CreateChild(Guid recordId, string displayName, string refName, string scopeName, string contextName, Dictionary intraActionState = null, int? recordOrder = null, IPagingLogger logger = null, bool isEmbedded = false, CancellationTokenSource cancellationTokenSource = null); + IExecutionContext CreateEmbeddedChild(string scopeName, string contextName); // logging long Write(string tag, string message); @@ -99,7 +100,6 @@ namespace GitHub.Runner.Worker // others void ForceTaskComplete(); void RegisterPostJobStep(IStep step); - IStep CreateCompositeStep(string scopeName, IActionRunner step, DictionaryContextData inputsData, Dictionary envData); } public sealed class ExecutionContext : RunnerService, IExecutionContext @@ -157,7 +157,9 @@ namespace GitHub.Runner.Worker public bool EchoOnActionCommand { get; set; } - public bool InsideComposite { get; private set; } + // An embedded execution context shares the same record ID, record name, and logger + // as its enclosing execution context. + public bool IsEmbedded { get; private set; } public TaskResult? Result { @@ -253,36 +255,7 @@ namespace GitHub.Runner.Worker Root.PostJobSteps.Push(step); } - /// - /// Helper function used in CompositeActionHandler::RunAsync to - /// add a child node, aka a step, to the current job to the Root.JobSteps based on the location. - /// - public IStep CreateCompositeStep( - string scopeName, - IActionRunner step, - DictionaryContextData inputsData, - Dictionary envData) - { - step.ExecutionContext = Root.CreateChild(_record.Id, _record.Name, _record.Id.ToString("N"), scopeName, step.Action.ContextName, logger: _logger, insideComposite: true, cancellationTokenSource: CancellationTokenSource.CreateLinkedTokenSource(_cancellationTokenSource.Token)); - step.ExecutionContext.ExpressionValues["inputs"] = inputsData; - step.ExecutionContext.ExpressionValues["steps"] = Global.StepsContext.GetScope(step.ExecutionContext.GetFullyQualifiedContextName()); - - // Add the composite action environment variables to each step. -#if OS_WINDOWS - var envContext = new DictionaryContextData(); -#else - var envContext = new CaseSensitiveDictionaryContextData(); -#endif - foreach (var pair in envData) - { - envContext[pair.Key] = new StringContextData(pair.Value ?? string.Empty); - } - step.ExecutionContext.ExpressionValues["env"] = envContext; - - return step; - } - - public IExecutionContext CreateChild(Guid recordId, string displayName, string refName, string scopeName, string contextName, Dictionary intraActionState = null, int? recordOrder = null, IPagingLogger logger = null, bool insideComposite = false, CancellationTokenSource cancellationTokenSource = null) + public IExecutionContext CreateChild(Guid recordId, string displayName, string refName, string scopeName, string contextName, Dictionary intraActionState = null, int? recordOrder = null, IPagingLogger logger = null, bool isEmbedded = false, CancellationTokenSource cancellationTokenSource = null) { Trace.Entering(); @@ -329,11 +302,20 @@ namespace GitHub.Runner.Worker child._logger.Setup(_mainTimelineId, recordId); } - child.InsideComposite = insideComposite; + child.IsEmbedded = isEmbedded; return child; } + /// + /// An embedded execution context shares the same record ID, record name, logger, + /// and a linked cancellation token. + /// + public IExecutionContext CreateEmbeddedChild(string scopeName, string contextName) + { + return Root.CreateChild(_record.Id, _record.Name, _record.Id.ToString("N"), scopeName, contextName, logger: _logger, isEmbedded: true, cancellationTokenSource: CancellationTokenSource.CreateLinkedTokenSource(_cancellationTokenSource.Token)); + } + public void Start(string currentOperation = null) { _record.CurrentOperation = currentOperation ?? _record.CurrentOperation; diff --git a/src/Runner.Worker/Handlers/CompositeActionHandler.cs b/src/Runner.Worker/Handlers/CompositeActionHandler.cs index d7f92b0c0..08d31eafd 100644 --- a/src/Runner.Worker/Handlers/CompositeActionHandler.cs +++ b/src/Runner.Worker/Handlers/CompositeActionHandler.cs @@ -26,65 +26,60 @@ namespace GitHub.Runner.Worker.Handlers public async Task RunAsync(ActionRunStage stage) { - // Validate args. + // Validate args Trace.Entering(); ArgUtil.NotNull(ExecutionContext, nameof(ExecutionContext)); ArgUtil.NotNull(Inputs, nameof(Inputs)); ArgUtil.NotNull(Data.Steps, nameof(Data.Steps)); - // Resolve action steps - var actionSteps = Data.Steps; - - // Create Context Data to reuse for each composite action step - var inputsData = new DictionaryContextData(); - foreach (var i in Inputs) - { - inputsData[i.Key] = new StringContextData(i.Value); - } - - // Initialize Composite Steps List of Steps - var compositeSteps = new List(); - - // Temporary hack until after M271-ish. After M271-ish the server will never send an empty - // context name. Generated context names start with "__" - var childScopeName = ExecutionContext.GetFullyQualifiedContextName(); - if (string.IsNullOrEmpty(childScopeName)) - { - childScopeName = $"__{Guid.NewGuid()}"; - } - - foreach (Pipelines.ActionStep actionStep in actionSteps) - { - var actionRunner = HostContext.CreateService(); - actionRunner.Action = actionStep; - actionRunner.Stage = stage; - actionRunner.Condition = actionStep.Condition; - - var step = ExecutionContext.CreateCompositeStep(childScopeName, actionRunner, inputsData, Environment); - - // Shallow copy github context - var gitHubContext = step.ExecutionContext.ExpressionValues["github"] as GitHubContext; - ArgUtil.NotNull(gitHubContext, nameof(gitHubContext)); - gitHubContext = gitHubContext.ShallowCopy(); - step.ExecutionContext.ExpressionValues["github"] = gitHubContext; - - // Set GITHUB_ACTION_PATH - step.ExecutionContext.SetGitHubContext("action_path", ActionDirectory); - - compositeSteps.Add(step); - } - try { - // This is where we run each step. - await RunStepsAsync(compositeSteps); + // Inputs of the composite step + var inputsData = new DictionaryContextData(); + foreach (var i in Inputs) + { + inputsData[i.Key] = new StringContextData(i.Value); + } - // Get the pointer of the correct "steps" object and pass it to the ExecutionContext so that we can process the outputs correctly + // Temporary hack until after M271-ish. After M271-ish the server will never send an empty + // context name. Generated context names start with "__" + var childScopeName = ExecutionContext.GetFullyQualifiedContextName(); + if (string.IsNullOrEmpty(childScopeName)) + { + childScopeName = $"__{Guid.NewGuid()}"; + } + + // Create nested steps + var nestedSteps = new List(); + foreach (Pipelines.ActionStep stepData in Data.Steps) + { + var step = HostContext.CreateService(); + step.Action = stepData; + step.Stage = stage; + step.Condition = stepData.Condition; + step.ExecutionContext = ExecutionContext.CreateEmbeddedChild(childScopeName, stepData.ContextName); + step.ExecutionContext.ExpressionValues["inputs"] = inputsData; + step.ExecutionContext.ExpressionValues["steps"] = ExecutionContext.Global.StepsContext.GetScope(childScopeName); + + // Shallow copy github context + var gitHubContext = step.ExecutionContext.ExpressionValues["github"] as GitHubContext; + ArgUtil.NotNull(gitHubContext, nameof(gitHubContext)); + gitHubContext = gitHubContext.ShallowCopy(); + step.ExecutionContext.ExpressionValues["github"] = gitHubContext; + + // Set GITHUB_ACTION_PATH + step.ExecutionContext.SetGitHubContext("action_path", ActionDirectory); + + nestedSteps.Add(step); + } + + // Run nested steps + await RunStepsAsync(nestedSteps); + + // Set outputs ExecutionContext.ExpressionValues["inputs"] = inputsData; - ExecutionContext.ExpressionValues["steps"] = ExecutionContext.Global.StepsContext.GetScope(ExecutionContext.GetFullyQualifiedContextName()); - - ProcessCompositeActionOutputs(); - + ExecutionContext.ExpressionValues["steps"] = ExecutionContext.Global.StepsContext.GetScope(childScopeName); + ProcessOutputs(); ExecutionContext.Global.StepsContext.ClearScope(childScopeName); } catch (Exception ex) @@ -96,7 +91,7 @@ namespace GitHub.Runner.Worker.Handlers } } - private void ProcessCompositeActionOutputs() + private void ProcessOutputs() { ArgUtil.NotNull(ExecutionContext, nameof(ExecutionContext)); @@ -113,69 +108,57 @@ namespace GitHub.Runner.Worker.Handlers evaluateContext[pair.Key] = pair.Value; } - // Get the evluated composite outputs' values mapped to the outputs named + // Evaluate outputs DictionaryContextData actionOutputs = actionManifestManager.EvaluateCompositeOutputs(ExecutionContext, Data.Outputs, evaluateContext); - // Set the outputs for the outputs object in the whole composite action - // Each pair is structured like this - // We ignore "description" for now - // { - // "the-output-name": { - // "description": "", - // "value": "the value" - // }, - // ... - // } + // Set outputs + // + // Each pair is structured like: + // { + // "the-output-name": { + // "description": "", + // "value": "the value" + // }, + // ... + // } foreach (var pair in actionOutputs) { - var outputsName = pair.Key; - var outputsAttributes = pair.Value as DictionaryContextData; - outputsAttributes.TryGetValue("value", out var val); - - if (val != null) + var outputName = pair.Key; + var outputDefinition = pair.Value as DictionaryContextData; + if (outputDefinition.TryGetValue("value", out var val)) { - var outputsValue = val as StringContextData; - // Set output in the whole composite scope. - if (!String.IsNullOrEmpty(outputsValue)) - { - ExecutionContext.SetOutput(outputsName, outputsValue, out _); - } - else - { - ExecutionContext.SetOutput(outputsName, "", out _); - } + var outputValue = val.AssertString("output value"); + ExecutionContext.SetOutput(outputName, outputValue.Value, out _); } } } } - private async Task RunStepsAsync(List compositeSteps) + private async Task RunStepsAsync(List nestedSteps) { - ArgUtil.NotNull(compositeSteps, nameof(compositeSteps)); + ArgUtil.NotNull(nestedSteps, nameof(nestedSteps)); - // The parent StepsRunner of the whole Composite Action Step handles the cancellation stuff already. - foreach (IStep step in compositeSteps) + foreach (IStep step in nestedSteps) { - Trace.Info($"Processing composite step: DisplayName='{step.DisplayName}'"); + Trace.Info($"Processing nested step: DisplayName='{step.DisplayName}'"); - step.ExecutionContext.ExpressionValues["steps"] = ExecutionContext.Global.StepsContext.GetScope(step.ExecutionContext.ScopeName); - - // Populate env context for each step - Trace.Info("Initialize Env context for step"); + // Initialize env context + Trace.Info("Initialize Env context for nested step"); #if OS_WINDOWS var envContext = new DictionaryContextData(); #else var envContext = new CaseSensitiveDictionaryContextData(); #endif + step.ExecutionContext.ExpressionValues["env"] = envContext; - // Global env + // Merge global env foreach (var pair in ExecutionContext.Global.EnvironmentVariables) { envContext[pair.Key] = new StringContextData(pair.Value ?? string.Empty); } - // Stomps over with outside step env - if (step.ExecutionContext.ExpressionValues.TryGetValue("env", out var envContextData)) + // Merge composite-step env + if (ExecutionContext.ExpressionValues.TryGetValue("env", out var envContextData)) { #if OS_WINDOWS var dict = envContextData as DictionaryContextData; @@ -188,13 +171,11 @@ namespace GitHub.Runner.Worker.Handlers } } - step.ExecutionContext.ExpressionValues["env"] = envContext; - var actionStep = step as IActionRunner; try { - // Evaluate and merge action's env block to env context + // Evaluate and merge nested-step env var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator(); var actionEnvironment = templateEvaluator.EvaluateStepEnvironment(actionStep.Action.Environment, step.ExecutionContext.ExpressionValues, step.ExecutionContext.ExpressionFunctions, Common.Util.VarUtil.EnvironmentVariableKeyComparer); foreach (var env in actionEnvironment) @@ -204,39 +185,28 @@ namespace GitHub.Runner.Worker.Handlers } catch (Exception ex) { - // fail the step since there is an evaluate error. - Trace.Info("Caught exception in Composite Steps Runner from expression for step.env"); - // evaluateStepEnvFailed = true; + // Evaluation error + Trace.Info("Caught exception from expression for nested step.env"); step.ExecutionContext.Error(ex); step.ExecutionContext.Complete(TaskResult.Failed); } await RunStepAsync(step); - // Directly after the step, check if the step has failed or cancelled - // If so, return that to the output + // Check failed or canceled if (step.ExecutionContext.Result == TaskResult.Failed || step.ExecutionContext.Result == TaskResult.Canceled) { ExecutionContext.Result = step.ExecutionContext.Result; break; } - - // TODO: Add compat for other types of steps. } - // Completion Status handled by StepsRunner for the whole Composite Action Step } private async Task RunStepAsync(IStep step) { - // Start the step. - Trace.Info("Starting the step."); + Trace.Info($"Starting: {step.DisplayName}"); step.ExecutionContext.Debug($"Starting: {step.DisplayName}"); - // TODO: Fix for Step Level Timeout Attributes for an individual Composite Run Step - // For now, we are not going to support this for an individual composite run step - - var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator(); - await Common.Util.EncodingUtil.SetEncoding(HostContext, Trace, step.ExecutionContext.CancellationToken); try @@ -261,7 +231,7 @@ namespace GitHub.Runner.Worker.Handlers } catch (Exception ex) { - // Log the error and fail the step. + // Log the error and fail the step Trace.Error($"Caught exception from step: {ex}"); step.ExecutionContext.Error(ex); step.ExecutionContext.Result = TaskResult.Failed; @@ -274,9 +244,7 @@ namespace GitHub.Runner.Worker.Handlers } Trace.Info($"Step result: {step.ExecutionContext.Result}"); - - // Complete the step context. - step.ExecutionContext.Debug($"Finishing: {step.DisplayName}"); + step.ExecutionContext.Debug($"Finished: {step.DisplayName}"); } } } diff --git a/src/Runner.Worker/Handlers/ScriptHandler.cs b/src/Runner.Worker/Handlers/ScriptHandler.cs index 022b59420..85f2a72b8 100644 --- a/src/Runner.Worker/Handlers/ScriptHandler.cs +++ b/src/Runner.Worker/Handlers/ScriptHandler.cs @@ -26,7 +26,7 @@ namespace GitHub.Runner.Worker.Handlers // We don't want to display the internal workings if composite (similar/equivalent information can be found in debug) void writeDetails(string message) { - if (ExecutionContext.InsideComposite) + if (ExecutionContext.IsEmbedded) { ExecutionContext.Debug(message); } @@ -52,7 +52,7 @@ namespace GitHub.Runner.Worker.Handlers firstLine = firstLine.Substring(0, firstNewLine); } - writeDetails(ExecutionContext.InsideComposite ? $"Run {firstLine}" : $"##[group]Run {firstLine}"); + writeDetails(ExecutionContext.IsEmbedded ? $"Run {firstLine}" : $"##[group]Run {firstLine}"); } else { @@ -138,7 +138,7 @@ namespace GitHub.Runner.Worker.Handlers } } - writeDetails(ExecutionContext.InsideComposite ? "" : "##[endgroup]"); + writeDetails(ExecutionContext.IsEmbedded ? "" : "##[endgroup]"); } public async Task RunAsync(ActionRunStage stage) diff --git a/src/Runner.Worker/StepsContext.cs b/src/Runner.Worker/StepsContext.cs index e12d526ca..fe9672537 100644 --- a/src/Runner.Worker/StepsContext.cs +++ b/src/Runner.Worker/StepsContext.cs @@ -10,11 +10,19 @@ using GitHub.Runner.Sdk; namespace GitHub.Runner.Worker { + /// + /// Manages the "steps" context. The "steps" context is used to track individual steps + /// "outcome", "conclusion", and "outputs". + /// public sealed class StepsContext { private static readonly Regex _propertyRegex = new Regex("^[a-zA-Z_][a-zA-Z0-9_]*$", RegexOptions.Compiled); private readonly DictionaryContextData _contextData = new DictionaryContextData(); + /// + /// Clears memory for a composite action's isolated "steps" context, after the action + /// is finished executing. + /// public void ClearScope(string scopeName) { if (_contextData.TryGetValue(scopeName, out _)) @@ -23,6 +31,14 @@ namespace GitHub.Runner.Worker } } + /// + /// Gets the "steps" context for a given scope. The root steps in a workflow use the + /// default "steps" context (i.e. scopeName=""). + /// + /// An isolated "steps" context is created for each composite action. All child steps + /// within a composite action, share an isolated "steps" context. The scope name matches + /// the composite action's fully qualified context name. + /// public DictionaryContextData GetScope(string scopeName) { if (scopeName == null) diff --git a/src/Runner.Worker/StepsRunner.cs b/src/Runner.Worker/StepsRunner.cs index 58845206b..a2db274e7 100644 --- a/src/Runner.Worker/StepsRunner.cs +++ b/src/Runner.Worker/StepsRunner.cs @@ -82,24 +82,21 @@ namespace GitHub.Runner.Worker step.ExecutionContext.ExpressionFunctions.Add(new FunctionInfo(PipelineTemplateConstants.Success, 0, 0)); step.ExecutionContext.ExpressionFunctions.Add(new FunctionInfo(PipelineTemplateConstants.HashFiles, 1, byte.MaxValue)); + // Expression values step.ExecutionContext.ExpressionValues["steps"] = step.ExecutionContext.Global.StepsContext.GetScope(step.ExecutionContext.ScopeName); - - // Populate env context for each step - Trace.Info("Initialize Env context for step"); #if OS_WINDOWS var envContext = new DictionaryContextData(); #else var envContext = new CaseSensitiveDictionaryContextData(); #endif + step.ExecutionContext.ExpressionValues["env"] = envContext; - // Global env + // Merge global env foreach (var pair in step.ExecutionContext.Global.EnvironmentVariables) { envContext[pair.Key] = new StringContextData(pair.Value ?? string.Empty); } - step.ExecutionContext.ExpressionValues["env"] = envContext; - bool evaluateStepEnvFailed = false; if (step is IActionRunner actionStep) { @@ -108,7 +105,7 @@ namespace GitHub.Runner.Worker try { - // Evaluate and merge action's env block to env context + // Evaluate and merge step env var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator(); var actionEnvironment = templateEvaluator.EvaluateStepEnvironment(actionStep.Action.Environment, step.ExecutionContext.ExpressionValues, step.ExecutionContext.ExpressionFunctions, VarUtil.EnvironmentVariableKeyComparer); foreach (var env in actionEnvironment) @@ -118,7 +115,7 @@ namespace GitHub.Runner.Worker } catch (Exception ex) { - // fail the step since there is an evaluate error. + // Fail the step since there is an evaluate error Trace.Info("Caught exception from expression for step.env"); evaluateStepEnvFailed = true; step.ExecutionContext.Error(ex); @@ -136,7 +133,7 @@ namespace GitHub.Runner.Worker // Test the condition again. The job was canceled after the condition was originally evaluated. jobCancelRegister = jobContext.CancellationToken.Register(() => { - // mark job as cancelled + // Mark job as cancelled jobContext.Result = TaskResult.Canceled; jobContext.JobContext.Status = jobContext.Result?.ToActionResult(); @@ -157,7 +154,7 @@ namespace GitHub.Runner.Worker } catch (Exception ex) { - // Cancel the step since we get exception while re-evaluate step condition. + // 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); } @@ -165,7 +162,7 @@ namespace GitHub.Runner.Worker if (!conditionReTestResult) { - // Cancel the step. + // Cancel the step Trace.Info("Cancel current running step."); step.ExecutionContext.CancelToken(); } @@ -175,13 +172,13 @@ namespace GitHub.Runner.Worker { if (jobContext.Result != TaskResult.Canceled) { - // mark job as cancelled + // Mark job as cancelled jobContext.Result = TaskResult.Canceled; jobContext.JobContext.Status = jobContext.Result?.ToActionResult(); } } - // Evaluate condition. + // Evaluate condition step.ExecutionContext.Debug($"Evaluating condition for step: '{step.DisplayName}'"); var conditionTraceWriter = new ConditionTraceWriter(Trace, step.ExecutionContext); var conditionResult = false; @@ -206,22 +203,21 @@ namespace GitHub.Runner.Worker } } - // no evaluate error but condition is false if (!conditionResult && conditionEvaluateError == null) { - // Condition == false + // Condition is false Trace.Info("Skipping step due to condition evaluation."); CompleteStep(step, TaskResult.Skipped, resultCode: conditionTraceWriter.Trace); } else if (conditionEvaluateError != null) { - // fail the step since there is an evaluate error. + // Condition error step.ExecutionContext.Error(conditionEvaluateError); CompleteStep(step, TaskResult.Failed); } else { - // Run the step. + // Run the step await RunStepAsync(step, jobContext.CancellationToken); CompleteStep(step); } @@ -236,7 +232,7 @@ namespace GitHub.Runner.Worker } } - // Update the job result. + // Update the job result if (step.ExecutionContext.Result == TaskResult.Failed) { Trace.Info($"Update job result with current step result '{step.ExecutionContext.Result}'."); @@ -262,7 +258,7 @@ namespace GitHub.Runner.Worker step.ExecutionContext.UpdateTimelineRecordDisplayName(actionRunner.DisplayName); } - // Start the step. + // Start the step Trace.Info("Starting the step."); step.ExecutionContext.Debug($"Starting: {step.DisplayName}"); @@ -303,7 +299,7 @@ namespace GitHub.Runner.Worker } else { - // Log the exception and cancel the step. + // Log the exception and cancel the step Trace.Error($"Caught cancellation exception from step: {ex}"); step.ExecutionContext.Error(ex); step.ExecutionContext.Result = TaskResult.Canceled; @@ -311,7 +307,7 @@ namespace GitHub.Runner.Worker } catch (Exception ex) { - // Log the error and fail the step. + // Log the error and fail the step Trace.Error($"Caught exception from step: {ex}"); step.ExecutionContext.Error(ex); step.ExecutionContext.Result = TaskResult.Failed; @@ -323,7 +319,7 @@ namespace GitHub.Runner.Worker step.ExecutionContext.Result = TaskResultUtil.MergeTaskResults(step.ExecutionContext.Result, step.ExecutionContext.CommandResult.Value); } - // Fixup the step result if ContinueOnError. + // Fixup the step result if ContinueOnError if (step.ExecutionContext.Result == TaskResult.Failed) { var continueOnError = false; @@ -348,7 +344,7 @@ namespace GitHub.Runner.Worker } Trace.Info($"Step result: {step.ExecutionContext.Result}"); - // Complete the step context. + // Complete the step context step.ExecutionContext.Debug($"Finishing: {step.DisplayName}"); } diff --git a/src/Runner.Worker/action_yaml.json b/src/Runner.Worker/action_yaml.json index a4a09181b..2873da7cd 100644 --- a/src/Runner.Worker/action_yaml.json +++ b/src/Runner.Worker/action_yaml.json @@ -32,10 +32,10 @@ "outputs": { "mapping": { "loose-key-type": "non-empty-string", - "loose-value-type": "outputs-attributes" + "loose-value-type": "output-definition" } }, - "outputs-attributes": { + "output-definition": { "mapping": { "properties": { "description": "string",