mirror of
https://github.com/actions/runner.git
synced 2025-12-18 00:07:08 +00:00
Continue on error for the composite actions (#1763)
* Added continue on error to composite action * changed from boolean-strategy-context -> boolean-steps-context for action_yaml * refactored composite handler to always set outcome * retrigger checks * fixed typo in ??= operator * boolean-steps-context accepts the same context as string-steps-context * setting the outcome only on continue-on-error * moved continue on error logic to the execution context * Added L0 table tests for continue-on-error ExecutionContext * Added missing mocks on StepsRunnerL0 for this update * removed empty line and added one line separating the call * Removed empty line Co-authored-by: Ferenc Hammerl <31069338+fhammerl@users.noreply.github.com> Co-authored-by: Ferenc Hammerl <31069338+fhammerl@users.noreply.github.com>
This commit is contained in:
@@ -8,6 +8,7 @@ using GitHub.DistributedTask.WebApi;
|
||||
using GitHub.Runner.Worker;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
using GitHub.DistributedTask.ObjectTemplating.Tokens;
|
||||
using Pipelines = GitHub.DistributedTask.Pipelines;
|
||||
|
||||
namespace GitHub.Runner.Common.Tests.Worker
|
||||
@@ -90,6 +91,63 @@ namespace GitHub.Runner.Common.Tests.Worker
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Worker")]
|
||||
public void ApplyContinueOnError_CheckResultAndOutcome()
|
||||
{
|
||||
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, 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 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>(), It.IsAny<long>())).Callback((Guid id, string msg, long? lineNumber) => { 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);
|
||||
|
||||
foreach (var tc in new List<(TemplateToken token, TaskResult result, TaskResult? expectedResult, TaskResult? expectedOutcome)> {
|
||||
(token: new BooleanToken(null, null, null, true), result: TaskResult.Failed, expectedResult: TaskResult.Succeeded, expectedOutcome: TaskResult.Failed),
|
||||
(token: new BooleanToken(null, null, null, true), result: TaskResult.Succeeded, expectedResult: TaskResult.Succeeded, expectedOutcome: null),
|
||||
(token: new BooleanToken(null, null, null, true), result: TaskResult.Canceled, expectedResult: TaskResult.Canceled, expectedOutcome: null),
|
||||
(token: new BooleanToken(null, null, null, false), result: TaskResult.Failed, expectedResult: TaskResult.Failed, expectedOutcome: null),
|
||||
(token: new BooleanToken(null, null, null, false), result: TaskResult.Succeeded, expectedResult: TaskResult.Succeeded, expectedOutcome: null),
|
||||
(token: new BooleanToken(null, null, null, false), result: TaskResult.Canceled, expectedResult: TaskResult.Canceled, expectedOutcome: null),
|
||||
})
|
||||
{
|
||||
ec.Result = tc.result;
|
||||
ec.Outcome = null;
|
||||
ec.ApplyContinueOnError(tc.token);
|
||||
Assert.Equal(ec.Result, tc.expectedResult);
|
||||
Assert.Equal(ec.Outcome, tc.expectedOutcome);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Worker")]
|
||||
|
||||
@@ -622,6 +622,40 @@ namespace GitHub.Runner.Common.Tests.Worker
|
||||
_stepContext.SetOutcome("", stepContext.Object.ContextName, (stepContext.Object.Outcome ?? stepContext.Object.Result ?? TaskResult.Succeeded).ToActionResult());
|
||||
_stepContext.SetConclusion("", stepContext.Object.ContextName, (stepContext.Object.Result ?? TaskResult.Succeeded).ToActionResult());
|
||||
});
|
||||
|
||||
stepContext.Setup(x => x.UpdateGlobalStepsContext()).Callback(() =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(stepContext.Object.ContextName) && !stepContext.Object.ContextName.StartsWith("__", StringComparison.Ordinal))
|
||||
{
|
||||
stepContext.Object.Global.StepsContext.SetOutcome(stepContext.Object.ScopeName, stepContext.Object.ContextName, (stepContext.Object.Outcome ?? stepContext.Object.Result ?? TaskResult.Succeeded).ToActionResult());
|
||||
stepContext.Object.Global.StepsContext.SetConclusion(stepContext.Object.ScopeName, stepContext.Object.ContextName, (stepContext.Object.Result ?? TaskResult.Succeeded).ToActionResult());
|
||||
}
|
||||
});
|
||||
stepContext.Setup(x => x.ApplyContinueOnError(It.IsAny<TemplateToken>())).Callback((TemplateToken token) =>
|
||||
{
|
||||
if (stepContext.Object.Result != TaskResult.Failed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var continueOnError = false;
|
||||
try
|
||||
{
|
||||
var templateEvaluator = stepContext.Object.ToPipelineTemplateEvaluator();
|
||||
continueOnError = templateEvaluator.EvaluateStepContinueOnError(token, stepContext.Object.ExpressionValues, stepContext.Object.ExpressionFunctions);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
stepContext.Object.Error("The step failed and an error occurred when attempting to determine whether to continue on error.");
|
||||
stepContext.Object.Error(ex);
|
||||
}
|
||||
|
||||
if (continueOnError)
|
||||
{
|
||||
stepContext.Object.Outcome = stepContext.Object.Result;
|
||||
stepContext.Object.Result = TaskResult.Succeeded;
|
||||
}
|
||||
stepContext.Object.UpdateGlobalStepsContext();
|
||||
});
|
||||
var trace = hc.GetTrace();
|
||||
stepContext.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>())).Callback((string tag, string message) => { trace.Info($"[{tag}]{message}"); });
|
||||
stepContext.Object.Result = result;
|
||||
|
||||
Reference in New Issue
Block a user