示例#1
0
        public void InitializeJob_LogsWarningsFromVariables()
        {
            using (TestHostContext hc = CreateTestContext())
            {
                // Arrange: Create a job request message.
                TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
                TimelineReference timeline          = new TimelineReference();
                JobEnvironment    environment       = new JobEnvironment();
                environment.SystemConnection = new ServiceEndpoint();
                environment.Variables["v1"]  = "v1-$(v2)";
                environment.Variables["v2"]  = "v2-$(v1)";
                List <TaskInstance> tasks = new List <TaskInstance>();
                Guid   JobId      = Guid.NewGuid();
                string jobName    = "some job name";
                var    jobRequest = new AgentJobRequestMessage(plan, timeline, JobId, jobName, environment, tasks);

                // Arrange: Setup the paging logger.
                var pagingLogger = new Mock <IPagingLogger>();
                hc.EnqueueInstance(pagingLogger.Object);

                var ec = new Agent.Worker.ExecutionContext();
                ec.Initialize(hc);

                // Act.
                ec.InitializeJob(jobRequest, CancellationToken.None);

                // Assert.
                pagingLogger.Verify(x => x.Write(It.Is <string>(y => y.IndexOf("##[warning]") >= 0)), Times.Exactly(2));
            }
        }
示例#2
0
        public void InitializeJob_should_set_JobSettings()
        {
            using (TestHostContext hc = CreateTestContext())
                using (var ec = new Agent.Worker.ExecutionContext())
                {
                    // Arrange: Create a job request message.
                    TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
                    TimelineReference timeline          = new TimelineReference();
                    JobEnvironment    environment       = new JobEnvironment();
                    environment.SystemConnection = new ServiceEndpoint();
                    List <TaskInstance> tasks = new List <TaskInstance>();
                    Guid   JobId      = Guid.NewGuid();
                    string jobName    = "some job name";
                    var    jobRequest = Pipelines.AgentJobRequestMessageUtil.Convert(new AgentJobRequestMessage(plan, timeline, JobId, jobName, jobName, environment, tasks));

                    // Arrange: Setup the paging logger.
                    var pagingLogger = new Mock <IPagingLogger>();
                    hc.EnqueueInstance(pagingLogger.Object);

                    ec.Initialize(hc);

                    // Act.
                    ec.InitializeJob(jobRequest, CancellationToken.None);

                    // Assert.
                    Assert.NotNull(ec.JobSettings);
                    Assert.Equal(Boolean.FalseString, ec.JobSettings[WellKnownJobSettings.HasMultipleCheckouts]);
                }
        }
示例#3
0
        /// <summary>
        /// Job request message sent to the runner
        /// </summary>
        /// <param name="environmentVariables">Hierarchy of environment variables to overlay, last wins.</param>
        public AgentJobRequestMessage(
            TaskOrchestrationPlanReference plan,
            TimelineReference timeline,
            Guid jobId,
            String jobDisplayName,
            String jobName,
            TemplateToken jobContainer,
            TemplateToken jobServiceContainers,
            IList <TemplateToken> environmentVariables,
            IDictionary <String, VariableValue> variables,
            IList <MaskHint> maskHints,
            JobResources jobResources,
            DictionaryContextData contextData,
            WorkspaceOptions workspaceOptions,
            IEnumerable <JobStep> steps,
            IList <String> fileTable,
            TemplateToken jobOutputs,
            IList <TemplateToken> defaults,
            ActionsEnvironmentReference actionsEnvironment)
        {
            this.MessageType          = JobRequestMessageTypes.PipelineAgentJobRequest;
            this.Plan                 = plan;
            this.JobId                = jobId;
            this.JobDisplayName       = jobDisplayName;
            this.JobName              = jobName;
            this.JobContainer         = jobContainer;
            this.JobServiceContainers = jobServiceContainers;
            this.Timeline             = timeline;
            this.Resources            = jobResources;
            this.Workspace            = workspaceOptions;
            this.JobOutputs           = jobOutputs;
            this.ActionsEnvironment   = actionsEnvironment;
            m_variables               = new Dictionary <String, VariableValue>(variables, StringComparer.OrdinalIgnoreCase);
            m_maskHints               = new List <MaskHint>(maskHints);
            m_steps = new List <JobStep>(steps);

            if (environmentVariables?.Count > 0)
            {
                m_environmentVariables = new List <TemplateToken>(environmentVariables);
            }

            if (defaults?.Count > 0)
            {
                m_defaults = new List <TemplateToken>(defaults);
            }

            this.ContextData = new Dictionary <String, PipelineContextData>(StringComparer.OrdinalIgnoreCase);
            if (contextData?.Count > 0)
            {
                foreach (var pair in contextData)
                {
                    this.ContextData[pair.Key] = pair.Value;
                }
            }

            if (fileTable?.Count > 0)
            {
                m_fileTable = new List <String>(fileTable);
            }
        }
示例#4
0
        /// <summary>
        /// Does a depth-first traversal, resolving all referenced sub-documents. Does not traverse
        /// any node twice. This effectively treats a directed graph as a tree.</summary>
        /// <param name="root">Root timeline</param>
        /// <param name="resolved">Resolved hash set to add to</param>
        private void ResolveAll(IHierarchicalTimeline root, HashSet <IHierarchicalTimeline> resolved)
        {
            resolved.Add(root);
            foreach (ITimelineReference refInterface in root.References)
            {
                TimelineReference reference = (TimelineReference)refInterface;
                //reference.Resolve();

                IDocument referencedDocument = null;
                Uri       refUri             = reference.Uri;
                if (refUri != null)
                {
                    referencedDocument = LoadOrCreateDocument(refUri, false); //this is not a master document
                }
                if (referencedDocument != null)
                {
                    // Switch from a possible relative path to an absolute path
                    reference.Uri = referencedDocument.Uri;

                    IHierarchicalTimeline child = reference.Target;
                    if (child != null &&
                        !resolved.Contains(child))
                    {
                        ResolveAll(child, resolved);
                    }
                }
            }
        }
