From e215a33c456389d374076ff3227cfc55ccebdb6a Mon Sep 17 00:00:00 2001 From: Francesco Renzi Date: Fri, 16 Jan 2026 01:57:06 +0000 Subject: [PATCH] steps are actually replayable! --- src/Runner.Worker/ExecutionContext.cs | 26 +++++++++++++++++++++++++- src/Runner.Worker/StepsRunner.cs | 3 +++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/Runner.Worker/ExecutionContext.cs b/src/Runner.Worker/ExecutionContext.cs index 5646d46aa..86aba9f1e 100644 --- a/src/Runner.Worker/ExecutionContext.cs +++ b/src/Runner.Worker/ExecutionContext.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Globalization; using System.IO; @@ -95,6 +95,7 @@ namespace GitHub.Runner.Worker // timeline record update methods void Start(string currentOperation = null); TaskResult Complete(TaskResult? result = null, string currentOperation = null, string resultCode = null); + void ResetForRerun(); void SetEnvContext(string name, string value); void SetRunnerContext(string name, string value); string GetGitHubContext(string name); @@ -545,6 +546,29 @@ namespace GitHub.Runner.Worker return Result.Value; } + /// + /// Resets the execution context for re-running (e.g., after step-back in DAP debugging). + /// Creates a new CancellationTokenSource since the previous one was disposed in Complete(). + /// + public void ResetForRerun() + { + // Create a new CancellationTokenSource since the old one was disposed + _cancellationTokenSource = new CancellationTokenSource(); + + // Reset record state to allow re-execution + _record.State = TimelineRecordState.Pending; + _record.FinishTime = null; + _record.PercentComplete = 0; + _record.ResultCode = null; + + // Reset result + Result = null; + Outcome = null; + + // Reset the force completed task + _forceCompleted = new TaskCompletionSource(); + } + public void UpdateGlobalStepsContext() { // Skip if generated context name. Generated context names start with "__". After 3.2 the server will never send an empty context name. diff --git a/src/Runner.Worker/StepsRunner.cs b/src/Runner.Worker/StepsRunner.cs index 3a9d3d487..e2e33bae6 100644 --- a/src/Runner.Worker/StepsRunner.cs +++ b/src/Runner.Worker/StepsRunner.cs @@ -222,9 +222,12 @@ namespace GitHub.Runner.Worker } // Queue the checkpoint's step and remaining steps + // Reset execution context for rerun since CancellationTokenSource was disposed in Complete() + checkpoint.CurrentStep.ExecutionContext.ResetForRerun(); jobContext.JobSteps.Enqueue(checkpoint.CurrentStep); foreach (var remainingStep in checkpoint.RemainingSteps) { + remainingStep.ExecutionContext.ResetForRerun(); jobContext.JobSteps.Enqueue(remainingStep); }