add support for job outputs. (#365)

* add support for job outputs.
This commit is contained in:
Tingluo Huang
2020-03-14 17:54:58 -04:00
committed by GitHub
parent c8890d0f3f
commit 2d6042421f
25 changed files with 445 additions and 116 deletions

View File

@@ -47,7 +47,7 @@ namespace GitHub.Runner.Worker
PlanFeatures Features { get; } PlanFeatures Features { get; }
Variables Variables { get; } Variables Variables { get; }
Dictionary<string, string> IntraActionState { get; } Dictionary<string, string> IntraActionState { get; }
HashSet<string> OutputVariables { get; } Dictionary<string, VariableValue> JobOutputs { get; }
IDictionary<String, String> EnvironmentVariables { get; } IDictionary<String, String> EnvironmentVariables { get; }
IDictionary<String, ContextScope> Scopes { get; } IDictionary<String, ContextScope> Scopes { get; }
IList<String> FileTable { get; } IList<String> FileTable { get; }
@@ -110,7 +110,6 @@ namespace GitHub.Runner.Worker
private readonly TimelineRecord _record = new TimelineRecord(); private readonly TimelineRecord _record = new TimelineRecord();
private readonly Dictionary<Guid, TimelineRecord> _detailRecords = new Dictionary<Guid, TimelineRecord>(); private readonly Dictionary<Guid, TimelineRecord> _detailRecords = new Dictionary<Guid, TimelineRecord>();
private readonly object _loggerLock = new object(); private readonly object _loggerLock = new object();
private readonly HashSet<string> _outputvariables = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private readonly object _matchersLock = new object(); private readonly object _matchersLock = new object();
private event OnMatcherChanged _onMatcherChanged; private event OnMatcherChanged _onMatcherChanged;
@@ -140,7 +139,7 @@ namespace GitHub.Runner.Worker
public List<ServiceEndpoint> Endpoints { get; private set; } public List<ServiceEndpoint> Endpoints { get; private set; }
public Variables Variables { get; private set; } public Variables Variables { get; private set; }
public Dictionary<string, string> IntraActionState { get; private set; } public Dictionary<string, string> IntraActionState { get; private set; }
public HashSet<string> OutputVariables => _outputvariables; public Dictionary<string, VariableValue> JobOutputs { get; private set; }
public IDictionary<String, String> EnvironmentVariables { get; private set; } public IDictionary<String, String> EnvironmentVariables { get; private set; }
public IDictionary<String, ContextScope> Scopes { get; private set; } public IDictionary<String, ContextScope> Scopes { get; private set; }
public IList<String> FileTable { get; private set; } public IList<String> FileTable { get; private set; }
@@ -557,6 +556,9 @@ namespace GitHub.Runner.Worker
// Environment variables shared across all actions // Environment variables shared across all actions
EnvironmentVariables = new Dictionary<string, string>(VarUtil.EnvironmentVariableKeyComparer); EnvironmentVariables = new Dictionary<string, string>(VarUtil.EnvironmentVariableKeyComparer);
// Job Outputs
JobOutputs = new Dictionary<string, VariableValue>(StringComparer.OrdinalIgnoreCase);
// Service container info // Service container info
ServiceContainers = new List<ContainerInfo>(); ServiceContainers = new List<ContainerInfo>();

View File

@@ -6,6 +6,8 @@ using System.Linq;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Threading.Tasks; using System.Threading.Tasks;
using GitHub.DistributedTask.Expressions2; using GitHub.DistributedTask.Expressions2;
using GitHub.DistributedTask.ObjectTemplating.Tokens;
using GitHub.DistributedTask.Pipelines.ContextData;
using GitHub.DistributedTask.Pipelines.ObjectTemplating; using GitHub.DistributedTask.Pipelines.ObjectTemplating;
using GitHub.DistributedTask.WebApi; using GitHub.DistributedTask.WebApi;
using GitHub.Runner.Common; using GitHub.Runner.Common;
@@ -291,6 +293,58 @@ namespace GitHub.Runner.Worker
context.Start(); context.Start();
context.Debug("Starting: Complete job"); 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) if (context.Variables.GetBoolean(Constants.Variables.Actions.RunnerDebug) ?? false)
{ {
Trace.Info("Support log upload starting."); Trace.Info("Support log upload starting.");

View File

@@ -231,7 +231,7 @@ namespace GitHub.Runner.Worker
} }
Trace.Info("Raising job completed event."); 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 completeJobRetryLimit = 5;
var exceptions = new List<Exception>(); var exceptions = new List<Exception>();

View File

@@ -90,10 +90,8 @@
"github", "github",
"strategy", "strategy",
"matrix", "matrix",
"steps",
"job", "job",
"runner", "runner"
"env"
], ],
"string": {} "string": {}
}, },

View File

@@ -15,6 +15,7 @@ namespace GitHub.DistributedTask.Expressions2
AddFunction<Join>("join", 1, 2); AddFunction<Join>("join", 1, 2);
AddFunction<StartsWith>("startsWith", 2, 2); AddFunction<StartsWith>("startsWith", 2, 2);
AddFunction<ToJson>("toJson", 1, 1); AddFunction<ToJson>("toJson", 1, 1);
AddFunction<FromJson>("fromJson", 1, 1);
AddFunction<HashFiles>("hashFiles", 1, 1); AddFunction<HashFiles>("hashFiles", 1, 1);
} }

View File

@@ -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();
}
}
}}

View File

