delete un-used code. (#218)

This commit is contained in:
Tingluo Huang
2019-12-16 17:05:26 -05:00
committed by GitHub
parent c3c66bb14a
commit d0a4a41a63
582 changed files with 155 additions and 66274 deletions

View File

@@ -16,180 +16,6 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating
{
internal static class PipelineTemplateConverter
{
internal static PipelineTemplate ConvertToPipeline(
TemplateContext context,
RepositoryResource self,
TemplateToken pipeline)
{
var result = new PipelineTemplate();
result.Resources.Repositories.Add(self);
var defaultStage = new Stage
{
Name = PipelineConstants.DefaultJobName,
};
result.Stages.Add(defaultStage);
try
{
if (pipeline == null || context.Errors.Count > 0)
{
return result;
}
var pipelineMapping = pipeline.AssertMapping("root");
foreach (var pipelinePair in pipelineMapping)
{
var pipelineKey = pipelinePair.Key.AssertString("root key");
switch (pipelineKey.Value)
{
case PipelineTemplateConstants.On:
break;
case PipelineTemplateConstants.Name:
break;
case PipelineTemplateConstants.Env:
result.EnvironmentVariables = pipelinePair.Value;
break;
case PipelineTemplateConstants.Jobs:
defaultStage.Phases.AddRange(ConvertToJobFactories(context, result.Resources, pipelinePair.Value));
break;
default:
pipelineKey.AssertUnexpectedValue("root key"); // throws
break;
}
}
}
catch (Exception ex)
{
context.Errors.Add(ex);
}
finally
{
if (context.Errors.Count > 0)
{
foreach (var error in context.Errors)
{
result.Errors.Add(new PipelineValidationError(error.Code, error.Message));
}
}
}
return result;
}
internal static String ConvertToJobDisplayName(
TemplateContext context,
TemplateToken displayName,
Boolean allowExpressions = false)
{
var result = default(String);
// Expression
if (allowExpressions && displayName is ExpressionToken)
{
return result;
}
// String
var displayNameString = displayName.AssertString($"job {PipelineTemplateConstants.Name}");
result = displayNameString.Value;
return result;
}
internal static PhaseTarget ConvertToJobTarget(
TemplateContext context,
TemplateToken runsOn,
Boolean allowExpressions = false)
{
var result = new AgentPoolTarget();
// Expression
if (allowExpressions && runsOn is ExpressionToken)
{
return result;
}
// String
if (runsOn is StringToken runsOnString)
{
result.Pool = new AgentPoolReference { Name = "GitHub Actions" };
result.AgentSpecification = new JObject
{
{ PipelineTemplateConstants.VmImage, runsOnString.Value }
};
}
// Mapping
else
{
var runsOnMapping = runsOn.AssertMapping($"job {PipelineTemplateConstants.RunsOn}");
foreach (var runsOnProperty in runsOnMapping)
{
// Expression
if (allowExpressions && runsOnProperty.Key is ExpressionToken)
{
continue;
}
// String
var propertyName = runsOnProperty.Key.AssertString($"job {PipelineTemplateConstants.RunsOn} key");
switch (propertyName.Value)
{
case PipelineTemplateConstants.Pool:
// Expression
if (allowExpressions && runsOnProperty.Value is ExpressionToken)
{
continue;
}
// Literal
var pool = runsOnProperty.Value.AssertString($"job {PipelineTemplateConstants.RunsOn} key");
result.Pool = new AgentPoolReference { Name = pool.Value };
break;
default:
propertyName.AssertUnexpectedValue($"job {PipelineTemplateConstants.RunsOn} key"); // throws
break;
}
}
}
return result;
}
internal static Int32? ConvertToJobTimeout(
TemplateContext context,
TemplateToken token,
Boolean allowExpressions = false)
{
if (allowExpressions && token is ExpressionToken)
{
return null;
}
var numberToken = token.AssertNumber($"job {PipelineTemplateConstants.TimeoutMinutes}");
return (Int32)numberToken.Value;
}
internal static Int32? ConvertToJobCancelTimeout(
TemplateContext context,
TemplateToken token,
Boolean allowExpressions = false)
{
if (allowExpressions && token is ExpressionToken)
{
return null;
}
var numberToken = token.AssertNumber($"job {PipelineTemplateConstants.CancelTimeoutMinutes}");
return (Int32)numberToken.Value;
}
internal static Boolean? ConvertToStepContinueOnError(
TemplateContext context,
TemplateToken token,
@@ -315,203 +141,6 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating
return (Int32)numberToken.Value;
}
internal static StrategyResult ConvertToStrategy(
TemplateContext context,
TemplateToken token,
String jobFactoryDisplayName,
Boolean allowExpressions = false)
{
var result = new StrategyResult();
// Expression
if (allowExpressions && token is ExpressionToken)
{
return result;
}
var strategyMapping = token.AssertMapping(PipelineTemplateConstants.Strategy);
var matrixBuilder = default(MatrixBuilder);
var hasExpressions = false;
foreach (var strategyPair in strategyMapping)
{
// Expression key
if (allowExpressions && strategyPair.Key is ExpressionToken)
{
hasExpressions = true;
continue;
}
// Literal key
var strategyKey = strategyPair.Key.AssertString("strategy key");
switch (strategyKey.Value)
{
// Fail-Fast
case PipelineTemplateConstants.FailFast:
if (allowExpressions && strategyPair.Value is ExpressionToken)
{
hasExpressions = true;
continue;
}
var failFastBooleanToken = strategyPair.Value.AssertBoolean($"strategy {PipelineTemplateConstants.FailFast}");
result.FailFast = failFastBooleanToken.Value;
break;
// Max-Parallel
case PipelineTemplateConstants.MaxParallel:
if (allowExpressions && strategyPair.Value is ExpressionToken)
{
hasExpressions = true;
continue;
}
var maxParallelNumberToken = strategyPair.Value.AssertNumber($"strategy {PipelineTemplateConstants.MaxParallel}");
result.MaxParallel = (Int32)maxParallelNumberToken.Value;
break;
// Matrix
case PipelineTemplateConstants.Matrix:
// Expression
if (allowExpressions && strategyPair.Value is ExpressionToken)
{
hasExpressions = true;
continue;
}
var matrix = strategyPair.Value.AssertMapping("matrix");
hasExpressions = hasExpressions || matrix.Traverse().Any(x => x is ExpressionToken);
matrixBuilder = new MatrixBuilder(context, jobFactoryDisplayName);
var hasVector = false;
foreach (var matrixPair in matrix)
{
// Expression key
if (allowExpressions && matrixPair.Key is ExpressionToken)
{
hasVector = true; // For validation, treat as if a vector is defined
continue;
}
var matrixKey = matrixPair.Key.AssertString("matrix key");
switch (matrixKey.Value)
{
case PipelineTemplateConstants.Include:
if (allowExpressions && matrixPair.Value is ExpressionToken)
{
continue;
}
var includeSequence = matrixPair.Value.AssertSequence("matrix includes");
matrixBuilder.Include(includeSequence);
break;
case PipelineTemplateConstants.Exclude:
if (allowExpressions && matrixPair.Value is ExpressionToken)
{
continue;
}
var excludeSequence = matrixPair.Value.AssertSequence("matrix excludes");
matrixBuilder.Exclude(excludeSequence);
break;
default:
hasVector = true;
if (allowExpressions && matrixPair.Value is ExpressionToken)
{
continue;
}
var vectorName = matrixKey.Value;
var vectorSequence = matrixPair.Value.AssertSequence("matrix vector value");
if (vectorSequence.Count == 0)
{
context.Error(vectorSequence, $"Matrix vector '{vectorName}' does not contain any values");
}
else
{
matrixBuilder.AddVector(vectorName, vectorSequence);
}
break;
}
}
if (!hasVector)
{
context.Error(matrix, $"Matrix must defined at least one vector");
}
break;
default:
strategyKey.AssertUnexpectedValue("strategy key"); // throws
break;
}
}
if (hasExpressions)
{
return result;
}
if (matrixBuilder != null)
{
result.Configurations.AddRange(matrixBuilder.Build());
}
for (var i = 0; i < result.Configurations.Count; i++)
{
var configuration = result.Configurations[i];
var strategy = new DictionaryContextData()
{
{
"fail-fast",
new BooleanContextData(result.FailFast)
},
{
"job-index",
new NumberContextData(i)
},
{
"job-total",
new NumberContextData(result.Configurations.Count)
}
};
if (result.MaxParallel > 0)
{
strategy.Add(
"max-parallel",
new NumberContextData(result.MaxParallel)
);
}
else
{
strategy.Add(
"max-parallel",
new NumberContextData(result.Configurations.Count)
);
}
configuration.ContextData.Add(PipelineTemplateConstants.Strategy, strategy);
context.Memory.AddBytes(PipelineTemplateConstants.Strategy);
context.Memory.AddBytes(strategy, traverse: true);
if (!configuration.ContextData.ContainsKey(PipelineTemplateConstants.Matrix))
{
configuration.ContextData.Add(PipelineTemplateConstants.Matrix, null);
context.Memory.AddBytes(PipelineTemplateConstants.Matrix);
}
}
return result;
}
internal static JobContainer ConvertToJobContainer(
TemplateContext context,
TemplateToken value,
@@ -616,532 +245,5 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating
return result;
}
private static IEnumerable<PhaseNode> ConvertToJobFactories(
TemplateContext context,
PipelineResources resources,
TemplateToken workflow)
{
var jobsMapping = workflow.AssertMapping(PipelineTemplateConstants.Jobs);
foreach (var jobsPair in jobsMapping)
{
var jobNameToken = jobsPair.Key.AssertString($"{PipelineTemplateConstants.Jobs} key");
if (!NameValidation.IsValid(jobNameToken.Value, true))
{
context.Error(jobNameToken, $"Job name {jobNameToken.Value} is invalid. Names must start with a letter or '_' and contain only alphanumeric characters, '-', or '_'");
}
var result = new JobFactory
{
Name = jobNameToken.Value
};
var jobFactoryDefinition = jobsPair.Value.AssertMapping($"{PipelineTemplateConstants.Jobs} value");
foreach (var jobFactoryProperty in jobFactoryDefinition)
{
var propertyName = jobFactoryProperty.Key.AssertString($"job property name");
switch (propertyName.Value)
{
case PipelineTemplateConstants.ContinueOnError:
var continueOnErrorBooleanToken = jobFactoryProperty.Value.AssertBoolean($"job {PipelineTemplateConstants.ContinueOnError}");
result.ContinueOnError = continueOnErrorBooleanToken.Value;
break;
case PipelineTemplateConstants.If:
var ifCondition = jobFactoryProperty.Value.AssertString($"job {PipelineTemplateConstants.If}");
result.Condition = ConvertToIfCondition(context, ifCondition, true, true);
break;
case PipelineTemplateConstants.Name:
var displayName = jobFactoryProperty.Value.AssertScalar($"job {PipelineTemplateConstants.Name}");
ConvertToJobDisplayName(context, displayName, allowExpressions: true); // Validate early if possible
if (displayName is StringToken)
{
result.DisplayName = displayName.ToString();
}
else
{
result.JobDisplayName = displayName.Clone(true) as ExpressionToken;
}
break;
case PipelineTemplateConstants.Needs:
if (jobFactoryProperty.Value is StringToken needsLiteral)
{
result.DependsOn.Add(needsLiteral.Value);
}
else
{
var needs = jobFactoryProperty.Value.AssertSequence($"job {PipelineTemplateConstants.Needs}");
foreach (var needsItem in needs)
{
var need = needsItem.AssertString($"job {PipelineTemplateConstants.Needs} item");
result.DependsOn.Add(need.Value);
}
}
break;
case PipelineTemplateConstants.RunsOn:
ConvertToJobTarget(context, jobFactoryProperty.Value, allowExpressions: true); // Validate early if possible
result.JobTarget = jobFactoryProperty.Value.Clone(true);
break;
case PipelineTemplateConstants.Scopes:
foreach (var scope in ConvertToScopes(context, jobFactoryProperty.Value))
{
result.Scopes.Add(scope);
}
break;
case PipelineTemplateConstants.Steps:
result.Steps.AddRange(ConvertToSteps(context, jobFactoryProperty.Value));
break;
case PipelineTemplateConstants.Strategy:
ConvertToStrategy(context, jobFactoryProperty.Value, null, allowExpressions: true); // Validate early if possible
result.Strategy = jobFactoryProperty.Value.Clone(true);
break;
case PipelineTemplateConstants.TimeoutMinutes:
ConvertToJobTimeout(context, jobFactoryProperty.Value, allowExpressions: true); // Validate early if possible
result.JobTimeout = jobFactoryProperty.Value.Clone(true) as ScalarToken;
break;
case PipelineTemplateConstants.CancelTimeoutMinutes:
ConvertToJobCancelTimeout(context, jobFactoryProperty.Value, allowExpressions: true); // Validate early if possible
result.JobCancelTimeout = jobFactoryProperty.Value.Clone(true) as ScalarToken;
break;
case PipelineTemplateConstants.Container:
ConvertToJobContainer(context, jobFactoryProperty.Value, allowExpressions: true);
result.JobContainer = jobFactoryProperty.Value.Clone(true);
break;
case PipelineTemplateConstants.Services:
ConvertToJobServiceContainers(context, jobFactoryProperty.Value, allowExpressions: true);
result.JobServiceContainers = jobFactoryProperty.Value.Clone(true);
break;
case PipelineTemplateConstants.Env:
result.EnvironmentVariables = jobFactoryProperty.Value.Clone(true);
break;
default:
propertyName.AssertUnexpectedValue("job key"); // throws
break;
}
}
// todo: Move "required" support into schema validation
if (result.JobTarget == null)
{
context.Error(jobFactoryDefinition, $"The '{PipelineTemplateConstants.RunsOn}' property is required");
}
if (String.IsNullOrEmpty(result.DisplayName))
{
result.DisplayName = result.Name;
}
if (result.Scopes.Count > 0)
{
result.Steps.Insert(
0,
new ActionStep
{
Reference = new ScriptReference(),
DisplayName = "WARNING: TEMPLATES ARE HIGHLY EXPERIMENTAL",
Inputs = new MappingToken(null, null, null)
{
{
new StringToken(null, null, null, PipelineConstants.ScriptStepInputs.Script),
new StringToken(null, null, null, "echo WARNING: TEMPLATES ARE HIGHLY EXPERIMENTAL")
}
}
});
result.Steps.Add(
new ActionStep
{
Reference = new ScriptReference(),
DisplayName = "WARNING: TEMPLATES ARE HIGHLY EXPERIMENTAL",
Inputs = new MappingToken(null, null, null)
{
{
new StringToken(null, null, null, PipelineConstants.ScriptStepInputs.Script),
new StringToken(null, null, null, "echo WARNING: TEMPLATES ARE HIGHLY EXPERIMENTAL")
}
}
});
}
yield return result;
}
}
private static IEnumerable<ContextScope> ConvertToScopes(
TemplateContext context,
TemplateToken scopes)
{
var scopesSequence = scopes.AssertSequence($"job {PipelineTemplateConstants.Scopes}");
foreach (var scopesItem in scopesSequence)
{
var result = new ContextScope();
var scope = scopesItem.AssertMapping($"{PipelineTemplateConstants.Scopes} item");
foreach (var scopeProperty in scope)
{
var propertyName = scopeProperty.Key.AssertString($"{PipelineTemplateConstants.Scopes} item key");
switch (propertyName.Value)
{
case PipelineTemplateConstants.Name:
var nameLiteral = scopeProperty.Value.AssertString($"{PipelineTemplateConstants.Scopes} item {PipelineTemplateConstants.Name}");
result.Name = nameLiteral.Value;
break;
case PipelineTemplateConstants.Inputs:
result.Inputs = scopeProperty.Value.AssertMapping($"{PipelineTemplateConstants.Scopes} item {PipelineTemplateConstants.Inputs}");
break;
case PipelineTemplateConstants.Outputs:
result.Outputs = scopeProperty.Value.AssertMapping($"{PipelineTemplateConstants.Scopes} item {PipelineTemplateConstants.Outputs}");
break;
}
}
yield return result;
}
}
private static List<Step> ConvertToSteps(
TemplateContext context,
TemplateToken steps)
{
var stepsSequence = steps.AssertSequence($"job {PipelineTemplateConstants.Steps}");
var result = new List<Step>();
foreach (var stepsItem in stepsSequence)
{
var step = ConvertToStep(context, stepsItem);
if (step != null) // step = null means we are hitting error during step conversion, there should be an error in context.errors
{
if (step.Enabled)
{
result.Add(step);
}
}
}
return result;
}
private static ActionStep ConvertToStep(
TemplateContext context,
TemplateToken stepsItem)
{
var step = stepsItem.AssertMapping($"{PipelineTemplateConstants.Steps} item");
var continueOnError = default(ScalarToken);
var env = default(TemplateToken);
var id = default(StringToken);
var ifCondition = default(String);
var ifToken = default(StringToken);
var name = default(ScalarToken);
var run = default(ScalarToken);
var scope = default(StringToken);
var timeoutMinutes = default(ScalarToken);
var uses = default(StringToken);
var with = default(TemplateToken);
var workingDir = default(ScalarToken);
var path = default(ScalarToken);
var clean = default(ScalarToken);
var fetchDepth = default(ScalarToken);
var lfs = default(ScalarToken);
var submodules = default(ScalarToken);
var shell = default(ScalarToken);
foreach (var stepProperty in step)
{
var propertyName = stepProperty.Key.AssertString($"{PipelineTemplateConstants.Steps} item key");
switch (propertyName.Value)
{
case PipelineTemplateConstants.Clean:
clean = stepProperty.Value.AssertScalar($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Clean}");
break;
case PipelineTemplateConstants.ContinueOnError:
ConvertToStepContinueOnError(context, stepProperty.Value, allowExpressions: true); // Validate early if possible
continueOnError = stepProperty.Value.AssertScalar($"{PipelineTemplateConstants.Steps} {PipelineTemplateConstants.ContinueOnError}");
break;
case PipelineTemplateConstants.Env:
ConvertToStepEnvironment(context, stepProperty.Value, StringComparer.Ordinal, allowExpressions: true); // Validate early if possible
env = stepProperty.Value;
break;
case PipelineTemplateConstants.FetchDepth:
fetchDepth = stepProperty.Value.AssertScalar($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.FetchDepth}");
break;
case PipelineTemplateConstants.Id:
id = stepProperty.Value.AssertString($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Id}");
if (!NameValidation.IsValid(id.Value, true))
{
context.Error(id, $"Step id {id.Value} is invalid. Ids must start with a letter or '_' and contain only alphanumeric characters, '-', or '_'");
}
break;
case PipelineTemplateConstants.If:
ifToken = stepProperty.Value.AssertString($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.If}");
break;
case PipelineTemplateConstants.Lfs:
lfs = stepProperty.Value.AssertScalar($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Lfs}");
break;
case PipelineTemplateConstants.Name:
name = stepProperty.Value.AssertScalar($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Name}");
break;
case PipelineTemplateConstants.Path:
path = stepProperty.Value.AssertScalar($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Path}");
break;
case PipelineTemplateConstants.Run:
run = stepProperty.Value.AssertScalar($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Run}");
break;
case PipelineTemplateConstants.Shell:
shell = stepProperty.Value.AssertScalar($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Shell}");
break;
case PipelineTemplateConstants.Scope:
scope = stepProperty.Value.AssertString($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Scope}");
break;
case PipelineTemplateConstants.Submodules:
submodules = stepProperty.Value.AssertScalar($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Submodules}");
break;
case PipelineTemplateConstants.TimeoutMinutes:
ConvertToStepTimeout(context, stepProperty.Value, allowExpressions: true); // Validate early if possible
timeoutMinutes = stepProperty.Value.AssertScalar($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.TimeoutMinutes}");
break;
case PipelineTemplateConstants.Uses:
uses = stepProperty.Value.AssertString($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Uses}");
break;
case PipelineTemplateConstants.With:
ConvertToStepInputs(context, stepProperty.Value, allowExpressions: true); // Validate early if possible
with = stepProperty.Value;
break;
case PipelineTemplateConstants.WorkingDirectory:
workingDir = stepProperty.Value.AssertScalar($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.WorkingDirectory}");
break;
default:
propertyName.AssertUnexpectedValue($"{PipelineTemplateConstants.Steps} item key"); // throws
break;
}
}
// Fixup the if-condition
var isDefaultScope = String.IsNullOrEmpty(scope?.Value);
ifCondition = ConvertToIfCondition(context, ifToken, false, isDefaultScope);
if (run != null)
{
var result = new ActionStep
{
ScopeName = scope?.Value,
ContextName = id?.Value,
ContinueOnError = continueOnError?.Clone(true) as ScalarToken,
DisplayNameToken = name?.Clone(true) as ScalarToken,
Condition = ifCondition,
TimeoutInMinutes = timeoutMinutes?.Clone(true) as ScalarToken,
Environment = env?.Clone(true),
Reference = new ScriptReference(),
};
var inputs = new MappingToken(null, null, null);
inputs.Add(new StringToken(null, null, null, PipelineConstants.ScriptStepInputs.Script), run.Clone(true));
if (workingDir != null)
{
inputs.Add(new StringToken(null, null, null, PipelineConstants.ScriptStepInputs.WorkingDirectory), workingDir.Clone(true));
}
if (shell != null)
{
inputs.Add(new StringToken(null, null, null, PipelineConstants.ScriptStepInputs.Shell), shell.Clone(true));
}
result.Inputs = inputs;
return result;
}
else if (uses != null)
{
var result = new ActionStep
{
ScopeName = scope?.Value,
ContextName = id?.Value,
ContinueOnError = continueOnError?.Clone(true) as ScalarToken,
DisplayNameToken = name?.Clone(true) as ScalarToken,
Condition = ifCondition,
TimeoutInMinutes = timeoutMinutes?.Clone(true) as ScalarToken,
Inputs = with,
Environment = env,
};
if (uses.Value.StartsWith("docker://", StringComparison.Ordinal))
{
var image = uses.Value.Substring("docker://".Length);
result.Reference = new ContainerRegistryReference { Image = image };
}
else if (uses.Value.StartsWith("./") || uses.Value.StartsWith(".\\"))
{
result.Reference = new RepositoryPathReference
{
RepositoryType = PipelineConstants.SelfAlias,
Path = uses.Value
};
}
else
{
var usesSegments = uses.Value.Split('@');
var pathSegments = usesSegments[0].Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
var gitRef = usesSegments.Length == 2 ? usesSegments[1] : String.Empty;
if (usesSegments.Length != 2 ||
pathSegments.Length < 2 ||
String.IsNullOrEmpty(pathSegments[0]) ||
String.IsNullOrEmpty(pathSegments[1]) ||
String.IsNullOrEmpty(gitRef))
{
// todo: loc
context.Error(uses, $"Expected format {{org}}/{{repo}}[/path]@ref. Actual '{uses.Value}'");
}
else
{
var repositoryName = $"{pathSegments[0]}/{pathSegments[1]}";
var directoryPath = pathSegments.Length > 2 ? String.Join("/", pathSegments.Skip(2)) : String.Empty;
result.Reference = new RepositoryPathReference
{
RepositoryType = RepositoryTypes.GitHub,
Name = repositoryName,
Ref = gitRef,
Path = directoryPath,
};
}
}
return result;
}
else
{
// todo: build a "required" concept into the parser
context.Error(step, $"Either '{PipelineTemplateConstants.Uses}' or '{PipelineTemplateConstants.Run}' is required");
return null;
}
}
private static String ConvertToIfCondition(
TemplateContext context,
StringToken ifCondition,
Boolean isJob,
Boolean isDefaultScope)
{
if (String.IsNullOrWhiteSpace(ifCondition?.Value))
{
return $"{PipelineTemplateConstants.Success}()";
}
var condition = ifCondition.Value;
var expressionParser = new ExpressionParser();
var functions = default(IFunctionInfo[]);
var namedValues = default(INamedValueInfo[]);
if (isJob)
{
namedValues = s_jobIfNamedValues;
functions = PhaseCondition.FunctionInfo;
}
else
{
namedValues = isDefaultScope ? s_stepNamedValues : s_stepInTemplateNamedValues;
functions = s_stepConditionFunctions;
}
var node = default(ExpressionNode);
try
{
node = expressionParser.CreateTree(condition, null, namedValues, functions) as ExpressionNode;
}
catch (Exception ex)
{
context.Error(ifCondition, ex);
return null;
}
if (node == null)
{
return $"{PipelineTemplateConstants.Success}()";
}
var hasStatusFunction = node.Traverse().Any(x =>
{
if (x is Function function)
{
return String.Equals(function.Name, PipelineTemplateConstants.Always, StringComparison.OrdinalIgnoreCase) ||
String.Equals(function.Name, PipelineTemplateConstants.Cancelled, StringComparison.OrdinalIgnoreCase) ||
String.Equals(function.Name, PipelineTemplateConstants.Failure, StringComparison.OrdinalIgnoreCase) ||
String.Equals(function.Name, PipelineTemplateConstants.Success, StringComparison.OrdinalIgnoreCase);
}
return false;
});
return hasStatusFunction ? condition : $"{PipelineTemplateConstants.Success}() && ({condition})";
}
private static readonly INamedValueInfo[] s_jobIfNamedValues = new INamedValueInfo[]
{
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.GitHub),
};
private static readonly INamedValueInfo[] s_stepNamedValues = new INamedValueInfo[]
{
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Strategy),
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Matrix),
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Steps),
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.GitHub),
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Job),
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Runner),
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Env),
};
private static readonly INamedValueInfo[] s_stepInTemplateNamedValues = new INamedValueInfo[]
{
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Strategy),
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Matrix),
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Steps),
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Inputs),
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.GitHub),
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Job),
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Runner),
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Env),
};
private static readonly IFunctionInfo[] s_stepConditionFunctions = new IFunctionInfo[]
{
new FunctionInfo<NoOperation>(PipelineTemplateConstants.Always, 0, 0),
new FunctionInfo<NoOperation>(PipelineTemplateConstants.Cancelled, 0, 0),
new FunctionInfo<NoOperation>(PipelineTemplateConstants.Failure, 0, 0),
new FunctionInfo<NoOperation>(PipelineTemplateConstants.Success, 0, 0),
};
}
}