Skip to content

Commit

Permalink
Add dockerized yarn runner (#5305)
Browse files Browse the repository at this point in the history
* Add Dockerized Jest runner

* Add possibility to pass Jest CLI options to the runner

* Fix buildJestArgs function to actually include default Jest options

Duplicated values are also dropped now

* Refactor the test runner to allow building packages

* Extend documentation of the runner

* Formatter and bug fix

Fixes a bug where the environment variables were not read

* Fix docker compose command

* Allow passing additional arguments which do not start with --

---------

Co-authored-by: Ian Yenien Serrano <63758389+yenienserrano@users.noreply.github.com>
  • Loading branch information
AlexRuiz7 and yenienserrano authored Mar 23, 2023
1 parent cf4e214 commit c7d97f2
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 0 deletions.
21 changes: 21 additions & 0 deletions docker/runner/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
version: "3"

# Parameters:
# -------------
# - APP: osd (OpenSearch Dashboards) or kbn (Kibana)
# - VERSION: OpenSearch Dashboards / Kibana version
# - REPO: Path to the Wazuh app local repository
# - CMD: yarn command to execute in the container
# - ARGS: (optional) Additional CLI options of the command

services:
test_runner:
container_name: runner
image: quay.io/wazuh/$APP-dev:$VERSION
working_dir: /home/node/kbn/plugins/wazuh
volumes:
- $REPO:/home/node/kbn/plugins/wazuh
command: /bin/bash -c '
yarn;
yarn $CMD $ARGS
'
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@
"es": "node ../../scripts/es",
"start": "plugin-helpers start",
"build": "yarn plugin-helpers build --opensearch-dashboards-version=$OPENSEARCH_DASHBOARDS_VERSION",
"build:runner": "node scripts/runner build",
"plugin-helpers": "node ../../scripts/plugin_helpers",
"test:ui:runner": "node ../../scripts/functional_test_runner.js",
"test:server": "plugin-helpers test:server",
"test:browser": "plugin-helpers test:browser",
"test:jest": "node scripts/jest",
"test:jest:runner": "node scripts/runner test",
"generate:api-4.0-info": "cd scripts/generate-api-4.0-info;./generate-api-4.0-info.sh;cd ../..",
"prebuild": "node scripts/generate-build-version"
},
Expand Down
17 changes: 17 additions & 0 deletions scripts/manifest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

/* eslint-disable @typescript-eslint/no-var-requires */

const fs = require('fs');

/**
* Reads the package.json file.
* @returns {Object} JSON object.
*/
function loadPackageJson() {
const packageJson = fs.readFileSync('./package.json');
return JSON.parse(packageJson);
}

module.exports = {
loadPackageJson
};
151 changes: 151 additions & 0 deletions scripts/runner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/* eslint-disable array-element-newline */
/* eslint-disable @typescript-eslint/no-var-requires */

/**
Runs yarn commands using a Docker container.
Intended to test and build locally.
Uses development images. Must be executed from the root folder of the project.
See /docker/runner/docker-compose.yml for available environment variables.
# Usage:
# -------------
# - node scripts/runner <command> [<command_args>]
# - yarn test:jest:runner [<jest_args>]
# - yarn build:runner
*/

const childProcess = require('child_process');
const { loadPackageJson } = require('./manifest');

const COMPOSE_DIR = './docker/runner';

function getProjectInfo() {
const manifest = loadPackageJson();

return {
app: manifest['keywords'].includes('opensearch_dashboards') ? 'osd' : 'kbn',
version: manifest['pluginPlatform']['version'],
repo: process.cwd(),
};
}

function getBuildArgs({ app, version }) {
return app === 'osd'
? `--opensearch-dashboards-version=${version}`
: `--kibana-version=${version}`;
}

/**
* Transforms the Jest CLI options from process.argv back to a string.
* If no options are provided, default ones are generated.
* @returns {String} Space separated string with all Jest CLI options provided.
*/
function getJestArgs() {
// Take args only after `test` word
const index = process.argv.indexOf('test');
const args = process.argv.slice(index + 1);
// Remove duplicates using set
return Array.from(new Set([ ...args, '--runInBand' ]))
.join(' ');
}

/**
* Generates the execution parameters if they are not set.
* @returns {Object} Default environment variables.
*/
const buildEnvVars = ({ app, version, repo, cmd, args }) => {
return {
APP: app,
VERSION: version,
REPO: repo,
CMD: cmd,
ARGS: args,
};
};

/**
* Captures the SIGINT signal (Ctrl + C) to stop the container and exit.
*/
function setupAbortController() {
process.on('SIGINT', () => {
childProcess.spawnSync('docker', [
'compose',
'--project-directory',
COMPOSE_DIR,
'stop',
]);
process.exit();
});
}

/**
* Start the container.
*/
function startRunner() {
const runner = childProcess.spawn('docker', [
'compose',
'--project-directory',
COMPOSE_DIR,
'up',
]);

runner.stdout.on('data', data => {
console.log(`${data}`);
});

runner.stderr.on('data', data => {
console.error(`${data}`);
});
}

/**
* Main function
*/
function main() {
if (process.argv.length < 2) {
process.stderr.write('Required parameters not provided');
process.exit(-1);
}

const projectInfo = getProjectInfo();
let envVars = {};

switch (process.argv[2]) {
case 'build':
envVars = buildEnvVars({
...projectInfo,
cmd: 'plugin-helpers build',
args: getBuildArgs({ ...projectInfo }),
});
break;

case 'test':
envVars = buildEnvVars({
...projectInfo,
cmd: 'test:jest',
args: getJestArgs(),
});
break;

default:
// usage();
console.error('Unsupported or invalid yarn command.');
process.exit(-1);
}

// Check the required environment variables are set
for (const [ key, value ] of Object.entries(envVars)) {
if (!process.env[key]) {
process.env[key] = value;
}
console.log(`${key}: ${process.env[key]}`);
}

setupAbortController();
startRunner();
}

main();

0 comments on commit c7d97f2

Please sign in to comment.