@@ -30,8 +30,7 @@ namespace GitHub.DistributedTask.ObjectTemplating.Schema
foreach (var propertiesPair in properties) foreach (var propertiesPair in properties)
{ {
var propertyName = propertiesPair.Key.AssertString($"{TemplateConstants.Definition} {TemplateConstants.Mapping} {TemplateConstants.Properties} key"); 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(propertiesPair.Value));
Properties.Add(propertyName.Value, new PropertyValue(propertyValue.Value));
} }
break; break;
@@ -85,7 +84,7 @@ namespace GitHub.DistributedTask.ObjectTemplating.Schema
} }
else 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 // Otherwise validate loose value type not be defined
@@ -95,9 +94,14 @@ namespace GitHub.DistributedTask.ObjectTemplating.Schema
} }
// Lookup each property // 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)) if (!String.IsNullOrEmpty(Inherits))

View File

@@ -1,18 +1,40 @@
using System; using System;
using GitHub.DistributedTask.ObjectTemplating.Tokens;
namespace GitHub.DistributedTask.ObjectTemplating.Schema namespace GitHub.DistributedTask.ObjectTemplating.Schema
{ {
internal sealed class PropertyValue internal sealed class PropertyValue
{ {
internal PropertyValue() internal PropertyValue(TemplateToken token)
{ {
} if (token is StringToken stringToken)
{
internal PropertyValue(String type) Type = stringToken.Value;
{ }
Type = type; 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 String Type { get; set; }
internal Boolean Required { get; set; }
} }
} }

View File

@@ -312,8 +312,8 @@ namespace GitHub.DistributedTask.ObjectTemplating.Schema
// template-schema // template-schema
mappingDefinition = new MappingDefinition(); mappingDefinition = new MappingDefinition();
mappingDefinition.Properties.Add(TemplateConstants.Version, new PropertyValue(TemplateConstants.NonEmptyString)); mappingDefinition.Properties.Add(TemplateConstants.Version, new PropertyValue(new StringToken(null, null, null, TemplateConstants.NonEmptyString)));
mappingDefinition.Properties.Add(TemplateConstants.Definitions, new PropertyValue(TemplateConstants.Definitions)); mappingDefinition.Properties.Add(TemplateConstants.Definitions, new PropertyValue(new StringToken(null, null, null, TemplateConstants.Definitions)));
schema.Definitions.Add(TemplateConstants.TemplateSchema, mappingDefinition); schema.Definitions.Add(TemplateConstants.TemplateSchema, mappingDefinition);
// definitions // definitions
@@ -335,9 +335,9 @@ namespace GitHub.DistributedTask.ObjectTemplating.Schema
// null-definition // null-definition
mappingDefinition = new MappingDefinition(); mappingDefinition = new MappingDefinition();
mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(TemplateConstants.String)); mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(new StringToken(null, null, null, TemplateConstants.String)));
mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(TemplateConstants.SequenceOfNonEmptyString)); mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(new StringToken(null, null, null, TemplateConstants.SequenceOfNonEmptyString)));
mappingDefinition.Properties.Add(TemplateConstants.Null, new PropertyValue(TemplateConstants.NullDefinitionProperties)); mappingDefinition.Properties.Add(TemplateConstants.Null, new PropertyValue(new StringToken(null, null, null, TemplateConstants.NullDefinitionProperties)));
schema.Definitions.Add(TemplateConstants.NullDefinition, mappingDefinition); schema.Definitions.Add(TemplateConstants.NullDefinition, mappingDefinition);
// null-definition-properties // null-definition-properties
@@ -346,9 +346,9 @@ namespace GitHub.DistributedTask.ObjectTemplating.Schema
// boolean-definition // boolean-definition
mappingDefinition = new MappingDefinition(); mappingDefinition = new MappingDefinition();
mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(TemplateConstants.String)); mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(new StringToken(null, null, null, TemplateConstants.String)));
mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(TemplateConstants.SequenceOfNonEmptyString)); mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(new StringToken(null, null, null, TemplateConstants.SequenceOfNonEmptyString)));
mappingDefinition.Properties.Add(TemplateConstants.Boolean, new PropertyValue(TemplateConstants.BooleanDefinitionProperties)); mappingDefinition.Properties.Add(TemplateConstants.Boolean, new PropertyValue(new StringToken(null, null, null, TemplateConstants.BooleanDefinitionProperties)));
schema.Definitions.Add(TemplateConstants.BooleanDefinition, mappingDefinition); schema.Definitions.Add(TemplateConstants.BooleanDefinition, mappingDefinition);
// boolean-definition-properties // boolean-definition-properties
@@ -357,9 +357,9 @@ namespace GitHub.DistributedTask.ObjectTemplating.Schema
// number-definition // number-definition
mappingDefinition = new MappingDefinition(); mappingDefinition = new MappingDefinition();
mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(TemplateConstants.String)); mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(new StringToken(null, null, null, TemplateConstants.String)));
mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(TemplateConstants.SequenceOfNonEmptyString)); mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(new StringToken(null, null, null, TemplateConstants.SequenceOfNonEmptyString)));
mappingDefinition.Properties.Add(TemplateConstants.Number, new PropertyValue(TemplateConstants.NumberDefinitionProperties)); mappingDefinition.Properties.Add(TemplateConstants.Number, new PropertyValue(new StringToken(null, null, null, TemplateConstants.NumberDefinitionProperties)));
schema.Definitions.Add(TemplateConstants.NumberDefinition, mappingDefinition); schema.Definitions.Add(TemplateConstants.NumberDefinition, mappingDefinition);
// number-definition-properties // number-definition-properties
@@ -368,55 +368,68 @@ namespace GitHub.DistributedTask.ObjectTemplating.Schema
// string-definition // string-definition
mappingDefinition = new MappingDefinition(); mappingDefinition = new MappingDefinition();
mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(TemplateConstants.String)); mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(new StringToken(null, null, null, TemplateConstants.String)));
mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(TemplateConstants.SequenceOfNonEmptyString)); mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(new StringToken(null, null, null, TemplateConstants.SequenceOfNonEmptyString)));
mappingDefinition.Properties.Add(TemplateConstants.String, new PropertyValue(TemplateConstants.StringDefinitionProperties)); mappingDefinition.Properties.Add(TemplateConstants.String, new PropertyValue(new StringToken(null, null, null, TemplateConstants.StringDefinitionProperties)));
schema.Definitions.Add(TemplateConstants.StringDefinition, mappingDefinition); schema.Definitions.Add(TemplateConstants.StringDefinition, mappingDefinition);
// string-definition-properties // string-definition-properties
mappingDefinition = new MappingDefinition(); mappingDefinition = new MappingDefinition();
mappingDefinition.Properties.Add(TemplateConstants.Constant, new PropertyValue(TemplateConstants.NonEmptyString)); mappingDefinition.Properties.Add(TemplateConstants.Constant, new PropertyValue(new StringToken(null, null, null, TemplateConstants.NonEmptyString)));
mappingDefinition.Properties.Add(TemplateConstants.IgnoreCase, new PropertyValue(TemplateConstants.Boolean)); mappingDefinition.Properties.Add(TemplateConstants.IgnoreCase, new PropertyValue(new StringToken(null, null, null,TemplateConstants.Boolean)));
mappingDefinition.Properties.Add(TemplateConstants.RequireNonEmpty, new PropertyValue(TemplateConstants.Boolean)); mappingDefinition.Properties.Add(TemplateConstants.RequireNonEmpty, new PropertyValue(new StringToken(null, null, null, TemplateConstants.Boolean)));
schema.Definitions.Add(TemplateConstants.StringDefinitionProperties, mappingDefinition); schema.Definitions.Add(TemplateConstants.StringDefinitionProperties, mappingDefinition);
// sequence-definition // sequence-definition
mappingDefinition = new MappingDefinition(); mappingDefinition = new MappingDefinition();
mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(TemplateConstants.String)); mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(new StringToken(null, null, null, TemplateConstants.String)));
mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(TemplateConstants.SequenceOfNonEmptyString)); mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(new StringToken(null, null, null, TemplateConstants.SequenceOfNonEmptyString)));
mappingDefinition.Properties.Add(TemplateConstants.Sequence, new PropertyValue(TemplateConstants.SequenceDefinitionProperties)); mappingDefinition.Properties.Add(TemplateConstants.Sequence, new PropertyValue(new StringToken(null, null, null, TemplateConstants.SequenceDefinitionProperties)));
schema.Definitions.Add(TemplateConstants.SequenceDefinition, mappingDefinition); schema.Definitions.Add(TemplateConstants.SequenceDefinition, mappingDefinition);
// sequence-definition-properties // sequence-definition-properties
mappingDefinition = new MappingDefinition(); 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); schema.Definitions.Add(TemplateConstants.SequenceDefinitionProperties, mappingDefinition);
// mapping-definition // mapping-definition
mappingDefinition = new MappingDefinition(); mappingDefinition = new MappingDefinition();
mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(TemplateConstants.String)); mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(new StringToken(null, null, null, TemplateConstants.String)));
mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(TemplateConstants.SequenceOfNonEmptyString)); mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(new StringToken(null, null, null, TemplateConstants.SequenceOfNonEmptyString)));
mappingDefinition.Properties.Add(TemplateConstants.Mapping, new PropertyValue(TemplateConstants.MappingDefinitionProperties)); mappingDefinition.Properties.Add(TemplateConstants.Mapping, new PropertyValue(new StringToken(null, null, null, TemplateConstants.MappingDefinitionProperties)));
schema.Definitions.Add(TemplateConstants.MappingDefinition, mappingDefinition); schema.Definitions.Add(TemplateConstants.MappingDefinition, mappingDefinition);
// mapping-definition-properties // mapping-definition-properties
mappingDefinition = new MappingDefinition(); mappingDefinition = new MappingDefinition();
mappingDefinition.Properties.Add(TemplateConstants.Properties, new PropertyValue(TemplateConstants.Properties)); mappingDefinition.Properties.Add(TemplateConstants.Properties, new PropertyValue(new StringToken(null, null, null, TemplateConstants.Properties)));
mappingDefinition.Properties.Add(TemplateConstants.LooseKeyType, new PropertyValue(TemplateConstants.NonEmptyString)); mappingDefinition.Properties.Add(TemplateConstants.LooseKeyType, new PropertyValue(new StringToken(null, null, null, TemplateConstants.NonEmptyString)));
mappingDefinition.Properties.Add(TemplateConstants.LooseValueType, new PropertyValue(TemplateConstants.NonEmptyString)); mappingDefinition.Properties.Add(TemplateConstants.LooseValueType, new PropertyValue(new StringToken(null, null, null, TemplateConstants.NonEmptyString)));
schema.Definitions.Add(TemplateConstants.MappingDefinitionProperties, mappingDefinition); schema.Definitions.Add(TemplateConstants.MappingDefinitionProperties, mappingDefinition);
// properties // properties
mappingDefinition = new MappingDefinition(); mappingDefinition = new MappingDefinition();
mappingDefinition.LooseKeyType = TemplateConstants.NonEmptyString; mappingDefinition.LooseKeyType = TemplateConstants.NonEmptyString;
mappingDefinition.LooseValueType = TemplateConstants.NonEmptyString; mappingDefinition.LooseValueType = TemplateConstants.PropertyValue;
schema.Definitions.Add(TemplateConstants.Properties, mappingDefinition); 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 // one-of-definition
mappingDefinition = new MappingDefinition(); mappingDefinition = new MappingDefinition();
mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(TemplateConstants.String)); mappingDefinition.Properties.Add(TemplateConstants.Description, new PropertyValue(new StringToken(null, null, null, TemplateConstants.String)));
mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(TemplateConstants.SequenceOfNonEmptyString)); mappingDefinition.Properties.Add(TemplateConstants.Context, new PropertyValue(new StringToken(null, null, null, TemplateConstants.SequenceOfNonEmptyString)));
mappingDefinition.Properties.Add(TemplateConstants.OneOf, new PropertyValue(TemplateConstants.SequenceOfNonEmptyString)); mappingDefinition.Properties.Add(TemplateConstants.OneOf, new PropertyValue(new StringToken(null, null, null, TemplateConstants.SequenceOfNonEmptyString)));
schema.Definitions.Add(TemplateConstants.OneOfDefinition, mappingDefinition); schema.Definitions.Add(TemplateConstants.OneOfDefinition, mappingDefinition);
// non-empty-string // 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 readonly Regex s_definitionNameRegex = new Regex("^[a-zA-Z_][a-zA-Z0-9_-]*$", RegexOptions.Compiled);
private static TemplateSchema s_schema; private static TemplateSchema s_schema;
} }
} }