示例#5
0
        private Pipelines.AgentJobRequestMessage CreateJobRequestMessage(string jobName)
        {
            TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference()
            {
                PlanId = Guid.NewGuid()
            };
            TimelineReference timeline = null;
            Dictionary <string, VariableValue> variables = new Dictionary <string, VariableValue>(StringComparer.OrdinalIgnoreCase);

            variables[Constants.Variables.System.Culture] = "en-US";
            Pipelines.JobResources resources = new Pipelines.JobResources();
            var serviceEndpoint = new ServiceEndpoint();

            serviceEndpoint.Authorization = new EndpointAuthorization();
            serviceEndpoint.Authorization.Parameters.Add("nullValue", null);
            resources.Endpoints.Add(serviceEndpoint);

            List <Pipelines.JobStep> tasks = new List <Pipelines.JobStep>();

            tasks.Add(new Pipelines.TaskStep()
            {
                Id        = Guid.NewGuid(),
                Reference = new Pipelines.TaskStepDefinitionReference()
                {
                    Id      = Guid.NewGuid(),
                    Name    = "TestTask",
                    Version = "1.0.0"
                }
            });
            Guid JobId      = Guid.NewGuid();
            var  jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, JobId, jobName, jobName, "ubuntu", variables, new List <MaskHint>(), resources, tasks);

            return(jobRequest);
        }
示例#6
0
        private Pipelines.AgentJobRequestMessage CreateJobRequestMessage(string jobName)
        {
            TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
            TimelineReference timeline          = null;
            Guid jobId = Guid.NewGuid();

            return(new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "test", "test", null, null, null, new Dictionary <string, VariableValue>(), new List <MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List <Pipelines.ActionStep>(), null, null, null, null));
        }
示例#7
0
        public void InitializeJob_should_mark_primary_repository_in_multicheckout()
        {
            // Note: the primary repository is defined as the first repository that is checked out in the job
            using (TestHostContext hc = CreateTestContext())
                using (var ec = new Agent.Worker.ExecutionContext())
                {
                    // Arrange: Create a job request message.
                    TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
                    TimelineReference timeline          = new TimelineReference();
                    JobEnvironment    environment       = new JobEnvironment();
                    environment.SystemConnection = new ServiceEndpoint();
                    List <TaskInstance> tasks = new List <TaskInstance>();
                    tasks.Add(new TaskInstance()
                    {
                        Id = Pipelines.PipelineConstants.CheckoutTask.Id, Version = Pipelines.PipelineConstants.CheckoutTask.Version, Inputs = { { Pipelines.PipelineConstants.CheckoutTaskInputs.Repository, "repo2" } }
                    });
                    tasks.Add(new TaskInstance()
                    {
                        Id = Pipelines.PipelineConstants.CheckoutTask.Id, Version = Pipelines.PipelineConstants.CheckoutTask.Version, Inputs = { { Pipelines.PipelineConstants.CheckoutTaskInputs.Repository, "repo3" } }
                    });
                    Guid   JobId      = Guid.NewGuid();
                    string jobName    = "some job name";
                    var    jobRequest = Pipelines.AgentJobRequestMessageUtil.Convert(new AgentJobRequestMessage(plan, timeline, JobId, jobName, jobName, environment, tasks));
                    var    repo1      = new Pipelines.RepositoryResource()
                    {
                        Alias = "self"
                    };
                    var repo2 = new Pipelines.RepositoryResource()
                    {
                        Alias = "repo2"
                    };
                    var repo3 = new Pipelines.RepositoryResource()
                    {
                        Alias = "repo3"
                    };
                    jobRequest.Resources.Repositories.Add(repo1);
                    jobRequest.Resources.Repositories.Add(repo2);
                    jobRequest.Resources.Repositories.Add(repo3);

                    // Arrange: Setup the paging logger.
                    var pagingLogger = new Mock <IPagingLogger>();
                    hc.EnqueueInstance(pagingLogger.Object);


                    ec.Initialize(hc);

                    // Act.
                    ec.InitializeJob(jobRequest, CancellationToken.None);

                    // Assert.
                    Assert.NotNull(ec.JobSettings);
                    Assert.Equal(Boolean.TrueString, ec.JobSettings[WellKnownJobSettings.HasMultipleCheckouts]);
                    Assert.Equal("repo2", ec.JobSettings[WellKnownJobSettings.FirstRepositoryCheckedOut]);
                    Assert.Equal(Boolean.FalseString, repo1.Properties.Get <string>(RepositoryUtil.IsPrimaryRepository, Boolean.FalseString));
                    Assert.Equal(Boolean.TrueString, repo2.Properties.Get <string>(RepositoryUtil.IsPrimaryRepository, Boolean.FalseString));
                    Assert.Equal(Boolean.FalseString, repo3.Properties.Get <string>(RepositoryUtil.IsPrimaryRepository, Boolean.FalseString));
                }
        }
