Skip to content

Commit e6a062e

Browse files
committed
Cleanup runner config when GetMessage returns 404
1 parent 9cd4f29 commit e6a062e

2 files changed

Lines changed: 102 additions & 1 deletion

File tree

src/Runner.Listener/Runner.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,7 @@ private async Task<int> RunAsync(RunnerSettings settings, bool runOnce = false,
498498
bool skipSessionDeletion = false;
499499
bool restartSession = false; // Flag to indicate session restart
500500
bool restartSessionPending = false;
501+
bool cleanupLocalConfigAfter404 = false;
501502
try
502503
{
503504
var notification = HostContext.GetService<IJobNotification>();
@@ -813,6 +814,14 @@ await configUpdater.UpdateRunnerConfigAsync(
813814
Trace.Error($"Received message {message.MessageId} with unsupported message type {message.MessageType}.");
814815
}
815816
}
817+
catch (Exception ex) when (ex is TaskAgentNotFoundException || ex is RunnerNotFoundException)
818+
{
819+
Trace.Info($"Runner registration no longer exists while retrieving messages. {ex.Message}");
820+
_term.WriteError("The runner no longer exists on the server. Cleaning up local configuration.");
821+
skipSessionDeletion = true;
822+
cleanupLocalConfigAfter404 = true;
823+
break;
824+
}
816825
finally
817826
{
818827
if (!skipMessageDeletion && message != null)
@@ -859,7 +868,7 @@ await configUpdater.UpdateRunnerConfigAsync(
859868

860869
messageQueueLoopTokenSource.Dispose();
861870

862-
if (settings.Ephemeral && runOnceJobCompleted)
871+
if ((settings.Ephemeral && runOnceJobCompleted) || cleanupLocalConfigAfter404)
863872
{
864873
configManager.DeleteLocalRunnerConfig();
865874
}

src/Test/L0/Listener/RunnerL0.cs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public sealed class RunnerL0 : IDisposable
2929
private Mock<ICredentialManager> _credentialManager;
3030
private Mock<IActionsRunServer> _actionsRunServer;
3131
private Mock<IRunServer> _runServer;
32+
private Mock<IBrokerServer> _brokerServer;
3233
private readonly string _returnJobResultForHosted;
3334

3435
public RunnerL0()
@@ -46,6 +47,7 @@ public RunnerL0()
4647
_credentialManager = new Mock<ICredentialManager>();
4748
_actionsRunServer = new Mock<IActionsRunServer>();
4849
_runServer = new Mock<IRunServer>();
50+
_brokerServer = new Mock<IBrokerServer>();
4951

5052
_returnJobResultForHosted = Environment.GetEnvironmentVariable("ACTIONS_RUNNER_RETURN_JOB_RESULT_FOR_HOSTED");
5153
Environment.SetEnvironmentVariable("ACTIONS_RUNNER_RETURN_JOB_RESULT_FOR_HOSTED", null);
@@ -175,6 +177,96 @@ public async Task TestRunAsync()
175177
}
176178
}
177179

180+
[Fact]
181+
[Trait("Level", "L0")]
182+
[Trait("Category", "Runner")]
183+
public async Task TestRunAsyncCleanupLocalConfigWhenGetNextMessageReturnsNotFound()
184+
{
185+
using (var hc = new TestHostContext(this))
186+
{
187+
//Arrange
188+
var runner = new Runner.Listener.Runner();
189+
hc.SetSingleton<IConfigurationManager>(_configurationManager.Object);
190+
hc.SetSingleton<IJobNotification>(_jobNotification.Object);
191+
hc.SetSingleton<IPromptManager>(_promptManager.Object);
192+
hc.SetSingleton<IRunnerServer>(_runnerServer.Object);
193+
hc.SetSingleton<IBrokerServer>(_brokerServer.Object);
194+
hc.SetSingleton<ICredentialManager>(_credentialManager.Object);
195+
hc.SetSingleton<IConfigurationStore>(_configStore.Object);
196+
hc.EnqueueInstance<IErrorThrottler>(_acquireJobThrottler.Object);
197+
hc.EnqueueInstance<IJobDispatcher>(_jobDispatcher.Object);
198+
199+
var messageListener = new MessageListener();
200+
messageListener.Initialize(hc);
201+
hc.SetSingleton<IMessageListener>(messageListener);
202+
203+
runner.Initialize(hc);
204+
205+
var settings = new RunnerSettings
206+
{
207+
AgentId = 1,
208+
AgentName = "myagent",
209+
PoolId = 43242,
210+
PoolName = "default",
211+
ServerUrl = "http://myserver",
212+
WorkFolder = "_work",
213+
Ephemeral = false,
214+
};
215+
216+
_configurationManager.Setup(x => x.LoadSettings())
217+
.Returns(settings);
218+
_configurationManager.Setup(x => x.IsConfigured())
219+
.Returns(true);
220+
_credentialManager.Setup(x => x.LoadCredentials(false)).Returns(new VssCredentials());
221+
_runnerServer.Setup(x => x.ConnectAsync(It.IsAny<Uri>(), It.IsAny<VssCredentials>()))
222+
.Returns(Task.CompletedTask);
223+
_runnerServer.Setup(x => x.CreateAgentSessionAsync(
224+
settings.PoolId,
225+
It.Is<TaskAgentSession>(x => x != null),
226+
It.IsAny<CancellationToken>()))
227+
.Returns(Task.FromResult(new TaskAgentSession()));
228+
_runnerServer.Setup(x => x.GetAgentMessageAsync(
229+
settings.PoolId,
230+
It.IsAny<Guid>(),
231+
It.IsAny<long?>(),
232+
TaskAgentStatus.Online,
233+
It.IsAny<string>(),
234+
It.IsAny<string>(),
235+
It.IsAny<string>(),
236+
It.IsAny<bool>(),
237+
It.IsAny<CancellationToken>()))
238+
.Throws(new TaskAgentNotFoundException("runner not found"));
239+
_jobNotification.Setup(x => x.StartClient(It.IsAny<string>()));
240+
_configStore.Setup(x => x.IsServiceConfigured()).Returns(false);
241+
242+
//Act
243+
var command = new CommandSettings(hc, new string[] { "run" });
244+
var result = await runner.ExecuteCommand(command);
245+
246+
//Assert
247+
Assert.Equal(Constants.Runner.ReturnCode.Success, result);
248+
_runnerServer.Verify(x => x.CreateAgentSessionAsync(
249+
settings.PoolId,
250+
It.Is<TaskAgentSession>(x => x != null),
251+
It.IsAny<CancellationToken>()), Times.Once());
252+
_runnerServer.Verify(x => x.GetAgentMessageAsync(
253+
settings.PoolId,
254+
It.IsAny<Guid>(),
255+
It.IsAny<long?>(),
256+
TaskAgentStatus.Online,
257+
It.IsAny<string>(),
258+
It.IsAny<string>(),
259+
It.IsAny<string>(),
260+
It.IsAny<bool>(),
261+
It.IsAny<CancellationToken>()), Times.Once());
262+
_runnerServer.Verify(x => x.DeleteAgentSessionAsync(
263+
It.IsAny<int>(),
264+
It.IsAny<Guid>(),
265+
It.IsAny<CancellationToken>()), Times.Never());
266+
_configurationManager.Verify(x => x.DeleteLocalRunnerConfig(), Times.Once());
267+
}
268+
}
269+
178270
public static TheoryData<string[], bool, Times> RunAsServiceTestData = new TheoryData<string[], bool, Times>()
179271
{
180272
// staring with run command, configured as run as service, should start the runner

0 commit comments

Comments
 (0)