Skip to content

Commit

Permalink
feat: optional skipping of docker registries logout in post step (#78)
Browse files Browse the repository at this point in the history
* feat: optional skipping of docker registries logout in post step

* address feedback

* package updates

* fix debug text

* package text fix
  • Loading branch information
allisaurus authored Oct 22, 2020
1 parent f26fdba commit dd3fdee
Show file tree
Hide file tree
Showing 5 changed files with 455 additions and 1,151 deletions.
3 changes: 3 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ inputs:
registries:
description: 'A comma-delimited list of AWS account IDs that are associated with the ECR registries. If you do not specify a registry, the default ECR registry is assumed.'
required: false
skip-logout:
description: 'Whether to skip explicit logout of the registries during post-job cleanup. Exists for backward compatibility on self-hosted runners. Not recommended.'
required: false
outputs:
registry:
description: 'The URI of the ECR registry i.e. aws_account_id.dkr.ecr.region.amazonaws.com. If multiple registries are provided as inputs, this output will not be set.'
Expand Down
103 changes: 19 additions & 84 deletions dist/cleanup/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -953,75 +953,13 @@ class ExecState extends events.EventEmitter {

/***/ }),

/***/ 82:
/***/ (function(__unusedmodule, exports) {

This comment has been minimized.

Copy link
@Flint05

Flint05 May 10, 2022

круто


"use strict";

// We use any as a valid input type
/* eslint-disable @typescript-eslint/no-explicit-any */
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Sanitizes an input into a string so it can be passed into issueCommand safely
* @param input input to sanitize into a string
*/
function toCommandValue(input) {

This comment has been minimized.

Copy link
@Flint05

Flint05 May 10, 2022

ни чего не понимаю

This comment has been minimized.

Copy link
@Flint05

Flint05 May 10, 2022

обьясните как это работает?

if (input === null || input === undefined) {
return '';
}
else if (typeof input === 'string' || input instanceof String) {
return input;
}
return JSON.stringify(input);
}
exports.toCommandValue = toCommandValue;
//# sourceMappingURL=utils.js.map

/***/ }),

/***/ 87:
/***/ (function(module) {

module.exports = require("os");

/***/ }),

/***/ 102:
/***/ (function(__unusedmodule, exports, __webpack_require__) {

"use strict";

// For internal use, subject to change.
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
// We use any as a valid input type
/* eslint-disable @typescript-eslint/no-explicit-any */
const fs = __importStar(__webpack_require__(747));
const os = __importStar(__webpack_require__(87));
const utils_1 = __webpack_require__(82);
function issueCommand(command, message) {
const filePath = process.env[`GITHUB_${command}`];
if (!filePath) {
throw new Error(`Unable to find environment variable for file command ${command}`);
}
if (!fs.existsSync(filePath)) {
throw new Error(`Missing file at path: ${filePath}`);
}
fs.appendFileSync(filePath, `${utils_1.toCommandValue(message)}${os.EOL}`, {
encoding: 'utf8'
});
}
exports.issueCommand = issueCommand;
//# sourceMappingURL=file-command.js.map

/***/ }),