示例#8
0
        public void TranslatePathForStepTarget_should_convert_path_only_for_containers(bool isCheckout, string jobTarget, string stepTarget)
        {
            // Note: the primary repository is defined as the first repository that is checked out in the job
            using (TestHostContext hc = CreateTestContext())
                using (var ec = new Agent.Worker.ExecutionContext())
                {
                    ec.Initialize(hc);

                    // Arrange: Create a container.
                    var pipeContainer = new Pipelines.ContainerResource
                    {
                        Alias = "container"
                    };
                    pipeContainer.Properties.Set <string>("image", "someimage");

                    // Arrange: Create a job request message.
                    TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
                    TimelineReference timeline          = new TimelineReference();
                    JobEnvironment    environment       = new JobEnvironment();
                    environment.SystemConnection = new ServiceEndpoint();
                    List <Pipelines.JobStep> steps = new List <Pipelines.JobStep>();
                    steps.Add(new Pipelines.TaskStep
                    {
                        Target = new Pipelines.StepTarget
                        {
                            Target = stepTarget
                        },
                        Reference = new Pipelines.TaskStepDefinitionReference()
                    });
                    var resources = new Pipelines.JobResources();
                    resources.Containers.Add(pipeContainer);
                    Guid   JobId      = Guid.NewGuid();
                    string jobName    = "some job name";
                    var    jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, JobId, jobName, jobName, jobTarget, new Dictionary <string, string>(),
                                                                             new Dictionary <string, VariableValue>(), new List <MaskHint>(), resources, new Pipelines.WorkspaceOptions(), steps);

                    // Arrange
                    var pagingLogger = new Mock <IPagingLogger>();
                    hc.EnqueueInstance(pagingLogger.Object);

                    // Act.
                    ec.InitializeJob(jobRequest, CancellationToken.None);
                    ec.SetStepTarget(steps[0].Target);
                    ec.Variables.Set(Constants.Variables.Task.SkipTranslatorForCheckout, isCheckout.ToString());

                    string stringBeforeTranslation = hc.GetDirectory(WellKnownDirectory.Work);
                    string stringAfterTranslation  = ec.TranslatePathForStepTarget(stringBeforeTranslation);

                    // Assert.
                    if ((stepTarget == "container") || (isCheckout is false && jobTarget == "container" && stepTarget == null))
                    {
                        string stringContainer = "C:\\__w";
                        if (ec.StepTarget().ExecutionOS != PlatformUtil.OS.Windows)
                        {
                            stringContainer = "/__w";
                        }
                        Assert.Equal(stringContainer, stringAfterTranslation);
                    }
示例#9
0
        private Pipelines.AgentJobRequestMessage CreateJobRequestMessage()
        {
            TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
            TimelineReference   timeline        = null;
            JobEnvironment      environment     = new JobEnvironment();
            List <TaskInstance> tasks           = new List <TaskInstance>();
            Guid JobId      = Guid.NewGuid();
            var  jobRequest = new AgentJobRequestMessage(plan, timeline, JobId, "someJob", "someJob", environment, tasks);

            return(Pipelines.AgentJobRequestMessageUtil.Convert(jobRequest));
        }
示例#10
0
        private Pipelines.AgentJobRequestMessage CreateJobRequestMessage(string jobName)
        {
            TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference()
            {
                PlanId = Guid.NewGuid()
            };
            TimelineReference timeline = null;
            Dictionary <string, VariableValue> variables = new Dictionary <string, VariableValue>(StringComparer.OrdinalIgnoreCase);

            variables[Constants.Variables.System.Culture] = "en-US";
            Pipelines.JobResources resources = new Pipelines.JobResources();
            var serviceEndpoint = new ServiceEndpoint();

            serviceEndpoint.Authorization = new EndpointAuthorization();
            serviceEndpoint.Authorization.Parameters.Add("nullValue", null);
            resources.Endpoints.Add(serviceEndpoint);

            List <Pipelines.ActionStep> actions = new List <Pipelines.ActionStep>();

            actions.Add(new Pipelines.ActionStep()
            {
                Id        = Guid.NewGuid(),
                Reference = new Pipelines.RepositoryPathReference()
                {
                    RepositoryType = "GitHub",
                    Name           = "actions/test",
                    Ref            = "v1"
                }
            });
            Guid JobId             = Guid.NewGuid();
            var  sidecarContainers = new MappingToken(null, null, null)
            {
                {
                    new StringToken(null, null, null, "nginx"),
                    new MappingToken(null, null, null)
                    {
                        {
                            new StringToken(null, null, null, "image"),
                            new StringToken(null, null, null, "nginx")
                        },
                    }
                },
            };
            var context = new Pipelines.ContextData.DictionaryContextData
            {
                {
                    "github",
                    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, null);

            return(jobRequest);
        }
示例#11
0
        private AgentJobRequestMessage CreateJobRequestMessage(string jobName)
        {
            TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
            TimelineReference   timeline        = null;
            JobEnvironment      environment     = new JobEnvironment();
            List <TaskInstance> tasks           = new List <TaskInstance>();
            Guid JobId      = Guid.NewGuid();
            var  jobRequest = new AgentJobRequestMessage(plan, timeline, JobId, jobName, environment, tasks);

            return(jobRequest as AgentJobRequestMessage);
        }
示例#12
0
        public void SidecarContainers_VerifyNotJobContainers()
        {
            using (TestHostContext hc = CreateTestContext())
                using (var ec = new Agent.Worker.ExecutionContext())
                {
                    ec.Initialize(hc);

                    var pipeContainer = new Pipelines.ContainerResource {
                        Alias = "container"
                    };
                    var pipeContainerSidecar = new Pipelines.ContainerResource {
                        Alias = "sidecar"
                    };
                    var pipeContainerExtra = new Pipelines.ContainerResource {
                        Alias = "extra"
                    };
                    pipeContainer.Properties.Set <string>("image", "someimage");
                    pipeContainerSidecar.Properties.Set <string>("image", "someimage");
                    pipeContainerExtra.Properties.Set <string>("image", "someimage");
                    // Arrange: Create a job request message.
                    TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
                    TimelineReference timeline          = new TimelineReference();
                    JobEnvironment    environment       = new JobEnvironment();
                    environment.SystemConnection = new ServiceEndpoint();
                    List <Pipelines.JobStep> steps = new List <Pipelines.JobStep>();
                    steps.Add(new Pipelines.TaskStep
                    {
                        Reference = new Pipelines.TaskStepDefinitionReference()
                    });
                    var resources = new Pipelines.JobResources();
                    resources.Containers.Add(pipeContainer);
                    resources.Containers.Add(pipeContainerSidecar);
                    resources.Containers.Add(pipeContainerExtra);
                    Guid   JobId             = Guid.NewGuid();
                    string jobName           = "some job name";
                    var    sidecarContainers = new Dictionary <string, string>();
                    sidecarContainers.Add("sidecar", "sidecar");
                    var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, JobId, jobName, jobName, null, sidecarContainers,
                                                                          new Dictionary <string, VariableValue>(), new List <MaskHint>(), resources, new Pipelines.WorkspaceOptions(), steps);

                    // Arrange: Setup command manager
                    var pagingLogger = new Mock <IPagingLogger>();
                    hc.EnqueueInstance(pagingLogger.Object);

                    // Act.
                    ec.InitializeJob(jobRequest, CancellationToken.None);

                    // Assert.
                    Assert.Equal(2, ec.Containers.Count());
                    Assert.Equal(1, ec.SidecarContainers.Count());
                    Assert.False(ec.SidecarContainers.First().IsJobContainer);
                }
        }
示例#13
0
        private JobRequestMessage CreateJobRequestMessage(string jobName)
        {
            TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
            TimelineReference timeline          = null;
            JobEnvironment    environment       = new JobEnvironment();

            environment.Variables[Constants.Variables.System.Culture] = "en-US";
            List <TaskInstance> tasks = new List <TaskInstance>();
            Guid JobId      = Guid.NewGuid();
            var  jobRequest = new JobRequestMessage(plan, timeline, JobId, jobName, environment, tasks);

            return(jobRequest);
        }
示例#14
0
        private JobRequestMessage CreateJobRequestMessage()
        {
            TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
            TimelineReference timeline          = new TimelineReference();
            JobEnvironment    environment       = new JobEnvironment();

            environment.SystemConnection = new ServiceEndpoint();
            environment.Variables["v1"]  = "v1";
            List <TaskInstance> tasks = new List <TaskInstance>();
            Guid   JobId   = Guid.NewGuid();
            string jobName = "some job name";

            return(new AgentJobRequestMessage(plan, timeline, JobId, jobName, environment, tasks));
        }
示例#15
0
        public void ActionResult_Lowercase()
        {
            using (TestHostContext hc = CreateTestContext())
            {
                TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
                TimelineReference timeline          = new TimelineReference();
                Guid   jobId      = Guid.NewGuid();
                string jobName    = "some job name";
                var    jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary <string, VariableValue>(), new List <MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List <Pipelines.ActionStep>(), null, null, null, null);
                jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
                {
                    Alias   = Pipelines.PipelineConstants.SelfAlias,
                    Id      = "github",
                    Version = "sha1"
                });
                jobRequest.ContextData["github"]           = new Pipelines.ContextData.DictionaryContextData();
                jobRequest.Variables["ACTIONS_STEP_DEBUG"] = "true";

                // Arrange: Setup the paging logger.
                var pagingLogger1  = new Mock <IPagingLogger>();
                var jobServerQueue = new Mock <IJobServerQueue>();
                hc.EnqueueInstance(pagingLogger1.Object);
                hc.SetSingleton(jobServerQueue.Object);

                var jobContext = new Runner.Worker.ExecutionContext();
                jobContext.Initialize(hc);

                // Act.
                jobContext.InitializeJob(jobRequest, CancellationToken.None);

                jobContext.Global.StepsContext.SetConclusion(null, "step1", ActionResult.Success);
                var conclusion1 = (jobContext.Global.StepsContext.GetScope(null)["step1"] as DictionaryContextData)["conclusion"].ToString();
                Assert.Equal(conclusion1, conclusion1.ToLowerInvariant());

                jobContext.Global.StepsContext.SetOutcome(null, "step2", ActionResult.Cancelled);
                var outcome1 = (jobContext.Global.StepsContext.GetScope(null)["step2"] as DictionaryContextData)["outcome"].ToString();
                Assert.Equal(outcome1, outcome1.ToLowerInvariant());

                jobContext.Global.StepsContext.SetConclusion(null, "step3", ActionResult.Failure);
                var conclusion2 = (jobContext.Global.StepsContext.GetScope(null)["step3"] as DictionaryContextData)["conclusion"].ToString();
                Assert.Equal(conclusion2, conclusion2.ToLowerInvariant());

                jobContext.Global.StepsContext.SetOutcome(null, "step4", ActionResult.Skipped);
                var outcome2 = (jobContext.Global.StepsContext.GetScope(null)["step4"] as DictionaryContextData)["outcome"].ToString();
                Assert.Equal(outcome2, outcome2.ToLowerInvariant());

                jobContext.JobContext.Status = ActionResult.Success;
                Assert.Equal(jobContext.JobContext["status"].ToString(), jobContext.JobContext["status"].ToString().ToLowerInvariant());
            }
        }
        public void EchoProcessCommandDebugOn()
        {
            using (TestHostContext hc = CreateTestContext())
            {
                // Set up a few things
                // 1. Job request message (with ACTIONS_STEP_DEBUG = true)
                TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
                TimelineReference timeline          = new TimelineReference();
                Guid   jobId      = Guid.NewGuid();
                string jobName    = "some job name";
                var    jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary <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()
                {
                    Alias   = Pipelines.PipelineConstants.SelfAlias,
                    Id      = "github",
                    Version = "sha1"
                });
                jobRequest.ContextData["github"]           = new Pipelines.ContextData.DictionaryContextData();
                jobRequest.Variables["ACTIONS_STEP_DEBUG"] = "true";

                // Some service dependencies
                var jobServerQueue = new Mock <IJobServerQueue>();
                jobServerQueue.Setup(x => x.QueueTimelineRecordUpdate(It.IsAny <Guid>(), It.IsAny <TimelineRecord>()));

                hc.SetSingleton(jobServerQueue.Object);

                var configurationStore = new Mock <IConfigurationStore>();
                configurationStore.Setup(x => x.GetSettings()).Returns(new RunnerSettings());
                hc.SetSingleton(configurationStore.Object);

                var pagingLogger = new Mock <IPagingLogger>();
                hc.EnqueueInstance(pagingLogger.Object);

                // Initialize the job (to exercise logic that sets EchoOnActionCommand)
                var ec = new Runner.Worker.ExecutionContext();
                ec.Initialize(hc);
                ec.InitializeJob(jobRequest, System.Threading.CancellationToken.None);

                ec.Complete();

                Assert.True(ec.EchoOnActionCommand);

                Assert.True(_commandManager.TryProcessCommand(ec, "::echo::off", null));
                Assert.False(ec.EchoOnActionCommand);

                Assert.True(_commandManager.TryProcessCommand(ec, "::echo::on", null));
                Assert.True(ec.EchoOnActionCommand);
            }
        }
