mirror of
https://github.com/docker/login-action.git
synced 2025-04-01 20:50:06 +02:00
Added input parameters which retry docker.login() in case of error
Signed-off-by: eegiazarov <52110484+eegiazarov@users.noreply.github.com>
This commit is contained in:
parent
dd4fa0671b
commit
c43cbe2c6a
6 changed files with 75 additions and 11 deletions
16
README.md
16
README.md
|
@ -454,13 +454,15 @@ jobs:
|
||||||
|
|
||||||
Following inputs can be used as `step.with` keys
|
Following inputs can be used as `step.with` keys
|
||||||
|
|
||||||
| Name | Type | Default | Description |
|
| Name | Type | Default | Description |
|
||||||
|------------------|---------|-----------------------------|------------------------------------|
|
|------------ --------|--------|---------|------------------------------------|
|
||||||
| `registry` | String | | Server address of Docker registry. If not set then will default to Docker Hub |
|
| `registry` | String | | Server address of Docker registry. If not set then will default to Docker Hub |
|
||||||
| `username` | String | | Username used to log against the Docker registry |
|
| `username` | String | | Username used to log against the Docker registry |
|
||||||
| `password` | String | | Password or personal access token used to log against the Docker registry |
|
| `password` | String | | Password or personal access token used to log against the Docker registry |
|
||||||
| `ecr` | String | `auto` | Specifies whether the given registry is ECR (`auto`, `true` or `false`) |
|
| `ecr` | String | `auto` | Specifies whether the given registry is ECR (`auto`, `true` or `false`) |
|
||||||
| `logout` | Bool | `true` | Log out from the Docker registry at the end of a job |
|
| `logout` | Bool | `true` | Log out from the Docker registry at the end of a job |
|
||||||
|
| `retries` | String | `3` | Maximum retries in case of errors (limit of 50 hardcoded) |
|
||||||
|
| `retryErrorPattern` | String | | Regexp to match error message |
|
||||||
|
|
||||||
## Keep up-to-date with GitHub Dependabot
|
## Keep up-to-date with GitHub Dependabot
|
||||||
|
|
||||||
|
|
|
@ -70,3 +70,23 @@ test('calls docker login', async () => {
|
||||||
expect(setLogoutSpy).toHaveBeenCalledWith(logout);
|
expect(setLogoutSpy).toHaveBeenCalledWith(logout);
|
||||||
expect(dockerSpy).toHaveBeenCalledWith(registry, username, password, ecr);
|
expect(dockerSpy).toHaveBeenCalledWith(registry, username, password, ecr);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('retried error without username and password', async () => {
|
||||||
|
const platSpy = jest.spyOn(osm, 'platform').mockImplementation(() => 'linux');
|
||||||
|
|
||||||
|
const setFailedSpy = jest.spyOn(core, 'setFailed');
|
||||||
|
const warningSpy = jest.spyOn(core, 'warning');
|
||||||
|
const dockerSpy = jest.spyOn(docker, 'login');
|
||||||
|
dockerSpy.mockImplementation(() => {
|
||||||
|
throw Error('Username and password required');
|
||||||
|
});
|
||||||
|
|
||||||
|
process.env['INPUT_LOGOUT'] = 'true'; // default value
|
||||||
|
process.env['INPUT_RETRYERRORPATTERN'] = '.*and password.*';
|
||||||
|
process.env['INPUT_RETRIES'] = '5';
|
||||||
|
|
||||||
|
await run();
|
||||||
|
expect(warningSpy).toHaveBeenCalledWith('Error <<<Username and password required>>> is recoverable, retrying...');
|
||||||
|
expect(warningSpy).toBeCalledTimes(4);
|
||||||
|
expect(setFailedSpy).toHaveBeenCalledWith('Username and password required');
|
||||||
|
});
|
||||||
|
|
|
@ -24,6 +24,13 @@ inputs:
|
||||||
description: 'Log out from the Docker registry at the end of a job'
|
description: 'Log out from the Docker registry at the end of a job'
|
||||||
default: 'true'
|
default: 'true'
|
||||||
required: false
|
required: false
|
||||||
|
retryErrorPattern:
|
||||||
|
description: "Regexp to match error message"
|
||||||
|
required: false
|
||||||
|
retries:
|
||||||
|
description: "Maximum retries in case of errors (limit of 50 hardcoded)"
|
||||||
|
default: "3"
|
||||||
|
required: false
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: 'node12'
|
using: 'node12'
|
||||||
|
|
22
dist/index.js
generated
vendored
22
dist/index.js
generated
vendored
|
@ -185,7 +185,9 @@ function getInputs() {
|
||||||
username: core.getInput('username'),
|
username: core.getInput('username'),
|
||||||
password: core.getInput('password'),
|
password: core.getInput('password'),
|
||||||
ecr: core.getInput('ecr'),
|
ecr: core.getInput('ecr'),
|
||||||
logout: core.getBooleanInput('logout')
|
logout: core.getBooleanInput('logout'),
|
||||||
|
retryErrorPattern: core.getInput('retryErrorPattern'),
|
||||||
|
retries: core.getInput('retries')
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
exports.getInputs = getInputs;
|
exports.getInputs = getInputs;
|
||||||
|
@ -329,7 +331,23 @@ async function run() {
|
||||||
const input = context.getInputs();
|
const input = context.getInputs();
|
||||||
stateHelper.setRegistry(input.registry);
|
stateHelper.setRegistry(input.registry);
|
||||||
stateHelper.setLogout(input.logout);
|
stateHelper.setLogout(input.logout);
|
||||||
await docker.login(input.registry, input.username, input.password, input.ecr);
|
let retryErrorPattern = input.retryErrorPattern;
|
||||||
|
let attemptCount = parseInt(input.retries);
|
||||||
|
if (isNaN(attemptCount))
|
||||||
|
attemptCount = 3;
|
||||||
|
attemptCount = Math.min(attemptCount, 50);
|
||||||
|
// eslint-disable-next-line no-constant-condition
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
await docker.login(input.registry, input.username, input.password, input.ecr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
if (!retryErrorPattern || !RegExp(retryErrorPattern).test(error.message) || --attemptCount <= 0)
|
||||||
|
throw error;
|
||||||
|
core.warning(`Error <<<${error.message}>>> is recoverable, retrying...`);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
core.setFailed(error.message);
|
core.setFailed(error.message);
|
||||||
|
|
|
@ -6,6 +6,8 @@ export interface Inputs {
|
||||||
password: string;
|
password: string;
|
||||||
ecr: string;
|
ecr: string;
|
||||||
logout: boolean;
|
logout: boolean;
|
||||||
|
retryErrorPattern: string;
|
||||||
|
retries: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getInputs(): Inputs {
|
export function getInputs(): Inputs {
|
||||||
|
@ -14,6 +16,8 @@ export function getInputs(): Inputs {
|
||||||
username: core.getInput('username'),
|
username: core.getInput('username'),
|
||||||
password: core.getInput('password'),
|
password: core.getInput('password'),
|
||||||
ecr: core.getInput('ecr'),
|
ecr: core.getInput('ecr'),
|
||||||
logout: core.getBooleanInput('logout')
|
logout: core.getBooleanInput('logout'),
|
||||||
|
retryErrorPattern: core.getInput('retryErrorPattern'),
|
||||||
|
retries: core.getInput('retries')
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
15
src/main.ts
15
src/main.ts
|
@ -8,7 +8,20 @@ export async function run(): Promise<void> {
|
||||||
const input: context.Inputs = context.getInputs();
|
const input: context.Inputs = context.getInputs();
|
||||||
stateHelper.setRegistry(input.registry);
|
stateHelper.setRegistry(input.registry);
|
||||||
stateHelper.setLogout(input.logout);
|
stateHelper.setLogout(input.logout);
|
||||||
await docker.login(input.registry, input.username, input.password, input.ecr);
|
let retryErrorPattern = input.retryErrorPattern;
|
||||||
|
let attemptCount = parseInt(input.retries);
|
||||||
|
if (isNaN(attemptCount)) attemptCount = 3;
|
||||||
|
attemptCount = Math.min(attemptCount, 50);
|
||||||
|
// eslint-disable-next-line no-constant-condition
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
await docker.login(input.registry, input.username, input.password, input.ecr);
|
||||||
|
break;
|
||||||
|
} catch (error: any) {
|
||||||
|
if (!retryErrorPattern || !RegExp(retryErrorPattern).test(error.message) || --attemptCount <= 0) throw error;
|
||||||
|
core.warning(`Error <<<${error.message}>>> is recoverable, retrying...`);
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
core.setFailed(error.message);
|
core.setFailed(error.message);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue