From 1cc3c08cf2fd1149774ae8098b2b99bcc320deb7 Mon Sep 17 00:00:00 2001 From: eric sciple Date: Sun, 19 Jul 2020 17:19:13 -0400 Subject: [PATCH] Prepare to switch GITHUB_ACTION to use ContextName instead of refname (#593) This PR changes GITHUB_ACTION to use the step ContextName, instead of refname. The behavior is behind a feature flag. Refname is an otherwise deprecated property. Primary motivation: For composite actions, we need a distinct GITHUB_ACTION for each nested step. This PR adds code to generate a default context name for nested steps. For nested steps, GITHUB_ACTION will be set to "{ScopeName}.{ContextName}" to ensure no collisions. A corresponding change will be made on the server so context name is never empty. Generated context names will start with "__". A follow-up PR is required to avoid tracking "step" context values (outputs/conclusion/result) for generated context names. Waiting on telemetry from the server to confirm it's safe to assume leading "__" is a generate context name. --- src/Runner.Worker/ActionManifestManager.cs | 61 ++- src/Runner.Worker/ExecutionContext.cs | 35 +- .../Handlers/CompositeActionHandler.cs | 67 +-- src/Runner.Worker/JobExtension.cs | 2 +- src/Runner.Worker/StepsRunner.cs | 11 +- src/Sdk/DTPipelines/Pipelines/ActionStep.cs | 4 - .../Pipelines/AgentJobRequestMessage.cs | 26 -- src/Sdk/DTPipelines/Pipelines/ContextScope.cs | 53 --- .../PipelineTemplateConstants.cs | 16 +- .../PipelineTemplateConverter.cs | 119 +++--- .../PipelineTemplateEvaluator.cs | 101 +---- .../ObjectTemplating/ReferenceNameBuilder.cs | 121 ++++++ src/Sdk/DTPipelines/workflow-v1.0.json | 395 +----------------- src/Test/L0/Listener/JobDispatcherL0.cs | 2 +- src/Test/L0/Listener/RunnerL0.cs | 2 +- src/Test/L0/Worker/ActionCommandManagerL0.cs | 2 +- src/Test/L0/Worker/ExecutionContextL0.cs | 10 +- src/Test/L0/Worker/JobExtensionL0.cs | 2 +- src/Test/L0/Worker/JobRunnerL0.cs | 2 +- src/Test/L0/Worker/WorkerL0.cs | 2 +- 20 files changed, 288 insertions(+), 745 deletions(-) delete mode 100644 src/Sdk/DTPipelines/Pipelines/ContextScope.cs create mode 100644 src/Sdk/DTPipelines/Pipelines/ObjectTemplating/ReferenceNameBuilder.cs diff --git a/src/Runner.Worker/ActionManifestManager.cs b/src/Runner.Worker/ActionManifestManager.cs index 57c59e34b..15734cb86 100644 --- a/src/Runner.Worker/ActionManifestManager.cs +++ b/src/Runner.Worker/ActionManifestManager.cs @@ -55,7 +55,7 @@ namespace GitHub.Runner.Worker public ActionDefinitionData Load(IExecutionContext executionContext, string manifestFile) { - var templateContext = CreateContext(executionContext); + var templateContext = CreateTemplateContext(executionContext); ActionDefinitionData actionDefinition = new ActionDefinitionData(); // Clean up file name real quick @@ -118,7 +118,7 @@ namespace GitHub.Runner.Worker break; case "inputs": - ConvertInputs(templateContext, actionPair.Value, actionDefinition); + ConvertInputs(actionPair.Value, actionDefinition); break; case "runs": @@ -177,19 +177,19 @@ namespace GitHub.Runner.Worker if (token != null) { - var context = CreateContext(executionContext, extraExpressionValues); + var templateContext = CreateTemplateContext(executionContext, extraExpressionValues); try { - token = TemplateEvaluator.Evaluate(context, "outputs", token, 0, null, omitHeader: true); - context.Errors.Check(); + token = TemplateEvaluator.Evaluate(templateContext, "outputs", token, 0, null, omitHeader: true); + templateContext.Errors.Check(); result = token.ToContextData().AssertDictionary("composite outputs"); } catch (Exception ex) when (!(ex is TemplateValidationException)) { - context.Errors.Add(ex); + templateContext.Errors.Add(ex); } - context.Errors.Check(); + templateContext.Errors.Check(); } return result ?? new DictionaryContextData(); @@ -204,11 +204,11 @@ namespace GitHub.Runner.Worker if (token != null) { - var context = CreateContext(executionContext, extraExpressionValues); + var templateContext = CreateTemplateContext(executionContext, extraExpressionValues); try { - var evaluateResult = TemplateEvaluator.Evaluate(context, "container-runs-args", token, 0, null, omitHeader: true); - context.Errors.Check(); + var evaluateResult = TemplateEvaluator.Evaluate(templateContext, "container-runs-args", token, 0, null, omitHeader: true); + templateContext.Errors.Check(); Trace.Info($"Arguments evaluate result: {StringUtil.ConvertToJson(evaluateResult)}"); @@ -225,10 +225,10 @@ namespace GitHub.Runner.Worker catch (Exception ex) when (!(ex is TemplateValidationException)) { Trace.Error(ex); - context.Errors.Add(ex); + templateContext.Errors.Add(ex); } - context.Errors.Check(); + templateContext.Errors.Check(); } return result; @@ -243,11 +243,11 @@ namespace GitHub.Runner.Worker if (token != null) { - var context = CreateContext(executionContext, extraExpressionValues); + var templateContext = CreateTemplateContext(executionContext, extraExpressionValues); try { - var evaluateResult = TemplateEvaluator.Evaluate(context, "container-runs-env", token, 0, null, omitHeader: true); - context.Errors.Check(); + var evaluateResult = TemplateEvaluator.Evaluate(templateContext, "container-runs-env", token, 0, null, omitHeader: true); + templateContext.Errors.Check(); Trace.Info($"Environments evaluate result: {StringUtil.ConvertToJson(evaluateResult)}"); @@ -269,10 +269,10 @@ namespace GitHub.Runner.Worker catch (Exception ex) when (!(ex is TemplateValidationException)) { Trace.Error(ex); - context.Errors.Add(ex); + templateContext.Errors.Add(ex); } - context.Errors.Check(); + templateContext.Errors.Check(); } return result; @@ -286,11 +286,11 @@ namespace GitHub.Runner.Worker string result = ""; if (token != null) { - var context = CreateContext(executionContext); + var templateContext = CreateTemplateContext(executionContext); try { - var evaluateResult = TemplateEvaluator.Evaluate(context, "input-default-context", token, 0, null, omitHeader: true); - context.Errors.Check(); + var evaluateResult = TemplateEvaluator.Evaluate(templateContext, "input-default-context", token, 0, null, omitHeader: true); + templateContext.Errors.Check(); Trace.Info($"Input '{inputName}': default value evaluate result: {StringUtil.ConvertToJson(evaluateResult)}"); @@ -300,16 +300,16 @@ namespace GitHub.Runner.Worker catch (Exception ex) when (!(ex is TemplateValidationException)) { Trace.Error(ex); - context.Errors.Add(ex); + templateContext.Errors.Add(ex); } - context.Errors.Check(); + templateContext.Errors.Check(); } return result; } - private TemplateContext CreateContext( + private TemplateContext CreateTemplateContext( IExecutionContext executionContext, IDictionary extraExpressionValues = null) { @@ -357,7 +357,7 @@ namespace GitHub.Runner.Worker private ActionExecutionData ConvertRuns( IExecutionContext executionContext, - TemplateContext context, + TemplateContext templateContext, TemplateToken inputsToken, MappingToken outputs = null) { @@ -375,7 +375,7 @@ namespace GitHub.Runner.Worker var postToken = default(StringToken); var postEntrypointToken = default(StringToken); var postIfToken = default(StringToken); - var stepsLoaded = default(List); + var steps = default(List); foreach (var run in runsMapping) { @@ -424,9 +424,9 @@ namespace GitHub.Runner.Worker case "steps": if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("TESTING_COMPOSITE_ACTIONS_ALPHA"))) { - var steps = run.Value.AssertSequence("steps"); - var evaluator = executionContext.ToPipelineTemplateEvaluator(); - stepsLoaded = evaluator.LoadCompositeSteps(steps); + var stepsToken = run.Value.AssertSequence("steps"); + steps = PipelineTemplateConverter.ConvertToSteps(templateContext, stepsToken); + templateContext.Errors.Check(); break; } throw new Exception("You aren't supposed to be using Composite Actions yet!"); @@ -479,7 +479,7 @@ namespace GitHub.Runner.Worker } else if (string.Equals(usingToken.Value, "composite", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("TESTING_COMPOSITE_ACTIONS_ALPHA"))) { - if (stepsLoaded == null) + if (steps == null) { // TODO: Add a more helpful error message + including file name, etc. to show user that it's because of their yaml file throw new ArgumentNullException($"No steps provided."); @@ -488,7 +488,7 @@ namespace GitHub.Runner.Worker { return new CompositeActionExecutionData() { - Steps = stepsLoaded, + Steps = steps.Cast().ToList(), Outputs = outputs }; } @@ -510,7 +510,6 @@ namespace GitHub.Runner.Worker } private void ConvertInputs( - TemplateContext context, TemplateToken inputsToken, ActionDefinitionData actionDefinition) { diff --git a/src/Runner.Worker/ExecutionContext.cs b/src/Runner.Worker/ExecutionContext.cs index b13f68784..18e7dd9d1 100644 --- a/src/Runner.Worker/ExecutionContext.cs +++ b/src/Runner.Worker/ExecutionContext.cs @@ -105,7 +105,7 @@ namespace GitHub.Runner.Worker // others void ForceTaskComplete(); void RegisterPostJobStep(IStep step); - IStep CreateCompositeStep(IActionRunner step, DictionaryContextData inputsData, Dictionary envData); + IStep CreateCompositeStep(string scopeName, IActionRunner step, DictionaryContextData inputsData, Dictionary envData); } public sealed class ExecutionContext : RunnerService, IExecutionContext @@ -120,9 +120,6 @@ namespace GitHub.Runner.Worker private event OnMatcherChanged _onMatcherChanged; - // Regex used for checking if ScopeName meets the condition that shows that its id is null. - private readonly static Regex _generatedContextNamePattern = new Regex("^__[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase); - private IssueMatcherConfig[] _matchers; private IPagingLogger _logger; @@ -273,23 +270,14 @@ namespace GitHub.Runner.Worker /// 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) { - // If the context name is empty and the scope name is empty, we would generate a unique scope name for this child in the following format: - // "__" - var safeContextName = !string.IsNullOrEmpty(ContextName) ? ContextName : $"__{Guid.NewGuid()}"; - - // Set Scope Name. Note, for our design, we consider each step in a composite action to have the same scope - // This makes it much simpler to handle their outputs at the end of the Composite Action - var childScopeName = !string.IsNullOrEmpty(ScopeName) ? $"{ScopeName}.{safeContextName}" : safeContextName; - - var childContextName = !string.IsNullOrEmpty(step.Action.ContextName) ? step.Action.ContextName : $"__{Guid.NewGuid()}"; - - step.ExecutionContext = Root.CreateChild(_record.Id, step.DisplayName, _record.Id.ToString("N"), childScopeName, childContextName, logger: _logger); - + step.ExecutionContext = Root.CreateChild(_record.Id, step.DisplayName, _record.Id.ToString("N"), scopeName, step.Action.ContextName, logger: _logger); step.ExecutionContext.ExpressionValues["inputs"] = inputsData; + step.ExecutionContext.ExpressionValues["steps"] = StepsContext.GetScope(step.ExecutionContext.GetFullyQualifiedContextName()); // Add the composite action environment variables to each step. #if OS_WINDOWS @@ -420,6 +408,7 @@ namespace GitHub.Runner.Worker _logger.End(); + // todo: Skip if generated context name. After M271-ish the server will never send an empty context name. Generated context names will start with "__" if (!string.IsNullOrEmpty(ContextName)) { StepsContext.SetOutcome(ScopeName, ContextName, (Outcome ?? Result ?? TaskResult.Succeeded).ToActionResult()); @@ -482,8 +471,8 @@ namespace GitHub.Runner.Worker { ArgUtil.NotNullOrEmpty(name, nameof(name)); - // if the ContextName follows the __GUID format which is set as the default value for ContextName if null for Composite Actions. - if (String.IsNullOrEmpty(ContextName) || _generatedContextNamePattern.IsMatch(ContextName)) + // todo: Skip if generated context name. After M271-ish the server will never send an empty context name. Generated context names will start with "__" + if (string.IsNullOrEmpty(ContextName)) { reference = null; return; @@ -923,6 +912,16 @@ namespace GitHub.Runner.Worker // Otherwise individual overloads would need to be implemented (depending on the unit test). public static class ExecutionContextExtension { + public static string GetFullyQualifiedContextName(this IExecutionContext context) + { + if (!string.IsNullOrEmpty(context.ScopeName)) + { + return $"{context.ScopeName}.{context.ContextName}"; + } + + return context.ContextName; + } + public static void Error(this IExecutionContext context, Exception ex) { context.Error(ex.Message); diff --git a/src/Runner.Worker/Handlers/CompositeActionHandler.cs b/src/Runner.Worker/Handlers/CompositeActionHandler.cs index c24a14f9d..2ebad979f 100644 --- a/src/Runner.Worker/Handlers/CompositeActionHandler.cs +++ b/src/Runner.Worker/Handlers/CompositeActionHandler.cs @@ -47,46 +47,22 @@ namespace GitHub.Runner.Worker.Handlers // Initialize Composite Steps List of Steps var compositeSteps = new List(); - foreach (Pipelines.ActionStep aStep in actionSteps) + // 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)) { - // Ex: - // runs: - // using: "composite" - // steps: - // - uses: example/test-composite@v2 (a) - // - run echo hello world (b) - // - run echo hello world 2 (c) - // - // ethanchewy/test-composite/action.yaml - // runs: - // using: "composite" - // steps: - // - run echo hello world 3 (d) - // - run echo hello world 4 (e) - // - // Steps processed as follow: - // | a | - // | a | => | d | - // (Run step d) - // | a | - // | a | => | e | - // (Run step e) - // | a | - // (Run step a) - // | b | - // (Run step b) - // | c | - // (Run step c) - // Done. + childScopeName = $"__{Guid.NewGuid()}"; + } + foreach (Pipelines.ActionStep actionStep in actionSteps) + { var actionRunner = HostContext.CreateService(); - actionRunner.Action = aStep; + actionRunner.Action = actionStep; actionRunner.Stage = stage; - actionRunner.Condition = aStep.Condition; - - var step = ExecutionContext.CreateCompositeStep(actionRunner, inputsData, Environment); - InitializeScope(step); + actionRunner.Condition = actionStep.Condition; + var step = ExecutionContext.CreateCompositeStep(childScopeName, actionRunner, inputsData, Environment); compositeSteps.Add(step); } @@ -96,10 +72,8 @@ namespace GitHub.Runner.Worker.Handlers await RunStepsAsync(compositeSteps); // Get the pointer of the correct "steps" object and pass it to the ExecutionContext so that we can process the outputs correctly - // This will always be the same for every step so we can pull this from the first step if it exists - var stepExecutionContext = compositeSteps.Count > 0 ? compositeSteps[0].ExecutionContext : null; ExecutionContext.ExpressionValues["inputs"] = inputsData; - ExecutionContext.ExpressionValues["steps"] = stepExecutionContext.StepsContext.GetScope(stepExecutionContext.ScopeName); + ExecutionContext.ExpressionValues["steps"] = ExecutionContext.StepsContext.GetScope(ExecutionContext.GetFullyQualifiedContextName()); ProcessCompositeActionOutputs(); } @@ -158,13 +132,6 @@ namespace GitHub.Runner.Worker.Handlers } } - private void InitializeScope(IStep step) - { - var stepsContext = step.ExecutionContext.StepsContext; - var scopeName = step.ExecutionContext.ScopeName; - step.ExecutionContext.ExpressionValues["steps"] = stepsContext.GetScope(scopeName); - } - private async Task RunStepsAsync(List compositeSteps) { ArgUtil.NotNull(compositeSteps, nameof(compositeSteps)); @@ -209,15 +176,7 @@ namespace GitHub.Runner.Worker.Handlers var actionStep = step as IActionRunner; // Set GITHUB_ACTION - // TODO: Fix this after SDK Changes. - if (!String.IsNullOrEmpty(step.ExecutionContext.ScopeName)) - { - step.ExecutionContext.SetGitHubContext("action", step.ExecutionContext.ScopeName); - } - else - { - step.ExecutionContext.SetGitHubContext("action", step.ExecutionContext.ContextName); - } + step.ExecutionContext.SetGitHubContext("action", step.ExecutionContext.GetFullyQualifiedContextName()); try { diff --git a/src/Runner.Worker/JobExtension.cs b/src/Runner.Worker/JobExtension.cs index 61f080c71..eb3f4fcd4 100644 --- a/src/Runner.Worker/JobExtension.cs +++ b/src/Runner.Worker/JobExtension.cs @@ -296,7 +296,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, actionStep.Action.ScopeName, actionStep.Action.ContextName, intraActionState); + actionStep.ExecutionContext = jobContext.CreateChild(actionStep.Action.Id, actionStep.DisplayName, actionStep.Action.Name, null, actionStep.Action.ContextName, intraActionState); } } diff --git a/src/Runner.Worker/StepsRunner.cs b/src/Runner.Worker/StepsRunner.cs index 39f22ee5f..dfe7e8778 100644 --- a/src/Runner.Worker/StepsRunner.cs +++ b/src/Runner.Worker/StepsRunner.cs @@ -103,7 +103,16 @@ namespace GitHub.Runner.Worker if (step is IActionRunner actionStep) { // Set GITHUB_ACTION - step.ExecutionContext.SetGitHubContext("action", actionStep.Action.Name); + // Warning: Do not turn on FF DistributedTask.UseContextNameForGITHUBACTION until after M271-ish. After M271-ish + // the server will never send an empty context name. Generated context names start with "__" + if (step.ExecutionContext.Variables.GetBoolean("DistributedTask.UseContextNameForGITHUBACTION") ?? false) + { + step.ExecutionContext.SetGitHubContext("action", actionStep.Action.Name); + } + else + { + step.ExecutionContext.SetGitHubContext("action", step.ExecutionContext.GetFullyQualifiedContextName()); + } try { diff --git a/src/Sdk/DTPipelines/Pipelines/ActionStep.cs b/src/Sdk/DTPipelines/Pipelines/ActionStep.cs index ab152d67a..f4ed5f041 100644 --- a/src/Sdk/DTPipelines/Pipelines/ActionStep.cs +++ b/src/Sdk/DTPipelines/Pipelines/ActionStep.cs @@ -24,7 +24,6 @@ namespace GitHub.DistributedTask.Pipelines Environment = actionToClone.Environment?.Clone(); Inputs = actionToClone.Inputs?.Clone(); ContextName = actionToClone?.ContextName; - ScopeName = actionToClone?.ScopeName; DisplayNameToken = actionToClone.DisplayNameToken?.Clone(); } @@ -41,9 +40,6 @@ namespace GitHub.DistributedTask.Pipelines [DataMember(EmitDefaultValue = false)] public TemplateToken DisplayNameToken { get; set; } - [DataMember(EmitDefaultValue = false)] - public String ScopeName { get; set; } - [DataMember(EmitDefaultValue = false)] public String ContextName { get; set; } diff --git a/src/Sdk/DTPipelines/Pipelines/AgentJobRequestMessage.cs b/src/Sdk/DTPipelines/Pipelines/AgentJobRequestMessage.cs index c94ff5913..7aa21e7ff 100644 --- a/src/Sdk/DTPipelines/Pipelines/AgentJobRequestMessage.cs +++ b/src/Sdk/DTPipelines/Pipelines/AgentJobRequestMessage.cs @@ -39,7 +39,6 @@ namespace GitHub.DistributedTask.Pipelines DictionaryContextData contextData, WorkspaceOptions workspaceOptions, IEnumerable steps, - IEnumerable scopes, IList fileTable, TemplateToken jobOutputs, IList defaults) @@ -60,11 +59,6 @@ namespace GitHub.DistributedTask.Pipelines m_maskHints = new List(maskHints); m_steps = new List(steps); - if (scopes != null) - { - m_scopes = new List(scopes); - } - if (environmentVariables?.Count > 0) { m_environmentVariables = new List(environmentVariables); @@ -261,18 +255,6 @@ namespace GitHub.DistributedTask.Pipelines } } - public IList Scopes - { - get - { - if (m_scopes == null) - { - m_scopes = new List(); - } - return m_scopes; - } - } - /// /// Gets the table of files used when parsing the pipeline (e.g. yaml files) /// @@ -415,11 +397,6 @@ namespace GitHub.DistributedTask.Pipelines m_maskHints = new List(this.m_maskHints.Distinct()); } - if (m_scopes?.Count == 0) - { - m_scopes = null; - } - if (m_variables?.Count == 0) { m_variables = null; @@ -447,9 +424,6 @@ namespace GitHub.DistributedTask.Pipelines [DataMember(Name = "Steps", EmitDefaultValue = false)] private List m_steps; - [DataMember(Name = "Scopes", EmitDefaultValue = false)] - private List m_scopes; - [DataMember(Name = "Variables", EmitDefaultValue = false)] private IDictionary m_variables; diff --git a/src/Sdk/DTPipelines/Pipelines/ContextScope.cs b/src/Sdk/DTPipelines/Pipelines/ContextScope.cs deleted file mode 100644 index 14a23c485..000000000 --- a/src/Sdk/DTPipelines/Pipelines/ContextScope.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Runtime.Serialization; -using GitHub.DistributedTask.ObjectTemplating.Tokens; -using Newtonsoft.Json; - -namespace GitHub.DistributedTask.Pipelines -{ - [DataContract] - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class ContextScope - { - [DataMember(EmitDefaultValue = false)] - public String Name { get; set; } - - [IgnoreDataMember] - public String ContextName - { - get - { - var index = Name.LastIndexOf('.'); - if (index >= 0) - { - return Name.Substring(index + 1); - } - - return Name; - } - } - - [IgnoreDataMember] - public String ParentName - { - get - { - var index = Name.LastIndexOf('.'); - if (index >= 0) - { - return Name.Substring(0, index); - } - - return String.Empty; - } - } - - [DataMember(EmitDefaultValue = false)] - public TemplateToken Inputs { get; set; } - - [DataMember(EmitDefaultValue = false)] - public TemplateToken Outputs { get; set; } - } -} diff --git a/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateConstants.cs b/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateConstants.cs index f2609462b..894b1ba6c 100644 --- a/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateConstants.cs +++ b/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateConstants.cs @@ -11,8 +11,7 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating public const String BooleanStrategyContext = "boolean-strategy-context"; public const String CancelTimeoutMinutes = "cancel-timeout-minutes"; public const String Cancelled = "cancelled"; - public const String Checkout = "checkout"; - public const String Clean = "clean"; + public const String Clean= "clean"; public const String Container = "container"; public const String ContinueOnError = "continue-on-error"; public const String Defaults = "defaults"; @@ -23,7 +22,6 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating public const String FailFast = "fail-fast"; public const String Failure = "failure"; public const String FetchDepth = "fetch-depth"; - public const String GeneratedId = "generated-id"; public const String GitHub = "github"; public const String HashFiles = "hashFiles"; public const String Id = "id"; @@ -36,7 +34,6 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating public const String JobIfResult = "job-if-result"; public const String JobOutputs = "job-outputs"; public const String Jobs = "jobs"; - public const String Labels = "labels"; public const String Lfs = "lfs"; public const String Matrix = "matrix"; public const String MaxParallel = "max-parallel"; @@ -52,24 +49,18 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating public const String Pool = "pool"; public const String Ports = "ports"; public const String Result = "result"; - public const String RunDisplayPrefix = "Run "; public const String Run = "run"; + public const String RunDisplayPrefix = "Run "; public const String Runner = "runner"; public const String RunsOn = "runs-on"; - public const String Scope = "scope"; - public const String Scopes = "scopes"; public const String Secrets = "secrets"; public const String Services = "services"; public const String Shell = "shell"; public const String Skipped = "skipped"; public const String StepEnv = "step-env"; public const String StepIfResult = "step-if-result"; - public const String Steps = "steps"; - public const String StepsInTemplate = "steps-in-template"; - public const String StepsScopeInputs = "steps-scope-inputs"; - public const String StepsScopeOutputs = "steps-scope-outputs"; - public const String StepsTemplateRoot = "steps-template-root"; public const String StepWith = "step-with"; + public const String Steps = "steps"; public const String Strategy = "strategy"; public const String StringStepsContext = "string-steps-context"; public const String StringStrategyContext = "string-strategy-context"; @@ -77,7 +68,6 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating public const String Success = "success"; public const String Template = "template"; public const String TimeoutMinutes = "timeout-minutes"; - public const String Token = "token"; public const String Uses = "uses"; public const String VmImage = "vmImage"; public const String Volumes = "volumes"; diff --git a/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateConverter.cs b/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateConverter.cs index a952f58fb..5a9bc11b9 100644 --- a/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateConverter.cs +++ b/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateConverter.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using System.Globalization; +using System.ComponentModel; using System.Linq; using GitHub.DistributedTask.Expressions2; using GitHub.DistributedTask.Expressions2.Sdk; @@ -14,8 +14,62 @@ using Newtonsoft.Json.Linq; namespace GitHub.DistributedTask.Pipelines.ObjectTemplating { - internal static class PipelineTemplateConverter + [EditorBrowsable(EditorBrowsableState.Never)] + public static class PipelineTemplateConverter { + public static List ConvertToSteps( + TemplateContext context, + TemplateToken steps) + { + var stepsSequence = steps.AssertSequence($"job {PipelineTemplateConstants.Steps}"); + + var result = new List(); + var nameBuilder = new ReferenceNameBuilder(); + foreach (var stepsItem in stepsSequence) + { + var step = ConvertToStep(context, stepsItem, nameBuilder); + if (step != null) // step = null means we are hitting error during step conversion, there should be an error in context.errors + { + if (step.Enabled) + { + result.Add(step); + } + } + } + + // Generate context name if empty + foreach (ActionStep step in result) + { + if (!String.IsNullOrEmpty(step.ContextName)) + { + continue; + } + + var name = default(string); + switch (step.Reference.Type) + { + case ActionSourceType.ContainerRegistry: + var containerReference = step.Reference as ContainerRegistryReference; + name = containerReference.Image; + break; + case ActionSourceType.Repository: + var repositoryReference = step.Reference as RepositoryPathReference; + name = !String.IsNullOrEmpty(repositoryReference.Name) ? repositoryReference.Name : PipelineConstants.SelfAlias; + break; + } + + if (String.IsNullOrEmpty(name)) + { + name = "run"; + } + + nameBuilder.AppendSegment($"__{name}"); + step.ContextName = nameBuilder.Build(); + } + + return result; + } + internal static Boolean ConvertToIfResult( TemplateContext context, TemplateToken ifResult) @@ -29,6 +83,7 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating var evaluationResult = EvaluationResult.CreateIntermediateResult(null, ifResult); return evaluationResult.IsTruthy; } + internal static Boolean? ConvertToStepContinueOnError( TemplateContext context, TemplateToken token, @@ -264,32 +319,10 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating return result; } - //Note: originally was List but we need to change to List to use the "Inputs" attribute - internal static List ConvertToSteps( - TemplateContext context, - TemplateToken steps) - { - var stepsSequence = steps.AssertSequence($"job {PipelineTemplateConstants.Steps}"); - - var result = new List(); - foreach (var stepsItem in stepsSequence) - { - var step = ConvertToStep(context, stepsItem); - if (step != null) // step = null means we are hitting error during step conversion, there should be an error in context.errors - { - if (step.Enabled) - { - result.Add(step); - } - } - } - - return result; - } - private static ActionStep ConvertToStep( TemplateContext context, - TemplateToken stepsItem) + TemplateToken stepsItem, + ReferenceNameBuilder nameBuilder) { var step = stepsItem.AssertMapping($"{PipelineTemplateConstants.Steps} item"); var continueOnError = default(ScalarToken); @@ -299,7 +332,6 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating var ifToken = default(ScalarToken); var name = default(ScalarToken); var run = default(ScalarToken); - var scope = default(StringToken); var timeoutMinutes = default(ScalarToken); var uses = default(StringToken); var with = default(TemplateToken); @@ -337,9 +369,12 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating case PipelineTemplateConstants.Id: id = stepProperty.Value.AssertString($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Id}"); - if (!NameValidation.IsValid(id.Value, true)) + if (!String.IsNullOrEmpty(id.Value)) { - context.Error(id, $"Step id {id.Value} is invalid. Ids must start with a letter or '_' and contain only alphanumeric characters, '-', or '_'"); + if (!nameBuilder.TryAddKnownName(id.Value, out var error)) + { + context.Error(id, error); + } } break; @@ -367,10 +402,6 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating shell = stepProperty.Value.AssertScalar($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Shell}"); break; - case PipelineTemplateConstants.Scope: - scope = stepProperty.Value.AssertString($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Scope}"); - break; - case PipelineTemplateConstants.Submodules: submodules = stepProperty.Value.AssertScalar($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Submodules}"); break; @@ -400,14 +431,12 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating } // Fixup the if-condition - var isDefaultScope = String.IsNullOrEmpty(scope?.Value); - ifCondition = ConvertToIfCondition(context, ifToken, false, isDefaultScope); + ifCondition = ConvertToIfCondition(context, ifToken, false); if (run != null) { var result = new ActionStep { - ScopeName = scope?.Value, ContextName = id?.Value, ContinueOnError = continueOnError, DisplayNameToken = name, @@ -439,7 +468,6 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating uses.AssertString($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Uses}"); var result = new ActionStep { - ScopeName = scope?.Value, ContextName = id?.Value, ContinueOnError = continueOnError, DisplayNameToken = name, @@ -503,8 +531,7 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating private static String ConvertToIfCondition( TemplateContext context, TemplateToken token, - Boolean isJob, - Boolean isDefaultScope) + Boolean isJob) { String condition; if (token is null) @@ -537,7 +564,7 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating } else { - namedValues = isDefaultScope ? s_stepNamedValues : s_stepInTemplateNamedValues; + namedValues = s_stepNamedValues; functions = s_stepConditionFunctions; } @@ -589,18 +616,6 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating new NamedValueInfo(PipelineTemplateConstants.Env), new NamedValueInfo(PipelineTemplateConstants.Needs), }; - private static readonly INamedValueInfo[] s_stepInTemplateNamedValues = new INamedValueInfo[] - { - new NamedValueInfo(PipelineTemplateConstants.Strategy), - new NamedValueInfo(PipelineTemplateConstants.Matrix), - new NamedValueInfo(PipelineTemplateConstants.Steps), - new NamedValueInfo(PipelineTemplateConstants.Inputs), - new NamedValueInfo(PipelineTemplateConstants.GitHub), - new NamedValueInfo(PipelineTemplateConstants.Job), - new NamedValueInfo(PipelineTemplateConstants.Runner), - new NamedValueInfo(PipelineTemplateConstants.Env), - new NamedValueInfo(PipelineTemplateConstants.Needs), - }; private static readonly IFunctionInfo[] s_stepConditionFunctions = new IFunctionInfo[] { new FunctionInfo(PipelineTemplateConstants.Always, 0, 0), diff --git a/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateEvaluator.cs b/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateEvaluator.cs index f09a905bb..a0041fbc5 100644 --- a/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateEvaluator.cs +++ b/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateEvaluator.cs @@ -51,60 +51,6 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating public Int32 MaxResultSize { get; set; } = 10 * 1024 * 1024; // 10 mb - public DictionaryContextData EvaluateStepScopeInputs( - TemplateToken token, - DictionaryContextData contextData, - IList expressionFunctions) - { - var result = default(DictionaryContextData); - - if (token != null && token.Type != TokenType.Null) - { - var context = CreateContext(contextData, expressionFunctions); - try - { - token = TemplateEvaluator.Evaluate(context, PipelineTemplateConstants.StepsScopeInputs, token, 0, null, omitHeader: true); - context.Errors.Check(); - result = token.ToContextData().AssertDictionary("steps scope inputs"); - } - catch (Exception ex) when (!(ex is TemplateValidationException)) - { - context.Errors.Add(ex); - } - - context.Errors.Check(); - } - - return result ?? new DictionaryContextData(); - } - - public DictionaryContextData EvaluateStepScopeOutputs( - TemplateToken token, - DictionaryContextData contextData, - IList expressionFunctions) - { - var result = default(DictionaryContextData); - - if (token != null && token.Type != TokenType.Null) - { - var context = CreateContext(contextData, expressionFunctions); - try - { - token = TemplateEvaluator.Evaluate(context, PipelineTemplateConstants.StepsScopeOutputs, token, 0, null, omitHeader: true); - context.Errors.Check(); - result = token.ToContextData().AssertDictionary("steps scope outputs"); - } - catch (Exception ex) when (!(ex is TemplateValidationException)) - { - context.Errors.Add(ex); - } - - context.Errors.Check(); - } - - return result ?? new DictionaryContextData(); - } - public Boolean EvaluateStepContinueOnError( TemplateToken token, DictionaryContextData contextData, @@ -159,31 +105,6 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating return result; } - public List LoadCompositeSteps( - TemplateToken token) - { - var result = default(List); - if (token != null && token.Type != TokenType.Null) - { - var context = CreateContext(null, null, setMissingContext: false); - // TODO: we might want to to have a bool to prevent it from filling in with missing context w/ dummy variables - try - { - token = TemplateEvaluator.Evaluate(context, PipelineTemplateConstants.StepsInTemplate, token, 0, null, omitHeader: true); - context.Errors.Check(); - result = PipelineTemplateConverter.ConvertToSteps(context, token); - } - catch (Exception ex) when (!(ex is TemplateValidationException)) - { - context.Errors.Add(ex); - } - - context.Errors.Check(); - } - return result; - } - - public Dictionary EvaluateStepEnvironment( TemplateToken token, DictionaryContextData contextData, @@ -425,8 +346,7 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating private TemplateContext CreateContext( DictionaryContextData contextData, IList expressionFunctions, - IEnumerable> expressionState = null, - bool setMissingContext = true) + IEnumerable> expressionState = null) { var result = new TemplateContext { @@ -475,21 +395,18 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating // - Evaluating early when all referenced contexts are available, even though all allowed // contexts may not yet be available. For example, evaluating step display name can often // be performed early. - if (setMissingContext) + foreach (var name in s_expressionValueNames) { - foreach (var name in s_expressionValueNames) + if (!result.ExpressionValues.ContainsKey(name)) { - if (!result.ExpressionValues.ContainsKey(name)) - { - result.ExpressionValues[name] = null; - } + result.ExpressionValues[name] = null; } - foreach (var name in s_expressionFunctionNames) + } + foreach (var name in s_expressionFunctionNames) + { + if (!functionNames.Contains(name)) { - if (!functionNames.Contains(name)) - { - result.ExpressionFunctions.Add(new FunctionInfo(name, 0, Int32.MaxValue)); - } + result.ExpressionFunctions.Add(new FunctionInfo(name, 0, Int32.MaxValue)); } } diff --git a/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/ReferenceNameBuilder.cs b/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/ReferenceNameBuilder.cs new file mode 100644 index 000000000..2b42f2918 --- /dev/null +++ b/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/ReferenceNameBuilder.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; +using GitHub.DistributedTask.Pipelines.Validation; + +namespace GitHub.DistributedTask.Pipelines.ObjectTemplating +{ + internal sealed class ReferenceNameBuilder + { + internal void AppendSegment(String value) + { + if (String.IsNullOrEmpty(value)) + { + return; + } + + if (m_name.Length == 0) + { + var first = value[0]; + if ((first >= 'a' && first <= 'z') || + (first >= 'A' && first <= 'Z') || + first == '_') + { + // Legal first char + } + else if ((first >= '0' && first <= '9') || first == '-') + { + // Illegal first char, but legal char. + // Prepend "_". + m_name.Append("_"); + } + else + { + // Illegal char + } + } + else + { + // Separator + m_name.Append(c_separator); + } + + foreach (var c in value) + { + if ((c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9') || + c == '_' || + c == '-') + { + // Legal + m_name.Append(c); + } + else + { + // Illegal + m_name.Append("_"); + } + } + } + + internal String Build() + { + var original = m_name.Length > 0 ? m_name.ToString() : "job"; + + var attempt = 1; + var suffix = default(String); + while (true) + { + if (attempt == 1) + { + suffix = String.Empty; + } + else if (attempt < 1000) + { + suffix = String.Format(CultureInfo.InvariantCulture, "_{0}", attempt); + } + else + { + throw new InvalidOperationException("Unable to create a unique name"); + } + + var candidate = original.Substring(0, Math.Min(original.Length, PipelineConstants.MaxNodeNameLength - suffix.Length)) + suffix; + + if (m_distinctNames.Add(candidate)) + { + m_name.Clear(); + return candidate; + } + + attempt++; + } + } + + internal Boolean TryAddKnownName( + String value, + out String error) + { + if (!NameValidation.IsValid(value, allowHyphens: true) && value.Length < PipelineConstants.MaxNodeNameLength) + { + error = $"The identifier '{value}' is invalid. IDs may only contain alphanumeric characters, '_', and '-'. IDs must start with a letter or '_' and and must be less than {PipelineConstants.MaxNodeNameLength} characters."; + return false; + } + else if (!m_distinctNames.Add(value)) + { + error = $"The identifier '{value}' may not be used more than once within the same scope."; + return false; + } + else + { + error = null; + return true; + } + } + + private const String c_separator = "_"; + private readonly HashSet m_distinctNames = new HashSet(StringComparer.OrdinalIgnoreCase); + private readonly StringBuilder m_name = new StringBuilder(); + } +} diff --git a/src/Sdk/DTPipelines/workflow-v1.0.json b/src/Sdk/DTPipelines/workflow-v1.0.json index 298470054..1903a90f7 100644 --- a/src/Sdk/DTPipelines/workflow-v1.0.json +++ b/src/Sdk/DTPipelines/workflow-v1.0.json @@ -16,116 +16,6 @@ } }, - "steps-template-root": { - "description": "Steps template file", - "mapping": { - "properties": { - "inputs": "steps-template-inputs", - "outputs": "steps-template-outputs", - "steps": "steps-in-template" - } - } - }, - - "steps-scope-inputs": { - "description": "Used when evaluating steps scope inputs", - "mapping": { - "loose-key-type": "non-empty-string", - "loose-value-type": "steps-scope-input-value" - } - }, - - "steps-scope-input-value": { - "context": [ - "github", - "needs", - "strategy", - "matrix", - "secrets", - "steps", - "inputs", - "job", - "runner", - "env" - ], - "one-of": [ - "string", - "sequence", - "mapping" - ] - }, - - "steps-scope-outputs": { - "description": "Used when evaluating steps scope outputs", - "mapping": { - "loose-key-type": "non-empty-string", - "loose-value-type": "steps-scope-output-value" - } - }, - - "steps-scope-output-value": { - "context": [ - "github", - "needs", - "strategy", - "matrix", - "secrets", - "steps", - "inputs", - "job", - "runner", - "env" - ], - "string": {} - }, - - "steps-template-inputs": { - "description": "Allowed inputs in a steps template", - "mapping": { - "loose-key-type": "non-empty-string", - "loose-value-type": "steps-template-input-value" - } - }, - - "steps-template-input-value": { - "description": "Default input values for a steps template", - "context": [ - "github", - "needs", - "strategy", - "matrix" - ], - "one-of": [ - "string", - "sequence", - "mapping" - ] - }, - - "steps-template-outputs": { - "description": "Output mapping for a steps template", - "mapping": { - "loose-key-type": "non-empty-string", - "loose-value-type": "steps-template-output-value" - } - }, - - "steps-template-output-value": { - "description": "Output values for a steps template", - "context": [ - "github", - "needs", - "strategy", - "matrix", - "secrets", - "steps", - "job", - "runner", - "env" - ], - "string": {} - }, - "workflow-defaults": { "mapping": { "properties": { @@ -240,54 +130,27 @@ "matrix": { "mapping": { "properties": { - "include": "matrix-include", - "exclude": "matrix-exclude" + "include": "matrix-filter", + "exclude": "matrix-filter" }, "loose-key-type": "non-empty-string", "loose-value-type": "sequence" } }, - "matrix-include": { + "matrix-filter": { "sequence": { - "item-type": "matrix-include-item" + "item-type": "matrix-filter-item" } }, - "matrix-include-item": { + "matrix-filter-item": { "mapping": { "loose-key-type": "non-empty-string", "loose-value-type": "any" } }, - "matrix-exclude": { - "sequence": { - "item-type": "matrix-exclude-item" - } - }, - - "matrix-exclude-item": { - "mapping": { - "loose-key-type": "non-empty-string", - "loose-value-type": "matrix-exclude-filter-item" - } - }, - - "matrix-exclude-filter-item": { - "one-of": [ - "string", - "matrix-exclude-mapping-filter" - ] - }, - - "matrix-exclude-mapping-filter": { - "mapping": { - "loose-key-type": "non-empty-string", - "loose-value-type": "matrix-exclude-filter-item" - } - }, - "runs-on": { "context": [ "github", @@ -364,25 +227,10 @@ } }, - "steps-in-template": { - "sequence": { - "item-type": "steps-item-in-template" - } - }, - "steps-item": { "one-of": [ "run-step", - "regular-step", - "steps-template-reference" - ] - }, - - "steps-item-in-template": { - "one-of": [ - "run-step-in-template", - "regular-step-in-template", - "steps-template-reference-in-template" + "regular-step" ] }, @@ -405,25 +253,6 @@ } }, - "run-step-in-template": { - "mapping": { - "properties": { - "name": "string-steps-context-in-template", - "id": "non-empty-string", - "if": "step-if-in-template", - "timeout-minutes": "number-steps-context-in-template", - "run": { - "type": "string-steps-context-in-template", - "required": true - }, - "continue-on-error": "boolean-steps-context-in-template", - "env": "step-env-in-template", - "working-directory": "string-steps-context-in-template", - "shell": "non-empty-string" - } - } - }, - "regular-step": { "mapping": { "properties": { @@ -442,24 +271,6 @@ } }, - "regular-step-in-template": { - "mapping": { - "properties": { - "name": "string-steps-context-in-template", - "id": "non-empty-string", - "if": "step-if-in-template", - "continue-on-error": "boolean-steps-context-in-template", - "timeout-minutes": "number-steps-context-in-template", - "uses": { - "type": "non-empty-string", - "required": true - }, - "with": "step-with-in-template", - "env": "step-env-in-template" - } - } - }, - "step-if": { "context": [ "github", @@ -479,26 +290,6 @@ "string": {} }, - "step-if-in-template": { - "context": [ - "github", - "needs", - "strategy", - "matrix", - "steps", - "inputs", - "job", - "runner", - "env", - "always(0,0)", - "failure(0,0)", - "cancelled(0,0)", - "success(0,0)", - "hashFiles(1,255)" - ], - "string": {} - }, - "step-if-result": { "context": [ "github", @@ -524,89 +315,6 @@ ] }, - "step-if-result-in-template": { - "context": [ - "github", - "strategy", - "matrix", - "steps", - "inputs", - "job", - "runner", - "env", - "always(0,0)", - "failure(0,0)", - "cancelled(0,0)", - "success(0,0)", - "hashFiles(1,255)" - ], - "one-of": [ - "null", - "boolean", - "number", - "string", - "sequence", - "mapping" - ] - }, - - "steps-template-reference": { - "mapping": { - "properties": { - "template": "non-empty-string", - "id": "non-empty-string", - "inputs": "steps-template-reference-inputs" - } - } - }, - - "steps-template-reference-in-template": { - "mapping": { - "properties": { - "template": "non-empty-string", - "id": "non-empty-string", - "inputs": "steps-template-reference-inputs-in-template" - } - } - }, - - "steps-template-reference-inputs": { - "context": [ - "github", - "needs", - "strategy", - "matrix", - "secrets", - "steps", - "job", - "runner", - "env" - ], - "mapping": { - "loose-key-type": "non-empty-string", - "loose-value-type": "string" - } - }, - - "steps-template-reference-inputs-in-template": { - "context": [ - "github", - "needs", - "strategy", - "matrix", - "secrets", - "steps", - "inputs", - "job", - "runner", - "env" - ], - "mapping": { - "loose-key-type": "non-empty-string", - "loose-value-type": "string" - } - }, - "step-env": { "context": [ "github", @@ -626,26 +334,6 @@ } }, - "step-env-in-template": { - "context": [ - "github", - "needs", - "strategy", - "matrix", - "secrets", - "steps", - "inputs", - "job", - "runner", - "env", - "hashFiles(1,255)" - ], - "mapping": { - "loose-key-type": "non-empty-string", - "loose-value-type": "string" - } - }, - "step-with": { "context": [ "github", @@ -665,26 +353,6 @@ } }, - "step-with-in-template": { - "context": [ - "github", - "needs", - "strategy", - "matrix", - "secrets", - "steps", - "inputs", - "job", - "runner", - "env", - "hashFiles(1,255)" - ], - "mapping": { - "loose-key-type": "non-empty-string", - "loose-value-type": "string" - } - }, - "container": { "context": [ "github", @@ -801,23 +469,6 @@ "boolean": {} }, - "boolean-steps-context-in-template": { - "context": [ - "github", - "needs", - "strategy", - "matrix", - "secrets", - "steps", - "inputs", - "job", - "runner", - "env", - "hashFiles(1,255)" - ], - "boolean": {} - }, - "number-steps-context": { "context": [ "github", @@ -834,23 +485,6 @@ "number": {} }, - "number-steps-context-in-template": { - "context": [ - "github", - "needs", - "strategy", - "matrix", - "secrets", - "steps", - "inputs", - "job", - "runner", - "env", - "hashFiles(1,255)" - ], - "number": {} - }, - "string-runner-context": { "context": [ "github", @@ -880,23 +514,6 @@ "hashFiles(1,255)" ], "string": {} - }, - - "string-steps-context-in-template": { - "context": [ - "github", - "needs", - "strategy", - "matrix", - "secrets", - "steps", - "inputs", - "job", - "runner", - "env", - "hashFiles(1,255)" - ], - "string": {} } } } \ No newline at end of file diff --git a/src/Test/L0/Listener/JobDispatcherL0.cs b/src/Test/L0/Listener/JobDispatcherL0.cs index a8062b206..9408da922 100644 --- a/src/Test/L0/Listener/JobDispatcherL0.cs +++ b/src/Test/L0/Listener/JobDispatcherL0.cs @@ -33,7 +33,7 @@ namespace GitHub.Runner.Common.Tests.Listener TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference(); TimelineReference timeline = null; Guid jobId = Guid.NewGuid(); - var result = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "someJob", "someJob", null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null, null); + var result = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "someJob", "someJob", null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null); result.ContextData["github"] = new Pipelines.ContextData.DictionaryContextData(); return result; } diff --git a/src/Test/L0/Listener/RunnerL0.cs b/src/Test/L0/Listener/RunnerL0.cs index 32a21521b..5d8bc3e0f 100644 --- a/src/Test/L0/Listener/RunnerL0.cs +++ b/src/Test/L0/Listener/RunnerL0.cs @@ -43,7 +43,7 @@ namespace GitHub.Runner.Common.Tests.Listener TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference(); TimelineReference timeline = null; Guid jobId = Guid.NewGuid(); - return new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "test", "test", null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null, null); + return new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "test", "test", null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null); } private JobCancelMessage CreateJobCancelMessage() diff --git a/src/Test/L0/Worker/ActionCommandManagerL0.cs b/src/Test/L0/Worker/ActionCommandManagerL0.cs index 568c1a86a..2ef9f5c5c 100644 --- a/src/Test/L0/Worker/ActionCommandManagerL0.cs +++ b/src/Test/L0/Worker/ActionCommandManagerL0.cs @@ -150,7 +150,7 @@ namespace GitHub.Runner.Common.Tests.Worker TimelineReference timeline = new TimelineReference(); Guid jobId = Guid.NewGuid(); string jobName = "some job name"; - var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null, null); + var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null); jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource() { Alias = Pipelines.PipelineConstants.SelfAlias, diff --git a/src/Test/L0/Worker/ExecutionContextL0.cs b/src/Test/L0/Worker/ExecutionContextL0.cs index 7dbbf099f..356b7f4e5 100644 --- a/src/Test/L0/Worker/ExecutionContextL0.cs +++ b/src/Test/L0/Worker/ExecutionContextL0.cs @@ -26,7 +26,7 @@ namespace GitHub.Runner.Common.Tests.Worker TimelineReference timeline = new TimelineReference(); Guid jobId = Guid.NewGuid(); string jobName = "some job name"; - var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null, null); + var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null); jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource() { Alias = Pipelines.PipelineConstants.SelfAlias, @@ -102,7 +102,7 @@ namespace GitHub.Runner.Common.Tests.Worker TimelineReference timeline = new TimelineReference(); Guid jobId = Guid.NewGuid(); string jobName = "some job name"; - var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null, null); + var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null); jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource() { Alias = Pipelines.PipelineConstants.SelfAlias, @@ -153,7 +153,7 @@ namespace GitHub.Runner.Common.Tests.Worker TimelineReference timeline = new TimelineReference(); Guid jobId = Guid.NewGuid(); string jobName = "some job name"; - var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null, null); + var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null); jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource() { Alias = Pipelines.PipelineConstants.SelfAlias, @@ -251,7 +251,7 @@ namespace GitHub.Runner.Common.Tests.Worker TimelineReference timeline = new TimelineReference(); Guid jobId = Guid.NewGuid(); string jobName = "some job name"; - var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null, null); + var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null); jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource() { Alias = Pipelines.PipelineConstants.SelfAlias, @@ -335,7 +335,7 @@ namespace GitHub.Runner.Common.Tests.Worker TimelineReference timeline = new TimelineReference(); Guid jobId = Guid.NewGuid(); string jobName = "some job name"; - var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null, null); + var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null); jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource() { Alias = Pipelines.PipelineConstants.SelfAlias, diff --git a/src/Test/L0/Worker/JobExtensionL0.cs b/src/Test/L0/Worker/JobExtensionL0.cs index 0101db135..4ce643d4e 100644 --- a/src/Test/L0/Worker/JobExtensionL0.cs +++ b/src/Test/L0/Worker/JobExtensionL0.cs @@ -98,7 +98,7 @@ namespace GitHub.Runner.Common.Tests.Worker }; Guid jobId = Guid.NewGuid(); - _message = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "test", "test", null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), steps, null, null, null, null); + _message = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "test", "test", null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), steps, null, null, null); GitHubContext github = new GitHubContext(); github["repository"] = new Pipelines.ContextData.StringContextData("actions/runner"); _message.ContextData.Add("github", github); diff --git a/src/Test/L0/Worker/JobRunnerL0.cs b/src/Test/L0/Worker/JobRunnerL0.cs index 198d378b9..61f418b12 100644 --- a/src/Test/L0/Worker/JobRunnerL0.cs +++ b/src/Test/L0/Worker/JobRunnerL0.cs @@ -60,7 +60,7 @@ namespace GitHub.Runner.Common.Tests.Worker TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference(); TimelineReference timeline = new Timeline(Guid.NewGuid()); Guid jobId = Guid.NewGuid(); - _message = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, testName, testName, null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null, null); + _message = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, testName, testName, null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null); _message.Variables[Constants.Variables.System.Culture] = "en-US"; _message.Resources.Endpoints.Add(new ServiceEndpoint() { diff --git a/src/Test/L0/Worker/WorkerL0.cs b/src/Test/L0/Worker/WorkerL0.cs index 80e5eaa0a..ed930f184 100644 --- a/src/Test/L0/Worker/WorkerL0.cs +++ b/src/Test/L0/Worker/WorkerL0.cs @@ -67,7 +67,7 @@ namespace GitHub.Runner.Common.Tests.Worker new Pipelines.ContextData.DictionaryContextData() }, }; - var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, JobId, jobName, jobName, new StringToken(null, null, null, "ubuntu"), sidecarContainers, null, variables, new List(), resources, context, null, actions, null, null, null, null); + var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, JobId, jobName, jobName, new StringToken(null, null, null, "ubuntu"), sidecarContainers, null, variables, new List(), resources, context, null, actions, null, null, null); return jobRequest; }