示例#17
0
        public void StepTarget_RestrictedCommands_Host()
        {
            using (TestHostContext hc = CreateTestContext())
                using (var ec = new Agent.Worker.ExecutionContext())
                {
                    ec.Initialize(hc);

                    var pipeContainer = new Pipelines.ContainerResource {
                        Alias = "container"
                    };
                    pipeContainer.Properties.Set <string>("image", "someimage");
                    // Arrange: Create a job request message.
                    TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
                    TimelineReference timeline          = new TimelineReference();
                    JobEnvironment    environment       = new JobEnvironment();
                    environment.SystemConnection = new ServiceEndpoint();
                    List <Pipelines.JobStep> steps = new List <Pipelines.JobStep>();
                    steps.Add(new Pipelines.TaskStep
                    {
                        Target = new Pipelines.StepTarget
                        {
                            Target   = "host",
                            Commands = "restricted"
                        },
                        Reference = new Pipelines.TaskStepDefinitionReference()
                    });
                    var resources = new Pipelines.JobResources();
                    resources.Containers.Add(pipeContainer);
                    Guid   JobId      = Guid.NewGuid();
                    string jobName    = "some job name";
                    var    jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, JobId, jobName, jobName, null, new Dictionary <string, string>(),
                                                                             new Dictionary <string, VariableValue>(), new List <MaskHint>(), resources, new Pipelines.WorkspaceOptions(), steps);

                    // Arrange: Setup command manager
                    var commandMock = new Mock <IWorkerCommandManager>();
                    hc.SetSingleton(commandMock.Object);
                    var pagingLogger = new Mock <IPagingLogger>();
                    hc.EnqueueInstance(pagingLogger.Object);

                    // Act.
                    ec.InitializeJob(jobRequest, CancellationToken.None);
                    ec.SetStepTarget(steps[0].Target);

                    // Assert.
                    Assert.IsType <HostInfo>(ec.StepTarget());
                    commandMock.Verify(x => x.SetCommandRestrictionPolicy(It.IsAny <AttributeBasedWorkerCommandRestrictionPolicy>()));
                }
        }
