mirror of
				https://github.com/docker/login-action.git
				synced 2025-10-31 01:40:11 +08:00 
			
		
		
		
	Feature: Enable Multi Registry login Authentication
Signed-off-by: unknown <arunkumarthiyagarajan95@gmail.com>
This commit is contained in:
		
							parent
							
								
									ef38ec311a
								
							
						
					
					
						commit
						8d9860ef0e
					
				
							
								
								
									
										31
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								README.md
									
									
									
									
									
								
							| @ -24,6 +24,7 @@ ___ | ||||
|   * [OCI Oracle Cloud Infrastructure Registry (OCIR)](#oci-oracle-cloud-infrastructure-registry-ocir) | ||||
|   * [Quay.io](#quayio) | ||||
|   * [DigitalOcean](#digitalocean-container-registry) | ||||
|   * [Multiple Registries](#multiple-registries) | ||||
| * [Customizing](#customizing) | ||||
|   * [inputs](#inputs) | ||||
| * [Contributing](#contributing) | ||||
| @ -494,6 +495,34 @@ jobs: | ||||
|           password: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }} | ||||
| ``` | ||||
| 
 | ||||
| ### Multiple Registries | ||||
| You can login to multiple registries by providing a multiline string for the registry input. Each registry will be processed sequentically using the same username and password. | ||||
| 
 | ||||
| ```yaml | ||||
| name: ci | ||||
| 
 | ||||
| on: | ||||
|   push: | ||||
|     branches: main | ||||
| 
 | ||||
| jobs: | ||||
|   login: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Login to Multiple Regsitries | ||||
|         uses: docker/login-action@v7 | ||||
|         with: | ||||
|           registry: | | ||||
|             ghcr.io | ||||
|             docker.io | ||||
|             registry.gitlab.com | ||||
|           # for single registry,  | ||||
|           # registry: "ghcr.io" | ||||
|           username: ${{ vars.REGISTRY_USERNAME }} | ||||
|           password: ${{ secrets.REGISTRY_PASSWORD }} | ||||
| ``` | ||||
| 
 | ||||
| ## Customizing | ||||
| 
 | ||||
| ### inputs | ||||
| @ -502,7 +531,7 @@ The 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 | | ||||
| | `registry` | String |         | Server address of Docker registry. If not set then will default to Docker Hub. Supports multiline string for multiplr registries. | | ||||
| | `username` | String |         | Username for authenticating to the Docker registry                            | | ||||
| | `password` | String |         | Password or personal access token for authenticating the Docker registry      | | ||||
| | `ecr`      | String | `auto`  | Specifies whether the given registry is ECR (`auto`, `true` or `false`)       | | ||||
|  | ||||
| @ -20,17 +20,34 @@ test('loginStandard calls exec', async () => { | ||||
| 
 | ||||
|   const username = 'dbowie'; | ||||
|   const password = 'groundcontrol'; | ||||
|   const registry = 'https://ghcr.io'; | ||||
|   // Define const registry as multiline input
 | ||||
|   const registry = `https://ghcr.io
 | ||||
| https://docker.io`;
 | ||||
| 
 | ||||
|   await loginStandard(registry, username, password); | ||||
|   const registryArray = registry.split('\n').map(r => r.trim()); | ||||
| 
 | ||||
|   expect(execSpy).toHaveBeenCalledTimes(1); | ||||
|   const callfunc = execSpy.mock.calls[0]; | ||||
|   if (callfunc && callfunc[1]) { | ||||
|     // we don't want to check env opt
 | ||||
|     callfunc[1].env = undefined; | ||||
|   for (const reg of registryArray) { | ||||
|     await loginStandard(reg, username, password); | ||||
|   } | ||||
|   expect(execSpy).toHaveBeenCalledWith(['login', '--password-stdin', '--username', username, registry], { | ||||
| 
 | ||||
|   expect(execSpy).toHaveBeenCalledTimes(2); | ||||
|   const firstcall = execSpy.mock.calls[0]; | ||||
|   if (firstcall && firstcall[1]) { | ||||
|     // we don't want to check env opt
 | ||||
|     firstcall[1].env = undefined; | ||||
|   } | ||||
|   expect(execSpy).toHaveBeenCalledWith(['login', '--password-stdin', '--username', username, registryArray[0]], { | ||||
|     input: Buffer.from(password), | ||||
|     silent: true, | ||||
|     ignoreReturnCode: true | ||||
|   }); | ||||
| 
 | ||||
|   const secondcall = execSpy.mock.calls[1]; | ||||
|   if (secondcall && secondcall[1]) { | ||||
|     // we don't want to check env opt
 | ||||
|     secondcall[1].env = undefined; | ||||
|   } | ||||
|   expect(execSpy).toHaveBeenCalledWith(['login', '--password-stdin', '--username', username, registryArray[1]], { | ||||
|     input: Buffer.from(password), | ||||
|     silent: true, | ||||
|     ignoreReturnCode: true | ||||
| @ -48,17 +65,32 @@ test('logout calls exec', async () => { | ||||
|     }; | ||||
|   }); | ||||
| 
 | ||||
|   const registry = 'https://ghcr.io'; | ||||
|   const registry = `https://ghcr.io
 | ||||
| https://docker.io`;
 | ||||
| 
 | ||||
|   await logout(registry); | ||||
|   const registryArray = registry.split('\n').map(r => r.trim()); | ||||
| 
 | ||||
|   expect(execSpy).toHaveBeenCalledTimes(1); | ||||
|   const callfunc = execSpy.mock.calls[0]; | ||||
|   if (callfunc && callfunc[1]) { | ||||
|     // we don't want to check env opt
 | ||||
|     callfunc[1].env = undefined; | ||||
|   for (const reg of registryArray) { | ||||
|     await logout(reg); | ||||
|   } | ||||
|   expect(execSpy).toHaveBeenCalledWith(['logout', registry], { | ||||
| 
 | ||||
|   expect(execSpy).toHaveBeenCalledTimes(2); | ||||
|   const firstcall = execSpy.mock.calls[0]; | ||||
|   if (firstcall && firstcall[1]) { | ||||
|     // we don't want to check env opt
 | ||||
|     firstcall[1].env = undefined; | ||||
|   } | ||||
|   expect(execSpy).toHaveBeenCalledWith(['logout', registryArray[0]], { | ||||
|     ignoreReturnCode: true | ||||
|   }); | ||||
| 
 | ||||
|   const secondcall = execSpy.mock.calls[1]; | ||||
|   if (secondcall && secondcall[1]) { | ||||
|     // we don't want to check env opt
 | ||||
|     secondcall[1].env = undefined; | ||||
|   } | ||||
| 
 | ||||
|   expect(execSpy).toHaveBeenCalledWith(['logout', registryArray[1]], { | ||||
|     ignoreReturnCode: true | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| import * as core from '@actions/core'; | ||||
| 
 | ||||
| export interface Inputs { | ||||
|   registry: string; | ||||
|   registry: string[]; | ||||
|   username: string; | ||||
|   password: string; | ||||
|   ecr: string; | ||||
| @ -10,7 +10,7 @@ export interface Inputs { | ||||
| 
 | ||||
| export function getInputs(): Inputs { | ||||
|   return { | ||||
|     registry: core.getInput('registry'), | ||||
|     registry: core.getMultilineInput('registry'), | ||||
|     username: core.getInput('username'), | ||||
|     password: core.getInput('password'), | ||||
|     ecr: core.getInput('ecr'), | ||||
|  | ||||
							
								
								
									
										11
									
								
								src/main.ts
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								src/main.ts
									
									
									
									
									
								
							| @ -4,18 +4,23 @@ import * as context from './context'; | ||||
| import * as docker from './docker'; | ||||
| import * as stateHelper from './state-helper'; | ||||
| 
 | ||||
| const input: context.Inputs = context.getInputs(); | ||||
| 
 | ||||
| export async function main(): Promise<void> { | ||||
|   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); | ||||
|   for (const reg of input.registry) { | ||||
|     await docker.login(reg, input.username, input.password, input.ecr); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| async function post(): Promise<void> { | ||||
|   if (!stateHelper.logout) { | ||||
|     return; | ||||
|   } | ||||
|   await docker.logout(stateHelper.registry); | ||||
|   for (const reg of input.registry) { | ||||
|     await docker.logout(reg); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| actionsToolkit.run(main, post); | ||||
|  | ||||
| @ -3,8 +3,9 @@ import * as core from '@actions/core'; | ||||
| export const registry = process.env['STATE_registry'] || ''; | ||||
| export const logout = /true/i.test(process.env['STATE_logout'] || ''); | ||||
| 
 | ||||
| export function setRegistry(registry: string) { | ||||
|   core.saveState('registry', registry); | ||||
| export function setRegistry(registry: string[]) { | ||||
|   core.info(`Setting registry: ${registry.join(',')}`); | ||||
|   core.saveState('registry', registry.join(',')); | ||||
| } | ||||
| 
 | ||||
| export function setLogout(logout: boolean) { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 unknown
						unknown