This commit is contained in:
Francesco Renzi
2026-03-13 11:32:56 +00:00
committed by GitHub
parent 9d33c82d61
commit 9cd74b0f26
5 changed files with 47 additions and 37 deletions

View File

@@ -19,7 +19,6 @@ namespace GitHub.Runner.Worker.Dap
}
/// <summary>
/// Production DAP debug session.
/// Handles step-level breakpoints with next/continue flow control,
/// scope/variable inspection, client reconnection, and cancellation
/// signal propagation.
@@ -116,7 +115,7 @@ namespace GitHub.Runner.Worker.Dap
return;
}
Trace.Info($"Handling DAP request: {request.Command}");
Trace.Info("Handling DAP request");
Response response;
if (request.Command == "evaluate")
@@ -156,7 +155,7 @@ namespace GitHub.Runner.Worker.Dap
}
catch (Exception ex)
{
Trace.Error($"Error handling request '{request?.Command}': {ex}");
Trace.Error($"Error handling DAP request ({ex.GetType().Name})");
if (request != null)
{
var maskedMessage = HostContext?.SecretMasker?.MaskSecrets(ex.Message) ?? ex.Message;
@@ -178,12 +177,12 @@ namespace GitHub.Runner.Worker.Dap
{
try
{
var clientCaps = request.Arguments.ToObject<InitializeRequestArguments>();
Trace.Info($"Client: {clientCaps?.ClientName ?? clientCaps?.ClientId ?? "unknown"}");
request.Arguments.ToObject<InitializeRequestArguments>();
Trace.Info("Initialize arguments received");
}
catch (Exception ex)
{
Trace.Warning($"Failed to parse initialize arguments: {ex.Message}");
Trace.Warning($"Failed to parse initialize arguments ({ex.GetType().Name})");
}
}
@@ -408,7 +407,7 @@ namespace GitHub.Runner.Worker.Dap
var frameId = args?.FrameId ?? CurrentFrameId;
var evalContext = args?.Context ?? "hover";
Trace.Info($"Evaluate request: '{expression}' (frame: {frameId}, context: {evalContext})");
Trace.Info("Evaluate request received");
// REPL context → route through the DSL dispatcher
if (string.Equals(evalContext, "repl", StringComparison.OrdinalIgnoreCase))
@@ -618,7 +617,7 @@ namespace GitHub.Runner.Worker.Dap
if (!shouldPause)
{
Trace.Info($"Step starting (not pausing): {step.DisplayName}");
Trace.Info("Step starting without debugger pause");
return;
}
@@ -627,7 +626,7 @@ namespace GitHub.Runner.Worker.Dap
? $"Stopped at job entry: {step.DisplayName}"
: $"Stopped before step: {step.DisplayName}";
Trace.Info($"Step starting: {step.DisplayName} (reason: {reason})");
Trace.Info("Step starting with debugger pause");
// Send stopped event to debugger (only if client is connected)
SendStoppedEvent(reason, description);
@@ -639,7 +638,7 @@ namespace GitHub.Runner.Worker.Dap
public void OnStepCompleted(IStep step)
{
var result = step.ExecutionContext?.Result;
Trace.Info($"Step completed: {step.DisplayName}, result: {result}");
Trace.Info("Step completed");
// Add to completed steps list for stack trace
lock (_stateLock)
@@ -797,7 +796,7 @@ namespace GitHub.Runner.Worker.Dap
{
var command = await _commandTcs.Task;
Trace.Info($"Received command: {command}");
Trace.Info("Received debugger command");
lock (_stateLock)
{
@@ -857,7 +856,7 @@ namespace GitHub.Runner.Worker.Dap
{
if (!_isClientConnected)
{
Trace.Info($"No client connected, deferring stopped event: {description}");
Trace.Info("No client connected, deferring stopped event");
return;
}

View File

@@ -56,7 +56,7 @@ namespace GitHub.Runner.Worker.Dap
}
catch (Exception ex)
{
_trace.Error($"REPL run command failed: {ex}");
_trace.Error($"REPL run command failed ({ex.GetType().Name})");
var maskedError = _hostContext.SecretMasker.MaskSecrets(ex.Message);
return ErrorResult($"Command failed: {maskedError}");
}
@@ -87,7 +87,7 @@ namespace GitHub.Runner.Worker.Dap
argFormat = ScriptHandlerHelpers.GetScriptArgumentsFormat(shellCommand);
}
_trace.Info($"REPL shell: {shellCommand}, argFormat: {argFormat}");
_trace.Info("Resolved REPL shell");
// 2. Expand ${{ }} expressions in the script body, just like
// ActionRunner evaluates step inputs before ScriptHandler sees them
@@ -142,7 +142,7 @@ namespace GitHub.Runner.Worker.Dap
workingDirectory = workspace ?? _hostContext.GetDirectory(WellKnownDirectory.Work);
}
_trace.Info($"REPL executing: {commandPath} {arguments} (cwd: {workingDirectory})");
_trace.Info("Executing REPL command");
// Stream execution info to debugger
SendOutput("console", $"$ {shellCommand} {command.Script.Substring(0, Math.Min(command.Script.Length, 80))}{(command.Script.Length > 80 ? "..." : "")}\n");
@@ -254,7 +254,7 @@ namespace GitHub.Runner.Worker.Dap
}
catch (Exception ex)
{
_trace.Warning($"Expression expansion failed for '{expr}': {ex.Message}");
_trace.Warning($"Expression expansion failed ({ex.GetType().Name})");
// Keep the original expression literal on failure
result.Append(input, start, end - start);
}
@@ -277,7 +277,7 @@ namespace GitHub.Runner.Worker.Dap
runDefaults.TryGetValue("shell", out var defaultShell) &&
!string.IsNullOrEmpty(defaultShell))
{
_trace.Info($"Using job default shell: {defaultShell}");
_trace.Info("Using job default shell");
return defaultShell;
}

View File

@@ -11,7 +11,7 @@ using Newtonsoft.Json;
namespace GitHub.Runner.Worker.Dap
{
/// <summary>
/// Production TCP server for the Debug Adapter Protocol.
/// TCP server for the Debug Adapter Protocol.
/// Handles Content-Length message framing, JSON serialization,
/// client reconnection, and graceful shutdown.
/// </summary>
@@ -116,7 +116,7 @@ namespace GitHub.Runner.Worker.Dap
}
catch (Exception ex)
{
Trace.Warning($"Connection error: {ex.Message}");
Trace.Warning($"Connection error ({ex.GetType().Name})");
CleanupConnection();
if (!_acceptConnections || cancellationToken.IsCancellationRequested)
@@ -219,11 +219,11 @@ namespace GitHub.Runner.Worker.Dap
}
catch (IOException ex)
{
Trace.Info($"Connection closed: {ex.Message}");
Trace.Info($"Connection closed ({ex.GetType().Name})");
}
catch (Exception ex)
{
Trace.Error($"Error in message loop: {ex}");
Trace.Error($"Error in message loop ({ex.GetType().Name})");
}
Trace.Info("DAP message processing loop ended");
@@ -237,11 +237,11 @@ namespace GitHub.Runner.Worker.Dap
request = JsonConvert.DeserializeObject<Request>(json);
if (request == null || request.Type != "request")
{
Trace.Warning($"Received non-request message: {json}");
Trace.Warning("Received DAP message that was not a request");
return;
}
Trace.Info($"Received request: seq={request.Seq}, command={request.Command}");
Trace.Info("Received DAP request");
if (_session == null)
{
@@ -256,11 +256,11 @@ namespace GitHub.Runner.Worker.Dap
}
catch (JsonException ex)
{
Trace.Error($"Failed to parse request: {ex.Message}");
Trace.Error($"Failed to parse request ({ex.GetType().Name})");
}
catch (Exception ex)
{
Trace.Error($"Error processing request: {ex}");
Trace.Error($"Error processing request ({ex.GetType().Name})");
if (request != null)
{
SendErrorResponse(request, ex.Message);
@@ -345,7 +345,7 @@ namespace GitHub.Runner.Worker.Dap
}
var json = Encoding.UTF8.GetString(buffer);
Trace.Verbose($"Received: {json}");
Trace.Verbose("Received DAP message body");
return json;
}
@@ -414,7 +414,7 @@ namespace GitHub.Runner.Worker.Dap
_stream.Write(bodyBytes, 0, bodyBytes.Length);
_stream.Flush();
Trace.Verbose($"Sent: {json}");
Trace.Verbose("Sent DAP message");
}
public void SendMessage(ProtocolMessage message)
@@ -438,7 +438,7 @@ namespace GitHub.Runner.Worker.Dap
}
catch (Exception ex)
{
Trace.Warning($"Failed to send message: {ex.Message}");
Trace.Warning($"Failed to send message ({ex.GetType().Name})");
}
}
@@ -451,7 +451,7 @@ namespace GitHub.Runner.Worker.Dap
{
if (_stream == null)
{
Trace.Warning($"Cannot send event '{evt.EventType}': no client connected");
Trace.Warning("Cannot send event: no client connected");
return;
}
evt.Seq = _nextSeq++;
@@ -461,11 +461,11 @@ namespace GitHub.Runner.Worker.Dap
{
_sendLock.Release();
}
Trace.Info($"Sent event: {evt.EventType}");
Trace.Info("Sent event");
}
catch (Exception ex)
{
Trace.Warning($"Failed to send event '{evt.EventType}': {ex.Message}");
Trace.Warning($"Failed to send event ({ex.GetType().Name})");
}
}
@@ -478,7 +478,7 @@ namespace GitHub.Runner.Worker.Dap
{
if (_stream == null)
{
Trace.Warning($"Cannot send response for '{response.Command}': no client connected");
Trace.Warning("Cannot send response: no client connected");
return;
}
response.Seq = _nextSeq++;
@@ -488,11 +488,11 @@ namespace GitHub.Runner.Worker.Dap
{
_sendLock.Release();
}
Trace.Info($"Sent response: seq={response.Seq}, command={response.Command}, success={response.Success}");
Trace.Info("Sent response");
}
catch (Exception ex)
{
Trace.Warning($"Failed to send response for '{response.Command}': {ex.Message}");
Trace.Warning($"Failed to send response ({ex.GetType().Name})");
}
}
}