示例#18
0
        public void InitializeJob_LogsWarningsFromVariables()
        {
            using (TestHostContext hc = new TestHostContext(this))
            {
                // Arrange: Create a job request message.
                TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
                TimelineReference timeline          = new TimelineReference();
                JobEnvironment    environment       = new JobEnvironment();
                environment.SystemConnection = new ServiceEndpoint();
                environment.Variables["v1"]  = "v1-$(v2)";
                environment.Variables["v2"]  = "v2-$(v1)";
                List <TaskInstance> tasks = new List <TaskInstance>();
                Guid   JobId      = Guid.NewGuid();
                string jobName    = "some job name";
                var    jobRequest = new AgentJobRequestMessage(plan, timeline, JobId, jobName, environment, tasks);

                // Arrange: Setup the configation store.
                var configurationStore = new Mock <IConfigurationStore>();
                configurationStore.Setup(x => x.GetSettings()).Returns(new AgentSettings());
                hc.SetSingleton(configurationStore.Object);

                // Arrange: Setup the secret masker.
                var secretMasker = new Mock <ISecretMasker>();
                secretMasker.Setup(x => x.MaskSecrets(It.IsAny <string>()))
                .Returns((string x) => x);
                hc.SetSingleton(secretMasker.Object);

                // Arrange: Setup the paging logger.
                var pagingLogger = new Mock <IPagingLogger>();
                hc.EnqueueInstance(pagingLogger.Object);

                // Arrange: Setup the proxy configation.
                var proxy = new Mock <IProxyConfiguration>();
                hc.SetSingleton(proxy.Object);

                // Arrange: Create the execution context.
                hc.SetSingleton(new Mock <IJobServerQueue>().Object);
                var ec = new Microsoft.VisualStudio.Services.Agent.Worker.ExecutionContext();
                ec.Initialize(hc);

                // Act.
                ec.InitializeJob(jobRequest, CancellationToken.None);

                // Assert.
                pagingLogger.Verify(x => x.Write(It.Is <string>(y => y.IndexOf("##[warning]") >= 0)), Times.Exactly(2));
            }
        }
