diff --git a/src/Runner.Worker/ActionManager.cs b/src/Runner.Worker/ActionManager.cs index 290c3518f..807f5ec66 100644 --- a/src/Runner.Worker/ActionManager.cs +++ b/src/Runner.Worker/ActionManager.cs @@ -73,7 +73,7 @@ namespace GitHub.Runner.Worker } // Clear the cache (local runner) - // IOUtil.DeleteDirectory(HostContext.GetDirectory(WellKnownDirectory.Actions), executionContext.CancellationToken); + IOUtil.DeleteDirectory(HostContext.GetDirectory(WellKnownDirectory.Actions), executionContext.CancellationToken); foreach (var action in actions) { @@ -126,7 +126,8 @@ namespace GitHub.Runner.Worker } } - if (!(action.Reference is Pipelines.RepositoryPathReference repoAction) || repoAction.RepositoryType != Pipelines.PipelineConstants.SelfAlias) + var repoAction = action.Reference as Pipelines.RepositoryPathReference; + if (repoAction.RepositoryType != Pipelines.PipelineConstants.SelfAlias) { var definition = LoadAction(executionContext, action); if (definition.Data.Execution.HasInit) @@ -138,6 +139,10 @@ namespace GitHub.Runner.Worker preStepTracker[action.Id] = actionRunner; } + else if (!definition.Data.Execution.HasMain && definition.Data.Execution.HasCleanup) + { + throw new NotSupportedException($"Action {repoAction.Name}@{repoAction.Ref} only has `post` execution, `pre` or `main` is required for an actions."); + } } } } @@ -801,7 +806,7 @@ namespace GitHub.Runner.Worker public override ActionExecutionType ExecutionType => ActionExecutionType.Container; public override bool HasInit => !string.IsNullOrEmpty(Init); - + public override bool HasMain => !string.IsNullOrEmpty(EntryPoint); public override bool HasCleanup => !string.IsNullOrEmpty(Cleanup); public string Image { get; set; } @@ -822,7 +827,7 @@ namespace GitHub.Runner.Worker public override ActionExecutionType ExecutionType => ActionExecutionType.NodeJS; public override bool HasInit => !string.IsNullOrEmpty(Init); - + public override bool HasMain => !string.IsNullOrEmpty(Script); public override bool HasCleanup => !string.IsNullOrEmpty(Cleanup); public string Script { get; set; } @@ -837,6 +842,7 @@ namespace GitHub.Runner.Worker public override ActionExecutionType ExecutionType => ActionExecutionType.Plugin; public override bool HasInit => false; + public override bool HasMain => true; public override bool HasCleanup => !string.IsNullOrEmpty(Cleanup); @@ -849,6 +855,7 @@ namespace GitHub.Runner.Worker { public override ActionExecutionType ExecutionType => ActionExecutionType.Script; public override bool HasInit => false; + public override bool HasMain => true; public override bool HasCleanup => false; } @@ -860,6 +867,7 @@ namespace GitHub.Runner.Worker public abstract ActionExecutionType ExecutionType { get; } public abstract bool HasInit { get; } + public abstract bool HasMain { get; } public abstract bool HasCleanup { get; } public string CleanupCondition diff --git a/src/Runner.Worker/ActionRunner.cs b/src/Runner.Worker/ActionRunner.cs index 46a3120f7..3c0198970 100644 --- a/src/Runner.Worker/ActionRunner.cs +++ b/src/Runner.Worker/ActionRunner.cs @@ -84,18 +84,9 @@ namespace GitHub.Runner.Worker // The action has post cleanup defined. // we need to create timeline record for them and add them to the step list that StepRunner is using - if (handlerData.HasCleanup && Stage == ActionRunStage.Main) + if (handlerData.HasCleanup && (Stage == ActionRunStage.Pre || Stage == ActionRunStage.Main)) { - string postDisplayName = null; - if (this.DisplayName.StartsWith(PipelineTemplateConstants.RunDisplayPrefix)) - { - postDisplayName = $"Post {this.DisplayName.Substring(PipelineTemplateConstants.RunDisplayPrefix.Length)}"; - } - else - { - postDisplayName = $"Post {this.DisplayName}"; - } - + string postDisplayName = $"Post {this.DisplayName}"; var repositoryReference = Action.Reference as RepositoryPathReference; var pathString = string.IsNullOrEmpty(repositoryReference.Path) ? string.Empty : $"/{repositoryReference.Path}"; var repoString = string.IsNullOrEmpty(repositoryReference.Ref) ? $"{repositoryReference.Name}{pathString}" : @@ -109,7 +100,7 @@ namespace GitHub.Runner.Worker actionRunner.Condition = handlerData.CleanupCondition; actionRunner.DisplayName = postDisplayName; - ExecutionContext.RegisterPostJobStep($"{actionRunner.Action.Name}_post", actionRunner); + ExecutionContext.RegisterPostJobStep(actionRunner); } IStepHost stepHost = HostContext.CreateService(); diff --git a/src/Runner.Worker/ContainerOperationProvider.cs b/src/Runner.Worker/ContainerOperationProvider.cs index a476b5464..9534e9290 100644 --- a/src/Runner.Worker/ContainerOperationProvider.cs +++ b/src/Runner.Worker/ContainerOperationProvider.cs @@ -49,7 +49,7 @@ namespace GitHub.Runner.Worker data: data); executionContext.Debug($"Register post job cleanup for stopping/deleting containers."); - executionContext.RegisterPostJobStep(nameof(StopContainersAsync), postJobStep); + executionContext.RegisterPostJobStep(postJobStep); // Check whether we are inside a container. // Our container feature requires to map working directory from host to the container. diff --git a/src/Runner.Worker/ExecutionContext.cs b/src/Runner.Worker/ExecutionContext.cs index 5c7bbfa7e..75f8562b0 100644 --- a/src/Runner.Worker/ExecutionContext.cs +++ b/src/Runner.Worker/ExecutionContext.cs @@ -98,7 +98,7 @@ namespace GitHub.Runner.Worker // others void ForceTaskComplete(); - void RegisterPostJobStep(string refName, IStep step); + void RegisterPostJobStep(IStep step); } public sealed class ExecutionContext : RunnerService, IExecutionContext @@ -154,6 +154,9 @@ namespace GitHub.Runner.Worker // Only job level ExecutionContext has PostJobSteps public Stack PostJobSteps { get; private set; } + // Only job level ExecutionContext has StepsWithPostRegisted + public HashSet StepsWithPostRegisted { get; private set; } + public bool EchoOnActionCommand { get; set; } @@ -239,9 +242,15 @@ namespace GitHub.Runner.Worker }); } - public void RegisterPostJobStep(string refName, IStep step) + public void RegisterPostJobStep(IStep step) { - step.ExecutionContext = Root.CreatePostChild(step.DisplayName, refName, IntraActionState); + if (step is IActionRunner actionRunner && !Root.StepsWithPostRegisted.Add(actionRunner.Action.Id)) + { + Trace.Info($"'post' of '{actionRunner.DisplayName}' already push to post step stack."); + return; + } + + step.ExecutionContext = Root.CreatePostChild(step.DisplayName, ScopeName, ContextName, IntraActionState); Root.PostJobSteps.Push(step); } @@ -618,6 +627,9 @@ namespace GitHub.Runner.Worker // PostJobSteps for job ExecutionContext PostJobSteps = new Stack(); + // StepsWithPostRegisted for job ExecutionContext + StepsWithPostRegisted = new HashSet(); + // Job timeline record. InitializeTimelineRecord( timelineId: message.Timeline.Id, @@ -818,7 +830,7 @@ namespace GitHub.Runner.Worker } } - private IExecutionContext CreatePostChild(string displayName, string refName, Dictionary intraActionState) + private IExecutionContext CreatePostChild(string displayName, string scopeName, string contextName, Dictionary intraActionState) { if (!_expandedForPostJob) { @@ -827,7 +839,8 @@ namespace GitHub.Runner.Worker _childTimelineRecordOrder = _childTimelineRecordOrder * 2; } - return CreateChild(Guid.NewGuid(), displayName, refName, null, null, intraActionState, _childTimelineRecordOrder - Root.PostJobSteps.Count); + var newGuid = Guid.NewGuid(); + return CreateChild(newGuid, displayName, newGuid.ToString("N"), scopeName, contextName, intraActionState, _childTimelineRecordOrder - Root.PostJobSteps.Count); } } diff --git a/src/Runner.Worker/JobExtension.cs b/src/Runner.Worker/JobExtension.cs index 5a176ded9..d900be642 100644 --- a/src/Runner.Worker/JobExtension.cs +++ b/src/Runner.Worker/JobExtension.cs @@ -163,15 +163,7 @@ namespace GitHub.Runner.Worker { Trace.Info($"Adding pre-{action.DisplayName}."); preStep.TryEvaluateDisplayName(contextData, context); - if (preStep.DisplayName.StartsWith(PipelineTemplateConstants.RunDisplayPrefix)) - { - preStep.DisplayName = $"Pre {preStep.DisplayName.Substring(PipelineTemplateConstants.RunDisplayPrefix.Length)}"; - } - else - { - preStep.DisplayName = $"Pre {preStep.DisplayName}"; - } - + preStep.DisplayName = $"Pre {preStep.DisplayName}"; preJobSteps.Add(preStep); } } @@ -197,7 +189,7 @@ namespace GitHub.Runner.Worker { ArgUtil.NotNull(actionStep, step.DisplayName); Guid stepId = Guid.NewGuid(); - actionStep.ExecutionContext = jobContext.CreateChild(stepId, actionStep.DisplayName, null, null, stepId.ToString("N"), intraActionStates[actionStep.Action.Id]); + actionStep.ExecutionContext = jobContext.CreateChild(stepId, actionStep.DisplayName, null, actionStep.Action.ScopeName, actionStep.Action.ContextName, intraActionStates[actionStep.Action.Id]); } } diff --git a/src/Test/L0/Worker/ExecutionContextL0.cs b/src/Test/L0/Worker/ExecutionContextL0.cs index 6293a3bef..e3cef7ecd 100644 --- a/src/Test/L0/Worker/ExecutionContextL0.cs +++ b/src/Test/L0/Worker/ExecutionContextL0.cs @@ -199,20 +199,20 @@ namespace GitHub.Runner.Common.Tests.Worker var postRunner1 = hc.CreateService(); - postRunner1.Action = new Pipelines.ActionStep() { Name = "post1", DisplayName = "Test 1", Reference = new Pipelines.RepositoryPathReference() { Name = "actions/action" } }; + postRunner1.Action = new Pipelines.ActionStep() { Id = Guid.NewGuid(), 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(); - postRunner2.Action = new Pipelines.ActionStep() { Name = "post2", DisplayName = "Test 2", Reference = new Pipelines.RepositoryPathReference() { Name = "actions/action" } }; + postRunner2.Action = new Pipelines.ActionStep() { Id = Guid.NewGuid(), 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); + action1.RegisterPostJobStep(postRunner1); + action2.RegisterPostJobStep(postRunner2); Assert.NotNull(jobContext.JobSteps); Assert.NotNull(jobContext.PostJobSteps);