2019-02-04 22:23:59 +00:00
#!/usr/bin/env node
2019-01-27 14:54:29 +00:00
2019-02-04 22:23:59 +00:00
var program = require('commander');
var spawn = require('child_process').spawn;
var chokidar = require('chokidar');
var fs = require('fs');
2019-02-13 22:04:57 +00:00
var kill = require('tree-kill');
2019-01-30 15:47:03 +00:00
2019-02-04 22:23:59 +00:00
program
.option('-s, --suite <suite>', 'The suite to run Authelia for. This suite represents a configuration for Authelia and a set of tests for that configuration.')
.parse(process.argv)
2019-01-30 15:47:03 +00:00
2019-02-04 22:23:59 +00:00
if (!program.suite) {
throw new Error('Please provide a suite.');
}
2019-01-27 14:54:29 +00:00
2019-02-04 22:23:59 +00:00
const ENVIRONMENT_FILENAME = '.suite';
2019-02-13 22:04:57 +00:00
const AUTHELIA_INTERRUPT_FILENAME = '.authelia-interrupt';
2019-01-27 14:54:29 +00:00
2019-01-30 15:47:03 +00:00
2019-02-13 22:04:57 +00:00
var tsWatcher = chokidar.watch(['server', 'shared/**/*.ts', 'node_modules', AUTHELIA_INTERRUPT_FILENAME], {
2019-02-04 22:23:59 +00:00
persistent: true,
ignoreInitial: true,
});
// Properly cleanup server and client if ctrl-c is hit
process.on('SIGINT', function() {
2019-02-13 22:04:57 +00:00
killServer();
killClient();
2019-02-04 22:23:59 +00:00
fs.unlinkSync(ENVIRONMENT_FILENAME);
process.exit();
});
let serverProcess;
function reloadServer() {
killServer(() => {
startServer();
});
}
function startServer() {
2019-02-13 22:04:57 +00:00
if (fs.existsSync(AUTHELIA_INTERRUPT_FILENAME)) {
console.log('Authelia is interrupted. Consider removing ' + AUTHELIA_INTERRUPT_FILENAME + ' if it\'s not expected.');
return;
}
serverProcess = spawn('./scripts/run-dev-server.sh', [`test/suites/${program.suite}/config.yml`]);
2019-02-04 22:23:59 +00:00
serverProcess.stdout.pipe(process.stdout);
serverProcess.stderr.pipe(process.stderr);
}
let clientProcess;
function startClient() {
clientProcess = spawn('npm', ['run', 'start'], {
cwd: './client',
env: {
...process.env,
'BROWSER': 'none'
}
});
clientProcess.stdout.pipe(process.stdout);
clientProcess.stderr.pipe(process.stderr);
}
function killServer(onExit) {
if (serverProcess) {
serverProcess.on('exit', () => {
serverProcess = undefined;
2019-02-13 22:04:57 +00:00
if (onExit) onExit();
2019-02-04 22:23:59 +00:00
});
2019-02-09 22:20:37 +00:00
try {
2019-02-13 22:04:57 +00:00
kill(serverProcess.pid, 'SIGKILL');
2019-02-09 22:20:37 +00:00
} catch (e) {
console.error(e);
2019-02-13 22:04:57 +00:00
if (onExit) onExit();
2019-02-09 22:20:37 +00:00
}
2019-02-13 22:04:57 +00:00
} else {
if (onExit) onExit();
2019-02-04 22:23:59 +00:00
}
}
function killClient(onExit) {
if (clientProcess) {
clientProcess.on('exit', () => {
clientProcess = undefined;
2019-02-13 22:04:57 +00:00
if (onExit) onExit();
2019-02-04 22:23:59 +00:00
});
2019-02-09 22:20:37 +00:00
try {
2019-02-13 22:04:57 +00:00
kill(clientProcess.pid, 'SIGKILL');
2019-02-09 22:20:37 +00:00
} catch (e) {
console.error(e);
2019-02-13 22:04:57 +00:00
if (onExit) onExit();
2019-02-09 22:20:37 +00:00
}
2019-02-13 22:04:57 +00:00
} else {
if (onExit) onExit();
2019-02-04 22:23:59 +00:00
}
}
function generateConfigurationSchema() {
exec('./node_modules/.bin/typescript-json-schema -o server/src/lib/configuration/Configuration.schema.json --strictNullChecks --required server/tsconfig.json Configuration');
}
function reload(path) {
console.log(`File ${path} has been changed, reloading...`);
if (path.startsWith('server/src/lib/configuration/schema')) {
console.log('Schema needs to be regenerated.');
generateConfigurationSchema();
}
2019-02-13 22:04:57 +00:00
else if (path === AUTHELIA_INTERRUPT_FILENAME) {
if (fs.existsSync(path)) {
console.log('Authelia is being interrupted.');
killServer();
} else {
console.log('Authelia is restarting.');
startServer();
}
return;
}
2019-02-04 22:23:59 +00:00
reloadServer();
}
2019-02-12 22:23:43 +00:00
function exec(command, args) {
return new Promise((resolve, reject) => {
const cmd = spawn(command, args);
cmd.stdout.pipe(process.stdout);
cmd.stderr.pipe(process.stderr);
cmd.on('close', (code) => {
if (code == 0) {
resolve();
return;
}
reject(new Error('Status code ' + code));
});
});
}
2019-02-04 22:23:59 +00:00
2019-02-12 22:23:43 +00:00
async function main() {
console.log(`Create suite file ${ENVIRONMENT_FILENAME}.`);
fs.writeFileSync(ENVIRONMENT_FILENAME, program.suite);
console.log(`Render nginx configuration...`);
await exec('./example/compose/nginx/portal/render.js');
console.log(`Prepare environment with docker-compose...`);
await exec('./scripts/utils/prepare-environment.sh');
console.log('Start watching...');
tsWatcher.on('add', reload);
2019-02-13 22:04:57 +00:00
tsWatcher.on('unlink', reload);
2019-02-12 22:23:43 +00:00
tsWatcher.on('change', reload);
startServer();
startClient();
}
2019-01-27 14:54:29 +00:00
2019-02-12 22:23:43 +00:00
main()