import * as aws from './aws'; 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, 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); } } } } export async function logout(registry: string): Promise { await Docker.getExecOutput(['logout', registry], { ignoreReturnCode: true }).then(res => { if (res.stderr.length > 0 && res.exitCode != 0) { core.warning(res.stderr.trim()); } }); } 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'); } if (!username) { throw new Error('Username required'); } if (!password) { throw new Error('Password required'); } const loginArgs: Array = ['login', '--password-stdin']; loginArgs.push('--username', username); loginArgs.push(registry); if (registry) { core.info(`Logging into ${registry}...`); } 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()); } core.info(`Login Succeeded!`); }); } export async function loginECR(registry: string, username: string, password: string): Promise { core.info(`Retrieving registries data through AWS SDK...`); const regDatas = await aws.getRegistriesData(registry, username, password); for (const regData of regDatas) { core.info(`Logging into ${regData.registry}...`); await Docker.getExecOutput(['login', '--password-stdin', '--username', regData.username, regData.registry], { ignoreReturnCode: true, silent: true, input: Buffer.from(regData.password) }).then(res => { if (res.stderr.length > 0 && res.exitCode != 0) { throw new Error(res.stderr.trim()); } core.info('Login Succeeded!'); }); } }