Skip to content

Commit

Permalink
Feature/add build args (#4)
Browse files Browse the repository at this point in the history
* Add option to add --build-arg's to docker
Add test for build args
Update jest and ts-jest to resolve an issue where the test file is missing: kulshekhar/ts-jest#1506

* Update action, readme, dist and version number
  • Loading branch information
bas-l committed Mar 9, 2021
1 parent e52348a commit 55c0574
Show file tree
Hide file tree
Showing 7 changed files with 1,252 additions and 702 deletions.
15 changes: 8 additions & 7 deletions README.md
Expand Up @@ -4,13 +4,14 @@ A Github action for building and pushing docker images.

## Inputs

| Input | Description |
| ---------------- | :------------------------------------------------------------------------- |
| imageName | The name of the docker image |
| workingDirectory | The working directory from which to run the docker commands (default: `.`) |
| dockerRegistry | The registry to push the image name (default: `docker.io`) |
| dockerfile | Path to Dockerfile (default: `Dockerfile`) |
| latestBranch | From which branch to create latest releases (default: `master`) |
| Input | Description |
| ---------------- | :------------------------------------------------------------------------------------------------------|
| imageName | The name of the docker image |
| workingDirectory | The working directory from which to run the docker commands (default: `.`) |
| dockerRegistry | The registry to push the image name (default: `docker.io`) |
| dockerfile | Path to Dockerfile (default: `Dockerfile`) |
| latestBranch | From which branch to create latest releases (default: `master`) |
| buildArgs | List of environment variables that are passed to docker via `--build-arg <BUILD_ARG>` (default: empty) |

## Outputs

Expand Down
3 changes: 3 additions & 0 deletions action.yml
Expand Up @@ -23,6 +23,9 @@ inputs:
currentBranch:
description: 'Optionally set the branch name to use for docker tag (some events do not set `GITHUB_REF` to current branch)'
required: false
buildArgs:
description: 'Optionally enter a list of `VARIABLE=value` strings that will be passed each as `--build-arg VARIABLE=value` to docker'
required: false
outputs:
dockerTag:
description: 'The docker tag of the built image'
Expand Down
120 changes: 107 additions & 13 deletions dist/index.js
Expand Up @@ -934,13 +934,75 @@ class ExecState extends events.EventEmitter {

/***/ }),

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

