mirror of
https://github.com/docker/login-action.git
synced 2024-11-27 05:09:02 +00:00
ecr: switch implementation to use the AWS SDK
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
parent
b776a64ec0
commit
faae4d6665
@ -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);
|
|
||||||
});
|
|
||||||
|
42412
dist/index.js
generated
vendored
42412
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",
|
||||||
|
100
src/aws.ts
100
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)) {
|
||||||
} else {
|
core.info(`AWS Public ECR detected with ${region} region`);
|
||||||
return res.stdout.trim();
|
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]
|
||||||
}
|
}
|
||||||
});
|
];
|
||||||
};
|
|
||||||
|
|
||||||
export const getCLIVersion = async (): Promise<string> => {
|
|
||||||
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]);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getDockerLoginCmds = async (cliVersion: string, registry: string, region: string, accountIDs: string[]): Promise<string[]> => {
|
|
||||||
let ecrCmd = (await isPubECR(registry)) ? 'ecr-public' : 'ecr';
|
|
||||||
if (semver.satisfies(cliVersion, '>=2.0.0') || (await isPubECR(registry))) {
|
|
||||||
return execCLI([ecrCmd, 'get-login-password', '--region', region]).then(pwd => {
|
|
||||||
return [`docker login --username AWS --password ${pwd} ${registry}`];
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
return execCLI([ecrCmd, 'get-login', '--region', region, '--registry-ids', accountIDs.join(' '), '--no-include-email']).then(dockerLoginCmds => {
|
core.info(`AWS ECR detected with ${region} region`);
|
||||||
return dockerLoginCmds.trim().split(`\n`);
|
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) {
|
||||||
|
throw new Error('Could not retrieve an authorization token from AWS ECR');
|
||||||
|
}
|
||||||
|
const regDatas: RegistryData[] = [];
|
||||||
|
for (const authData of authTokenResponse.authorizationData) {
|
||||||
|
const authToken = Buffer.from(authData.authorizationToken || '', 'base64').toString('utf-8');
|
||||||
|
const creds = authToken.split(':', 2);
|
||||||
|
regDatas.push({
|
||||||
|
registry: authData.proxyEndpoint || '',
|
||||||
|
username: creds[0],
|
||||||
|
password: creds[1]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
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!');
|
||||||
core.info(`Login Succeeded! (${index}/${loginCmds.length})`);
|
|
||||||
} else {
|
|
||||||
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