/***/ 129:
/***/ (function(module) {

Expand Down Expand Up @@ -1114,7 +1052,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
};
Object.defineProperty(exports, "__esModule", { value: true });
const os = __importStar(__webpack_require__(87));
const utils_1 = __webpack_require__(82);
/**
* Commands
*
Expand Down Expand Up @@ -1168,14 +1105,28 @@ class Command {
return cmdStr;
}
}
/**
* Sanitizes an input into a string so it can be passed into issueCommand safely
* @param input input to sanitize into a string
*/
function toCommandValue(input) {

This comment has been minimized.

Copy link
@Flint05

Flint05 May 10, 2022

как это работает?

if (input === null || input === undefined) {
return '';
}
else if (typeof input === 'string' || input instanceof String) {
return input;
}
return JSON.stringify(input);
}
exports.toCommandValue = toCommandValue;
function escapeData(s) {
return utils_1.toCommandValue(s)
return toCommandValue(s)
.replace(/%/g, '%25')
.replace(/\r/g, '%0D')
.replace(/\n/g, '%0A');
}
function escapeProperty(s) {
return utils_1.toCommandValue(s)
return toCommandValue(s)
.replace(/%/g, '%25')
.replace(/\r/g, '%0D')
.replace(/\n/g, '%0A')
Expand Down Expand Up @@ -1209,8 +1160,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
};
Object.defineProperty(exports, "__esModule", { value: true });

This comment has been minimized.

Copy link
@Flint05

Flint05 May 10, 2022

обьясните как сдесь заработать

const command_1 = __webpack_require__(431);
const file_command_1 = __webpack_require__(102);
const utils_1 = __webpack_require__(82);
const os = __importStar(__webpack_require__(87));
const path = __importStar(__webpack_require__(622));
/**
Expand All @@ -1237,17 +1186,9 @@ var ExitCode;
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function exportVariable(name, val) {
const convertedVal = utils_1.toCommandValue(val);
const convertedVal = command_1.toCommandValue(val);
process.env[name] = convertedVal;
const filePath = process.env['GITHUB_ENV'] || '';
if (filePath) {
const delimiter = '_GitHubActionsFileCommandDelimeter_';
const commandValue = `${name}<<${delimiter}${os.EOL}${convertedVal}${os.EOL}${delimiter}`;
file_command_1.issueCommand('ENV', commandValue);
}
else {
command_1.issueCommand('set-env', { name }, convertedVal);
}
command_1.issueCommand('set-env', { name }, convertedVal);
}
exports.exportVariable = exportVariable;
/**
Expand All @@ -1263,13 +1204,7 @@ exports.setSecret = setSecret;
* @param inputPath
*/
function addPath(inputPath) {
const filePath = process.env['GITHUB_PATH'] || '';
if (filePath) {
file_command_1.issueCommand('PATH', inputPath);
}
else {
command_1.issueCommand('add-path', {}, inputPath);
}
command_1.issueCommand('add-path', {}, inputPath);
process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`;
}
exports.addPath = addPath;
Expand Down
1,414 changes: 351 additions & 1,063 deletions dist/index.js

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const aws = require('aws-sdk');

async function run() {
const registryUriState = [];
const skipLogout = core.getInput('skip-logout', { required: false });

try {
const registries = core.getInput('registries', { required: false });
Expand Down Expand Up @@ -67,7 +68,10 @@ async function run() {

// Pass the logged-in registry URIs to the post action for logout
if (registryUriState.length) {
core.saveState('registries', registryUriState.join());
if (!skipLogout) {
core.saveState('registries', registryUriState.join());
}
core.debug(`'skip-logout' is ${skipLogout} for ${registryUriState.length} registries.`);
}
}

Expand Down
80 changes: 77 additions & 3 deletions index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@ const exec = require('@actions/exec');
jest.mock('@actions/core');
jest.mock('@actions/exec');

function mockGetInput(requestResponse) {
return function (name, options) { // eslint-disable-line no-unused-vars
return requestResponse[name]
}
}

const DEFAULT_INPUTS = {
'registries': undefined,
'skip-logout': undefined
};

const mockEcrGetAuthToken = jest.fn();
jest.mock('aws-sdk', () => {
return {
Expand All @@ -19,6 +30,10 @@ describe('Login to ECR', () => {
beforeEach(() => {
jest.clearAllMocks();

core.getInput = jest
.fn()
.mockImplementation(mockGetInput(DEFAULT_INPUTS));

mockEcrGetAuthToken.mockImplementation(() => {
return {
promise() {
Expand Down Expand Up @@ -50,7 +65,10 @@ describe('Login to ECR', () => {
});

test('gets auth token from ECR and logins the Docker client for each provided registry', async () => {
core.getInput = jest.fn().mockReturnValueOnce('123456789012,111111111111');
const mockInputs = {'registries' : '123456789012,111111111111'};
core.getInput = jest
.fn()
.mockImplementation(mockGetInput(mockInputs));
mockEcrGetAuthToken.mockImplementation(() => {
return {
promise() {
Expand Down Expand Up @@ -90,7 +108,10 @@ describe('Login to ECR', () => {
});

test('outputs the registry ID if a single registry is provided in the input', async () => {
core.getInput = jest.fn().mockReturnValueOnce('111111111111');
const mockInputs = {'registries' : '111111111111'};
core.getInput = jest
.fn()
.mockImplementation(mockGetInput(mockInputs));
mockEcrGetAuthToken.mockImplementation(() => {
return {
promise() {
Expand Down Expand Up @@ -135,7 +156,10 @@ describe('Login to ECR', () => {
test('logged-in registries are saved as state even if the action fails', async () => {
exec.exec.mockReturnValue(1).mockReturnValueOnce(0);

core.getInput = jest.fn().mockReturnValueOnce('123456789012,111111111111');
const mockInputs = {'registries' : '123456789012,111111111111'};
core.getInput = jest
.fn()
.mockImplementation(mockGetInput(mockInputs));
mockEcrGetAuthToken.mockImplementation(() => {
return {
promise() {
Expand Down Expand Up @@ -187,4 +211,54 @@ describe('Login to ECR', () => {
expect(core.setOutput).toHaveBeenCalledTimes(0);
expect(core.saveState).toHaveBeenCalledTimes(0);
});

test('skips logout when specified and logging into default registry', async () => {
const mockInputs = {'skip-logout' : true};
core.getInput = jest
.fn()
.mockImplementation(mockGetInput(mockInputs));

await run();
expect(mockEcrGetAuthToken).toHaveBeenCalled();
expect(core.setOutput).toHaveBeenNthCalledWith(1, 'registry', '123456789012.dkr.ecr.aws-region-1.amazonaws.com');
expect(exec.exec).toHaveBeenNthCalledWith(1,
'docker login',
['-u', 'hello', '-p', 'world', 'https://123456789012.dkr.ecr.aws-region-1.amazonaws.com'],
expect.anything());
expect(core.saveState).toHaveBeenCalledTimes(0);
});

test('skips logout when specified and logging into multiple registries', async () => {
const mockInputs = {'registries' : '123456789012,111111111111', 'skip-logout' : true};
core.getInput = jest
.fn()
.mockImplementation(mockGetInput(mockInputs));
mockEcrGetAuthToken.mockImplementation(() => {
return {
promise() {
return Promise.resolve({
authorizationData: [
{
authorizationToken: Buffer.from('hello:world').toString('base64'),
proxyEndpoint: 'https://123456789012.dkr.ecr.aws-region-1.amazonaws.com'
},
{
authorizationToken: Buffer.from('foo:bar').toString('base64'),
proxyEndpoint: 'https://111111111111.dkr.ecr.aws-region-1.amazonaws.com'
}
]
});
}
};
});

await run();

expect(mockEcrGetAuthToken).toHaveBeenCalledWith({
registryIds: ['123456789012','111111111111']
});
expect(core.setOutput).toHaveBeenCalledTimes(0);
expect(exec.exec).toHaveBeenCalledTimes(2);
expect(core.saveState).toHaveBeenCalledTimes(0);
});
});

0 comments on commit dd3fdee

Please sign in to comment.