예제 #1
0
        public static List <Step> ConvertToSteps(
            TemplateContext context,
            TemplateToken steps)
        {
            var stepsSequence = steps.AssertSequence($"job {PipelineTemplateConstants.Steps}");

            var result      = new List <Step>();
            var nameBuilder = new ReferenceNameBuilder();

            foreach (var stepsItem in stepsSequence)
            {
                var step = ConvertToStep(context, stepsItem, nameBuilder);
                if (step != null) // step = null means we are hitting error during step conversion, there should be an error in context.errors
                {
                    if (step.Enabled)
                    {
                        result.Add(step);
                    }
                }
            }

            // Generate context name if empty
            foreach (ActionStep step in result)
            {
                if (!String.IsNullOrEmpty(step.ContextName))
                {
                    continue;
                }

                var name = default(string);
                switch (step.Reference.Type)
                {
                case ActionSourceType.ContainerRegistry:
                    var containerReference = step.Reference as ContainerRegistryReference;
                    name = containerReference.Image;
                    break;

                case ActionSourceType.Repository:
                    var repositoryReference = step.Reference as RepositoryPathReference;
                    name = !String.IsNullOrEmpty(repositoryReference.Name) ? repositoryReference.Name : PipelineConstants.SelfAlias;
                    break;
                }

                if (String.IsNullOrEmpty(name))
                {
                    name = "run";
                }

                nameBuilder.AppendSegment($"__{name}");
                step.ContextName = nameBuilder.Build();
            }

            return(result);
        }
예제 #2
0
        private static ActionStep ConvertToStep(
            TemplateContext context,
            TemplateToken stepsItem,
            ReferenceNameBuilder nameBuilder)
        {
            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(ScalarToken);
            var name           = default(ScalarToken);
            var run            = default(ScalarToken);
            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 (!String.IsNullOrEmpty(id.Value))
                    {
                        if (!nameBuilder.TryAddKnownName(id.Value, out var error))
                        {
                            context.Error(id, error);
                        }
                    }
                    break;

                case PipelineTemplateConstants.If:
                    ifToken = stepProperty.Value.AssertScalar($"{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.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
            ifCondition = ConvertToIfCondition(context, ifToken, false);

            if (run != null)
            {
                var result = new ActionStep
                {
                    ContextName      = id?.Value,
                    ContinueOnError  = continueOnError,
                    DisplayNameToken = name,
                    Condition        = ifCondition,
                    TimeoutInMinutes = timeoutMinutes,
                    Environment      = env,
                    Reference        = new ScriptReference(),
                };

                var inputs = new MappingToken(null, null, null);
                inputs.Add(new StringToken(null, null, null, PipelineConstants.ScriptStepInputs.Script), run);

                if (workingDir != null)
                {
                    inputs.Add(new StringToken(null, null, null, PipelineConstants.ScriptStepInputs.WorkingDirectory), workingDir);
                }

                if (shell != null)
                {
                    inputs.Add(new StringToken(null, null, null, PipelineConstants.ScriptStepInputs.Shell), shell);
                }

                result.Inputs = inputs;

                return(result);
            }
            else
            {
                uses.AssertString($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Uses}");
                var result = new ActionStep
                {
                    ContextName      = id?.Value,
                    ContinueOnError  = continueOnError,
                    DisplayNameToken = name,
                    Condition        = ifCondition,
                    TimeoutInMinutes = timeoutMinutes,
                    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);
            }
        }