"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) {
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 @@ -992,6 +1054,7 @@ exports.docker = async () => {
const dockerfile = core.getInput('dockerfile', { required: true });
const latestBranch = core.getInput('latestBranch', { required: true });
const currentBranch = core.getInput('currentBranch');
const buildArgs = core.getInput('buildArgs').split("\n").filter(x => x !== "");
const dockerTag = getDockerTag(currentBranch !== '' ? currentBranch : process.env['GITHUB_REF'], latestBranch);
core.setOutput('dockerTag', dockerTag);
core.info(`
Expand All @@ -1002,9 +1065,10 @@ exports.docker = async () => {
WorkingDirectory: ${workingDirectory}
LatestBranch : ${latestBranch}
DockerTag : ${dockerTag}
BuildArgs : ${buildArgs.join(' ')}
`);
await runInGroup('Building image', async () => {
const buildErrorCode = await exec_1.exec(`docker build -f ${dockerfile} -t ${dockerRegistry}/${imageName}:${dockerTag} .`, [], {
const buildErrorCode = await exec_1.exec(`docker build ${buildArgs.map(a => '--build-arg ' + a + ' ').join('')}-f ${dockerfile} -t ${dockerRegistry}/${imageName}:${dockerTag} .`, [], {
cwd: workingDirectory,
});
if (buildErrorCode !== 0) {
Expand Down Expand Up @@ -1043,6 +1107,7 @@ 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 @@ -1097,13 +1162,13 @@ class Command {
}
}
function escapeData(s) {
return (s || '')
return utils_1.toCommandValue(s)
.replace(/%/g, '%25')
.replace(/\r/g, '%0D')
.replace(/\n/g, '%0A');
}
function escapeProperty(s) {
return (s || '')
return utils_1.toCommandValue(s)
.replace(/%/g, '%25')
.replace(/\r/g, '%0D')
.replace(/\n/g, '%0A')
Expand Down Expand Up @@ -1137,6 +1202,8 @@ var __importStar = (this && this.__importStar) || function (mod) {
};
Object.defineProperty(exports, "__esModule", { value: true });
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 @@ -1159,11 +1226,21 @@ var ExitCode;
/**
* Sets env variable for this action and future actions in the job
* @param name the name of the variable to set
* @param val the value of the variable
* @param val the value of the variable. Non-string values will be converted to a string via JSON.stringify
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function exportVariable(name, val) {
process.env[name] = val;
command_1.issueCommand('set-env', { name }, val);
const convertedVal = utils_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);
}
}
exports.exportVariable = exportVariable;
/**
Expand All @@ -1179,7 +1256,13 @@ exports.setSecret = setSecret;
* @param inputPath
*/
function addPath(inputPath) {
command_1.issueCommand('add-path', {}, inputPath);
const filePath = process.env['GITHUB_PATH'] || '';
if (filePath) {
file_command_1.issueCommand('PATH', inputPath);
}
else {
command_1.issueCommand('add-path', {}, inputPath);
}
process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`;
}
exports.addPath = addPath;
Expand All @@ -1202,12 +1285,22 @@ exports.getInput = getInput;
* Sets the value of an output.
*
* @param name name of the output to set
* @param value value to store
* @param value value to store. Non-string values will be converted to a string via JSON.stringify
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function setOutput(name, value) {
command_1.issueCommand('set-output', { name }, value);
}
exports.setOutput = setOutput;
/**
* Enables or disables the echoing of commands into stdout for the rest of the step.
* Echoing is disabled by default if ACTIONS_STEP_DEBUG is not set.
*
*/
function setCommandEcho(enabled) {
command_1.issue('echo', enabled ? 'on' : 'off');
}
exports.setCommandEcho = setCommandEcho;
//-----------------------------------------------------------------------
// Results
//-----------------------------------------------------------------------
Expand Down Expand Up @@ -1241,18 +1334,18 @@ function debug(message) {
exports.debug = debug;
/**
* Adds an error issue
* @param message error issue message
* @param message error issue message. Errors will be converted to string via toString()
*/
function error(message) {
command_1.issue('error', message);
command_1.issue('error', message instanceof Error ? message.toString() : message);
}
exports.error = error;
/**
* Adds an warning issue
* @param message warning issue message
* @param message warning issue message. Errors will be converted to string via toString()
*/
function warning(message) {
command_1.issue('warning', message);
command_1.issue('warning', message instanceof Error ? message.toString() : message);
}
exports.warning = warning;
/**
Expand Down Expand Up @@ -1310,8 +1403,9 @@ exports.group = group;
* Saves state for current action, the state can only be retrieved by this action's post job execution.
*
* @param name name of the state to store
* @param value value to store
* @param value value to store. Non-string values will be converted to a string via JSON.stringify
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function saveState(name, value) {
command_1.issueCommand('save-state', { name }, value);
}
Expand Down
6 changes: 3 additions & 3 deletions package.json
@@ -1,6 +1,6 @@
{
"name": "docker-action",
"version": "1.0.1",
"version": "1.1.0",
"main": "index.js",
"license": "MIT",
"scripts": {
Expand All @@ -15,8 +15,8 @@
"@types/jest": "^25.2.1",
"@types/node": "^13.11.0",
"@zeit/ncc": "^0.22.1",
"jest": "^25.2.7",
"ts-jest": "^25.3.1",
"jest": "^26.1.4",
"ts-jest": "^26.1.4",
"typescript": "^3.8.3"
}
}
17 changes: 17 additions & 0 deletions src/docker.test.ts
Expand Up @@ -17,6 +17,7 @@ describe('Docker action', () => {
process.env['INPUT_DOCKERFILE'] = 'Dockerfile';
process.env['INPUT_LATESTBRANCH'] = 'master';
process.env['GITHUB_REF'] = 'refs/heads/develop';
delete process.env['INPUT_BUILDARGS'];
delete process.env['INPUT_CURRENTBRANCH'];
});

Expand Down Expand Up @@ -98,6 +99,22 @@ describe('Docker action', () => {
await expect(setOutput).toHaveBeenCalledWith('dockerTag', 'latest');
});

it('should add the build args as --build-arg to the docker build', async () => {
process.env['INPUT_BUILDARGS'] = 'HOST=localhost\nPORT=8080';
const mockedExec = exec as jest.Mock<Promise<number>>;
mockedExec.mockReturnValue(Promise.resolve(0));

await docker();

await expect(exec).toHaveBeenCalledWith(
'docker build --build-arg HOST=localhost --build-arg PORT=8080 -f Dockerfile -t test-registry.io/HelloWorld:develop .',
[],
{
cwd: 'src',
},
);
});

it('should build the docker image', async () => {
const mockedExec = exec as jest.Mock<Promise<number>>;
mockedExec.mockReturnValue(Promise.resolve(0));
Expand Down
4 changes: 3 additions & 1 deletion src/docker.ts
Expand Up @@ -30,6 +30,7 @@ export const docker = async () => {
const dockerfile = core.getInput('dockerfile', { required: true });
const latestBranch = core.getInput('latestBranch', { required: true });
const currentBranch = core.getInput('currentBranch');
const buildArgs: string[] = core.getInput('buildArgs').split("\n").filter(x => x !== "");

const dockerTag = getDockerTag(
currentBranch !== '' ? currentBranch : process.env['GITHUB_REF']!,
Expand All @@ -45,11 +46,12 @@ export const docker = async () => {
WorkingDirectory: ${workingDirectory}
LatestBranch : ${latestBranch}
DockerTag : ${dockerTag}
BuildArgs : ${buildArgs.join(' ')}
`);

await runInGroup('Building image', async () => {
const buildErrorCode = await exec(
`docker build -f ${dockerfile} -t ${dockerRegistry}/${imageName}:${dockerTag} .`,
`docker build ${buildArgs.map(a => '--build-arg ' + a + ' ').join('')}-f ${dockerfile} -t ${dockerRegistry}/${imageName}:${dockerTag} .`,
[],
{
cwd: workingDirectory,
Expand Down

0 comments on commit 55c0574

Please sign in to comment.