mirror of
				https://github.com/docker/login-action.git
				synced 2025-10-31 18:20:10 +08: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
					
				| @ -455,12 +455,14 @@ jobs: | ||||
| Following inputs can be used as `step.with` keys | ||||
| 
 | ||||
| | Name                | Type   | Default | Description                        | | ||||
| |------------------|---------|-----------------------------|------------------------------------| | ||||
| |------------ --------|--------|---------|------------------------------------| | ||||
| | `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 | | ||||
| | `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`) | | ||||
| | `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 | ||||
| 
 | ||||
|  | ||||
| @ -70,3 +70,23 @@ test('calls docker login', async () => { | ||||
|   expect(setLogoutSpy).toHaveBeenCalledWith(logout); | ||||
|   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' | ||||
|     default: 'true' | ||||
|     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: | ||||
|   using: 'node12' | ||||
|  | ||||
							
								
								
									
										20
									
								
								dist/index.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										20
									
								
								dist/index.js
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -185,7 +185,9 @@ function getInputs() { | ||||
|         username: core.getInput('username'), | ||||
|         password: core.getInput('password'), | ||||
|         ecr: core.getInput('ecr'), | ||||
|         logout: core.getBooleanInput('logout') | ||||
|         logout: core.getBooleanInput('logout'), | ||||
|         retryErrorPattern: core.getInput('retryErrorPattern'), | ||||
|         retries: core.getInput('retries') | ||||
|     }; | ||||
| } | ||||
| exports.getInputs = getInputs; | ||||
| @ -329,7 +331,23 @@ async function run() { | ||||
|         const input = context.getInputs(); | ||||
|         stateHelper.setRegistry(input.registry); | ||||
|         stateHelper.setLogout(input.logout); | ||||
|         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) { | ||||
|         core.setFailed(error.message); | ||||
|  | ||||
| @ -6,6 +6,8 @@ export interface Inputs { | ||||
|   password: string; | ||||
|   ecr: string; | ||||
|   logout: boolean; | ||||
|   retryErrorPattern: string; | ||||
|   retries: string; | ||||
| } | ||||
| 
 | ||||
| export function getInputs(): Inputs { | ||||
| @ -14,6 +16,8 @@ export function getInputs(): Inputs { | ||||
|     username: core.getInput('username'), | ||||
|     password: core.getInput('password'), | ||||
|     ecr: core.getInput('ecr'), | ||||
|     logout: core.getBooleanInput('logout') | ||||
|     logout: core.getBooleanInput('logout'), | ||||
|     retryErrorPattern: core.getInput('retryErrorPattern'), | ||||
|     retries: core.getInput('retries') | ||||
|   }; | ||||
| } | ||||
|  | ||||
							
								
								
									
										13
									
								
								src/main.ts
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								src/main.ts
									
									
									
									
									
								
							| @ -8,7 +8,20 @@ export async function run(): Promise<void> { | ||||
|     const input: context.Inputs = context.getInputs(); | ||||
|     stateHelper.setRegistry(input.registry); | ||||
|     stateHelper.setLogout(input.logout); | ||||
|     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) { | ||||
|     core.setFailed(error.message); | ||||
|   } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 eegiazarov
						eegiazarov