示例#19
0
        public void Debug_Multilines()
        {
            using (TestHostContext hc = CreateTestContext())
            {
                // Arrange: Create a job request message.
                TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
                TimelineReference timeline          = new TimelineReference();
                Guid   jobId      = Guid.NewGuid();
                string jobName    = "some job name";
                var    jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary <string, VariableValue>(), new List <MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List <Pipelines.ActionStep>(), null);
                jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
                {
                    Alias   = Pipelines.PipelineConstants.SelfAlias,
                    Id      = "github",
                    Version = "sha1"
                });
                jobRequest.ContextData["github"]           = new Pipelines.ContextData.DictionaryContextData();
                jobRequest.Variables["ACTIONS_STEP_DEBUG"] = "true";

                // Arrange: Setup the paging logger.
                var pagingLogger   = new Mock <IPagingLogger>();
                var jobServerQueue = new Mock <IJobServerQueue>();
                jobServerQueue.Setup(x => x.QueueTimelineRecordUpdate(It.IsAny <Guid>(), It.IsAny <TimelineRecord>()));
                jobServerQueue.Setup(x => x.QueueWebConsoleLine(It.IsAny <Guid>(), It.IsAny <string>())).Callback((Guid id, string msg) => { hc.GetTrace().Info(msg); });

                hc.EnqueueInstance(pagingLogger.Object);
                hc.SetSingleton(jobServerQueue.Object);

                var ec = new Runner.Worker.ExecutionContext();
                ec.Initialize(hc);

                // Act.
                ec.InitializeJob(jobRequest, CancellationToken.None);

                ec.Debug(null);
                ec.Debug("");
                ec.Debug("\n");
                ec.Debug("\r\n");
                ec.Debug("test");
                ec.Debug("te\nst");
                ec.Debug("te\r\nst");

                ec.Complete();

                jobServerQueue.Verify(x => x.QueueWebConsoleLine(It.IsAny <Guid>(), It.IsAny <string>()), Times.Exactly(10));
            }
        }
示例#20
0
        private JobRequestMessage CreateJobRequestMessage(string jobName)
        {
            TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
            TimelineReference timeline          = null;
            JobEnvironment    environment       = new JobEnvironment();
            var serviceEndpoint = new ServiceEndpoint();

            serviceEndpoint.Authorization = new EndpointAuthorization();
            serviceEndpoint.Authorization.Parameters.Add("nullValue", null);
            environment.Endpoints.Add(serviceEndpoint);
            environment.Variables[Constants.Variables.System.Culture] = "en-US";
            List <TaskInstance> tasks = new List <TaskInstance>();
            Guid JobId      = Guid.NewGuid();
            var  jobRequest = new AgentJobRequestMessage(plan, timeline, JobId, jobName, environment, tasks);

            return(jobRequest);
        }
示例#21
0
            // Persists relative references instead of absolute references
            protected override void WriteElement(DomNode node, System.Xml.XmlWriter writer)
            {
                TimelineReference reference = node.As <TimelineReference>();
                Uri originalUri             = null;

                if (reference != null && reference.Uri != null && reference.Uri.IsAbsoluteUri)
                {
                    originalUri   = reference.Uri;
                    reference.Uri = Uri.MakeRelativeUri(reference.Uri);
                }

                base.WriteElement(node, writer);

                if (originalUri != null)
                {
                    reference.Uri = originalUri;
                }
            }
示例#22
0
        public void AddIssue_CountWarningsErrors()
        {
            using (TestHostContext hc = CreateTestContext())
            {
                // Arrange: Create a job request message.
                TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
                TimelineReference timeline          = new TimelineReference();
                Guid   jobId      = Guid.NewGuid();
                string jobName    = "some job name";
                var    jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary <string, VariableValue>(), new List <MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List <Pipelines.ActionStep>(), null);
                jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
                {
                    Alias   = Pipelines.PipelineConstants.SelfAlias,
                    Id      = "github",
                    Version = "sha1"
                });
                jobRequest.ContextData["github"] = new Pipelines.ContextData.DictionaryContextData();

                // Arrange: Setup the paging logger.
                var pagingLogger   = new Mock <IPagingLogger>();
                var jobServerQueue = new Mock <IJobServerQueue>();
                jobServerQueue.Setup(x => x.QueueTimelineRecordUpdate(It.IsAny <Guid>(), It.IsAny <TimelineRecord>()));

                hc.EnqueueInstance(pagingLogger.Object);
                hc.SetSingleton(jobServerQueue.Object);

                var ec = new Runner.Worker.ExecutionContext();
                ec.Initialize(hc);

                // Act.
                ec.InitializeJob(jobRequest, CancellationToken.None);

                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Error, Message = "error"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Error, Message = "error"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Error, Message = "error"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Error, Message = "error"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Error, Message = "error"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Error, Message = "error"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Error, Message = "error"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Error, Message = "error"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Error, Message = "error"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Error, Message = "error"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Error, Message = "error"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Error, Message = "error"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Error, Message = "error"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Error, Message = "error"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Error, Message = "error"
                });

                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Warning, Message = "warning"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Warning, Message = "warning"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Warning, Message = "warning"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Warning, Message = "warning"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Warning, Message = "warning"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Warning, Message = "warning"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Warning, Message = "warning"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Warning, Message = "warning"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Warning, Message = "warning"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Warning, Message = "warning"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Warning, Message = "warning"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Warning, Message = "warning"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Warning, Message = "warning"
                });
                ec.AddIssue(new Issue()
                {
                    Type = IssueType.Warning, Message = "warning"
                });

                ec.Complete();

                // Assert.
                jobServerQueue.Verify(x => x.QueueTimelineRecordUpdate(It.IsAny <Guid>(), It.Is <TimelineRecord>(t => t.ErrorCount == 15)), Times.AtLeastOnce);
                jobServerQueue.Verify(x => x.QueueTimelineRecordUpdate(It.IsAny <Guid>(), It.Is <TimelineRecord>(t => t.WarningCount == 14)), Times.AtLeastOnce);
                jobServerQueue.Verify(x => x.QueueTimelineRecordUpdate(It.IsAny <Guid>(), It.Is <TimelineRecord>(t => t.Issues.Where(i => i.Type == IssueType.Error).Count() == 10)), Times.AtLeastOnce);
                jobServerQueue.Verify(x => x.QueueTimelineRecordUpdate(It.IsAny <Guid>(), It.Is <TimelineRecord>(t => t.Issues.Where(i => i.Type == IssueType.Warning).Count() == 10)), Times.AtLeastOnce);
            }
        }
