Skip to content

Commit 6603bfb

Browse files
enescakirthboop
andauthored
Add a retry logic to docker login operation (#3089)
While there's an existing retry mechanism for the `docker pull` command [^1], it's missing for `docker login`. Similar to the `docker pull` scenario, the container registry could potentially be briefly unavailable or inaccessible, leading to failed `docker login` attempt and subsequent workflow run failures. Since it's container based workflow, there is not way to retry on customer side. The runner should retry itself. It also aligns with community feedback [^2]. [^1]: https://github.com/actions/runner/blob/8e0cd36cd8c74c3067ffe10189c1e42f7e753af2/src/Runner.Worker/ContainerOperationProvider.cs#L201 [^2]: https://github.com/orgs/community/discussions/73069 Co-authored-by: Thomas Boop <[email protected]>
1 parent b19b946 commit 6603bfb

File tree

1 file changed

+29
-7
lines changed

1 file changed

+29
-7
lines changed

src/Runner.Worker/ContainerOperationProvider.cs

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -466,17 +466,39 @@ private async Task<string> ContainerRegistryLogin(IExecutionContext executionCon
466466
{
467467
throw new InvalidOperationException($"Failed to create directory to store registry client credentials: {e.Message}");
468468
}
469-
var loginExitCode = await _dockerManager.DockerLogin(
470-
executionContext,
471-
configLocation,
472-
container.RegistryServer,
473-
container.RegistryAuthUsername,
474-
container.RegistryAuthPassword);
475469

476-
if (loginExitCode != 0)
470+
// Login docker with retry up to 3 times
471+
int retryCount = 0;
472+
int loginExitCode = 0;
473+
while (retryCount < 3)
474+
{
475+
loginExitCode = await _dockerManager.DockerLogin(
476+
executionContext,
477+
configLocation,
478+
container.RegistryServer,
479+
container.RegistryAuthUsername,
480+
container.RegistryAuthPassword);
481+
if (loginExitCode == 0)
482+
{
483+
break;
484+
}
485+
else
486+
{
487+
retryCount++;
488+
if (retryCount < 3)
489+
{
490+
var backOff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(10));
491+
executionContext.Warning($"Docker login for '{container.RegistryServer}' failed with exit code {loginExitCode}, back off {backOff.TotalSeconds} seconds before retry.");
492+
await Task.Delay(backOff);
493+
}
494+
}
495+
}
496+
497+
if (retryCount == 3 && loginExitCode != 0)
477498
{
478499
throw new InvalidOperationException($"Docker login for '{container.RegistryServer}' failed with exit code {loginExitCode}");
479500
}
501+
480502
return configLocation;
481503
}
482504

0 commit comments

Comments
 (0)