View File

@@ -124,14 +124,18 @@ namespace GitHub.Runner.Common.Tests.Worker
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public void ResolveDefaultShell_NoJobDefaults_ReturnsSh()
public void ResolveDefaultShell_NoJobDefaults_ReturnsPlatformDefault()
{
using (CreateTestContext())
{
var context = CreateMockContext();
var result = _executor.ResolveDefaultShell(context.Object);
#if OS_WINDOWS
Assert.True(result == "pwsh" || result == "powershell");
#else
Assert.Equal("sh", result);
#endif
}
}

View File

@@ -164,9 +164,10 @@ namespace GitHub.Runner.Common.Tests.Worker
var cts1 = new CancellationTokenSource();
await _server.StartAsync(0, cts1.Token);
await _server.StopAsync();
}
_server = new DapServer();
_server.Initialize(CreateTestContext());
using (CreateTestContext($"{nameof(StartAndStopMultipleTimesDoesNotThrow)}_SecondStart"))
{
var cts2 = new CancellationTokenSource();
await _server.StartAsync(0, cts2.Token);
await _server.StopAsync();
@@ -194,8 +195,10 @@ namespace GitHub.Runner.Common.Tests.Worker
var listener = (TcpListener)listenerField.GetValue(_server);
var port = ((IPEndPoint)listener.LocalEndpoint).Port;
var connectionTask = _server.WaitForConnectionAsync(cts.Token);
using var client = new TcpClient();
await client.ConnectAsync(IPAddress.Loopback, port);
await connectionTask;
var stream = client.GetStream();
// Send a valid DAP request with Content-Length framing
@@ -237,8 +240,10 @@ namespace GitHub.Runner.Common.Tests.Worker
var listener = (TcpListener)listenerField.GetValue(_server);
var port = ((IPEndPoint)listener.LocalEndpoint).Port;
var connectionTask = _server.WaitForConnectionAsync(cts.Token);
using var client = new TcpClient();
await client.ConnectAsync(IPAddress.Loopback, port);
await connectionTask;
var stream = client.GetStream();
// Send a response whose protocol fields collide with secrets
@@ -288,8 +293,10 @@ namespace GitHub.Runner.Common.Tests.Worker
var listener = (TcpListener)listenerField.GetValue(_server);
var port = ((IPEndPoint)listener.LocalEndpoint).Port;
var connectionTask = _server.WaitForConnectionAsync(cts.Token);
using var client = new TcpClient();
await client.ConnectAsync(IPAddress.Loopback, port);
await connectionTask;
var stream = client.GetStream();
_server.SendEvent(new Event