View File

@@ -22,9 +22,11 @@ namespace GitHub.DistributedTask.ObjectTemplating
internal const String ItemType = "item-type"; internal const String ItemType = "item-type";
internal const String LooseKeyType = "loose-key-type"; internal const String LooseKeyType = "loose-key-type";
internal const String LooseValueType = "loose-value-type"; internal const String LooseValueType = "loose-value-type";
internal const String MaxConstant = "MAX";
internal const String Mapping = "mapping"; internal const String Mapping = "mapping";
internal const String MappingDefinition = "mapping-definition"; internal const String MappingDefinition = "mapping-definition";
internal const String MappingDefinitionProperties = "mapping-definition-properties"; internal const String MappingDefinitionProperties = "mapping-definition-properties";
internal const String MappingPropertyValue = "mapping-property-value";
internal const String NonEmptyString = "non-empty-string"; internal const String NonEmptyString = "non-empty-string";
internal const String Null = "null"; internal const String Null = "null";
internal const String NullDefinition = "null-definition"; internal const String NullDefinition = "null-definition";
@@ -35,7 +37,9 @@ namespace GitHub.DistributedTask.ObjectTemplating
internal const String OneOf = "one-of"; internal const String OneOf = "one-of";
internal const String OneOfDefinition = "one-of-definition"; internal const String OneOfDefinition = "one-of-definition";
internal const String OpenExpression = "${{"; internal const String OpenExpression = "${{";
internal const String PropertyValue = "property-value";
internal const String Properties = "properties"; internal const String Properties = "properties";
internal const String Required = "required";
internal const String RequireNonEmpty = "require-non-empty"; internal const String RequireNonEmpty = "require-non-empty";
internal const String Scalar = "scalar"; internal const String Scalar = "scalar";
internal const String ScalarDefinition = "scalar-definition"; internal const String ScalarDefinition = "scalar-definition";
@@ -43,6 +47,7 @@ namespace GitHub.DistributedTask.ObjectTemplating
internal const String Sequence = "sequence"; internal const String Sequence = "sequence";
internal const String SequenceDefinition = "sequence-definition"; internal const String SequenceDefinition = "sequence-definition";
internal const String SequenceDefinitionProperties = "sequence-definition-properties"; internal const String SequenceDefinitionProperties = "sequence-definition-properties";
internal const String Type = "type";
internal const String SequenceOfNonEmptyString = "sequence-of-non-empty-string"; internal const String SequenceOfNonEmptyString = "sequence-of-non-empty-string";
internal const String String = "string"; internal const String String = "string";
internal const String StringDefinition = "string-definition"; internal const String StringDefinition = "string-definition";