示例#23
0
        public async Task RunIPCEndToEnd()
        {
            using (var server = new ProcessChannel())
            {
                JobRequestMessage result            = null;
                TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
                TimelineReference   timeline        = null;
                JobEnvironment      environment     = new JobEnvironment();
                List <TaskInstance> tasks           = new List <TaskInstance>();
                Guid    JobId      = Guid.NewGuid();
                var     jobRequest = new JobRequestMessage(plan, timeline, JobId, "someJob", environment, tasks);
                Process jobProcess;
                server.StartServer((p1, p2) =>
                {
                    string clientFileName          = $"Test{IOUtil.ExeExtension}";
                    jobProcess                     = new Process();
                    jobProcess.StartInfo.FileName  = clientFileName;
                    jobProcess.StartInfo.Arguments = "spawnclient " + p1 + " " + p2;
                    jobProcess.EnableRaisingEvents = true;
                    jobProcess.Start();
                });
                var cs = new CancellationTokenSource();
                await server.SendAsync(MessageType.NewJobRequest, JsonUtility.ToString(jobRequest), cs.Token);

                var    packetReceiveTask = server.ReceiveAsync(cs.Token);
                Task[] taskToWait        = { packetReceiveTask, Task.Delay(5000) };
                await Task.WhenAny(taskToWait);

                bool timedOut = !packetReceiveTask.IsCompleted;

                // Wait until response is received
                if (timedOut)
                {
                    cs.Cancel();
                    try
                    {
                        await packetReceiveTask;
                    }
                    catch (OperationCanceledException)
                    {
                        // Ignore OperationCanceledException and TaskCanceledException exceptions
                    }
                    catch (AggregateException errors)
                    {
                        // Ignore OperationCanceledException and TaskCanceledException exceptions
                        errors.Handle(e => e is OperationCanceledException);
                    }
                }
                else
                {
                    result = JsonUtility.FromString <JobRequestMessage>(packetReceiveTask.Result.Body);
                }

                // Wait until response is received
                if (timedOut)
                {
                    Assert.True(false, "Test timed out.");
                }
                else
                {
                    Assert.True(jobRequest.JobId.Equals(result.JobId) && jobRequest.JobName.Equals(result.JobName));
                }
            }
        }
示例#24
0
        public void AddIssue_CountWarningsErrors()
        {
            using (TestHostContext hc = CreateTestContext())
                using (var ec = new Agent.Worker.ExecutionContext())
                {
                    // Arrange: Create a job request message.
                    TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
                    TimelineReference timeline          = new TimelineReference();
                    JobEnvironment    environment       = new JobEnvironment();
                    environment.SystemConnection = new ServiceEndpoint();
                    List <TaskInstance> tasks = new List <TaskInstance>();
                    Guid   JobId      = Guid.NewGuid();
                    string jobName    = "some job name";
                    var    jobRequest = Pipelines.AgentJobRequestMessageUtil.Convert(new AgentJobRequestMessage(plan, timeline, JobId, jobName, jobName, environment, tasks));

                    // Arrange: Setup the paging logger.
                    var pagingLogger   = new Mock <IPagingLogger>();
                    var jobServerQueue = new Mock <IJobServerQueue>();
                    jobServerQueue.Setup(x => x.QueueTimelineRecordUpdate(It.IsAny <Guid>(), It.IsAny <TimelineRecord>()));

                    hc.EnqueueInstance(pagingLogger.Object);
                    hc.SetSingleton(jobServerQueue.Object);

                    ec.Initialize(hc);

                    // Act.
                    ec.InitializeJob(jobRequest, CancellationToken.None);

                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Error, Message = "error"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Error, Message = "error"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Error, Message = "error"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Error, Message = "error"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Error, Message = "error"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Error, Message = "error"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Error, Message = "error"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Error, Message = "error"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Error, Message = "error"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Error, Message = "error"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Error, Message = "error"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Error, Message = "error"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Error, Message = "error"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Error, Message = "error"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Error, Message = "error"
                    });

                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Warning, Message = "warning"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Warning, Message = "warning"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Warning, Message = "warning"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Warning, Message = "warning"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Warning, Message = "warning"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Warning, Message = "warning"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Warning, Message = "warning"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Warning, Message = "warning"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Warning, Message = "warning"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Warning, Message = "warning"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Warning, Message = "warning"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Warning, Message = "warning"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Warning, Message = "warning"
                    });
                    ec.AddIssue(new Issue()
                    {
                        Type = IssueType.Warning, Message = "warning"
                    });

                    ec.Complete();

                    // Assert.
                    jobServerQueue.Verify(x => x.QueueTimelineRecordUpdate(It.IsAny <Guid>(), It.Is <TimelineRecord>(t => t.ErrorCount == 15)), Times.AtLeastOnce);
                    jobServerQueue.Verify(x => x.QueueTimelineRecordUpdate(It.IsAny <Guid>(), It.Is <TimelineRecord>(t => t.WarningCount == 14)), Times.AtLeastOnce);
                    jobServerQueue.Verify(x => x.QueueTimelineRecordUpdate(It.IsAny <Guid>(), It.Is <TimelineRecord>(t => t.Issues.Where(i => i.Type == IssueType.Error).Count() == 10)), Times.AtLeastOnce);
                    jobServerQueue.Verify(x => x.QueueTimelineRecordUpdate(It.IsAny <Guid>(), It.Is <TimelineRecord>(t => t.Issues.Where(i => i.Type == IssueType.Warning).Count() == 10)), Times.AtLeastOnce);
                }
        }
