mirror of
				https://github.com/docker/login-action.git
				synced 2025-10-31 10:10:09 +08:00 
			
		
		
		
	Merge pull request #126 from crazy-max/aws-sdk
ecr: switch implementation to use the AWS SDK
This commit is contained in:
		
						commit
						b20b9f5e31
					
				
							
								
								
									
										44
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										44
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							| @ -83,8 +83,7 @@ jobs: | |||||||
|       matrix: |       matrix: | ||||||
|         os: |         os: | ||||||
|           - ubuntu-latest |           - ubuntu-latest | ||||||
|           - ubuntu-20.04 |           - windows-latest | ||||||
|           - ubuntu-18.04 |  | ||||||
|     steps: |     steps: | ||||||
|       - |       - | ||||||
|         name: Checkout |         name: Checkout | ||||||
| @ -103,8 +102,7 @@ jobs: | |||||||
|       matrix: |       matrix: | ||||||
|         os: |         os: | ||||||
|           - ubuntu-latest |           - ubuntu-latest | ||||||
|           - ubuntu-20.04 |           - windows-latest | ||||||
|           - ubuntu-18.04 |  | ||||||
|     steps: |     steps: | ||||||
|       - |       - | ||||||
|         name: Checkout |         name: Checkout | ||||||
| @ -124,8 +122,7 @@ jobs: | |||||||
|       matrix: |       matrix: | ||||||
|         os: |         os: | ||||||
|           - ubuntu-latest |           - ubuntu-latest | ||||||
|           - ubuntu-20.04 |           - windows-latest | ||||||
|           - ubuntu-18.04 |  | ||||||
|     steps: |     steps: | ||||||
|       - |       - | ||||||
|         name: Checkout |         name: Checkout | ||||||
| @ -150,8 +147,7 @@ jobs: | |||||||
|       matrix: |       matrix: | ||||||
|         os: |         os: | ||||||
|           - ubuntu-latest |           - ubuntu-latest | ||||||
|           - ubuntu-20.04 |           - windows-latest | ||||||
|           - ubuntu-18.04 |  | ||||||
|     steps: |     steps: | ||||||
|       - |       - | ||||||
|         name: Checkout |         name: Checkout | ||||||
| @ -165,7 +161,13 @@ jobs: | |||||||
|           password: ${{ secrets.AWS_SECRET_ACCESS_KEY }} |           password: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | ||||||
| 
 | 
 | ||||||
|   github-container: |   github-container: | ||||||
|     runs-on: ubuntu-latest |     runs-on: ${{ matrix.os }} | ||||||
|  |     strategy: | ||||||
|  |       fail-fast: false | ||||||
|  |       matrix: | ||||||
|  |         os: | ||||||
|  |           - ubuntu-latest | ||||||
|  |           - windows-latest | ||||||
|     steps: |     steps: | ||||||
|       - |       - | ||||||
|         name: Checkout |         name: Checkout | ||||||
| @ -179,7 +181,13 @@ jobs: | |||||||
|           password: ${{ secrets.GITHUB_TOKEN }} |           password: ${{ secrets.GITHUB_TOKEN }} | ||||||
| 
 | 
 | ||||||
|   gitlab: |   gitlab: | ||||||
|     runs-on: ubuntu-latest |     runs-on: ${{ matrix.os }} | ||||||
|  |     strategy: | ||||||
|  |       fail-fast: false | ||||||
|  |       matrix: | ||||||
|  |         os: | ||||||
|  |           - ubuntu-latest | ||||||
|  |           - windows-latest | ||||||
|     steps: |     steps: | ||||||
|       - |       - | ||||||
|         name: Checkout |         name: Checkout | ||||||
| @ -193,7 +201,13 @@ jobs: | |||||||
|           password: ${{ secrets.GITLAB_TOKEN }} |           password: ${{ secrets.GITLAB_TOKEN }} | ||||||
| 
 | 
 | ||||||
|   google-artifact: |   google-artifact: | ||||||
|     runs-on: ubuntu-latest |     runs-on: ${{ matrix.os }} | ||||||
|  |     strategy: | ||||||
|  |       fail-fast: false | ||||||
|  |       matrix: | ||||||
|  |         os: | ||||||
|  |           - ubuntu-latest | ||||||
|  |           - windows-latest | ||||||
|     steps: |     steps: | ||||||
|       - |       - | ||||||
|         name: Checkout |         name: Checkout | ||||||
| @ -207,7 +221,13 @@ jobs: | |||||||
|           password: ${{ secrets.GAR_JSON_KEY }} |           password: ${{ secrets.GAR_JSON_KEY }} | ||||||
| 
 | 
 | ||||||
|   google-container: |   google-container: | ||||||
|     runs-on: ubuntu-latest |     runs-on: ${{ matrix.os }} | ||||||
|  |     strategy: | ||||||
|  |       fail-fast: false | ||||||
|  |       matrix: | ||||||
|  |         os: | ||||||
|  |           - ubuntu-latest | ||||||
|  |           - windows-latest | ||||||
|     steps: |     steps: | ||||||
|       - |       - | ||||||
|         name: Checkout |         name: Checkout | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| import * as semver from 'semver'; |  | ||||||
| import * as aws from '../src/aws'; | import * as aws from '../src/aws'; | ||||||
|  | import {AuthorizationData} from 'aws-sdk/clients/ecr'; | ||||||
| 
 | 
 | ||||||
