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
					
				
							
								
								
									
										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…
	
		Reference in New Issue
	
	Block a user
	 eegiazarov
						eegiazarov