示例#25
0
        public void RegisterPostJobAction_ShareState()
        {
            using (TestHostContext hc = CreateTestContext())
            {
                // Arrange: Create a job request message.
                TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
                TimelineReference timeline          = new TimelineReference();
                Guid   jobId      = Guid.NewGuid();
                string jobName    = "some job name";
                var    jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary <string, VariableValue>(), new List <MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List <Pipelines.ActionStep>(), null);
                jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
                {
                    Alias   = Pipelines.PipelineConstants.SelfAlias,
                    Id      = "github",
                    Version = "sha1"
                });
                jobRequest.ContextData["github"]           = new Pipelines.ContextData.DictionaryContextData();
                jobRequest.Variables["ACTIONS_STEP_DEBUG"] = "true";

                // Arrange: Setup the paging logger.
                var pagingLogger1  = new Mock <IPagingLogger>();
                var pagingLogger2  = new Mock <IPagingLogger>();
                var pagingLogger3  = new Mock <IPagingLogger>();
                var pagingLogger4  = new Mock <IPagingLogger>();
                var pagingLogger5  = new Mock <IPagingLogger>();
                var jobServerQueue = new Mock <IJobServerQueue>();
                jobServerQueue.Setup(x => x.QueueTimelineRecordUpdate(It.IsAny <Guid>(), It.IsAny <TimelineRecord>()));
                jobServerQueue.Setup(x => x.QueueWebConsoleLine(It.IsAny <Guid>(), It.IsAny <string>())).Callback((Guid id, string msg) => { hc.GetTrace().Info(msg); });

                var actionRunner1 = new ActionRunner();
                actionRunner1.Initialize(hc);
                var actionRunner2 = new ActionRunner();
                actionRunner2.Initialize(hc);

                hc.EnqueueInstance(pagingLogger1.Object);
                hc.EnqueueInstance(pagingLogger2.Object);
                hc.EnqueueInstance(pagingLogger3.Object);
                hc.EnqueueInstance(pagingLogger4.Object);
                hc.EnqueueInstance(pagingLogger5.Object);
                hc.EnqueueInstance(actionRunner1 as IActionRunner);
                hc.EnqueueInstance(actionRunner2 as IActionRunner);
                hc.SetSingleton(jobServerQueue.Object);

                var jobContext = new Runner.Worker.ExecutionContext();
                jobContext.Initialize(hc);

                // Act.
                jobContext.InitializeJob(jobRequest, CancellationToken.None);

                var action1 = jobContext.CreateChild(Guid.NewGuid(), "action_1", "action_1", null, null);
                action1.IntraActionState["state"] = "1";
                var action2 = jobContext.CreateChild(Guid.NewGuid(), "action_2", "action_2", null, null);
                action2.IntraActionState["state"] = "2";


                var postRunner1 = hc.CreateService <IActionRunner>();
                postRunner1.Action = new Pipelines.ActionStep()
                {
                    Name = "post1", DisplayName = "Test 1", Reference = new Pipelines.RepositoryPathReference()
                    {
                        Name = "actions/action"
                    }
                };
                postRunner1.Stage       = ActionRunStage.Post;
                postRunner1.Condition   = "always()";
                postRunner1.DisplayName = "post1";


                var postRunner2 = hc.CreateService <IActionRunner>();
                postRunner2.Action = new Pipelines.ActionStep()
                {
                    Name = "post2", DisplayName = "Test 2", Reference = new Pipelines.RepositoryPathReference()
                    {
                        Name = "actions/action"
                    }
                };
                postRunner2.Stage       = ActionRunStage.Post;
                postRunner2.Condition   = "always()";
                postRunner2.DisplayName = "post2";

                action1.RegisterPostJobStep("post1", postRunner1);
                action2.RegisterPostJobStep("post2", postRunner2);

                Assert.NotNull(jobContext.JobSteps);
                Assert.NotNull(jobContext.PostJobSteps);
                Assert.Null(action1.JobSteps);
                Assert.Null(action2.JobSteps);
                Assert.Null(action1.PostJobSteps);
                Assert.Null(action2.PostJobSteps);

                var post1 = jobContext.PostJobSteps.Pop();
                var post2 = jobContext.PostJobSteps.Pop();

                Assert.Equal("post2", (post1 as IActionRunner).Action.Name);
                Assert.Equal("post1", (post2 as IActionRunner).Action.Name);

                Assert.Equal(ActionRunStage.Post, (post1 as IActionRunner).Stage);
                Assert.Equal(ActionRunStage.Post, (post2 as IActionRunner).Stage);

                Assert.Equal("always()", (post1 as IActionRunner).Condition);
                Assert.Equal("always()", (post2 as IActionRunner).Condition);

                Assert.Equal("2", (post1 as IActionRunner).ExecutionContext.IntraActionState["state"]);
                Assert.Equal("1", (post2 as IActionRunner).ExecutionContext.IntraActionState["state"]);
            }
        }