163 lines
4.1 KiB
JavaScript
Executable File
163 lines
4.1 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
|
|
var program = require('commander');
|
|
var spawn = require('child_process').spawn;
|
|
var chokidar = require('chokidar');
|
|
var fs = require('fs');
|
|
var kill = require('tree-kill');
|
|
|
|
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)
|
|
|
|
if (!program.suite) {
|
|
throw new Error('Please provide a suite.');
|
|
}
|
|
|
|
const ENVIRONMENT_FILENAME = '.suite';
|
|
const AUTHELIA_INTERRUPT_FILENAME = '.authelia-interrupt';
|
|
const CONFIG_FILEPATH = `test/suites/${program.suite}/config.yml`;
|
|
|
|
|
|
var tsWatcher = chokidar.watch(['server', 'shared/**/*.ts', 'node_modules', AUTHELIA_INTERRUPT_FILENAME, CONFIG_FILEPATH], {
|
|
persistent: true,
|
|
ignoreInitial: true,
|
|
});
|
|
|
|
// Properly cleanup server and client if ctrl-c is hit
|
|
process.on('SIGINT', function() {
|
|
killServer();
|
|
killClient();
|
|
fs.unlinkSync(ENVIRONMENT_FILENAME);
|
|
process.exit();
|
|
});
|
|
|
|
|
|
let serverProcess;
|
|
function reloadServer() {
|
|
killServer(() => {
|
|
startServer();
|
|
});
|
|
}
|
|
|
|
function startServer() {
|
|
if (fs.existsSync(AUTHELIA_INTERRUPT_FILENAME)) {
|
|
console.log('Authelia is interrupted. Consider removing ' + AUTHELIA_INTERRUPT_FILENAME + ' if it\'s not expected.');
|
|
return;
|
|
}
|
|
exec('./node_modules/.bin/tslint', ['-c', 'server/tslint.json', '-p', 'server/tsconfig.json'])
|
|
.then(function() {
|
|
serverProcess = spawn('./scripts/run-dev-server.sh', [CONFIG_FILEPATH]);
|
|
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;
|
|
if (onExit) onExit();
|
|
});
|
|
try {
|
|
kill(serverProcess.pid, 'SIGKILL');
|
|
} catch (e) {
|
|
console.error(e);
|
|
if (onExit) onExit();
|
|
}
|
|
} else {
|
|
if (onExit) onExit();
|
|
}
|
|
}
|
|
|
|
function killClient(onExit) {
|
|
if (clientProcess) {
|
|
clientProcess.on('exit', () => {
|
|
clientProcess = undefined;
|
|
if (onExit) onExit();
|
|
});
|
|
try {
|
|
kill(clientProcess.pid, 'SIGKILL');
|
|
} catch (e) {
|
|
console.error(e);
|
|
if (onExit) onExit();
|
|
}
|
|
} else {
|
|
if (onExit) onExit();
|
|
}
|
|
}
|
|
|
|
function generateConfigurationSchema() {
|
|
return ixec('./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();
|
|
}
|
|
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;
|
|
}
|
|
reloadServer();
|
|
}
|
|
|
|
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));
|
|
});
|
|
});
|
|
}
|
|
|
|
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);
|
|
tsWatcher.on('unlink', reload);
|
|
tsWatcher.on('change', reload);
|
|
|
|
startServer();
|
|
startClient();
|
|
}
|
|
|
|
main()
|