From b909aa9ffec01ca1a916c38ca0d9188025c0aa91 Mon Sep 17 00:00:00 2001 From: Fedor Dikarev Date: Thu, 23 Jan 2025 02:47:49 +0100 Subject: [PATCH] add retries logic Signed-off-by: Fedor Dikarev --- src/docker.ts | 32 +++++++++++++++++++++++++++----- src/main.ts | 2 +- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/docker.ts b/src/docker.ts index 5e2c1d5..89e2d6f 100644 --- a/src/docker.ts +++ b/src/docker.ts @@ -3,11 +3,23 @@ import * as core from '@actions/core'; import {Docker} from '@docker/actions-toolkit/lib/docker/docker'; -export async function login(registry: string, username: string, password: string, ecr: string): Promise { - if (/true/i.test(ecr) || (ecr == 'auto' && aws.isECR(registry))) { - await loginECR(registry, username, password); - } else { - await loginStandard(registry, username, password); +export async function login(registry: string, username: string, password: string, ecr: string, http_errors_to_retry: string[], max_attempts: number, retry_timeout: number): Promise { + let succeeded: boolean = false; + for (let attempt = 1; (attempt <= max_attempts) && (!succeeded); attempt++) { + try { + if (/true/i.test(ecr) || (ecr == 'auto' && aws.isECR(registry))) { + await loginECR(registry, username, password); + } else { + await loginStandard(registry, username, password); + } + } catch (error) { + if ((attempt < max_attempts) && (isRetriableError(error, http_errors_to_retry))) { + core.info("Attempt ", attempt, "out of ", max_attempts, "failed, retrying after ", retry_timeout, "seconds"); + await new Promise(r => setTimeout(r, retry_timeout * 1000)); + } else { + throw new Error(error); + } + } } } @@ -21,6 +33,16 @@ export async function logout(registry: string): Promise { }); } +function isRetriableError(stderr: string, http_errors_to_retry: string[]): boolean { + const trimmedError = stderr.trim(); + for (const err_code in http_errors_to_retry) { + if (trimmedError.includes("failed with status: " + err_code)) { + return true; + } + } + return false; +} + export async function loginStandard(registry: string, username: string, password: string): Promise { if (!username && !password) { throw new Error('Username and password required'); diff --git a/src/main.ts b/src/main.ts index f35fa21..6b07005 100644 --- a/src/main.ts +++ b/src/main.ts @@ -8,7 +8,7 @@ export async function main(): Promise { const input: context.Inputs = context.getInputs(); stateHelper.setRegistry(input.registry); stateHelper.setLogout(input.logout); - await docker.login(input.registry, input.username, input.password, input.ecr); + await docker.login(input.registry, input.username, input.password, input.ecr, input.http_errors_to_retry, input.max_attempts, input.retry_timeout); } async function post(): Promise {