From 2d6042421f9f07e72a9113c0d7261b85f75b9f5c Mon Sep 17 00:00:00 2001 From: Tingluo Huang Date: Sat, 14 Mar 2020 17:54:58 -0400 Subject: [PATCH] add support for job outputs. (#365) * add support for job outputs. --- src/Runner.Worker/ExecutionContext.cs | 8 +- src/Runner.Worker/JobExtension.cs | 54 +++++ src/Runner.Worker/JobRunner.cs | 2 +- src/Runner.Worker/action_yaml.json | 4 +- .../Expressions2/ExpressionConstants.cs | 1 + .../Expressions2/Sdk/Functions/FromJson.cs | 24 ++ .../Schema/MappingDefinition.cs | 14 +- .../ObjectTemplating/Schema/PropertyValue.cs | 34 ++- .../ObjectTemplating/Schema/TemplateSchema.cs | 77 ++++--- .../ObjectTemplating/TemplateConstants.cs | 5 + .../ObjectTemplating/TemplateEvaluator.cs | 17 +- .../ObjectTemplating/TemplateReader.cs | 17 +- .../Pipelines/AgentJobRequestMessage.cs | 11 +- .../PipelineTemplateConstants.cs | 2 + .../PipelineTemplateEvaluator.cs | 37 ++++ src/Sdk/DTPipelines/workflow-v1.0.json | 209 ++++++++++++++---- src/Sdk/DTWebApi/WebApi/JobEvent.cs | 24 +- 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 | 6 +- src/Test/L0/Worker/JobExtensionL0.cs | 2 +- src/Test/L0/Worker/JobRunnerL0.cs | 2 +- src/Test/L0/Worker/StepsRunnerL0.cs | 3 + src/Test/L0/Worker/WorkerL0.cs | 2 +- 25 files changed, 445 insertions(+), 116 deletions(-) create mode 100644 src/Sdk/DTExpressions2/Expressions2/Sdk/Functions/FromJson.cs diff --git a/src/Runner.Worker/ExecutionContext.cs b/src/Runner.Worker/ExecutionContext.cs index d390a9e86..b48936b08 100644 --- a/src/Runner.Worker/ExecutionContext.cs +++ b/src/Runner.Worker/ExecutionContext.cs @@ -47,7 +47,7 @@ namespace GitHub.Runner.Worker PlanFeatures Features { get; } Variables Variables { get; } Dictionary IntraActionState { get; } - HashSet OutputVariables { get; } + Dictionary JobOutputs { get; } IDictionary EnvironmentVariables { get; } IDictionary Scopes { get; } IList FileTable { get; } @@ -110,7 +110,6 @@ namespace GitHub.Runner.Worker private readonly TimelineRecord _record = new TimelineRecord(); private readonly Dictionary _detailRecords = new Dictionary(); private readonly object _loggerLock = new object(); - private readonly HashSet _outputvariables = new HashSet(StringComparer.OrdinalIgnoreCase); private readonly object _matchersLock = new object(); private event OnMatcherChanged _onMatcherChanged; @@ -140,7 +139,7 @@ namespace GitHub.Runner.Worker public List Endpoints { get; private set; } public Variables Variables { get; private set; } public Dictionary IntraActionState { get; private set; } - public HashSet OutputVariables => _outputvariables; + public Dictionary JobOutputs { get; private set; } public IDictionary EnvironmentVariables { get; private set; } public IDictionary Scopes { get; private set; } public IList FileTable { get; private set; } @@ -557,6 +556,9 @@ namespace GitHub.Runner.Worker // Environment variables shared across all actions EnvironmentVariables = new Dictionary(VarUtil.EnvironmentVariableKeyComparer); + // Job Outputs + JobOutputs = new Dictionary(StringComparer.OrdinalIgnoreCase); + // Service container info ServiceContainers = new List(); diff --git a/src/Runner.Worker/JobExtension.cs b/src/Runner.Worker/JobExtension.cs index 3db3e61d0..c0de945a0 100644 --- a/src/Runner.Worker/JobExtension.cs +++ b/src/Runner.Worker/JobExtension.cs @@ -6,6 +6,8 @@ using System.Linq; using System.Runtime.Serialization; using System.Threading.Tasks; using GitHub.DistributedTask.Expressions2; +using GitHub.DistributedTask.ObjectTemplating.Tokens; +using GitHub.DistributedTask.Pipelines.ContextData; using GitHub.DistributedTask.Pipelines.ObjectTemplating; using GitHub.DistributedTask.WebApi; using GitHub.Runner.Common; @@ -291,6 +293,58 @@ namespace GitHub.Runner.Worker context.Start(); context.Debug("Starting: Complete job"); + // Evaluate job outputs + if (message.JobOutputs != null && message.JobOutputs.Type != TokenType.Null) + { + try + { + context.Output($"Evaluate and set job outputs"); + + // Populate env context for each step + Trace.Info("Initialize Env context for evaluating job outputs"); +#if OS_WINDOWS + var envContext = new DictionaryContextData(); +#else + var envContext = new CaseSensitiveDictionaryContextData(); +#endif + context.ExpressionValues["env"] = envContext; + foreach (var pair in context.EnvironmentVariables) + { + envContext[pair.Key] = new StringContextData(pair.Value ?? string.Empty); + } + + Trace.Info("Initialize steps context for evaluating job outputs"); + context.ExpressionValues["steps"] = context.StepsContext.GetScope(context.ScopeName); + + var templateEvaluator = context.ToPipelineTemplateEvaluator(); + var outputs = templateEvaluator.EvaluateJobOutput(message.JobOutputs, context.ExpressionValues); + foreach (var output in outputs) + { + if (string.IsNullOrEmpty(output.Value)) + { + context.Debug($"Skip output '{output.Key}' since it's empty"); + continue; + } + + if (!string.Equals(output.Value, HostContext.SecretMasker.MaskSecrets(output.Value))) + { + context.Warning($"Skip output '{output.Key}' since it may contain secret."); + continue; + } + + context.Output($"Set output '{output.Key}'"); + jobContext.JobOutputs[output.Key] = output.Value; + } + } + catch (Exception ex) + { + context.Result = TaskResult.Failed; + context.Error($"Fail to evaluate job outputs"); + context.Error(ex); + jobContext.Result = TaskResultUtil.MergeTaskResults(jobContext.Result, TaskResult.Failed); + } + } + if (context.Variables.GetBoolean(Constants.Variables.Actions.RunnerDebug) ?? false) { Trace.Info("Support log upload starting."); diff --git a/src/Runner.Worker/JobRunner.cs b/src/Runner.Worker/JobRunner.cs index 585885ffe..a94d7dd3d 100644 --- a/src/Runner.Worker/JobRunner.cs +++ b/src/Runner.Worker/JobRunner.cs @@ -231,7 +231,7 @@ namespace GitHub.Runner.Worker } Trace.Info("Raising job completed event."); - var jobCompletedEvent = new JobCompletedEvent(message.RequestId, message.JobId, result); + var jobCompletedEvent = new JobCompletedEvent(message.RequestId, message.JobId, result, jobContext.JobOutputs); var completeJobRetryLimit = 5; var exceptions = new List(); diff --git a/src/Runner.Worker/action_yaml.json b/src/Runner.Worker/action_yaml.json index a30de1606..c9eb2d38d 100644 --- a/src/Runner.Worker/action_yaml.json +++ b/src/Runner.Worker/action_yaml.json @@ -90,10 +90,8 @@ "github", "strategy", "matrix", - "steps", "job", - "runner", - "env" + "runner" ], "string": {} }, diff --git a/src/Sdk/DTExpressions2/Expressions2/ExpressionConstants.cs b/src/Sdk/DTExpressions2/Expressions2/ExpressionConstants.cs index a0291cee0..7974c85bc 100644 --- a/src/Sdk/DTExpressions2/Expressions2/ExpressionConstants.cs +++ b/src/Sdk/DTExpressions2/Expressions2/ExpressionConstants.cs @@ -15,6 +15,7 @@ namespace GitHub.DistributedTask.Expressions2 AddFunction("join", 1, 2); AddFunction("startsWith", 2, 2); AddFunction("toJson", 1, 1); + AddFunction("fromJson", 1, 1); AddFunction("hashFiles", 1, 1); } diff --git a/src/Sdk/DTExpressions2/Expressions2/Sdk/Functions/FromJson.cs b/src/Sdk/DTExpressions2/Expressions2/Sdk/Functions/FromJson.cs new file mode 100644 index 000000000..347c70467 --- /dev/null +++ b/src/Sdk/DTExpressions2/Expressions2/Sdk/Functions/FromJson.cs @@ -0,0 +1,24 @@ +using System; +using System.IO; +using GitHub.DistributedTask.Pipelines.ContextData; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace GitHub.DistributedTask.Expressions2.Sdk.Functions +{ + internal sealed class FromJson : Function + { + protected sealed override Object EvaluateCore( + EvaluationContext context, + out ResultMemory resultMemory) + { + resultMemory = null; + var json = Parameters[0].Evaluate(context).ConvertToString(); + using (var stringReader = new StringReader(json)) + using (var jsonReader = new JsonTextReader(stringReader) { DateParseHandling = DateParseHandling.None, FloatParseHandling = FloatParseHandling.Double }) + { + var token = JToken.ReadFrom(jsonReader); + return token.ToPipelineContextData(); + } + } + }} diff --git a/src/Sdk/DTObjectTemplating/ObjectTemplating/Schema/MappingDefinition.cs b/src/Sdk/DTObjectTemplating/ObjectTemplating/Schema/MappingDefinition.cs index 8e43e53ed..3da980185 100644 --- a/src/Sdk/DTObjectTemplating/ObjectTemplating/Schema/MappingDefinition.cs +++ b/src/Sdk/DTObjectTemplating/ObjectTemplating/Schema/MappingDefinition.cs @@ -30,8 +30,7 @@ namespace GitHub.DistributedTask.ObjectTemplating.Schema foreach (var propertiesPair in properties) { var propertyName = propertiesPair.Key.AssertString($"{TemplateConstants.Definition} {TemplateConstants.Mapping} {TemplateConstants.Properties} key"); - var propertyValue = propertiesPair.Value.AssertString($"{TemplateConstants.Definition} {TemplateConstants.Mapping} {TemplateConstants.Properties} value"); - Properties.Add(propertyName.Value, new PropertyValue(propertyValue.Value)); + Properties.Add(propertyName.Value, new PropertyValue(propertiesPair.Value)); } break; @@ -85,7 +84,7 @@ namespace GitHub.DistributedTask.ObjectTemplating.Schema } else { - throw new ArgumentException($"Property '{TemplateConstants.LooseKeyType}' is defined but '{TemplateConstants.LooseValueType}' is not defined"); + throw new ArgumentException($"Property '{TemplateConstants.LooseKeyType}' is defined but '{TemplateConstants.LooseValueType}' is not defined on '{name}'"); } } // Otherwise validate loose value type not be defined @@ -95,9 +94,14 @@ namespace GitHub.DistributedTask.ObjectTemplating.Schema } // Lookup each property - foreach (var property in Properties.Values) + foreach (var property in Properties) { - schema.GetDefinition(property.Type); + if (String.IsNullOrEmpty(property.Value.Type)) + { + throw new ArgumentException($"Type not specified for the '{property.Key}' property on the '{name}' type"); + } + + schema.GetDefinition(property.Value.Type); } if (!String.IsNullOrEmpty(Inherits)) diff --git a/src/Sdk/DTObjectTemplating/ObjectTemplating/Schema/PropertyValue.cs b/src/Sdk/DTObjectTemplating/ObjectTemplating/Schema/PropertyValue.cs index 5a95b0171..4064159aa 100644 --- a/src/Sdk/DTObjectTemplating/ObjectTemplating/Schema/PropertyValue.cs +++ b/src/Sdk/DTObjectTemplating/ObjectTemplating/Schema/PropertyValue.cs @@ -1,18 +1,40 @@ using System; +using GitHub.DistributedTask.ObjectTemplating.Tokens; namespace GitHub.DistributedTask.ObjectTemplating.Schema { internal sealed class PropertyValue { - internal PropertyValue() + internal PropertyValue(TemplateToken token) { - } - - internal PropertyValue(String type) - { - Type = type; + if (token is StringToken stringToken) + { + Type = stringToken.Value; + } + else + { + var mapping = token.AssertMapping($"{TemplateConstants.MappingPropertyValue}"); + foreach (var mappingPair in mapping) + { + var mappingKey = mappingPair.Key.AssertString($"{TemplateConstants.MappingPropertyValue} key"); + switch (mappingKey.Value) + { + case TemplateConstants.Type: + Type = mappingPair.Value.AssertString($"{TemplateConstants.MappingPropertyValue} {TemplateConstants.Type}").Value; + break; + case TemplateConstants.Required: + Required = mappingPair.Value.AssertBoolean($"{TemplateConstants.MappingPropertyValue} {TemplateConstants.Required}").Value; + break; + default: + mappingKey.AssertUnexpectedValue($"{TemplateConstants.MappingPropertyValue} key"); + break; + } + } + } } internal String Type { get; set; } + + internal Boolean Required { get; set; } } } diff --git a/src/Sdk/DTObjectTemplating/ObjectTemplating/Schema/TemplateSchema.cs b/src/Sdk/DTObjectTemplating/ObjectTemplating/Schema/TemplateSchema.cs index 9ac6b2453..699af9ba9 100644 --- a/src/Sdk/DTObjectTemplating/ObjectTemplating/Schema/TemplateSchema.cs +++ b/src/Sdk/DTObjectTemplating/ObjectTemplating/Schema/TemplateSchema.cs @@ -312,8 +312,8 @@ namespace GitHub.DistributedTask.ObjectTemplating.Schema // template-schema mappingDefinition = new MappingDefinition(); - mappingDefinition.Properties.Add(TemplateConstants.Version, new PropertyValue(TemplateConstants.NonEmptyString)); - mappingDefinition.Properties.Add(TemplateConstants.Definitions, new PropertyValue(TemplateConstants.Definitions)); + mappingDefinition.Properties.Add(TemplateConstants.Version, new PropertyValue(new StringToken(null, null, null, TemplateConstants.NonEmptyString))); + mappingDefinition.Properties.Add(TemplateConstants.Definitions, new PropertyValue(new StringToken(null, null, null, TemplateConstants.Definitions))); schema.Definitions.Add(TemplateConstants.TemplateSchema, mappingDefinition); // definitions @@ -335,9 +335,9 @@ namespace GitHub.DistributedTask.ObjectTemplating.Schema // null-definition mappingDefinition = new MappingDefinition(); - mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(TemplateConstants.String)); - mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(TemplateConstants.SequenceOfNonEmptyString)); - mappingDefinition.Properties.Add(TemplateConstants.Null, new PropertyValue(TemplateConstants.NullDefinitionProperties)); + mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(new StringToken(null, null, null, TemplateConstants.String))); + mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(new StringToken(null, null, null, TemplateConstants.SequenceOfNonEmptyString))); + mappingDefinition.Properties.Add(TemplateConstants.Null, new PropertyValue(new StringToken(null, null, null, TemplateConstants.NullDefinitionProperties))); schema.Definitions.Add(TemplateConstants.NullDefinition, mappingDefinition); // null-definition-properties @@ -346,9 +346,9 @@ namespace GitHub.DistributedTask.ObjectTemplating.Schema // boolean-definition mappingDefinition = new MappingDefinition(); - mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(TemplateConstants.String)); - mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(TemplateConstants.SequenceOfNonEmptyString)); - mappingDefinition.Properties.Add(TemplateConstants.Boolean, new PropertyValue(TemplateConstants.BooleanDefinitionProperties)); + mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(new StringToken(null, null, null, TemplateConstants.String))); + mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(new StringToken(null, null, null, TemplateConstants.SequenceOfNonEmptyString))); + mappingDefinition.Properties.Add(TemplateConstants.Boolean, new PropertyValue(new StringToken(null, null, null, TemplateConstants.BooleanDefinitionProperties))); schema.Definitions.Add(TemplateConstants.BooleanDefinition, mappingDefinition); // boolean-definition-properties @@ -357,9 +357,9 @@ namespace GitHub.DistributedTask.ObjectTemplating.Schema // number-definition mappingDefinition = new MappingDefinition(); - mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(TemplateConstants.String)); - mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(TemplateConstants.SequenceOfNonEmptyString)); - mappingDefinition.Properties.Add(TemplateConstants.Number, new PropertyValue(TemplateConstants.NumberDefinitionProperties)); + mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(new StringToken(null, null, null, TemplateConstants.String))); + mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(new StringToken(null, null, null, TemplateConstants.SequenceOfNonEmptyString))); + mappingDefinition.Properties.Add(TemplateConstants.Number, new PropertyValue(new StringToken(null, null, null, TemplateConstants.NumberDefinitionProperties))); schema.Definitions.Add(TemplateConstants.NumberDefinition, mappingDefinition); // number-definition-properties @@ -368,55 +368,68 @@ namespace GitHub.DistributedTask.ObjectTemplating.Schema // string-definition mappingDefinition = new MappingDefinition(); - mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(TemplateConstants.String)); - mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(TemplateConstants.SequenceOfNonEmptyString)); - mappingDefinition.Properties.Add(TemplateConstants.String, new PropertyValue(TemplateConstants.StringDefinitionProperties)); + mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(new StringToken(null, null, null, TemplateConstants.String))); + mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(new StringToken(null, null, null, TemplateConstants.SequenceOfNonEmptyString))); + mappingDefinition.Properties.Add(TemplateConstants.String, new PropertyValue(new StringToken(null, null, null, TemplateConstants.StringDefinitionProperties))); schema.Definitions.Add(TemplateConstants.StringDefinition, mappingDefinition); // string-definition-properties mappingDefinition = new MappingDefinition(); - mappingDefinition.Properties.Add(TemplateConstants.Constant, new PropertyValue(TemplateConstants.NonEmptyString)); - mappingDefinition.Properties.Add(TemplateConstants.IgnoreCase, new PropertyValue(TemplateConstants.Boolean)); - mappingDefinition.Properties.Add(TemplateConstants.RequireNonEmpty, new PropertyValue(TemplateConstants.Boolean)); + mappingDefinition.Properties.Add(TemplateConstants.Constant, new PropertyValue(new StringToken(null, null, null, TemplateConstants.NonEmptyString))); + mappingDefinition.Properties.Add(TemplateConstants.IgnoreCase, new PropertyValue(new StringToken(null, null, null,TemplateConstants.Boolean))); + mappingDefinition.Properties.Add(TemplateConstants.RequireNonEmpty, new PropertyValue(new StringToken(null, null, null, TemplateConstants.Boolean))); schema.Definitions.Add(TemplateConstants.StringDefinitionProperties, mappingDefinition); // sequence-definition mappingDefinition = new MappingDefinition(); - mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(TemplateConstants.String)); - mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(TemplateConstants.SequenceOfNonEmptyString)); - mappingDefinition.Properties.Add(TemplateConstants.Sequence, new PropertyValue(TemplateConstants.SequenceDefinitionProperties)); + mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(new StringToken(null, null, null, TemplateConstants.String))); + mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(new StringToken(null, null, null, TemplateConstants.SequenceOfNonEmptyString))); + mappingDefinition.Properties.Add(TemplateConstants.Sequence, new PropertyValue(new StringToken(null, null, null, TemplateConstants.SequenceDefinitionProperties))); schema.Definitions.Add(TemplateConstants.SequenceDefinition, mappingDefinition); // sequence-definition-properties mappingDefinition = new MappingDefinition(); - mappingDefinition.Properties.Add(TemplateConstants.ItemType, new PropertyValue(TemplateConstants.NonEmptyString)); + mappingDefinition.Properties.Add(TemplateConstants.ItemType, new PropertyValue(new StringToken(null, null, null, TemplateConstants.NonEmptyString))); schema.Definitions.Add(TemplateConstants.SequenceDefinitionProperties, mappingDefinition); // mapping-definition mappingDefinition = new MappingDefinition(); - mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(TemplateConstants.String)); - mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(TemplateConstants.SequenceOfNonEmptyString)); - mappingDefinition.Properties.Add(TemplateConstants.Mapping, new PropertyValue(TemplateConstants.MappingDefinitionProperties)); + mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(new StringToken(null, null, null, TemplateConstants.String))); + mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(new StringToken(null, null, null, TemplateConstants.SequenceOfNonEmptyString))); + mappingDefinition.Properties.Add(TemplateConstants.Mapping, new PropertyValue(new StringToken(null, null, null, TemplateConstants.MappingDefinitionProperties))); schema.Definitions.Add(TemplateConstants.MappingDefinition, mappingDefinition); // mapping-definition-properties mappingDefinition = new MappingDefinition(); - mappingDefinition.Properties.Add(TemplateConstants.Properties, new PropertyValue(TemplateConstants.Properties)); - mappingDefinition.Properties.Add(TemplateConstants.LooseKeyType, new PropertyValue(TemplateConstants.NonEmptyString)); - mappingDefinition.Properties.Add(TemplateConstants.LooseValueType, new PropertyValue(TemplateConstants.NonEmptyString)); + mappingDefinition.Properties.Add(TemplateConstants.Properties, new PropertyValue(new StringToken(null, null, null, TemplateConstants.Properties))); + mappingDefinition.Properties.Add(TemplateConstants.LooseKeyType, new PropertyValue(new StringToken(null, null, null, TemplateConstants.NonEmptyString))); + mappingDefinition.Properties.Add(TemplateConstants.LooseValueType, new PropertyValue(new StringToken(null, null, null, TemplateConstants.NonEmptyString))); schema.Definitions.Add(TemplateConstants.MappingDefinitionProperties, mappingDefinition); // properties mappingDefinition = new MappingDefinition(); mappingDefinition.LooseKeyType = TemplateConstants.NonEmptyString; - mappingDefinition.LooseValueType = TemplateConstants.NonEmptyString; + mappingDefinition.LooseValueType = TemplateConstants.PropertyValue; schema.Definitions.Add(TemplateConstants.Properties, mappingDefinition); + // property-value + oneOfDefinition = new OneOfDefinition(); + oneOfDefinition.OneOf.Add(TemplateConstants.NonEmptyString); + oneOfDefinition.OneOf.Add(TemplateConstants.MappingPropertyValue); + schema.Definitions.Add(TemplateConstants.PropertyValue, oneOfDefinition); + + // mapping-property-value + mappingDefinition = new MappingDefinition(); + mappingDefinition.Properties.Add(TemplateConstants.Type, new PropertyValue(new StringToken(null, null, null, TemplateConstants.NonEmptyString))); + mappingDefinition.Properties.Add(TemplateConstants.Required, new PropertyValue(new StringToken(null, null, null, TemplateConstants.Boolean))); + schema.Definitions.Add(TemplateConstants.MappingPropertyValue, mappingDefinition); + + // one-of-definition mappingDefinition = new MappingDefinition(); - mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(TemplateConstants.String)); - mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(TemplateConstants.SequenceOfNonEmptyString)); - mappingDefinition.Properties.Add(TemplateConstants.OneOf, new PropertyValue(TemplateConstants.SequenceOfNonEmptyString)); + mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(new StringToken(null, null, null, TemplateConstants.String))); + mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(new StringToken(null, null, null, TemplateConstants.SequenceOfNonEmptyString))); + mappingDefinition.Properties.Add(TemplateConstants.OneOf, new PropertyValue(new StringToken(null, null, null, TemplateConstants.SequenceOfNonEmptyString))); schema.Definitions.Add(TemplateConstants.OneOfDefinition, mappingDefinition); // non-empty-string @@ -477,4 +490,4 @@ namespace GitHub.DistributedTask.ObjectTemplating.Schema private static readonly Regex s_definitionNameRegex = new Regex("^[a-zA-Z_][a-zA-Z0-9_-]*$", RegexOptions.Compiled); private static TemplateSchema s_schema; } -} +} \ No newline at end of file diff --git a/src/Sdk/DTObjectTemplating/ObjectTemplating/TemplateConstants.cs b/src/Sdk/DTObjectTemplating/ObjectTemplating/TemplateConstants.cs index 72ebae5ab..21e70e4b9 100644 --- a/src/Sdk/DTObjectTemplating/ObjectTemplating/TemplateConstants.cs +++ b/src/Sdk/DTObjectTemplating/ObjectTemplating/TemplateConstants.cs @@ -22,9 +22,11 @@ namespace GitHub.DistributedTask.ObjectTemplating internal const String ItemType = "item-type"; internal const String LooseKeyType = "loose-key-type"; internal const String LooseValueType = "loose-value-type"; + internal const String MaxConstant = "MAX"; internal const String Mapping = "mapping"; internal const String MappingDefinition = "mapping-definition"; internal const String MappingDefinitionProperties = "mapping-definition-properties"; + internal const String MappingPropertyValue = "mapping-property-value"; internal const String NonEmptyString = "non-empty-string"; internal const String Null = "null"; internal const String NullDefinition = "null-definition"; @@ -35,7 +37,9 @@ namespace GitHub.DistributedTask.ObjectTemplating internal const String OneOf = "one-of"; internal const String OneOfDefinition = "one-of-definition"; internal const String OpenExpression = "${{"; + internal const String PropertyValue = "property-value"; internal const String Properties = "properties"; + internal const String Required = "required"; internal const String RequireNonEmpty = "require-non-empty"; internal const String Scalar = "scalar"; internal const String ScalarDefinition = "scalar-definition"; @@ -43,6 +47,7 @@ namespace GitHub.DistributedTask.ObjectTemplating internal const String Sequence = "sequence"; internal const String SequenceDefinition = "sequence-definition"; internal const String SequenceDefinitionProperties = "sequence-definition-properties"; + internal const String Type = "type"; internal const String SequenceOfNonEmptyString = "sequence-of-non-empty-string"; internal const String String = "string"; internal const String StringDefinition = "string-definition"; diff --git a/src/Sdk/DTObjectTemplating/ObjectTemplating/TemplateEvaluator.cs b/src/Sdk/DTObjectTemplating/ObjectTemplating/TemplateEvaluator.cs index 48670a9f3..63f516319 100644 --- a/src/Sdk/DTObjectTemplating/ObjectTemplating/TemplateEvaluator.cs +++ b/src/Sdk/DTObjectTemplating/ObjectTemplating/TemplateEvaluator.cs @@ -47,7 +47,7 @@ namespace GitHub.DistributedTask.ObjectTemplating var evaluator = new TemplateEvaluator(context, template, removeBytes); try { - var availableContext = new HashSet(context.ExpressionValues.Keys); + var availableContext = new HashSet(context.ExpressionValues.Keys.Concat(context.ExpressionFunctions.Select(x => $"{x.Name}({x.MinParameters},{x.MaxParameters})"))); var definitionInfo = new DefinitionInfo(context.Schema, type, availableContext); result = evaluator.Evaluate(definitionInfo); @@ -182,12 +182,14 @@ namespace GitHub.DistributedTask.ObjectTemplating } var keys = new HashSet(StringComparer.OrdinalIgnoreCase); + var hasExpressionKey = false; while (m_unraveler.AllowScalar(definition.Expand, out ScalarToken nextKeyScalar)) { // Expression if (nextKeyScalar is ExpressionToken) { + hasExpressionKey = true; var anyDefinition = new DefinitionInfo(definition, TemplateConstants.Any); mapping.Add(nextKeyScalar, Evaluate(anyDefinition)); continue; @@ -268,6 +270,19 @@ namespace GitHub.DistributedTask.ObjectTemplating String listToDeDuplicate = String.Join(", ", nonDuplicates); m_context.Error(mapping, TemplateStrings.UnableToDetermineOneOf(listToDeDuplicate)); } + else if (mappingDefinitions.Count == 1 && !hasExpressionKey) + { + foreach (var property in mappingDefinitions[0].Properties) + { + if (property.Value.Required) + { + if (!keys.Contains(property.Key)) + { + m_context.Error(mapping, $"Required property is missing: {property.Key}"); + } + } + } + } m_unraveler.ReadMappingEnd(); } diff --git a/src/Sdk/DTObjectTemplating/ObjectTemplating/TemplateReader.cs b/src/Sdk/DTObjectTemplating/ObjectTemplating/TemplateReader.cs index 56b149c3f..eab601bc0 100644 --- a/src/Sdk/DTObjectTemplating/ObjectTemplating/TemplateReader.cs +++ b/src/Sdk/DTObjectTemplating/ObjectTemplating/TemplateReader.cs @@ -178,14 +178,15 @@ namespace GitHub.DistributedTask.ObjectTemplating } var keys = new HashSet(StringComparer.OrdinalIgnoreCase); + var hasExpressionKey = false; while (m_objectReader.AllowLiteral(out LiteralToken rawLiteral)) { var nextKeyScalar = ParseScalar(rawLiteral, definition.AllowedContext); - // Expression if (nextKeyScalar is ExpressionToken) { + hasExpressionKey = true; // Legal if (definition.AllowedContext.Length > 0) { @@ -280,7 +281,19 @@ namespace GitHub.DistributedTask.ObjectTemplating String listToDeDuplicate = String.Join(", ", nonDuplicates); m_context.Error(mapping, TemplateStrings.UnableToDetermineOneOf(listToDeDuplicate)); } - + else if (mappingDefinitions.Count == 1 && !hasExpressionKey) + { + foreach (var property in mappingDefinitions[0].Properties) + { + if (property.Value.Required) + { + if (!keys.Contains(property.Key)) + { + m_context.Error(mapping, $"Required property is missing: {property.Key}"); + } + } + } + } ExpectMappingEnd(); } diff --git a/src/Sdk/DTPipelines/Pipelines/AgentJobRequestMessage.cs b/src/Sdk/DTPipelines/Pipelines/AgentJobRequestMessage.cs index 36a8864cd..576c3cb6f 100644 --- a/src/Sdk/DTPipelines/Pipelines/AgentJobRequestMessage.cs +++ b/src/Sdk/DTPipelines/Pipelines/AgentJobRequestMessage.cs @@ -40,7 +40,8 @@ namespace GitHub.DistributedTask.Pipelines WorkspaceOptions workspaceOptions, IEnumerable steps, IEnumerable scopes, - IList fileTable) + IList fileTable, + TemplateToken jobOutputs) { this.MessageType = JobRequestMessageTypes.PipelineAgentJobRequest; this.Plan = plan; @@ -52,6 +53,7 @@ namespace GitHub.DistributedTask.Pipelines this.Timeline = timeline; this.Resources = jobResources; this.Workspace = workspaceOptions; + this.JobOutputs = jobOutputs; m_variables = new Dictionary(variables, StringComparer.OrdinalIgnoreCase); m_maskHints = new List(maskHints); @@ -138,6 +140,13 @@ namespace GitHub.DistributedTask.Pipelines private set; } + [DataMember(EmitDefaultValue = false)] + public TemplateToken JobOutputs + { + get; + private set; + } + [DataMember] public Int64 RequestId { diff --git a/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateConstants.cs b/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateConstants.cs index 0675b993c..72853f5b2 100644 --- a/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateConstants.cs +++ b/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateConstants.cs @@ -29,7 +29,9 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating public const String Include = "include"; public const String Inputs = "inputs"; public const String Job = "job"; + 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"; diff --git a/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateEvaluator.cs b/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateEvaluator.cs index 1d10a3adc..ea9193ee1 100644 --- a/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateEvaluator.cs +++ b/src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateEvaluator.cs @@ -231,6 +231,42 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating return result; } + public Dictionary EvaluateJobOutput( + TemplateToken token, + DictionaryContextData contextData) + { + var result = default(Dictionary); + + if (token != null && token.Type != TokenType.Null) + { + var context = CreateContext(contextData); + try + { + token = TemplateEvaluator.Evaluate(context, PipelineTemplateConstants.JobOutputs, token, 0, null, omitHeader: true); + context.Errors.Check(); + result = new Dictionary(StringComparer.OrdinalIgnoreCase); + var mapping = token.AssertMapping("outputs"); + foreach (var pair in mapping) + { + // Literal key + var key = pair.Key.AssertString("output key"); + + // Literal value + var value = pair.Value.AssertString("output value"); + result[key.Value] = value.Value; + } + } + catch (Exception ex) when (!(ex is TemplateValidationException)) + { + context.Errors.Add(ex); + } + + context.Errors.Check(); + } + + return result; + } + public IList> EvaluateJobServiceContainers( TemplateToken token, DictionaryContextData contextData) @@ -364,6 +400,7 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating PipelineTemplateConstants.GitHub, PipelineTemplateConstants.Strategy, PipelineTemplateConstants.Matrix, + PipelineTemplateConstants.Needs, PipelineTemplateConstants.Secrets, PipelineTemplateConstants.Steps, PipelineTemplateConstants.Inputs, diff --git a/src/Sdk/DTPipelines/workflow-v1.0.json b/src/Sdk/DTPipelines/workflow-v1.0.json index 21e6d2b63..203a686ad 100644 --- a/src/Sdk/DTPipelines/workflow-v1.0.json +++ b/src/Sdk/DTPipelines/workflow-v1.0.json @@ -38,6 +38,7 @@ "context": [ "github", "strategy", + "needs", "matrix", "secrets", "steps", @@ -66,6 +67,7 @@ "github", "strategy", "matrix", + "needs", "secrets", "steps", "inputs", @@ -89,7 +91,8 @@ "context": [ "github", "strategy", - "matrix" + "matrix", + "needs" ], "one-of": [ "string", @@ -112,6 +115,7 @@ "github", "strategy", "matrix", + "needs", "secrets", "steps", "job", @@ -143,16 +147,20 @@ "mapping": { "properties": { "needs": "needs", - "if": "string", + "if": "job-if", "strategy": "strategy", "name": "string-strategy-context", - "runs-on": "runs-on", + "runs-on": { + "type": "runs-on", + "required": true + }, "timeout-minutes": "number-strategy-context", "cancel-timeout-minutes": "number-strategy-context", - "continue-on-error": "boolean", + "continue-on-error": "boolean-strategy-context", "container": "container", "services": "services", "env": "job-env", + "outputs": "job-outputs", "steps": "steps" } } @@ -165,9 +173,22 @@ ] }, + "job-if": { + "context": [ + "github", + "needs", + "always(0,0)", + "failure(0,MAX)", + "cancelled(0,0)", + "success(0,MAX)" + ], + "string": {} + }, + "strategy": { "context": [ - "github" + "github", + "needs" ], "mapping": { "properties": { @@ -233,24 +254,23 @@ "context": [ "github", "strategy", - "matrix" + "matrix", + "needs" ], "one-of": [ - "runs-on-string", + "non-empty-string", + "sequence-of-non-empty-string", "runs-on-mapping" ] }, - "runs-on-string": { - "string": { - "require-non-empty": true - } - }, - "runs-on-mapping": { "mapping": { "properties": { - "pool": "non-empty-string" + "pool": { + "type": "non-empty-string", + "required": true + } } } }, @@ -260,7 +280,8 @@ "github", "secrets", "strategy", - "matrix" + "matrix", + "needs" ], "mapping": { "loose-key-type": "non-empty-string", @@ -268,6 +289,13 @@ } }, + "job-outputs": { + "mapping": { + "loose-key-type": "non-empty-string", + "loose-value-type": "string-runner-context" + } + }, + "steps": { "sequence": { "item-type": "steps-item" @@ -301,9 +329,12 @@ "properties": { "name": "string-steps-context", "id": "non-empty-string", - "if": "string", + "if": "step-if", "timeout-minutes": "number-steps-context", - "run": "string-steps-context", + "run": { + "type": "string-steps-context", + "required": true + }, "continue-on-error": "boolean-steps-context", "env": "step-env", "working-directory": "string-steps-context", @@ -317,9 +348,12 @@ "properties": { "name": "string-steps-context-in-template", "id": "non-empty-string", - "if": "string", + "if": "step-if-in-template", "timeout-minutes": "number-steps-context-in-template", - "run": "string-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", @@ -333,10 +367,13 @@ "properties": { "name": "string-steps-context", "id": "non-empty-string", - "if": "string", + "if": "step-if", "continue-on-error": "boolean-steps-context", "timeout-minutes": "number-steps-context", - "uses": "non-empty-string", + "uses": { + "type": "non-empty-string", + "required": true + }, "with": "step-with", "env": "step-env" } @@ -348,16 +385,56 @@ "properties": { "name": "string-steps-context-in-template", "id": "non-empty-string", - "if": "string", + "if": "step-if-in-template", "continue-on-error": "boolean-steps-context-in-template", "timeout-minutes": "number-steps-context-in-template", - "uses": "non-empty-string", + "uses": { + "type": "non-empty-string", + "required": true + }, "with": "step-with-in-template", "env": "step-env-in-template" } } }, + "step-if": { + "context": [ + "github", + "strategy", + "matrix", + "needs", + "steps", + "job", + "runner", + "env", + "always(0,0)", + "failure(0,0)", + "cancelled(0,0)", + "success(0,0)" + ], + "string": {} + }, + + "step-if-in-template": { + "context": [ + "github", + "strategy", + "matrix", + "needs", + "steps", + "inputs", + "job", + "runner", + "env", + "always(0,0)", + "failure(0,0)", + "cancelled(0,0)", + "success(0,0)" + ], + "string": {} + }, + "steps-template-reference": { "mapping": { "properties": { @@ -383,6 +460,7 @@ "github", "strategy", "matrix", + "needs", "secrets", "steps", "job", @@ -400,6 +478,7 @@ "github", "strategy", "matrix", + "needs", "secrets", "steps", "inputs", @@ -418,6 +497,7 @@ "github", "strategy", "matrix", + "needs", "secrets", "steps", "job", @@ -435,6 +515,7 @@ "github", "strategy", "matrix", + "needs", "secrets", "steps", "inputs", @@ -453,6 +534,7 @@ "github", "strategy", "matrix", + "needs", "secrets", "steps", "job", @@ -469,7 +551,8 @@ "context": [ "github", "strategy", - "matrix" + "matrix", + "needs" ], "one-of": [ "string", @@ -493,7 +576,8 @@ "context": [ "github", "strategy", - "matrix" + "matrix", + "needs" ], "mapping": { "loose-key-type": "non-empty-string", @@ -505,7 +589,8 @@ "context": [ "github", "strategy", - "matrix" + "matrix", + "needs" ], "one-of": [ "non-empty-string", @@ -521,23 +606,24 @@ }, "step-with-in-template": { - "context": [ - "github", - "strategy", - "matrix", - "secrets", - "steps", - "inputs", - "job", - "runner", - "env" - ], - "mapping": { - "loose-key-type": "non-empty-string", - "loose-value-type": "string" - } - }, - + "context": [ + "github", + "strategy", + "matrix", + "needs", + "secrets", + "steps", + "inputs", + "job", + "runner", + "env" + ], + "mapping": { + "loose-key-type": "non-empty-string", + "loose-value-type": "string" + } + }, + "non-empty-string": { "string": { "require-non-empty": true @@ -550,11 +636,22 @@ } }, + "boolean-strategy-context": { + "context": [ + "github", + "strategy", + "matrix", + "needs" + ], + "boolean": {} + }, + "number-strategy-context": { "context": [ "github", "strategy", - "matrix" + "matrix", + "needs" ], "number": {} }, @@ -563,7 +660,8 @@ "context": [ "github", "strategy", - "matrix" + "matrix", + "needs" ], "string": {} }, @@ -573,6 +671,7 @@ "github", "strategy", "matrix", + "needs", "secrets", "steps", "job", @@ -587,6 +686,7 @@ "github", "strategy", "matrix", + "needs", "secrets", "steps", "inputs", @@ -602,6 +702,7 @@ "github", "strategy", "matrix", + "needs", "secrets", "steps", "job", @@ -616,6 +717,7 @@ "github", "strategy", "matrix", + "needs", "secrets", "steps", "inputs", @@ -626,11 +728,27 @@ "number": {} }, + "string-runner-context": { + "context": [ + "github", + "strategy", + "matrix", + "needs", + "secrets", + "steps", + "job", + "runner", + "env" + ], + "string": {} + }, + "string-steps-context": { "context": [ "github", "strategy", "matrix", + "needs", "secrets", "steps", "job", @@ -645,6 +763,7 @@ "github", "strategy", "matrix", + "needs", "secrets", "steps", "inputs", diff --git a/src/Sdk/DTWebApi/WebApi/JobEvent.cs b/src/Sdk/DTWebApi/WebApi/JobEvent.cs index 3bfbdd53b..7566cde94 100644 --- a/src/Sdk/DTWebApi/WebApi/JobEvent.cs +++ b/src/Sdk/DTWebApi/WebApi/JobEvent.cs @@ -31,7 +31,7 @@ namespace GitHub.DistributedTask.WebApi } protected JobEvent( - String name, + String name, Guid jobId) { this.Name = name; @@ -123,11 +123,12 @@ namespace GitHub.DistributedTask.WebApi Int64 requestId, Guid jobId, TaskResult result, - IDictionary outputVariables) + Dictionary outputs) : base(JobEventTypes.JobCompleted, jobId) { this.RequestId = requestId; this.Result = result; + this.Outputs = outputs; } [DataMember(EmitDefaultValue = false)] @@ -143,6 +144,13 @@ namespace GitHub.DistributedTask.WebApi get; set; } + + [DataMember(EmitDefaultValue = false)] + public IDictionary Outputs + { + get; + set; + } } [DataContract] @@ -153,9 +161,9 @@ namespace GitHub.DistributedTask.WebApi } protected TaskEvent( - string name, - Guid jobId, - Guid taskId) + string name, + Guid jobId, + Guid taskId) : base(name, jobId) { TaskId = taskId; @@ -185,9 +193,9 @@ namespace GitHub.DistributedTask.WebApi } public override Object ReadJson( - JsonReader reader, - Type objectType, - Object existingValue, + JsonReader reader, + Type objectType, + Object existingValue, JsonSerializer serializer) { var eventObject = JObject.Load(reader); diff --git a/src/Test/L0/Listener/JobDispatcherL0.cs b/src/Test/L0/Listener/JobDispatcherL0.cs index b81606d54..6ee79360e 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); + 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 07e80e9ce..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); + 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 a6cdc086e..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); + 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 513d286cc..190bcda76 100644 --- a/src/Test/L0/Worker/ExecutionContextL0.cs +++ b/src/Test/L0/Worker/ExecutionContextL0.cs @@ -25,7 +25,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); + 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, @@ -101,7 +101,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); + 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, @@ -152,7 +152,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); + 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 209f915e9..b2c5dbddd 100644 --- a/src/Test/L0/Worker/JobExtensionL0.cs +++ b/src/Test/L0/Worker/JobExtensionL0.cs @@ -100,7 +100,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); + _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 a88e6b8a7..574654720 100644 --- a/src/Test/L0/Worker/JobRunnerL0.cs +++ b/src/Test/L0/Worker/JobRunnerL0.cs @@ -63,7 +63,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); + _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/StepsRunnerL0.cs b/src/Test/L0/Worker/StepsRunnerL0.cs index e3ef3d2f7..fd215b718 100644 --- a/src/Test/L0/Worker/StepsRunnerL0.cs +++ b/src/Test/L0/Worker/StepsRunnerL0.cs @@ -55,6 +55,9 @@ namespace GitHub.Runner.Common.Tests.Worker _ec.Setup(x => x.PostJobSteps).Returns(new Stack()); + var trace = hc.GetTrace(); + _ec.Setup(x => x.Write(It.IsAny(), It.IsAny())).Callback((string tag, string message) => { trace.Info($"[{tag}]{message}"); }); + _stepsRunner = new StepsRunner(); _stepsRunner.Initialize(hc); return hc; diff --git a/src/Test/L0/Worker/WorkerL0.cs b/src/Test/L0/Worker/WorkerL0.cs index b48542e79..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); + 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; }