| describe('isECR', () => { | describe('isECR', () => { | ||||||
|   test.each([ |   test.each([ | ||||||
| @ -10,7 +10,7 @@ describe('isECR', () => { | |||||||
|     ['390948362332.dkr.ecr.cn-northwest-1.amazonaws.com.cn', true], |     ['390948362332.dkr.ecr.cn-northwest-1.amazonaws.com.cn', true], | ||||||
|     ['public.ecr.aws', true] |     ['public.ecr.aws', true] | ||||||
|   ])('given registry %p', async (registry, expected) => { |   ])('given registry %p', async (registry, expected) => { | ||||||
|     expect(await aws.isECR(registry)).toEqual(expected); |     expect(aws.isECR(registry)).toEqual(expected); | ||||||
|   }); |   }); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| @ -23,40 +23,7 @@ describe('isPubECR', () => { | |||||||
|     ['390948362332.dkr.ecr.cn-northwest-1.amazonaws.com.cn', false], |     ['390948362332.dkr.ecr.cn-northwest-1.amazonaws.com.cn', false], | ||||||
|     ['public.ecr.aws', true] |     ['public.ecr.aws', true] | ||||||
|   ])('given registry %p', async (registry, expected) => { |   ])('given registry %p', async (registry, expected) => { | ||||||
|     expect(await aws.isPubECR(registry)).toEqual(expected); |     expect(aws.isPubECR(registry)).toEqual(expected); | ||||||
|   }); |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| describe('getCLI', () => { |  | ||||||
|   it('exists', async () => { |  | ||||||
|     const awsPath = await aws.getCLI(); |  | ||||||
|     console.log(`awsPath: ${awsPath}`); |  | ||||||
|     expect(awsPath).not.toEqual(''); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| describe('execCLI', () => { |  | ||||||
|   it('--version not empty', async () => { |  | ||||||
|     const cliCmdOutput = await aws.execCLI(['--version']); |  | ||||||
|     console.log(`cliCmdOutput: ${cliCmdOutput}`); |  | ||||||
|     expect(cliCmdOutput).not.toEqual(''); |  | ||||||
|   }, 100000); |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| describe('getCLIVersion', () => { |  | ||||||
|   it('valid', async () => { |  | ||||||
|     const cliVersion = await aws.getCLIVersion(); |  | ||||||
|     console.log(`cliVersion: ${cliVersion}`); |  | ||||||
|     expect(semver.valid(cliVersion)).not.toBeNull(); |  | ||||||
|   }, 100000); |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| describe('parseCLIVersion', () => { |  | ||||||
|   test.each([ |  | ||||||
|     ['v1', 'aws-cli/1.18.120 Python/2.7.17 Linux/5.3.0-1034-azure botocore/1.17.43', '1.18.120'], |  | ||||||
|     ['v2', 'aws-cli/2.0.41 Python/3.7.3 Linux/4.19.104-microsoft-standard exe/x86_64.ubuntu.18', '2.0.41'] |  | ||||||
|   ])('given aws %p', async (version, stdout, expected) => { |  | ||||||
|     expect(await aws.parseCLIVersion(stdout)).toEqual(expected); |  | ||||||
|   }); |   }); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| @ -67,7 +34,7 @@ describe('getRegion', () => { | |||||||
|     ['390948362332.dkr.ecr.cn-northwest-1.amazonaws.com.cn', 'cn-northwest-1'], |     ['390948362332.dkr.ecr.cn-northwest-1.amazonaws.com.cn', 'cn-northwest-1'], | ||||||
|     ['public.ecr.aws', 'us-east-1'] |     ['public.ecr.aws', 'us-east-1'] | ||||||
|   ])('given registry %p', async (registry, expected) => { |   ])('given registry %p', async (registry, expected) => { | ||||||
|     expect(await aws.getRegion(registry)).toEqual(expected); |     expect(aws.getRegion(registry)).toEqual(expected); | ||||||
|   }); |   }); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| @ -82,6 +49,111 @@ describe('getAccountIDs', () => { | |||||||
|     if (accountIDsEnv) { |     if (accountIDsEnv) { | ||||||
|       process.env.AWS_ACCOUNT_IDS = accountIDsEnv; |       process.env.AWS_ACCOUNT_IDS = accountIDsEnv; | ||||||
|     } |     } | ||||||
|     expect(await aws.getAccountIDs(registry)).toEqual(expected); |     expect(aws.getAccountIDs(registry)).toEqual(expected); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | const mockEcrGetAuthToken = jest.fn(); | ||||||
|  | const mockEcrPublicGetAuthToken = jest.fn(); | ||||||
|  | jest.mock('aws-sdk', () => { | ||||||
|  |   return { | ||||||
|  |     ECR: jest.fn(() => ({ | ||||||
|  |       getAuthorizationToken: mockEcrGetAuthToken | ||||||
|  |     })), | ||||||
|  |     ECRPUBLIC: jest.fn(() => ({ | ||||||
|  |       getAuthorizationToken: mockEcrPublicGetAuthToken | ||||||
|  |     })) | ||||||
|  |   }; | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | describe('getRegistriesData', () => { | ||||||
|  |   beforeEach(() => { | ||||||
|  |     jest.clearAllMocks(); | ||||||
|  |     delete process.env.AWS_ACCOUNT_IDS; | ||||||
|  |   }); | ||||||
|  |   // prettier-ignore
 | ||||||
|  |   test.each([ | ||||||
|  |     [ | ||||||
|  |       '012345678901.dkr.ecr.aws-region-1.amazonaws.com', | ||||||
|  |       'dkr.ecr.aws-region-1.amazonaws.com', undefined, | ||||||
|  |       [ | ||||||
|  |         { | ||||||
|  |           registry: '012345678901.dkr.ecr.aws-region-1.amazonaws.com', | ||||||
|  |           username: '012345678901', | ||||||
|  |           password: 'world' | ||||||
|  |         } | ||||||
|  |       ] | ||||||
|  |     ], | ||||||
|  |     [ | ||||||
|  |       '012345678901.dkr.ecr.eu-west-3.amazonaws.com', | ||||||
|  |       'dkr.ecr.eu-west-3.amazonaws.com', | ||||||
|  |       '012345678910,023456789012', | ||||||
|  |       [ | ||||||
|  |         { | ||||||
|  |           registry: '012345678901.dkr.ecr.eu-west-3.amazonaws.com', | ||||||
|  |           username: '012345678901', | ||||||
|  |           password: 'world' | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           registry: '012345678910.dkr.ecr.eu-west-3.amazonaws.com', | ||||||
|  |           username: '012345678910', | ||||||
|  |           password: 'world' | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           registry: '023456789012.dkr.ecr.eu-west-3.amazonaws.com', | ||||||
|  |           username: '023456789012', | ||||||
|  |           password: 'world' | ||||||
|  |         } | ||||||
|  |       ] | ||||||
|  |     ], | ||||||
|  |     [ | ||||||
|  |       'public.ecr.aws', | ||||||
|  |       undefined, | ||||||
|  |       undefined, | ||||||
|  |       [ | ||||||
|  |         { | ||||||
|  |           registry: 'public.ecr.aws', | ||||||
|  |           username: 'AWS', | ||||||
|  |           password: 'world' | ||||||
|  |         } | ||||||
|  |       ] | ||||||
|  |     ] | ||||||
|  |   ])('given registry %p', async (registry, fqdn, accountIDsEnv, expected: aws.RegistryData[]) => { | ||||||
|  |     if (accountIDsEnv) { | ||||||
|  |       process.env.AWS_ACCOUNT_IDS = accountIDsEnv; | ||||||
|  |     } | ||||||
|  |     const accountIDs = aws.getAccountIDs(registry); | ||||||
|  |     const authData: AuthorizationData[] = []; | ||||||
|  |     if (accountIDs.length == 0) { | ||||||
|  |       mockEcrPublicGetAuthToken.mockImplementation(() => { | ||||||
|  |         return { | ||||||
|  |           promise() { | ||||||
|  |             return Promise.resolve({ | ||||||
|  |               authorizationData: { | ||||||
|  |                 authorizationToken: Buffer.from(`AWS:world`).toString('base64'), | ||||||
|  |               } | ||||||
|  |             }); | ||||||
|  |           } | ||||||
|  |         }; | ||||||
|  |       }); | ||||||
|  |     } else { | ||||||
|  |       aws.getAccountIDs(registry).forEach(accountID => { | ||||||
|  |         authData.push({ | ||||||
|  |           authorizationToken: Buffer.from(`${accountID}:world`).toString('base64'), | ||||||
|  |           proxyEndpoint: `${accountID}.${fqdn}` | ||||||
|  |         }); | ||||||
|  |       }); | ||||||
|  |       mockEcrGetAuthToken.mockImplementation(() => { | ||||||
|  |         return { | ||||||
|  |           promise() { | ||||||
|  |             return Promise.resolve({ | ||||||
|  |               authorizationData: authData | ||||||
|  |             }); | ||||||
|  |           } | ||||||
|  |         }; | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |     const regData = await aws.getRegistriesData(registry); | ||||||
|  |     expect(regData).toEqual(expected); | ||||||
|   }); |   }); | ||||||
| }); | }); | ||||||
|  | |||||||
| @ -1,5 +1,3 @@ | |||||||
| import osm = require('os'); |  | ||||||
| 
 |  | ||||||
| import {getInputs} from '../src/context'; | import {getInputs} from '../src/context'; | ||||||
| 
 | 
 | ||||||
| test('with password and username getInputs does not throw error', async () => { | test('with password and username getInputs does not throw error', async () => { | ||||||
|  | |||||||
| @ -1,5 +1,4 @@ | |||||||
| import {loginECR, loginStandard, logout} from '../src/docker'; | import {loginStandard, logout} from '../src/docker'; | ||||||
| import * as aws from '../src/aws'; |  | ||||||
| 
 | 
 | ||||||
| import * as path from 'path'; | import * as path from 'path'; | ||||||
| 
 | 
 | ||||||
| @ -48,78 +47,3 @@ test('logout calls exec', async () => { | |||||||
|     ignoreReturnCode: true |     ignoreReturnCode: true | ||||||
|   }); |   }); | ||||||
| }); | }); | ||||||
| 
 |  | ||||||
| test('loginECR sets AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY if username and password is set', async () => { |  | ||||||
|   const execSpy: jest.SpyInstance = jest.spyOn(aws, 'getDockerLoginCmds'); |  | ||||||
|   execSpy.mockImplementation(() => Promise.resolve([])); |  | ||||||
|   jest.spyOn(aws, 'getCLI').mockImplementation(() => Promise.resolve('')); |  | ||||||
|   jest.spyOn(aws, 'getCLIVersion').mockImplementation(() => Promise.resolve('')); |  | ||||||
|   jest.spyOn(aws, 'getRegion').mockImplementation(() => ''); |  | ||||||
|   jest.spyOn(aws, 'getAccountIDs').mockImplementation(() => []); |  | ||||||
|   jest.spyOn(aws, 'isPubECR').mockImplementation(() => false); |  | ||||||
| 
 |  | ||||||
|   const username: string = 'dbowie'; |  | ||||||
|   const password: string = 'groundcontrol'; |  | ||||||
|   const registry: string = 'https://ghcr.io'; |  | ||||||
| 
 |  | ||||||
|   await loginECR(registry, username, password); |  | ||||||
| 
 |  | ||||||
|   expect(process.env.AWS_ACCESS_KEY_ID).toEqual(username); |  | ||||||
|   expect(process.env.AWS_SECRET_ACCESS_KEY).toEqual(password); |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| test('loginECR keeps AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY if set', async () => { |  | ||||||
|   const execSpy: jest.SpyInstance = jest.spyOn(aws, 'getDockerLoginCmds'); |  | ||||||
|   execSpy.mockImplementation(() => Promise.resolve([])); |  | ||||||
|   jest.spyOn(aws, 'getCLI').mockImplementation(() => Promise.resolve('')); |  | ||||||
|   jest.spyOn(aws, 'getCLIVersion').mockImplementation(() => Promise.resolve('')); |  | ||||||
|   jest.spyOn(aws, 'getRegion').mockImplementation(() => ''); |  | ||||||
|   jest.spyOn(aws, 'getAccountIDs').mockImplementation(() => []); |  | ||||||
|   jest.spyOn(aws, 'isPubECR').mockImplementation(() => false); |  | ||||||
| 
 |  | ||||||
|   process.env.AWS_ACCESS_KEY_ID = 'banana'; |  | ||||||
|   process.env.AWS_SECRET_ACCESS_KEY = 'supersecret'; |  | ||||||
| 
 |  | ||||||
|   await loginECR('ecr.aws', '', ''); |  | ||||||
| 
 |  | ||||||
|   expect(process.env.AWS_ACCESS_KEY_ID).toEqual('banana'); |  | ||||||
|   expect(process.env.AWS_SECRET_ACCESS_KEY).toEqual('supersecret'); |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| test('loginECR overrides AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY if username and password set', async () => { |  | ||||||
|   const execSpy: jest.SpyInstance = jest.spyOn(aws, 'getDockerLoginCmds'); |  | ||||||
|   execSpy.mockImplementation(() => Promise.resolve([])); |  | ||||||
|   jest.spyOn(aws, 'getCLI').mockImplementation(() => Promise.resolve('')); |  | ||||||
|   jest.spyOn(aws, 'getCLIVersion').mockImplementation(() => Promise.resolve('')); |  | ||||||
|   jest.spyOn(aws, 'getRegion').mockImplementation(() => ''); |  | ||||||
|   jest.spyOn(aws, 'getAccountIDs').mockImplementation(() => []); |  | ||||||
|   jest.spyOn(aws, 'isPubECR').mockImplementation(() => false); |  | ||||||
| 
 |  | ||||||
|   process.env.AWS_ACCESS_KEY_ID = 'banana'; |  | ||||||
|   process.env.AWS_SECRET_ACCESS_KEY = 'supersecret'; |  | ||||||
|   const username = 'myotheruser'; |  | ||||||
|   const password = 'providedpassword'; |  | ||||||
| 
 |  | ||||||
|   await loginECR('ecr.aws', username, password); |  | ||||||
| 
 |  | ||||||
|   expect(process.env.AWS_ACCESS_KEY_ID).toEqual(username); |  | ||||||
|   expect(process.env.AWS_SECRET_ACCESS_KEY).toEqual(password); |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| test('loginECR does not set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY if not set', async () => { |  | ||||||
|   const execSpy: jest.SpyInstance = jest.spyOn(aws, 'getDockerLoginCmds'); |  | ||||||
|   execSpy.mockImplementation(() => Promise.resolve([])); |  | ||||||
|   jest.spyOn(aws, 'getCLI').mockImplementation(() => Promise.resolve('')); |  | ||||||
|   jest.spyOn(aws, 'getCLIVersion').mockImplementation(() => Promise.resolve('')); |  | ||||||
|   jest.spyOn(aws, 'getRegion').mockImplementation(() => ''); |  | ||||||
|   jest.spyOn(aws, 'getAccountIDs').mockImplementation(() => []); |  | ||||||
|   jest.spyOn(aws, 'isPubECR').mockImplementation(() => false); |  | ||||||
| 
 |  | ||||||
|   delete process.env.AWS_ACCESS_KEY_ID; |  | ||||||
|   delete process.env.AWS_SECRET_ACCESS_KEY; |  | ||||||
| 
 |  | ||||||
|   await loginECR('ecr.aws', '', ''); |  | ||||||
| 
 |  | ||||||
|   expect('AWS_ACCESS_KEY_ID' in process.env).toEqual(false); |  | ||||||
|   expect('AWS_SECRET_ACCESS_KEY' in process.env).toEqual(false); |  | ||||||
| }); |  | ||||||
|  | |||||||
							
								
								
									
										42344
									
								
								dist/index.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										42344
									
								
								dist/index.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @ -66,18 +66,6 @@ FROM docker:${DOCKER_VERSION} as docker | |||||||
| FROM docker/buildx-bin:${BUILDX_VERSION} as buildx | FROM docker/buildx-bin:${BUILDX_VERSION} as buildx | ||||||
| 
 | 
 | ||||||
| FROM deps AS test | FROM deps AS test | ||||||
| RUN apk add --no-cache binutils curl unzip |  | ||||||
| ENV GLIBC_VER=2.31-r0 |  | ||||||
| RUN curl -sL "https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub" -o "/etc/apk/keys/sgerrand.rsa.pub" \ |  | ||||||
|   && curl -sLO "https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VER}/glibc-${GLIBC_VER}.apk" \ |  | ||||||
|   && curl -sLO "https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VER}/glibc-bin-${GLIBC_VER}.apk" \ |  | ||||||
|   && apk add --no-cache \ |  | ||||||
|     glibc-${GLIBC_VER}.apk \ |  | ||||||
|     glibc-bin-${GLIBC_VER}.apk \ |  | ||||||
|   && curl -sL "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \ |  | ||||||
|   && unzip -qq "awscliv2.zip" \ |  | ||||||
|   && ./aws/install \ |  | ||||||
|   && aws --version |  | ||||||
| ENV RUNNER_TEMP=/tmp/github_runner | ENV RUNNER_TEMP=/tmp/github_runner | ||||||
| ENV RUNNER_TOOL_CACHE=/tmp/github_tool_cache | ENV RUNNER_TOOL_CACHE=/tmp/github_tool_cache | ||||||
| RUN --mount=type=bind,target=.,rw \ | RUN --mount=type=bind,target=.,rw \ | ||||||
|  | |||||||
| @ -30,7 +30,7 @@ | |||||||
|     "@actions/core": "^1.6.0", |     "@actions/core": "^1.6.0", | ||||||
|     "@actions/exec": "^1.1.0", |     "@actions/exec": "^1.1.0", | ||||||
|     "@actions/io": "^1.1.1", |     "@actions/io": "^1.1.1", | ||||||
|     "semver": "^7.3.5" |     "aws-sdk": "^2.1046.0" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "@types/jest": "^26.0.23", |     "@types/jest": "^26.0.23", | ||||||
|  | |||||||
							
								
								
									
										98
									
								
								src/aws.ts
									
									
									
									
									
								
							
							
						
						
									
										98
									
								
								src/aws.ts
									
									
									
									
									
								
							| @ -1,6 +1,5 @@ | |||||||
| import * as semver from 'semver'; | import * as core from '@actions/core'; | ||||||
| import * as exec from '@actions/exec'; | import * as aws from 'aws-sdk'; | ||||||
| import * as io from '@actions/io'; |  | ||||||
| 
 | 
 | ||||||
| const ecrRegistryRegex = /^(([0-9]{12})\.dkr\.ecr\.(.+)\.amazonaws\.com(.cn)?)(\/([^:]+)(:.+)?)?$/; | const ecrRegistryRegex = /^(([0-9]{12})\.dkr\.ecr\.(.+)\.amazonaws\.com(.cn)?)(\/([^:]+)(:.+)?)?$/; | ||||||
| 
 | 
 | ||||||
| @ -38,48 +37,65 @@ export const getAccountIDs = (registry: string): string[] => { | |||||||
|   return accountIDs.filter((item, index) => accountIDs.indexOf(item) === index); |   return accountIDs.filter((item, index) => accountIDs.indexOf(item) === index); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export const getCLI = async (): Promise<string> => { | export interface RegistryData { | ||||||
|   return io.which('aws', true); |   registry: string; | ||||||
| }; |   username: string; | ||||||
|  |   password: string; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| export const execCLI = async (args: string[]): Promise<string> => { | export const getRegistriesData = async (registry: string, username?: string, password?: string): Promise<RegistryData[]> => { | ||||||
|   return exec |   const region = getRegion(registry); | ||||||
|     .getExecOutput(await getCLI(), args, { |   const accountIDs = getAccountIDs(registry); | ||||||
|       ignoreReturnCode: true, | 
 | ||||||
|       silent: true |   const authTokenRequest = {}; | ||||||
|     }) |   if (accountIDs.length > 0) { | ||||||
|     .then(res => { |     core.debug(`Requesting AWS ECR auth token for ${accountIDs.join(', ')}`); | ||||||
|       if (res.stderr.length > 0 && res.exitCode != 0) { |     authTokenRequest['registryIds'] = accountIDs; | ||||||
|         throw new Error(res.stderr.trim()); |   } | ||||||
|       } else if (res.stderr.length > 0) { | 
 | ||||||
|         return res.stderr.trim(); |   if (isPubECR(registry)) { | ||||||
|  |     core.info(`AWS Public ECR detected with ${region} region`); | ||||||
|  |     const ecrPublic = new aws.ECRPUBLIC({ | ||||||
|  |       customUserAgent: 'docker-login-action', | ||||||
|  |       accessKeyId: username || process.env.AWS_ACCESS_KEY_ID || '', | ||||||
|  |       secretAccessKey: password || process.env.AWS_SECRET_ACCESS_KEY || '', | ||||||
|  |       region: region | ||||||
|  |     }); | ||||||
|  |     const authTokenResponse = await ecrPublic.getAuthorizationToken(authTokenRequest).promise(); | ||||||
|  |     if (!authTokenResponse.authorizationData || !authTokenResponse.authorizationData.authorizationToken) { | ||||||
|  |       throw new Error('Could not retrieve an authorization token from AWS Public ECR'); | ||||||
|  |     } | ||||||
|  |     const authToken = Buffer.from(authTokenResponse.authorizationData.authorizationToken, 'base64').toString('utf-8'); | ||||||
|  |     const creds = authToken.split(':', 2); | ||||||
|  |     return [ | ||||||
|  |       { | ||||||
|  |         registry: 'public.ecr.aws', | ||||||
|  |         username: creds[0], | ||||||
|  |         password: creds[1] | ||||||
|  |       } | ||||||
|  |     ]; | ||||||
|   } else { |   } else { | ||||||
|         return res.stdout.trim(); |     core.info(`AWS ECR detected with ${region} region`); | ||||||
|       } |     const ecr = new aws.ECR({ | ||||||
|  |       customUserAgent: 'docker-login-action', | ||||||
|  |       accessKeyId: username || process.env.AWS_ACCESS_KEY_ID || '', | ||||||
|  |       secretAccessKey: password || process.env.AWS_SECRET_ACCESS_KEY || '', | ||||||
|  |       region: region | ||||||
|     }); |     }); | ||||||
| }; |     const authTokenResponse = await ecr.getAuthorizationToken(authTokenRequest).promise(); | ||||||
| 
 |     if (!Array.isArray(authTokenResponse.authorizationData) || !authTokenResponse.authorizationData.length) { | ||||||
| export const getCLIVersion = async (): Promise<string> => { |       throw new Error('Could not retrieve an authorization token from AWS ECR'); | ||||||
|   return parseCLIVersion(await execCLI(['--version'])); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| export const parseCLIVersion = async (stdout: string): Promise<string> => { |  | ||||||
|   const matches = /aws-cli\/([0-9.]+)/.exec(stdout); |  | ||||||
|   if (!matches) { |  | ||||||
|     throw new Error(`Cannot parse AWS CLI version`); |  | ||||||
|     } |     } | ||||||
|   return semver.clean(matches[1]); |     const regDatas: RegistryData[] = []; | ||||||
| }; |     for (const authData of authTokenResponse.authorizationData) { | ||||||
| 
 |       const authToken = Buffer.from(authData.authorizationToken || '', 'base64').toString('utf-8'); | ||||||
| export const getDockerLoginCmds = async (cliVersion: string, registry: string, region: string, accountIDs: string[]): Promise<string[]> => { |       const creds = authToken.split(':', 2); | ||||||
|   let ecrCmd = (await isPubECR(registry)) ? 'ecr-public' : 'ecr'; |       regDatas.push({ | ||||||
|   if (semver.satisfies(cliVersion, '>=2.0.0') || (await isPubECR(registry))) { |         registry: authData.proxyEndpoint || '', | ||||||
|     return execCLI([ecrCmd, 'get-login-password', '--region', region]).then(pwd => { |         username: creds[0], | ||||||
|       return [`docker login --username AWS --password ${pwd} ${registry}`]; |         password: creds[1] | ||||||
|     }); |  | ||||||
|   } else { |  | ||||||
|     return execCLI([ecrCmd, 'get-login', '--region', region, '--registry-ids', accountIDs.join(' '), '--no-include-email']).then(dockerLoginCmds => { |  | ||||||
|       return dockerLoginCmds.trim().split(`\n`); |  | ||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
|  |     return regDatas; | ||||||
|  |   } | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ import * as core from '@actions/core'; | |||||||
| import * as exec from '@actions/exec'; | import * as exec from '@actions/exec'; | ||||||
| 
 | 
 | ||||||
| export async function login(registry: string, username: string, password: string): Promise<void> { | export async function login(registry: string, username: string, password: string): Promise<void> { | ||||||
|   if (await aws.isECR(registry)) { |   if (aws.isECR(registry)) { | ||||||
|     await loginECR(registry, username, password); |     await loginECR(registry, username, password); | ||||||
|   } else { |   } else { | ||||||
|     await loginStandard(registry, username, password); |     await loginStandard(registry, username, password); | ||||||
| @ -51,43 +51,21 @@ export async function loginStandard(registry: string, username: string, password | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function loginECR(registry: string, username: string, password: string): Promise<void> { | export async function loginECR(registry: string, username: string, password: string): Promise<void> { | ||||||
|   const cliPath = await aws.getCLI(); |   core.info(`Retrieving registries data through AWS SDK...`); | ||||||
|   const cliVersion = await aws.getCLIVersion(); |   const regDatas = await aws.getRegistriesData(registry, username, password); | ||||||
|   const region = await aws.getRegion(registry); |   for (const regData of regDatas) { | ||||||
|   const accountIDs = await aws.getAccountIDs(registry); |     core.info(`Logging into ${regData.registry}...`); | ||||||
| 
 |     await exec | ||||||
|   if (await aws.isPubECR(registry)) { |       .getExecOutput('docker', ['login', '--password-stdin', '--username', regData.username, regData.registry], { | ||||||
|     core.info(`AWS Public ECR detected with ${region} region`); |  | ||||||
|   } else { |  | ||||||
|     core.info(`AWS ECR detected with ${region} region`); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   if (username) { |  | ||||||
|     process.env.AWS_ACCESS_KEY_ID = username; |  | ||||||
|   } |  | ||||||
|   if (password) { |  | ||||||
|     process.env.AWS_SECRET_ACCESS_KEY = password; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   core.info(`Retrieving docker login command through AWS CLI ${cliVersion} (${cliPath})...`); |  | ||||||
|   const loginCmds = await aws.getDockerLoginCmds(cliVersion, registry, region, accountIDs); |  | ||||||
| 
 |  | ||||||
|   core.info(`Logging into ${registry}...`); |  | ||||||
|   loginCmds.forEach((loginCmd, index) => { |  | ||||||
|     exec |  | ||||||
|       .getExecOutput(loginCmd, [], { |  | ||||||
|         ignoreReturnCode: true, |         ignoreReturnCode: true, | ||||||
|         silent: true |         silent: true, | ||||||
|  |         input: Buffer.from(regData.password) | ||||||
|       }) |       }) | ||||||
|       .then(res => { |       .then(res => { | ||||||
|         if (res.stderr.length > 0 && res.exitCode != 0) { |         if (res.stderr.length > 0 && res.exitCode != 0) { | ||||||
|           throw new Error(res.stderr.trim()); |           throw new Error(res.stderr.trim()); | ||||||
|         } |         } | ||||||
|         if (loginCmds.length > 1) { |  | ||||||
|           core.info(`Login Succeeded! (${index}/${loginCmds.length})`); |  | ||||||
|         } else { |  | ||||||
|         core.info('Login Succeeded!'); |         core.info('Login Succeeded!'); | ||||||
|         } |  | ||||||
|       }); |  | ||||||
|       }); |       }); | ||||||
|   } |   } | ||||||
|  | } | ||||||
|  | |||||||
							
								
								
									
										99
									
								
								yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										99
									
								
								yarn.lock
									
									
									
									
									
								
							| @ -763,6 +763,21 @@ atob@^2.1.2: | |||||||
|   resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" |   resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" | ||||||
|   integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== |   integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== | ||||||
| 
 | 
 | ||||||
|  | aws-sdk@^2.1046.0: | ||||||
|  |   version "2.1046.0" | ||||||
|  |   resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1046.0.tgz#9147b0fa1c86acbebd1a061e951ab5012f4499d7" | ||||||
|  |   integrity sha512-ocwHclMXdIA+NWocUyvp9Ild3/zy2vr5mHp3mTyodf0WU5lzBE8PocCVLSWhMAXLxyia83xv2y5f5AzAcetbqA== | ||||||
|  |   dependencies: | ||||||
|  |     buffer "4.9.2" | ||||||
|  |     events "1.1.1" | ||||||
|  |     ieee754 "1.1.13" | ||||||
|  |     jmespath "0.15.0" | ||||||
|  |     querystring "0.2.0" | ||||||
|  |     sax "1.2.1" | ||||||
|  |     url "0.10.3" | ||||||
|  |     uuid "3.3.2" | ||||||
|  |     xml2js "0.4.19" | ||||||
|  | 
 | ||||||
| babel-jest@^26.6.3: | babel-jest@^26.6.3: | ||||||
|   version "26.6.3" |   version "26.6.3" | ||||||
|   resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.6.3.tgz#d87d25cb0037577a0c89f82e5755c5d293c01056" |   resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.6.3.tgz#d87d25cb0037577a0c89f82e5755c5d293c01056" | ||||||
| @ -829,6 +844,11 @@ balanced-match@^1.0.0: | |||||||
|   resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" |   resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" | ||||||
|   integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== |   integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== | ||||||
| 
 | 
 | ||||||
|  | base64-js@^1.0.2: | ||||||
|  |   version "1.5.1" | ||||||
|  |   resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" | ||||||
|  |   integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== | ||||||
|  | 
 | ||||||
| base@^0.11.1: | base@^0.11.1: | ||||||
|   version "0.11.2" |   version "0.11.2" | ||||||
|   resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" |   resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" | ||||||
| @ -908,6 +928,15 @@ buffer-from@1.x, buffer-from@^1.0.0: | |||||||
|   resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" |   resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" | ||||||
|   integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== |   integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== | ||||||
| 
 | 
 | ||||||
|  | buffer@4.9.2: | ||||||
|  |   version "4.9.2" | ||||||
|  |   resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" | ||||||
|  |   integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== | ||||||
|  |   dependencies: | ||||||
|  |     base64-js "^1.0.2" | ||||||
|  |     ieee754 "^1.1.4" | ||||||
|  |     isarray "^1.0.0" | ||||||
|  | 
 | ||||||
| cache-base@^1.0.1: | cache-base@^1.0.1: | ||||||
|   version "1.0.1" |   version "1.0.1" | ||||||
|   resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" |   resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" | ||||||
| @ -1307,6 +1336,11 @@ esutils@^2.0.2: | |||||||
|   resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" |   resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" | ||||||
|   integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== |   integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== | ||||||
| 
 | 
 | ||||||
|  | events@1.1.1: | ||||||
|  |   version "1.1.1" | ||||||
|  |   resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" | ||||||
|  |   integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= | ||||||
|  | 
 | ||||||
| exec-sh@^0.3.2: | exec-sh@^0.3.2: | ||||||
|   version "0.3.6" |   version "0.3.6" | ||||||
|   resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.6.tgz#ff264f9e325519a60cb5e273692943483cca63bc" |   resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.6.tgz#ff264f9e325519a60cb5e273692943483cca63bc" | ||||||
| @ -1632,6 +1666,16 @@ iconv-lite@0.4.24: | |||||||
|   dependencies: |   dependencies: | ||||||
|     safer-buffer ">= 2.1.2 < 3" |     safer-buffer ">= 2.1.2 < 3" | ||||||
| 
 | 
 | ||||||
|  | ieee754@1.1.13: | ||||||
|  |   version "1.1.13" | ||||||
|  |   resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" | ||||||
|  |   integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== | ||||||
|  | 
 | ||||||
|  | ieee754@^1.1.4: | ||||||
|  |   version "1.2.1" | ||||||
|  |   resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" | ||||||
|  |   integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== | ||||||
|  | 
 | ||||||
| import-local@^3.0.2: | import-local@^3.0.2: | ||||||
|   version "3.0.2" |   version "3.0.2" | ||||||
|   resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6" |   resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6" | ||||||
| @ -1806,7 +1850,7 @@ is-wsl@^2.2.0: | |||||||
|   dependencies: |   dependencies: | ||||||
|     is-docker "^2.0.0" |     is-docker "^2.0.0" | ||||||
| 
 | 
 | ||||||
| isarray@1.0.0: | isarray@1.0.0, isarray@^1.0.0: | ||||||
|   version "1.0.0" |   version "1.0.0" | ||||||
|   resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" |   resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" | ||||||
|   integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= |   integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= | ||||||
| @ -2269,6 +2313,11 @@ jest@^26.6.3: | |||||||
|     import-local "^3.0.2" |     import-local "^3.0.2" | ||||||
|     jest-cli "^26.6.3" |     jest-cli "^26.6.3" | ||||||
| 
 | 
 | ||||||
|  | jmespath@0.15.0: | ||||||
|  |   version "0.15.0" | ||||||
|  |   resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217" | ||||||
|  |   integrity sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc= | ||||||
|  | 
 | ||||||
| js-tokens@^4.0.0: | js-tokens@^4.0.0: | ||||||
|   version "4.0.0" |   version "4.0.0" | ||||||
|   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" |   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" | ||||||
| @ -2809,11 +2858,21 @@ pump@^3.0.0: | |||||||
|     end-of-stream "^1.1.0" |     end-of-stream "^1.1.0" | ||||||
|     once "^1.3.1" |     once "^1.3.1" | ||||||
| 
 | 
 | ||||||
|  | punycode@1.3.2: | ||||||
|  |   version "1.3.2" | ||||||
|  |   resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" | ||||||
|  |   integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= | ||||||
|  | 
 | ||||||
| punycode@^2.1.1: | punycode@^2.1.1: | ||||||
|   version "2.1.1" |   version "2.1.1" | ||||||
|   resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" |   resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" | ||||||
|   integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== |   integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== | ||||||
| 
 | 
 | ||||||
|  | querystring@0.2.0: | ||||||
|  |   version "0.2.0" | ||||||
|  |   resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" | ||||||
|  |   integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= | ||||||
|  | 
 | ||||||
| react-is@^17.0.1: | react-is@^17.0.1: | ||||||
|   version "17.0.2" |   version "17.0.2" | ||||||
|   resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" |   resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" | ||||||
| @ -2945,6 +3004,16 @@ sane@^4.0.3: | |||||||
|     minimist "^1.1.1" |     minimist "^1.1.1" | ||||||
|     walker "~1.0.5" |     walker "~1.0.5" | ||||||
| 
 | 
 | ||||||
|  | sax@1.2.1: | ||||||
|  |   version "1.2.1" | ||||||
|  |   resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" | ||||||
|  |   integrity sha1-e45lYZCyKOgaZq6nSEgNgozS03o= | ||||||
|  | 
 | ||||||
|  | sax@>=0.6.0: | ||||||
|  |   version "1.2.4" | ||||||
|  |   resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" | ||||||
|  |   integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== | ||||||
|  | 
 | ||||||
| saxes@^5.0.1: | saxes@^5.0.1: | ||||||
|   version "5.0.1" |   version "5.0.1" | ||||||
|   resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" |   resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" | ||||||
| @ -2957,7 +3026,7 @@ saxes@^5.0.1: | |||||||
|   resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" |   resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" | ||||||
|   integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== |   integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== | ||||||
| 
 | 
 | ||||||
| semver@7.x, semver@^7.3.2, semver@^7.3.5: | semver@7.x, semver@^7.3.2: | ||||||
|   version "7.3.5" |   version "7.3.5" | ||||||
|   resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" |   resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" | ||||||
|   integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== |   integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== | ||||||
| @ -3397,11 +3466,24 @@ urix@^0.1.0: | |||||||
|   resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" |   resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" | ||||||
|   integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= |   integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= | ||||||
| 
 | 
 | ||||||
|  | url@0.10.3: | ||||||
|  |   version "0.10.3" | ||||||
|  |   resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64" | ||||||
|  |   integrity sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ= | ||||||
|  |   dependencies: | ||||||
|  |     punycode "1.3.2" | ||||||
|  |     querystring "0.2.0" | ||||||
|  | 
 | ||||||
| use@^3.1.0: | use@^3.1.0: | ||||||
|   version "3.1.1" |   version "3.1.1" | ||||||
|   resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" |   resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" | ||||||
|   integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== |   integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== | ||||||
| 
 | 
 | ||||||
|  | uuid@3.3.2: | ||||||
|  |   version "3.3.2" | ||||||
|  |   resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" | ||||||
|  |   integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== | ||||||
|  | 
 | ||||||
| uuid@^8.3.0: | uuid@^8.3.0: | ||||||
|   version "8.3.2" |   version "8.3.2" | ||||||
|   resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" |   resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" | ||||||
| @ -3534,6 +3616,19 @@ xml-name-validator@^3.0.0: | |||||||
|   resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" |   resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" | ||||||
|   integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== |   integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== | ||||||
| 
 | 
 | ||||||
|  | xml2js@0.4.19: | ||||||
|  |   version "0.4.19" | ||||||
|  |   resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" | ||||||
|  |   integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== | ||||||
|  |   dependencies: | ||||||
|  |     sax ">=0.6.0" | ||||||
|  |     xmlbuilder "~9.0.1" | ||||||
|  | 
 | ||||||
|  | xmlbuilder@~9.0.1: | ||||||
|  |   version "9.0.7" | ||||||
|  |   resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" | ||||||
|  |   integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= | ||||||
|  | 
 | ||||||
| xmlchars@^2.2.0: | xmlchars@^2.2.0: | ||||||
|   version "2.2.0" |   version "2.2.0" | ||||||
|   resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" |   resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 CrazyMax
						CrazyMax