From a4072e71ae450119e8bec02af67d0681abb47fef Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Feb 2026 02:23:58 +0000 Subject: [PATCH 1/4] Initial plan From 5ba673a0140857370ff34c61efe5822b7f59ff7b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Feb 2026 02:32:09 +0000 Subject: [PATCH 2/4] Add test for work directory creation failure during runner startup Co-authored-by: TingluoHuang <1750815+TingluoHuang@users.noreply.github.com> --- src/Test/L0/Listener/RunnerL0.cs | 64 ++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/src/Test/L0/Listener/RunnerL0.cs b/src/Test/L0/Listener/RunnerL0.cs index 456f51cc977..b0b1b59e65a 100644 --- a/src/Test/L0/Listener/RunnerL0.cs +++ b/src/Test/L0/Listener/RunnerL0.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using GitHub.DistributedTask.WebApi; @@ -1076,5 +1077,68 @@ public async Task TestRunnerEnableAuthMigrationByDefault() Assert.True(hc.AllowAuthMigration); } } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Runner")] + public async Task RunCommand_ShouldReturnTerminatedError_WhenWorkDirCreationFails() + { + using (var hostCtx = new TestHostContext(this)) + { + // Setup: arrange mocks and runner instance + var runnerInstance = new Runner.Listener.Runner(); + hostCtx.SetSingleton(_configurationManager.Object); + hostCtx.SetSingleton(_jobNotification.Object); + hostCtx.SetSingleton(_messageListener.Object); + hostCtx.SetSingleton(_promptManager.Object); + hostCtx.SetSingleton(_configStore.Object); + hostCtx.SetSingleton(_runnerServer.Object); + hostCtx.EnqueueInstance(_acquireJobThrottler.Object); + + runnerInstance.Initialize(hostCtx); + + // Create a file at the work directory path to block directory creation + string workPath = hostCtx.GetDirectory(WellKnownDirectory.Work); + + // Clean up any existing directory first + if (Directory.Exists(workPath)) + { + Directory.Delete(workPath, recursive: true); + } + + // Place a file where the work directory should be - this blocks Directory.CreateDirectory + string parentPath = Path.GetDirectoryName(workPath); + Directory.CreateDirectory(parentPath); + File.WriteAllText(workPath, "blocking file content"); + + var runnerConfig = new RunnerSettings + { + PoolId = 12345, + AgentId = 67890 + }; + + _configurationManager.Setup(m => m.LoadSettings()).Returns(runnerConfig); + _configurationManager.Setup(m => m.IsConfigured()).Returns(true); + _configStore.Setup(m => m.IsServiceConfigured()).Returns(false); + + try + { + // Execute: run the command which should fail during work dir validation + var cmd = new CommandSettings(hostCtx, new string[] { "run" }); + int exitCode = await runnerInstance.ExecuteCommand(cmd); + + // Verify: should return TerminatedError code when dir creation fails + Assert.Equal(Constants.Runner.ReturnCode.TerminatedError, exitCode); + } + finally + { + // Cleanup: remove the blocking file + if (File.Exists(workPath)) + { + File.Delete(workPath); + } + } + } + } } } From 4b97e637f56731d0e22b88fc6a1ab10c027a03ef Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Feb 2026 02:33:53 +0000 Subject: [PATCH 3/4] Address code review feedback: remove unused import and use named constants Co-authored-by: TingluoHuang <1750815+TingluoHuang@users.noreply.github.com> --- src/Test/L0/Listener/RunnerL0.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Test/L0/Listener/RunnerL0.cs b/src/Test/L0/Listener/RunnerL0.cs index b0b1b59e65a..ed90b7d1f9a 100644 --- a/src/Test/L0/Listener/RunnerL0.cs +++ b/src/Test/L0/Listener/RunnerL0.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using GitHub.DistributedTask.WebApi; @@ -1111,10 +1110,13 @@ public async Task RunCommand_ShouldReturnTerminatedError_WhenWorkDirCreationFail Directory.CreateDirectory(parentPath); File.WriteAllText(workPath, "blocking file content"); + const int testPoolId = 12345; + const int testAgentId = 67890; + var runnerConfig = new RunnerSettings { - PoolId = 12345, - AgentId = 67890 + PoolId = testPoolId, + AgentId = testAgentId }; _configurationManager.Setup(m => m.LoadSettings()).Returns(runnerConfig); From 81255a9ac1f278f5cda17b4efe47386e9e144d78 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Feb 2026 02:47:23 +0000 Subject: [PATCH 4/4] Improve test robustness with path validation and named constant Co-authored-by: TingluoHuang <1750815+TingluoHuang@users.noreply.github.com> --- src/Test/L0/Listener/RunnerL0.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Test/L0/Listener/RunnerL0.cs b/src/Test/L0/Listener/RunnerL0.cs index ed90b7d1f9a..a8f432a0686 100644 --- a/src/Test/L0/Listener/RunnerL0.cs +++ b/src/Test/L0/Listener/RunnerL0.cs @@ -1107,8 +1107,12 @@ public async Task RunCommand_ShouldReturnTerminatedError_WhenWorkDirCreationFail // Place a file where the work directory should be - this blocks Directory.CreateDirectory string parentPath = Path.GetDirectoryName(workPath); + Assert.NotNull(parentPath); + Assert.NotEmpty(parentPath); Directory.CreateDirectory(parentPath); - File.WriteAllText(workPath, "blocking file content"); + + const string blockingFileContent = "test file blocking directory creation"; + File.WriteAllText(workPath, blockingFileContent); const int testPoolId = 12345; const int testAgentId = 67890;