View File

@@ -47,7 +47,7 @@ namespace GitHub.DistributedTask.ObjectTemplating
var evaluator = new TemplateEvaluator(context, template, removeBytes); var evaluator = new TemplateEvaluator(context, template, removeBytes);
try try
{ {
var availableContext = new HashSet<String>(context.ExpressionValues.Keys); var availableContext = new HashSet<String>(context.ExpressionValues.Keys.Concat(context.ExpressionFunctions.Select(x => $"{x.Name}({x.MinParameters},{x.MaxParameters})")));
var definitionInfo = new DefinitionInfo(context.Schema, type, availableContext); var definitionInfo = new DefinitionInfo(context.Schema, type, availableContext);
result = evaluator.Evaluate(definitionInfo); result = evaluator.Evaluate(definitionInfo);
@@ -182,12 +182,14 @@ namespace GitHub.DistributedTask.ObjectTemplating
} }
var keys = new HashSet<String>(StringComparer.OrdinalIgnoreCase); var keys = new HashSet<String>(StringComparer.OrdinalIgnoreCase);
var hasExpressionKey = false;
while (m_unraveler.AllowScalar(definition.Expand, out ScalarToken nextKeyScalar)) while (m_unraveler.AllowScalar(definition.Expand, out ScalarToken nextKeyScalar))
{ {
// Expression // Expression
if (nextKeyScalar is ExpressionToken) if (nextKeyScalar is ExpressionToken)
{ {
hasExpressionKey = true;
var anyDefinition = new DefinitionInfo(definition, TemplateConstants.Any); var anyDefinition = new DefinitionInfo(definition, TemplateConstants.Any);
mapping.Add(nextKeyScalar, Evaluate(anyDefinition)); mapping.Add(nextKeyScalar, Evaluate(anyDefinition));
continue; continue;
@@ -268,6 +270,19 @@ namespace GitHub.DistributedTask.ObjectTemplating
String listToDeDuplicate = String.Join(", ", nonDuplicates); String listToDeDuplicate = String.Join(", ", nonDuplicates);
m_context.Error(mapping, TemplateStrings.UnableToDetermineOneOf(listToDeDuplicate)); 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(); m_unraveler.ReadMappingEnd();
} }

View File

@@ -178,14 +178,15 @@ namespace GitHub.DistributedTask.ObjectTemplating
} }
var keys = new HashSet<String>(StringComparer.OrdinalIgnoreCase); var keys = new HashSet<String>(StringComparer.OrdinalIgnoreCase);
var hasExpressionKey = false;
while (m_objectReader.AllowLiteral(out LiteralToken rawLiteral)) while (m_objectReader.AllowLiteral(out LiteralToken rawLiteral))
{ {
var nextKeyScalar = ParseScalar(rawLiteral, definition.AllowedContext); var nextKeyScalar = ParseScalar(rawLiteral, definition.AllowedContext);
// Expression // Expression
if (nextKeyScalar is ExpressionToken) if (nextKeyScalar is ExpressionToken)
{ {
hasExpressionKey = true;
// Legal // Legal
if (definition.AllowedContext.Length > 0) if (definition.AllowedContext.Length > 0)
{ {
@@ -280,7 +281,19 @@ namespace GitHub.DistributedTask.ObjectTemplating
String listToDeDuplicate = String.Join(", ", nonDuplicates); String listToDeDuplicate = String.Join(", ", nonDuplicates);
m_context.Error(mapping, TemplateStrings.UnableToDetermineOneOf(listToDeDuplicate)); 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(); ExpectMappingEnd();
} }

View File

@@ -40,7 +40,8 @@ namespace GitHub.DistributedTask.Pipelines
WorkspaceOptions workspaceOptions, WorkspaceOptions workspaceOptions,
IEnumerable<JobStep> steps, IEnumerable<JobStep> steps,
IEnumerable<ContextScope> scopes, IEnumerable<ContextScope> scopes,
IList<String> fileTable) IList<String> fileTable,
TemplateToken jobOutputs)
{ {
this.MessageType = JobRequestMessageTypes.PipelineAgentJobRequest; this.MessageType = JobRequestMessageTypes.PipelineAgentJobRequest;
this.Plan = plan; this.Plan = plan;
@@ -52,6 +53,7 @@ namespace GitHub.DistributedTask.Pipelines
this.Timeline = timeline; this.Timeline = timeline;
this.Resources = jobResources; this.Resources = jobResources;
this.Workspace = workspaceOptions; this.Workspace = workspaceOptions;
this.JobOutputs = jobOutputs;
m_variables = new Dictionary<String, VariableValue>(variables, StringComparer.OrdinalIgnoreCase); m_variables = new Dictionary<String, VariableValue>(variables, StringComparer.OrdinalIgnoreCase);
m_maskHints = new List<MaskHint>(maskHints); m_maskHints = new List<MaskHint>(maskHints);
@@ -138,6 +140,13 @@ namespace GitHub.DistributedTask.Pipelines
private set; private set;
} }
[DataMember(EmitDefaultValue = false)]
public TemplateToken JobOutputs
{
get;
private set;
}
[DataMember] [DataMember]
public Int64 RequestId public Int64 RequestId
{ {

View File

@@ -29,7 +29,9 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating
public const String Include = "include"; public const String Include = "include";
public const String Inputs = "inputs"; public const String Inputs = "inputs";
public const String Job = "job"; public const String Job = "job";
public const String JobOutputs = "job-outputs";
public const String Jobs = "jobs"; public const String Jobs = "jobs";
public const String Labels = "labels";
public const String Lfs = "lfs"; public const String Lfs = "lfs";
public const String Matrix = "matrix"; public const String Matrix = "matrix";
public const String MaxParallel = "max-parallel"; public const String MaxParallel = "max-parallel";

View File

@@ -231,6 +231,42 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating
return result; return result;
} }
public Dictionary<String, String> EvaluateJobOutput(
TemplateToken token,
DictionaryContextData contextData)
{
var result = default(Dictionary<String, String>);
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<String, String>(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<KeyValuePair<String, JobContainer>> EvaluateJobServiceContainers( public IList<KeyValuePair<String, JobContainer>> EvaluateJobServiceContainers(
TemplateToken token, TemplateToken token,
DictionaryContextData contextData) DictionaryContextData contextData)
@@ -364,6 +400,7 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating
PipelineTemplateConstants.GitHub, PipelineTemplateConstants.GitHub,
PipelineTemplateConstants.Strategy, PipelineTemplateConstants.Strategy,
PipelineTemplateConstants.Matrix, PipelineTemplateConstants.Matrix,
PipelineTemplateConstants.Needs,
PipelineTemplateConstants.Secrets, PipelineTemplateConstants.Secrets,
PipelineTemplateConstants.Steps, PipelineTemplateConstants.Steps,
PipelineTemplateConstants.Inputs, PipelineTemplateConstants.Inputs,

View File

@@ -38,6 +38,7 @@
"context": [ "context": [
"github", "github",
"strategy", "strategy",
"needs",
"matrix", "matrix",
"secrets", "secrets",
"steps", "steps",
@@ -66,6 +67,7 @@
"github", "github",
"strategy", "strategy",
"matrix", "matrix",
"needs",
"secrets", "secrets",
"steps", "steps",
"inputs", "inputs",
@@ -89,7 +91,8 @@
"context": [ "context": [
"github", "github",
"strategy", "strategy",
"matrix" "matrix",
"needs"
], ],
"one-of": [ "one-of": [
"string", "string",
@@ -112,6 +115,7 @@
"github", "github",
"strategy", "strategy",
"matrix", "matrix",
"needs",
"secrets", "secrets",
"steps", "steps",
"job", "job",
@@ -143,16 +147,20 @@
"mapping": { "mapping": {
"properties": { "properties": {
"needs": "needs", "needs": "needs",
"if": "string", "if": "job-if",
"strategy": "strategy", "strategy": "strategy",
"name": "string-strategy-context", "name": "string-strategy-context",
"runs-on": "runs-on", "runs-on": {
"type": "runs-on",
"required": true
},
"timeout-minutes": "number-strategy-context", "timeout-minutes": "number-strategy-context",
"cancel-timeout-minutes": "number-strategy-context", "cancel-timeout-minutes": "number-strategy-context",
"continue-on-error": "boolean", "continue-on-error": "boolean-strategy-context",
"container": "container", "container": "container",
"services": "services", "services": "services",
"env": "job-env", "env": "job-env",
"outputs": "job-outputs",
"steps": "steps" "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": { "strategy": {
"context": [ "context": [
"github" "github",
"needs"
], ],
"mapping": { "mapping": {
"properties": { "properties": {
@@ -233,24 +254,23 @@
"context": [ "context": [
"github", "github",
"strategy", "strategy",
"matrix" "matrix",
"needs"
], ],
"one-of": [ "one-of": [
"runs-on-string", "non-empty-string",
"sequence-of-non-empty-string",
"runs-on-mapping" "runs-on-mapping"
] ]
}, },
"runs-on-string": {
"string": {
"require-non-empty": true
}
},
"runs-on-mapping": { "runs-on-mapping": {
"mapping": { "mapping": {
"properties": { "properties": {
"pool": "non-empty-string" "pool": {
"type": "non-empty-string",
"required": true
}
} }
} }
}, },
@@ -260,7 +280,8 @@
"github", "github",
"secrets", "secrets",
"strategy", "strategy",
"matrix" "matrix",
"needs"
], ],
"mapping": { "mapping": {
"loose-key-type": "non-empty-string", "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": { "steps": {
"sequence": { "sequence": {
"item-type": "steps-item" "item-type": "steps-item"
@@ -301,9 +329,12 @@
"properties": { "properties": {
"name": "string-steps-context", "name": "string-steps-context",
"id": "non-empty-string", "id": "non-empty-string",
"if": "string", "if": "step-if",
"timeout-minutes": "number-steps-context", "timeout-minutes": "number-steps-context",
"run": "string-steps-context", "run": {
"type": "string-steps-context",
"required": true
},
"continue-on-error": "boolean-steps-context", "continue-on-error": "boolean-steps-context",
"env": "step-env", "env": "step-env",
"working-directory": "string-steps-context", "working-directory": "string-steps-context",
@@ -317,9 +348,12 @@
"properties": { "properties": {
"name": "string-steps-context-in-template", "name": "string-steps-context-in-template",
"id": "non-empty-string", "id": "non-empty-string",
"if": "string", "if": "step-if-in-template",
"timeout-minutes": "number-steps-context-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", "continue-on-error": "boolean-steps-context-in-template",
"env": "step-env-in-template", "env": "step-env-in-template",
"working-directory": "string-steps-context-in-template", "working-directory": "string-steps-context-in-template",
@@ -333,10 +367,13 @@
"properties": { "properties": {
"name": "string-steps-context", "name": "string-steps-context",
"id": "non-empty-string", "id": "non-empty-string",
"if": "string", "if": "step-if",
"continue-on-error": "boolean-steps-context", "continue-on-error": "boolean-steps-context",
"timeout-minutes": "number-steps-context", "timeout-minutes": "number-steps-context",
"uses": "non-empty-string", "uses": {
"type": "non-empty-string",
"required": true
},
"with": "step-with", "with": "step-with",
"env": "step-env" "env": "step-env"
} }
@@ -348,16 +385,56 @@
"properties": { "properties": {
"name": "string-steps-context-in-template", "name": "string-steps-context-in-template",
"id": "non-empty-string", "id": "non-empty-string",
"if": "string", "if": "step-if-in-template",
"continue-on-error": "boolean-steps-context-in-template", "continue-on-error": "boolean-steps-context-in-template",
"timeout-minutes": "number-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", "with": "step-with-in-template",
"env": "step-env-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": { "steps-template-reference": {
"mapping": { "mapping": {
"properties": { "properties": {
@@ -383,6 +460,7 @@
"github", "github",
"strategy", "strategy",
"matrix", "matrix",
"needs",
"secrets", "secrets",
"steps", "steps",
"job", "job",
@@ -400,6 +478,7 @@
"github", "github",
"strategy", "strategy",
"matrix", "matrix",
"needs",
"secrets", "secrets",
"steps", "steps",
"inputs", "inputs",
@@ -418,6 +497,7 @@
"github", "github",
"strategy", "strategy",
"matrix", "matrix",
"needs",
"secrets", "secrets",
"steps", "steps",
"job", "job",
@@ -435,6 +515,7 @@
"github", "github",
"strategy", "strategy",
"matrix", "matrix",
"needs",
"secrets", "secrets",
"steps", "steps",
"inputs", "inputs",
@@ -453,6 +534,7 @@
"github", "github",
"strategy", "strategy",
"matrix", "matrix",
"needs",
"secrets", "secrets",
"steps", "steps",
"job", "job",
@@ -469,7 +551,8 @@
"context": [ "context": [
"github", "github",
"strategy", "strategy",
"matrix" "matrix",
"needs"
], ],
"one-of": [ "one-of": [
"string", "string",
@@ -493,7 +576,8 @@
"context": [ "context": [
"github", "github",
"strategy", "strategy",
"matrix" "matrix",
"needs"
], ],
"mapping": { "mapping": {
"loose-key-type": "non-empty-string", "loose-key-type": "non-empty-string",
@@ -505,7 +589,8 @@
"context": [ "context": [
"github", "github",
"strategy", "strategy",
"matrix" "matrix",
"needs"
], ],
"one-of": [ "one-of": [
"non-empty-string", "non-empty-string",
@@ -521,23 +606,24 @@
}, },
"step-with-in-template": { "step-with-in-template": {
"context": [ "context": [
"github", "github",
"strategy", "strategy",
"matrix", "matrix",
"secrets", "needs",
"steps", "secrets",
"inputs", "steps",
"job", "inputs",
"runner", "job",
"env" "runner",
], "env"
"mapping": { ],
"loose-key-type": "non-empty-string", "mapping": {
"loose-value-type": "string" "loose-key-type": "non-empty-string",
} "loose-value-type": "string"
}, }
},
"non-empty-string": { "non-empty-string": {
"string": { "string": {
"require-non-empty": true "require-non-empty": true
@@ -550,11 +636,22 @@
} }
}, },
"boolean-strategy-context": {
"context": [
"github",
"strategy",
"matrix",
"needs"
],
"boolean": {}
},
"number-strategy-context": { "number-strategy-context": {
"context": [ "context": [
"github", "github",
"strategy", "strategy",
"matrix" "matrix",
"needs"
], ],
"number": {} "number": {}
}, },
@@ -563,7 +660,8 @@
"context": [ "context": [
"github", "github",
"strategy", "strategy",
"matrix" "matrix",
"needs"
], ],
"string": {} "string": {}
}, },
@@ -573,6 +671,7 @@
"github", "github",
"strategy", "strategy",
"matrix", "matrix",
"needs",
"secrets", "secrets",
"steps", "steps",
"job", "job",
@@ -587,6 +686,7 @@
"github", "github",
"strategy", "strategy",
"matrix", "matrix",
"needs",
"secrets", "secrets",
"steps", "steps",
"inputs", "inputs",
@@ -602,6 +702,7 @@
"github", "github",
"strategy", "strategy",
"matrix", "matrix",
"needs",
"secrets", "secrets",
"steps", "steps",
"job", "job",
@@ -616,6 +717,7 @@
"github", "github",
"strategy", "strategy",
"matrix", "matrix",
"needs",
"secrets", "secrets",
"steps", "steps",
"inputs", "inputs",
@@ -626,11 +728,27 @@
"number": {} "number": {}
}, },
"string-runner-context": {
"context": [
"github",
"strategy",
"matrix",
"needs",
"secrets",
"steps",
"job",
"runner",
"env"
],
"string": {}
},
"string-steps-context": { "string-steps-context": {
"context": [ "context": [
"github", "github",
"strategy", "strategy",
"matrix", "matrix",
"needs",
"secrets", "secrets",
"steps", "steps",
"job", "job",
@@ -645,6 +763,7 @@
"github", "github",
"strategy", "strategy",
"matrix", "matrix",
"needs",
"secrets", "secrets",
"steps", "steps",
"inputs", "inputs",

View File

@@ -31,7 +31,7 @@ namespace GitHub.DistributedTask.WebApi
} }
protected JobEvent( protected JobEvent(
String name, String name,
Guid jobId) Guid jobId)
{ {
this.Name = name; this.Name = name;
@@ -123,11 +123,12 @@ namespace GitHub.DistributedTask.WebApi
Int64 requestId, Int64 requestId,
Guid jobId, Guid jobId,
TaskResult result, TaskResult result,
IDictionary<String, VariableValue> outputVariables) Dictionary<String, VariableValue> outputs)
: base(JobEventTypes.JobCompleted, jobId) : base(JobEventTypes.JobCompleted, jobId)
{ {
this.RequestId = requestId; this.RequestId = requestId;
this.Result = result; this.Result = result;
this.Outputs = outputs;
} }
[DataMember(EmitDefaultValue = false)] [DataMember(EmitDefaultValue = false)]
@@ -143,6 +144,13 @@ namespace GitHub.DistributedTask.WebApi
get; get;
set; set;
} }
[DataMember(EmitDefaultValue = false)]
public IDictionary<String, VariableValue> Outputs
{
get;
set;
}
} }
[DataContract] [DataContract]
@@ -153,9 +161,9 @@ namespace GitHub.DistributedTask.WebApi
} }
protected TaskEvent( protected TaskEvent(
string name, string name,
Guid jobId, Guid jobId,
Guid taskId) Guid taskId)
: base(name, jobId) : base(name, jobId)
{ {
TaskId = taskId; TaskId = taskId;
@@ -185,9 +193,9 @@ namespace GitHub.DistributedTask.WebApi
} }
public override Object ReadJson( public override Object ReadJson(
JsonReader reader, JsonReader reader,
Type objectType, Type objectType,
Object existingValue, Object existingValue,
JsonSerializer serializer) JsonSerializer serializer)
{ {
var eventObject = JObject.Load(reader); var eventObject = JObject.Load(reader);

View File

@@ -33,7 +33,7 @@ namespace GitHub.Runner.Common.Tests.Listener
TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference(); TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
TimelineReference timeline = null; TimelineReference timeline = null;
Guid jobId = Guid.NewGuid(); Guid jobId = Guid.NewGuid();
var result = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "someJob", "someJob", null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null); var result = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "someJob", "someJob", null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null, null);
result.ContextData["github"] = new Pipelines.ContextData.DictionaryContextData(); result.ContextData["github"] = new Pipelines.ContextData.DictionaryContextData();
return result; return result;
} }

View File

@@ -43,7 +43,7 @@ namespace GitHub.Runner.Common.Tests.Listener
TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference(); TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
TimelineReference timeline = null; TimelineReference timeline = null;
Guid jobId = Guid.NewGuid(); Guid jobId = Guid.NewGuid();
return new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "test", "test", null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null); return new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "test", "test", null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null, null);
} }
private JobCancelMessage CreateJobCancelMessage() private JobCancelMessage CreateJobCancelMessage()

View File

@@ -150,7 +150,7 @@ namespace GitHub.Runner.Common.Tests.Worker
TimelineReference timeline = new TimelineReference(); TimelineReference timeline = new TimelineReference();
Guid jobId = Guid.NewGuid(); Guid jobId = Guid.NewGuid();
string jobName = "some job name"; string jobName = "some job name";
var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null); var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null, null);
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource() jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
{ {
Alias = Pipelines.PipelineConstants.SelfAlias, Alias = Pipelines.PipelineConstants.SelfAlias,

View File

@@ -25,7 +25,7 @@ namespace GitHub.Runner.Common.Tests.Worker
TimelineReference timeline = new TimelineReference(); TimelineReference timeline = new TimelineReference();
Guid jobId = Guid.NewGuid(); Guid jobId = Guid.NewGuid();
string jobName = "some job name"; string jobName = "some job name";
var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null); var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null, null);
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource() jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
{ {
Alias = Pipelines.PipelineConstants.SelfAlias, Alias = Pipelines.PipelineConstants.SelfAlias,
@@ -101,7 +101,7 @@ namespace GitHub.Runner.Common.Tests.Worker
TimelineReference timeline = new TimelineReference(); TimelineReference timeline = new TimelineReference();
Guid jobId = Guid.NewGuid(); Guid jobId = Guid.NewGuid();
string jobName = "some job name"; string jobName = "some job name";
var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null); var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null, null);
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource() jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
{ {
Alias = Pipelines.PipelineConstants.SelfAlias, Alias = Pipelines.PipelineConstants.SelfAlias,
@@ -152,7 +152,7 @@ namespace GitHub.Runner.Common.Tests.Worker
TimelineReference timeline = new TimelineReference(); TimelineReference timeline = new TimelineReference();
Guid jobId = Guid.NewGuid(); Guid jobId = Guid.NewGuid();
string jobName = "some job name"; string jobName = "some job name";
var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null); var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null, null);
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource() jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
{ {
Alias = Pipelines.PipelineConstants.SelfAlias, Alias = Pipelines.PipelineConstants.SelfAlias,

View File

@@ -100,7 +100,7 @@ namespace GitHub.Runner.Common.Tests.Worker
}; };
Guid jobId = Guid.NewGuid(); Guid jobId = Guid.NewGuid();
_message = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "test", "test", null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), 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<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), steps, null, null, null);
GitHubContext github = new GitHubContext(); GitHubContext github = new GitHubContext();
github["repository"] = new Pipelines.ContextData.StringContextData("actions/runner"); github["repository"] = new Pipelines.ContextData.StringContextData("actions/runner");
_message.ContextData.Add("github", github); _message.ContextData.Add("github", github);

View File

@@ -63,7 +63,7 @@ namespace GitHub.Runner.Common.Tests.Worker
TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference(); TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
TimelineReference timeline = new Timeline(Guid.NewGuid()); TimelineReference timeline = new Timeline(Guid.NewGuid());
Guid jobId = Guid.NewGuid(); Guid jobId = Guid.NewGuid();
_message = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, testName, testName, null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null); _message = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, testName, testName, null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null, null);
_message.Variables[Constants.Variables.System.Culture] = "en-US"; _message.Variables[Constants.Variables.System.Culture] = "en-US";
_message.Resources.Endpoints.Add(new ServiceEndpoint() _message.Resources.Endpoints.Add(new ServiceEndpoint()
{ {

View File

@@ -55,6 +55,9 @@ namespace GitHub.Runner.Common.Tests.Worker
_ec.Setup(x => x.PostJobSteps).Returns(new Stack<IStep>()); _ec.Setup(x => x.PostJobSteps).Returns(new Stack<IStep>());
var trace = hc.GetTrace();
_ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>())).Callback((string tag, string message) => { trace.Info($"[{tag}]{message}"); });
_stepsRunner = new StepsRunner(); _stepsRunner = new StepsRunner();
_stepsRunner.Initialize(hc); _stepsRunner.Initialize(hc);
return hc; return hc;

View File

@@ -67,7 +67,7 @@ namespace GitHub.Runner.Common.Tests.Worker
new Pipelines.ContextData.DictionaryContextData() 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<MaskHint>(), 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<MaskHint>(), resources, context, null, actions, null, null, null);
return jobRequest; return jobRequest;
} }