diff --git a/src/context.ts b/src/context.ts index 8a38168..103287e 100644 --- a/src/context.ts +++ b/src/context.ts @@ -6,6 +6,7 @@ export interface Inputs { password: string; ecr: string; logout: boolean; + attempts: number; } export function getInputs(): Inputs { @@ -14,6 +15,7 @@ export function getInputs(): Inputs { username: core.getInput('username'), password: core.getInput('password'), ecr: core.getInput('ecr'), - logout: core.getBooleanInput('logout') + logout: core.getBooleanInput('logout'), + attempts: Number.parseInt(core.getInput('attempts')) }; } diff --git a/src/docker.ts b/src/docker.ts index 5e2c1d5..45d64a1 100644 --- a/src/docker.ts +++ b/src/docker.ts @@ -3,11 +3,11 @@ 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 { +export async function login(registry: string, username: string, password: string, ecr: string, attempts: number): Promise { if (/true/i.test(ecr) || (ecr == 'auto' && aws.isECR(registry))) { await loginECR(registry, username, password); } else { - await loginStandard(registry, username, password); + await loginStandard(registry, username, password, attempts); } } @@ -21,7 +21,7 @@ export async function logout(registry: string): Promise { }); } -export async function loginStandard(registry: string, username: string, password: string): Promise { +export async function loginStandard(registry: string, username: string, password: string, attempts: number): Promise { if (!username && !password) { throw new Error('Username and password required'); } @@ -41,16 +41,29 @@ export async function loginStandard(registry: string, username: string, password } else { core.info(`Logging into Docker Hub...`); } - await Docker.getExecOutput(loginArgs, { - ignoreReturnCode: true, - silent: true, - input: Buffer.from(password) - }).then(res => { - if (res.stderr.length > 0 && res.exitCode != 0) { - throw new Error(res.stderr.trim()); + let attempt: number = 1 + let succeeded: boolean = false + for (let attempt = 1; (attempt <= attempts) && (!succeeded); attempt++) { + await Docker.getExecOutput(loginArgs, { + ignoreReturnCode: true, + silent: true, + input: Buffer.from(password) + }).then(res => { + if (res.stderr.length > 0 && res.exitCode != 0) { + let isRetriable: boolean + isRetriable = res.stderr.endsWith("502 Bad Gateway") + if (!isRetriable || (attempt >= attempts) { + throw new Error(res.stderr.trim()); + } + } else { + core.info(`Login Succeeded!`); + succeeded = true; + } + }); + if ((attempt < attempts) && !succeeded) { + await new Promise(r => setTimeout(r, 10000)) } - core.info(`Login Succeeded!`); - }); + } } export async function loginECR(registry: string, username: string, password: string): Promise { diff --git a/src/main.ts b/src/main.ts index f35fa21..f8481c3 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.attempts); } async function post(): Promise {