From 88875ca1b071c0cf999ad0a82596ed1290b6ac83 Mon Sep 17 00:00:00 2001 From: Tingluo Huang Date: Tue, 17 Mar 2020 21:18:42 -0400 Subject: [PATCH] set steps..outcome and steps..conclusion. (#372) --- src/Runner.Worker/ExecutionContext.cs | 9 +++ src/Runner.Worker/StepsContext.cs | 15 ++++- src/Runner.Worker/StepsRunner.cs | 1 + src/Test/L0/Worker/StepsRunnerL0.cs | 83 ++++++++++++++++++++++++++- 4 files changed, 102 insertions(+), 6 deletions(-) diff --git a/src/Runner.Worker/ExecutionContext.cs b/src/Runner.Worker/ExecutionContext.cs index b48936b08..667e93e8c 100644 --- a/src/Runner.Worker/ExecutionContext.cs +++ b/src/Runner.Worker/ExecutionContext.cs @@ -39,6 +39,7 @@ namespace GitHub.Runner.Worker string ContextName { get; } Task ForceCompleted { get; } TaskResult? Result { get; set; } + TaskResult? Outcome { get; set; } string ResultCode { get; set; } TaskResult? CommandResult { get; set; } CancellationToken CancellationToken { get; } @@ -171,6 +172,8 @@ namespace GitHub.Runner.Worker } } + public TaskResult? Outcome { get; set; } + public TaskResult? CommandResult { get; set; } private string ContextType => _record.RecordType; @@ -346,6 +349,12 @@ namespace GitHub.Runner.Worker _logger.End(); + if (!string.IsNullOrEmpty(ContextName)) + { + StepsContext.SetOutcome(ScopeName, ContextName, (Outcome ?? Result ?? TaskResult.Succeeded).ToActionResult().ToString()); + StepsContext.SetConclusion(ScopeName, ContextName, (Result ?? TaskResult.Succeeded).ToActionResult().ToString()); + } + return Result.Value; } diff --git a/src/Runner.Worker/StepsContext.cs b/src/Runner.Worker/StepsContext.cs index 41ea72961..d9add5a09 100644 --- a/src/Runner.Worker/StepsContext.cs +++ b/src/Runner.Worker/StepsContext.cs @@ -56,13 +56,22 @@ namespace GitHub.Runner.Worker } } - public void SetResult( + public void SetConclusion( string scopeName, string stepName, - string result) + string conclusion) { var step = GetStep(scopeName, stepName); - step["result"] = new StringContextData(result); + step["conclusion"] = new StringContextData(conclusion); + } + + public void SetOutcome( + string scopeName, + string stepName, + string outcome) + { + var step = GetStep(scopeName, stepName); + step["outcome"] = new StringContextData(outcome); } private DictionaryContextData GetStep(string scopeName, string stepName) diff --git a/src/Runner.Worker/StepsRunner.cs b/src/Runner.Worker/StepsRunner.cs index f69530672..ec1d7069c 100644 --- a/src/Runner.Worker/StepsRunner.cs +++ b/src/Runner.Worker/StepsRunner.cs @@ -351,6 +351,7 @@ namespace GitHub.Runner.Worker if (continueOnError) { + step.ExecutionContext.Outcome = step.ExecutionContext.Result; step.ExecutionContext.Result = TaskResult.Succeeded; Trace.Info($"Updated step result (continue on error)"); } diff --git a/src/Test/L0/Worker/StepsRunnerL0.cs b/src/Test/L0/Worker/StepsRunnerL0.cs index fd215b718..23534813f 100644 --- a/src/Test/L0/Worker/StepsRunnerL0.cs +++ b/src/Test/L0/Worker/StepsRunnerL0.cs @@ -11,6 +11,7 @@ using Xunit; using GitHub.DistributedTask.Expressions2; using GitHub.DistributedTask.Pipelines.ContextData; using GitHub.DistributedTask.ObjectTemplating.Tokens; +using GitHub.Runner.Common.Util; namespace GitHub.Runner.Common.Tests.Worker { @@ -57,7 +58,7 @@ namespace GitHub.Runner.Common.Tests.Worker var trace = hc.GetTrace(); _ec.Setup(x => x.Write(It.IsAny(), It.IsAny())).Callback((string tag, string message) => { trace.Info($"[{tag}]{message}"); }); - + _stepsRunner = new StepsRunner(); _stepsRunner.Initialize(hc); return hc; @@ -516,7 +517,78 @@ namespace GitHub.Runner.Common.Tests.Worker } } - private Mock CreateStep(TestHostContext hc, TaskResult result, string condition, Boolean continueOnError = false, MappingToken env = null, string name = "Test", bool setOutput = false) + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public async Task StepContextOutcome() + { + using (TestHostContext hc = CreateTestContext()) + { + // Arrange. + var step1 = CreateStep(hc, TaskResult.Succeeded, "success()", contextName: "step1"); + var step2 = CreateStep(hc, TaskResult.Failed, "steps.step1.outcome == 'success'", continueOnError: true, contextName: "step2"); + var step3 = CreateStep(hc, TaskResult.Succeeded, "steps.step1.outcome == 'success' && steps.step2.outcome == 'failure'", contextName: "step3"); + + _ec.Object.Result = null; + + _ec.Setup(x => x.JobSteps).Returns(new Queue(new[] { step1.Object, step2.Object, step3.Object })); + + // Act. + await _stepsRunner.RunAsync(jobContext: _ec.Object); + + // Assert. + Assert.Equal(TaskResult.Succeeded, _ec.Object.Result ?? TaskResult.Succeeded); + + step1.Verify(x => x.RunAsync(), Times.Once); + step2.Verify(x => x.RunAsync(), Times.Once); + step3.Verify(x => x.RunAsync(), Times.Once); + + Assert.Equal(TaskResult.Succeeded.ToActionResult().ToString(), _stepContext.GetScope(null)["step1"].AssertDictionary("")["outcome"].AssertString("")); + Assert.Equal(TaskResult.Succeeded.ToActionResult().ToString(), _stepContext.GetScope(null)["step1"].AssertDictionary("")["conclusion"].AssertString("")); + Assert.Equal(TaskResult.Failed.ToActionResult().ToString(), _stepContext.GetScope(null)["step2"].AssertDictionary("")["outcome"].AssertString("")); + Assert.Equal(TaskResult.Succeeded.ToActionResult().ToString(), _stepContext.GetScope(null)["step2"].AssertDictionary("")["conclusion"].AssertString("")); + Assert.Equal(TaskResult.Succeeded.ToActionResult().ToString(), _stepContext.GetScope(null)["step3"].AssertDictionary("")["outcome"].AssertString("")); + Assert.Equal(TaskResult.Succeeded.ToActionResult().ToString(), _stepContext.GetScope(null)["step3"].AssertDictionary("")["conclusion"].AssertString("")); + + } + } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public async Task StepContextConclusion() + { + using (TestHostContext hc = CreateTestContext()) + { + // Arrange. + var step1 = CreateStep(hc, TaskResult.Succeeded, "false", contextName: "step1"); + var step2 = CreateStep(hc, TaskResult.Failed, "steps.step1.conclusion == 'skipped'", continueOnError: true, contextName: "step2"); + var step3 = CreateStep(hc, TaskResult.Succeeded, "steps.step1.outcome == 'skipped' && steps.step2.outcome == 'failure' && steps.step2.conclusion == 'success'", contextName: "step3"); + + _ec.Object.Result = null; + + _ec.Setup(x => x.JobSteps).Returns(new Queue(new[] { step1.Object, step2.Object, step3.Object })); + + // Act. + await _stepsRunner.RunAsync(jobContext: _ec.Object); + + // Assert. + Assert.Equal(TaskResult.Succeeded, _ec.Object.Result ?? TaskResult.Succeeded); + + step1.Verify(x => x.RunAsync(), Times.Never); + step2.Verify(x => x.RunAsync(), Times.Once); + step3.Verify(x => x.RunAsync(), Times.Once); + + Assert.Equal(TaskResult.Skipped.ToActionResult().ToString(), _stepContext.GetScope(null)["step1"].AssertDictionary("")["outcome"].AssertString("")); + Assert.Equal(TaskResult.Skipped.ToActionResult().ToString(), _stepContext.GetScope(null)["step1"].AssertDictionary("")["conclusion"].AssertString("")); + Assert.Equal(TaskResult.Failed.ToActionResult().ToString(), _stepContext.GetScope(null)["step2"].AssertDictionary("")["outcome"].AssertString("")); + Assert.Equal(TaskResult.Succeeded.ToActionResult().ToString(), _stepContext.GetScope(null)["step2"].AssertDictionary("")["conclusion"].AssertString("")); + Assert.Equal(TaskResult.Succeeded.ToActionResult().ToString(), _stepContext.GetScope(null)["step3"].AssertDictionary("")["outcome"].AssertString("")); + Assert.Equal(TaskResult.Succeeded.ToActionResult().ToString(), _stepContext.GetScope(null)["step3"].AssertDictionary("")["conclusion"].AssertString("")); + } + } + + private Mock CreateStep(TestHostContext hc, TaskResult result, string condition, Boolean continueOnError = false, MappingToken env = null, string name = "Test", bool setOutput = false, string contextName = null) { // Setup the step. var step = new Mock(); @@ -527,7 +599,8 @@ namespace GitHub.Runner.Common.Tests.Worker { Name = name, Id = Guid.NewGuid(), - Environment = env + Environment = env, + ContextName = contextName ?? "Test" }); // Setup the step execution context. @@ -539,6 +612,7 @@ namespace GitHub.Runner.Common.Tests.Worker stepContext.Setup(x => x.ExpressionValues).Returns(_contexts); stepContext.Setup(x => x.JobContext).Returns(_jobContext); stepContext.Setup(x => x.StepsContext).Returns(_stepContext); + stepContext.Setup(x => x.ContextName).Returns(step.Object.Action.ContextName); stepContext.Setup(x => x.Complete(It.IsAny(), It.IsAny(), It.IsAny())) .Callback((TaskResult? r, string currentOperation, string resultCode) => { @@ -546,6 +620,9 @@ namespace GitHub.Runner.Common.Tests.Worker { stepContext.Object.Result = r; } + + _stepContext.SetOutcome("", stepContext.Object.ContextName, (stepContext.Object.Outcome ?? stepContext.Object.Result ?? TaskResult.Succeeded).ToActionResult().ToString()); + _stepContext.SetConclusion("", stepContext.Object.ContextName, (stepContext.Object.Result ?? TaskResult.Succeeded).ToActionResult().ToString()); }); var trace = hc.GetTrace(); stepContext.Setup(x => x.Write(It.IsAny(), It.IsAny())).Callback((string tag, string message) => { trace.Info($"[{tag}]{message}"); });