fix step insertion

This commit is contained in:
Francesco Renzi
2026-01-22 11:22:13 +00:00
committed by GitHub
parent 8fbe9aa963
commit 514d122c9d
4 changed files with 376 additions and 18 deletions

View File

@@ -247,6 +247,24 @@ namespace GitHub.Runner.Worker.Dap
/// <param name="checkpointIndex">The index of the checkpoint to restore</param>
/// <param name="jobContext">The job execution context</param>
void RestoreCheckpoint(int checkpointIndex, IExecutionContext jobContext);
/// <summary>
/// Gets whether a step was inserted "here" (before current step) while paused.
/// When true, StepsRunner should skip current step execution and re-process from queue.
/// </summary>
bool HasStepInsertedHere { get; }
/// <summary>
/// Consumes the "step inserted here" flag (resets it to false).
/// Called by StepsRunner after handling the insertion.
/// </summary>
void ConsumeStepInsertedHere();
/// <summary>
/// Sets the "step inserted here" flag.
/// Called by StepManipulator when --here insertion occurs.
/// </summary>
void SetStepInsertedHere();
}
/// <summary>
@@ -320,6 +338,9 @@ namespace GitHub.Runner.Worker.Dap
// Job cancellation token for REPL commands and blocking waits
private CancellationToken _jobCancellationToken;
// Flag for step inserted "here" (before current step)
private bool _hasStepInsertedHere;
public bool IsActive => _state == DapSessionState.Ready || _state == DapSessionState.Paused || _state == DapSessionState.Running;
public DapSessionState State => _state;
@@ -328,6 +349,18 @@ namespace GitHub.Runner.Worker.Dap
public bool HasPendingRestore => _pendingRestoreCheckpoint.HasValue;
public bool HasStepInsertedHere => _hasStepInsertedHere;
public void ConsumeStepInsertedHere()
{
_hasStepInsertedHere = false;
}
public void SetStepInsertedHere()
{
_hasStepInsertedHere = true;
}
public override void Initialize(IHostContext hostContext)
{
base.Initialize(hostContext);

View File

@@ -4,6 +4,7 @@ using System.Linq;
using GitHub.DistributedTask.Pipelines;
using GitHub.Runner.Common;
using GitHub.Runner.Sdk;
using GitHub.Runner.Worker.Dap;
namespace GitHub.Runner.Worker.Dap.StepCommands
{
@@ -195,8 +196,13 @@ namespace GitHub.Runner.Worker.Dap.StepCommands
index++;
}
// Add current step if present
if (_currentStep != null)
// Check if we're in "step inserted here" state
var debugSession = HostContext.GetService<IDapDebugSession>();
var stepInsertedHere = debugSession?.HasStepInsertedHere ?? false;
// Add current step if present AND not in "step inserted here" state
// (In that state, the current step has been re-queued and will show in pending)
if (_currentStep != null && !stepInsertedHere)
{
var info = StepInfo.FromStep(_currentStep, index, StepStatus.Current);
ApplyChangeInfo(info);
@@ -207,12 +213,19 @@ namespace GitHub.Runner.Worker.Dap.StepCommands
// Add pending steps from queue
if (_jobContext?.JobSteps != null)
{
bool isFirstPending = true;
foreach (var step in _jobContext.JobSteps)
{
var info = StepInfo.FromStep(step, index, StepStatus.Pending);
// In "step inserted here" state, mark the first pending step as current
var status = (stepInsertedHere && isFirstPending)
? StepStatus.Current
: StepStatus.Pending;
var info = StepInfo.FromStep(step, index, status);
ApplyChangeInfo(info);
result.Add(info);
index++;
isFirstPending = false;
}
}
@@ -316,26 +329,29 @@ namespace GitHub.Runner.Worker.Dap.StepCommands
var pending = _jobContext.JobSteps.ToList();
_jobContext.JobSteps.Clear();
// Re-queue the current step at the front of pending
pending.Insert(0, _currentStep);
// Insert the new step before it (at position 0)
// Insert the new step at the front (it will run first)
pending.Insert(0, step);
// Insert the original current step after it (it will run second)
// This re-queues the step that was already dequeued by StepsRunner
pending.Insert(1, _currentStep);
// Re-queue all steps
foreach (var s in pending)
{
_jobContext.JobSteps.Enqueue(s);
}
// The new step becomes the current step
_currentStep = step;
// Signal to StepsRunner that it should skip the current iteration
// and re-process from the queue (which now has our new step first)
var debugSession = HostContext.GetService<IDapDebugSession>();
debugSession?.SetStepInsertedHere();
// Calculate the 1-based index (new step takes current step's position)
// Calculate the 1-based index (new step takes position after completed steps)
var newIndex = _completedSteps.Count + 1;
// Track the change
var stepInfo = StepInfo.FromStep(step, newIndex, StepStatus.Current);
var stepInfo = StepInfo.FromStep(step, newIndex, StepStatus.Pending);
stepInfo.Change = ChangeType.Added;
if (step is IActionRunner runner && runner.Action != null)
@@ -345,6 +361,9 @@ namespace GitHub.Runner.Worker.Dap.StepCommands
_changes.Add(StepChange.Added(stepInfo, newIndex));
// Note: We do NOT update _currentStep here. The StepsRunner will
// pick up the new step from the queue and that will become current.
Trace.Info($"Inserted step '{step.DisplayName}' at position {newIndex} (--here, before current step)");
return newIndex;
}
@@ -461,22 +480,25 @@ namespace GitHub.Runner.Worker.Dap.StepCommands
var step = pending[fromQueueIndex];
pending.RemoveAt(fromQueueIndex);
// Re-queue the current step at the front of pending
pending.Insert(0, _currentStep);
// Insert the moved step before the current step (at position 0)
// Insert the moved step at the front (it will run first)
pending.Insert(0, step);
// Insert the original current step after it (it will run second)
// This re-queues the step that was already dequeued by StepsRunner
pending.Insert(1, _currentStep);
// Re-queue all steps
foreach (var s in pending)
{
_jobContext.JobSteps.Enqueue(s);
}
// The moved step becomes the current step
_currentStep = step;
// Signal to StepsRunner that it should skip the current iteration
// and re-process from the queue (which now has our moved step first)
var debugSession = HostContext.GetService<IDapDebugSession>();
debugSession?.SetStepInsertedHere();
// Calculate the new 1-based index (step takes current step's position)
// Calculate the new 1-based index (step takes position after completed steps)
var newIndex = _completedSteps.Count + 1;
// Track the change
@@ -488,6 +510,9 @@ namespace GitHub.Runner.Worker.Dap.StepCommands
_modifiedStepIds.Add(runner.Action.Id);
}
// Note: We do NOT update _currentStep here. The StepsRunner will
// pick up the moved step from the queue and that will become current.
Trace.Info($"Moved step '{step.DisplayName}' from position {fromIndex} to {newIndex} (--here, before current step)");
return newIndex;
}

View File

@@ -242,6 +242,25 @@ namespace GitHub.Runner.Worker
}
}
// Check if a step was inserted "here" (before current step)
if (debugSession.HasStepInsertedHere)
{
debugSession.ConsumeStepInsertedHere();
// The queue now contains: [new step, original current step, rest...]
// We need to skip this iteration and let the loop pick up the new step
// Clear pending step info since we're not executing this step now
debugSession.ClearPendingStepInfo();
// Don't increment stepIndex - the new step takes this position
Trace.Info("Step inserted here - skipping current iteration to process new step");
// Skip to next iteration - will dequeue and process the new step
continue;
}
// User pressed next/continue - create checkpoint NOW
// This captures any REPL modifications made while paused
if (debugSession.ShouldCreateCheckpoint())