diff --git a/src/Runner.Worker/ActionRunner.cs b/src/Runner.Worker/ActionRunner.cs index 78c7943c7..0c4cc76ce 100644 --- a/src/Runner.Worker/ActionRunner.cs +++ b/src/Runner.Worker/ActionRunner.cs @@ -94,6 +94,13 @@ namespace GitHub.Runner.Worker if (handlerData.HasPost && (Stage == ActionRunStage.Pre || Stage == ActionRunStage.Main)) { string postDisplayName = $"Post {this.DisplayName}"; + if (Stage == ActionRunStage.Pre && + this.DisplayName.StartsWith("Pre ", StringComparison.OrdinalIgnoreCase)) + { + // Trim the leading `Pre ` from the display name. + // Otherwise, we will get `Post Pre xxx` as DisplayName for the Post step. + postDisplayName = $"Post {this.DisplayName.Substring("Pre ".Length)}"; + } 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}" : @@ -155,6 +162,13 @@ namespace GitHub.Runner.Worker } var validInputs = new HashSet(StringComparer.OrdinalIgnoreCase); + if (handlerData.ExecutionType == ActionExecutionType.Container) + { + // container action always accept 'entryPoint' and 'args' as inputs + // https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idstepswithargs + validInputs.Add("entryPoint"); + validInputs.Add("args"); + } // Merge the default inputs from the definition if (definition.Data?.Inputs != null) { diff --git a/src/Runner.Worker/ExecutionContext.cs b/src/Runner.Worker/ExecutionContext.cs index 54dbe3826..7bfe0932a 100644 --- a/src/Runner.Worker/ExecutionContext.cs +++ b/src/Runner.Worker/ExecutionContext.cs @@ -364,7 +364,11 @@ namespace GitHub.Runner.Worker } } - _cancellationTokenSource?.Dispose(); + if (Root != this) + { + // only dispose TokenSource for step level ExecutionContext + _cancellationTokenSource?.Dispose(); + } _logger.End(); @@ -852,7 +856,7 @@ namespace GitHub.Runner.Worker { Interlocked.Add(ref _totalThrottlingDelayInMilliseconds, Convert.ToInt64(data.Delay.TotalMilliseconds)); - if (!_throttlingReported && + if (!_throttlingReported && _totalThrottlingDelayInMilliseconds > _throttlingDelayReportThreshold) { this.Warning(string.Format("The job is currently being throttled by the server. You may experience delays in console line output, job status reporting, and action log uploads.")); diff --git a/src/Runner.Worker/JobRunner.cs b/src/Runner.Worker/JobRunner.cs index a94d7dd3d..58cf26bf4 100644 --- a/src/Runner.Worker/JobRunner.cs +++ b/src/Runner.Worker/JobRunner.cs @@ -254,6 +254,12 @@ namespace GitHub.Runner.Worker Trace.Error(ex); return TaskResult.Failed; } + catch (TaskOrchestrationPlanTerminatedException ex) + { + Trace.Error($"TaskOrchestrationPlanTerminatedException received, while attempting to raise JobCompletedEvent for job {message.JobId}."); + Trace.Error(ex); + return TaskResult.Failed; + } catch (Exception ex) { Trace.Error($"Catch exception while attempting to raise JobCompletedEvent for job {message.JobId}, job request {message.RequestId}."); diff --git a/src/Runner.Worker/StepsRunner.cs b/src/Runner.Worker/StepsRunner.cs index 3e758c6d5..485a4cdf9 100644 --- a/src/Runner.Worker/StepsRunner.cs +++ b/src/Runner.Worker/StepsRunner.cs @@ -98,124 +98,139 @@ namespace GitHub.Runner.Worker envContext[pair.Key] = new StringContextData(pair.Value ?? string.Empty); } + bool evaluateStepEnvFailed = false; if (step is IActionRunner actionStep) { // Set GITHUB_ACTION step.ExecutionContext.SetGitHubContext("action", actionStep.Action.Name); - // Evaluate and merge action's env block to env context - var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator(); - var actionEnvironment = templateEvaluator.EvaluateStepEnvironment(actionStep.Action.Environment, step.ExecutionContext.ExpressionValues, step.ExecutionContext.ExpressionFunctions, VarUtil.EnvironmentVariableKeyComparer); - foreach (var env in actionEnvironment) + try { - envContext[env.Key] = new StringContextData(env.Value ?? string.Empty); - } - } - - try - { - // Register job cancellation call back only if job cancellation token not been fire before each step run - if (!jobContext.CancellationToken.IsCancellationRequested) - { - // Test the condition again. The job was canceled after the condition was originally evaluated. - jobCancelRegister = jobContext.CancellationToken.Register(() => + // Evaluate and merge action's env block to env context + var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator(); + var actionEnvironment = templateEvaluator.EvaluateStepEnvironment(actionStep.Action.Environment, step.ExecutionContext.ExpressionValues, step.ExecutionContext.ExpressionFunctions, VarUtil.EnvironmentVariableKeyComparer); + foreach (var env in actionEnvironment) { - // mark job as cancelled - jobContext.Result = TaskResult.Canceled; - jobContext.JobContext.Status = jobContext.Result?.ToActionResult(); - - step.ExecutionContext.Debug($"Re-evaluate condition on job cancellation for step: '{step.DisplayName}'."); - var conditionReTestTraceWriter = new ConditionTraceWriter(Trace, null); // host tracing only - var conditionReTestResult = false; - if (HostContext.RunnerShutdownToken.IsCancellationRequested) - { - step.ExecutionContext.Debug($"Skip Re-evaluate condition on runner shutdown."); - } - else - { - try - { - var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator(conditionReTestTraceWriter); - var condition = new BasicExpressionToken(null, null, null, step.Condition); - conditionReTestResult = templateEvaluator.EvaluateStepIf(condition, step.ExecutionContext.ExpressionValues, step.ExecutionContext.ExpressionFunctions, step.ExecutionContext.ToExpressionState()); - } - catch (Exception ex) - { - // Cancel the step since we get exception while re-evaluate step condition. - Trace.Info("Caught exception from expression when re-test condition on job cancellation."); - step.ExecutionContext.Error(ex); - } - } - - if (!conditionReTestResult) - { - // Cancel the step. - Trace.Info("Cancel current running step."); - step.ExecutionContext.CancelToken(); - } - }); - } - else - { - if (jobContext.Result != TaskResult.Canceled) - { - // mark job as cancelled - jobContext.Result = TaskResult.Canceled; - jobContext.JobContext.Status = jobContext.Result?.ToActionResult(); + envContext[env.Key] = new StringContextData(env.Value ?? string.Empty); } } - - // Evaluate condition. - step.ExecutionContext.Debug($"Evaluating condition for step: '{step.DisplayName}'"); - var conditionTraceWriter = new ConditionTraceWriter(Trace, step.ExecutionContext); - var conditionResult = false; - var conditionEvaluateError = default(Exception); - if (HostContext.RunnerShutdownToken.IsCancellationRequested) - { - step.ExecutionContext.Debug($"Skip evaluate condition on runner shutdown."); - } - else - { - try - { - var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator(conditionTraceWriter); - var condition = new BasicExpressionToken(null, null, null, step.Condition); - conditionResult = templateEvaluator.EvaluateStepIf(condition, step.ExecutionContext.ExpressionValues, step.ExecutionContext.ExpressionFunctions, step.ExecutionContext.ToExpressionState()); - } - catch (Exception ex) - { - Trace.Info("Caught exception from expression."); - Trace.Error(ex); - conditionEvaluateError = ex; - } - } - - // no evaluate error but condition is false - if (!conditionResult && conditionEvaluateError == null) - { - // Condition == false - Trace.Info("Skipping step due to condition evaluation."); - CompleteStep(step, nextStep, TaskResult.Skipped, resultCode: conditionTraceWriter.Trace); - } - else if (conditionEvaluateError != null) + catch (Exception ex) { // fail the step since there is an evaluate error. - step.ExecutionContext.Error(conditionEvaluateError); + Trace.Info("Caught exception from expression for step.env"); + evaluateStepEnvFailed = true; + step.ExecutionContext.Error(ex); CompleteStep(step, nextStep, TaskResult.Failed); } - else - { - // Run the step. - await RunStepAsync(step, jobContext.CancellationToken); - CompleteStep(step, nextStep); - } } - finally + + if (!evaluateStepEnvFailed) { - if (jobCancelRegister != null) + try { - jobCancelRegister?.Dispose(); - jobCancelRegister = null; + // Register job cancellation call back only if job cancellation token not been fire before each step run + if (!jobContext.CancellationToken.IsCancellationRequested) + { + // Test the condition again. The job was canceled after the condition was originally evaluated. + jobCancelRegister = jobContext.CancellationToken.Register(() => + { + // mark job as cancelled + jobContext.Result = TaskResult.Canceled; + jobContext.JobContext.Status = jobContext.Result?.ToActionResult(); + + step.ExecutionContext.Debug($"Re-evaluate condition on job cancellation for step: '{step.DisplayName}'."); + var conditionReTestTraceWriter = new ConditionTraceWriter(Trace, null); // host tracing only + var conditionReTestResult = false; + if (HostContext.RunnerShutdownToken.IsCancellationRequested) + { + step.ExecutionContext.Debug($"Skip Re-evaluate condition on runner shutdown."); + } + else + { + try + { + var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator(conditionReTestTraceWriter); + var condition = new BasicExpressionToken(null, null, null, step.Condition); + conditionReTestResult = templateEvaluator.EvaluateStepIf(condition, step.ExecutionContext.ExpressionValues, step.ExecutionContext.ExpressionFunctions, step.ExecutionContext.ToExpressionState()); + } + catch (Exception ex) + { + // Cancel the step since we get exception while re-evaluate step condition. + Trace.Info("Caught exception from expression when re-test condition on job cancellation."); + step.ExecutionContext.Error(ex); + } + } + + if (!conditionReTestResult) + { + // Cancel the step. + Trace.Info("Cancel current running step."); + step.ExecutionContext.CancelToken(); + } + }); + } + else + { + if (jobContext.Result != TaskResult.Canceled) + { + // mark job as cancelled + jobContext.Result = TaskResult.Canceled; + jobContext.JobContext.Status = jobContext.Result?.ToActionResult(); + } + } + + // Evaluate condition. + step.ExecutionContext.Debug($"Evaluating condition for step: '{step.DisplayName}'"); + var conditionTraceWriter = new ConditionTraceWriter(Trace, step.ExecutionContext); + var conditionResult = false; + var conditionEvaluateError = default(Exception); + if (HostContext.RunnerShutdownToken.IsCancellationRequested) + { + step.ExecutionContext.Debug($"Skip evaluate condition on runner shutdown."); + } + else + { + try + { + var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator(conditionTraceWriter); + var condition = new BasicExpressionToken(null, null, null, step.Condition); + conditionResult = templateEvaluator.EvaluateStepIf(condition, step.ExecutionContext.ExpressionValues, step.ExecutionContext.ExpressionFunctions, step.ExecutionContext.ToExpressionState()); + } + catch (Exception ex) + { + Trace.Info("Caught exception from expression."); + Trace.Error(ex); + conditionEvaluateError = ex; + } + } + + // no evaluate error but condition is false + if (!conditionResult && conditionEvaluateError == null) + { + // Condition == false + Trace.Info("Skipping step due to condition evaluation."); + CompleteStep(step, nextStep, TaskResult.Skipped, resultCode: conditionTraceWriter.Trace); + } + else if (conditionEvaluateError != null) + { + // fail the step since there is an evaluate error. + step.ExecutionContext.Error(conditionEvaluateError); + CompleteStep(step, nextStep, TaskResult.Failed); + } + else + { + // Run the step. + await RunStepAsync(step, jobContext.CancellationToken); + CompleteStep(step, nextStep); + } + } + finally + { + if (jobCancelRegister != null) + { + jobCancelRegister?.Dispose(); + jobCancelRegister = null; + } } } } diff --git a/src/runnerversion b/src/runnerversion index 93c284c97..127f551ee 100644 --- a/src/runnerversion +++ b/src/runnerversion @@ -1 +1 @@ -2.262.0 +2.262.1