#1107 Back tests from Jenkins
This commit is contained in:
parent
796a3e1a76
commit
7e0ccfcc11
|
@ -62,14 +62,12 @@ pipeline {
|
||||||
environment {
|
environment {
|
||||||
NODE_ENV = ""
|
NODE_ENV = ""
|
||||||
FIREFOX_BIN = "/opt/firefox/firefox-bin"
|
FIREFOX_BIN = "/opt/firefox/firefox-bin"
|
||||||
|
DOCKER_HOST = "${env.DOCKER_HOST_2}"
|
||||||
}
|
}
|
||||||
steps {
|
steps {
|
||||||
nodejs('node-lts') {
|
nodejs('node-lts') {
|
||||||
sh 'karma start --junit'
|
sh 'karma start --junit'
|
||||||
|
sh 'gulp backTestDocker --junit --random --run-chown'
|
||||||
sh 'gulp docker'
|
|
||||||
// sh 'gulp backendUnitTest --junit' // FIXME: Docker isn't at localhost
|
|
||||||
sh 'docker rm -f salix-db'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
125
gulpfile.js
125
gulpfile.js
|
@ -16,6 +16,13 @@ let langs = ['es', 'en'];
|
||||||
let srcDir = './front';
|
let srcDir = './front';
|
||||||
let modulesDir = './modules';
|
let modulesDir = './modules';
|
||||||
let buildDir = 'dist';
|
let buildDir = 'dist';
|
||||||
|
let containerId = 'salix-db';
|
||||||
|
|
||||||
|
let dataSources = require('./loopback/server/datasources.json');
|
||||||
|
let dbConf = dataSources.vn;
|
||||||
|
|
||||||
|
if (process.env.DOCKER_HOST)
|
||||||
|
dbConf.host = process.env.DOCKER_HOST;
|
||||||
|
|
||||||
let backSources = [
|
let backSources = [
|
||||||
'!node_modules',
|
'!node_modules',
|
||||||
|
@ -66,43 +73,55 @@ defaultTask.description = `Starts all application services`;
|
||||||
|
|
||||||
// Backend tests
|
// Backend tests
|
||||||
|
|
||||||
function backendUnitTest() {
|
async function backTestOnly() {
|
||||||
|
let bootOptions;
|
||||||
|
|
||||||
|
if (argv['random'])
|
||||||
|
bootOptions = {dataSources};
|
||||||
|
|
||||||
let app = require(`./loopback/server/server`);
|
let app = require(`./loopback/server/server`);
|
||||||
|
app.boot(bootOptions);
|
||||||
|
|
||||||
let specFiles = [
|
await new Promise((resolve, reject) => {
|
||||||
'back/**/*.spec.js',
|
const jasmine = require('gulp-jasmine');
|
||||||
'loopback/**/*.spec.js',
|
|
||||||
'modules/*/back/**/*.spec.js'
|
|
||||||
];
|
|
||||||
|
|
||||||
const jasmine = require('gulp-jasmine');
|
let options = {errorOnFail: false};
|
||||||
let options = {errorOnFail: false};
|
|
||||||
|
|
||||||
if (argv.junit || argv.j) {
|
if (argv.junit) {
|
||||||
const reporters = require('jasmine-reporters');
|
const reporters = require('jasmine-reporters');
|
||||||
options.reporter = new reporters.JUnitXmlReporter();
|
options.reporter = new reporters.JUnitXmlReporter();
|
||||||
}
|
}
|
||||||
|
|
||||||
return gulp.src(specFiles)
|
let backSpecFiles = [
|
||||||
.pipe(jasmine(options))
|
'back/**/*.spec.js',
|
||||||
.on('jasmineDone', function() {
|
'loopback/**/*.spec.js',
|
||||||
app.disconnect();
|
'modules/*/back/**/*.spec.js'
|
||||||
});
|
];
|
||||||
|
|
||||||
|
gulp.src(backSpecFiles)
|
||||||
|
.pipe(jasmine(options))
|
||||||
|
.on('end', resolve)
|
||||||
|
.resume();
|
||||||
|
});
|
||||||
|
|
||||||
|
await app.disconnect();
|
||||||
}
|
}
|
||||||
backendUnitTest.description = `Runs the backend tests only, can receive args --junit or -j to save reports on a xml file`;
|
backTestOnly.description = `Runs the backend tests only, can receive --junit arg to save reports on a xml file`;
|
||||||
|
|
||||||
const dockerAndBackTest = gulp.series(docker, backendUnitTest);
|
async function backTestDocker() {
|
||||||
dockerAndBackTest.description = `Restarts database and runs the backend tests`;
|
let containerId = await docker();
|
||||||
|
await backTestOnly();
|
||||||
|
if (argv['random'])
|
||||||
|
await execP(`docker rm -fv ${containerId}`);
|
||||||
|
}
|
||||||
|
backTestDocker.description = `Runs backend tests using in site container`;
|
||||||
|
|
||||||
function backTest(done) {
|
function backTest(done) {
|
||||||
const nodemon = require('gulp-nodemon');
|
const nodemon = require('gulp-nodemon');
|
||||||
let gulpBin = isWindows
|
|
||||||
? 'node_modules/.bin/gulp.cmd'
|
|
||||||
: 'node_modules/.bin/gulp';
|
|
||||||
|
|
||||||
nodemon({
|
nodemon({
|
||||||
exec: gulpBin,
|
exec: ['node ./node_modules/gulp/bin/gulp.js'],
|
||||||
args: ['backendUnitTest'],
|
args: ['backTestOnly'],
|
||||||
watch: backSources,
|
watch: backSources,
|
||||||
done: done
|
done: done
|
||||||
});
|
});
|
||||||
|
@ -324,20 +343,35 @@ watch.description = `Watches for changes in routes and locale files`;
|
||||||
* to avoid a bug with OverlayFS driver on MacOS.
|
* to avoid a bug with OverlayFS driver on MacOS.
|
||||||
*/
|
*/
|
||||||
async function docker() {
|
async function docker() {
|
||||||
try {
|
|
||||||
await execP('docker rm -fv salix-db');
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
let d = new Date();
|
let d = new Date();
|
||||||
let pad = v => v < 10 ? '0' + v : v;
|
let pad = v => v < 10 ? '0' + v : v;
|
||||||
let stamp = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
let stamp = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
||||||
await execP(`docker build --build-arg STAMP=${stamp} -t salix-db ./services/db`);
|
await execP(`docker build --build-arg STAMP=${stamp} -t salix-db ./services/db`);
|
||||||
|
|
||||||
|
let dockerArgs = `--name ${containerId} -p 3306:${dbConf.port}`;
|
||||||
|
|
||||||
|
if (argv['random'])
|
||||||
|
dockerArgs = '-p 3306';
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
await execP(`docker rm -fv ${containerId}`);
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
|
||||||
let runChown = process.platform != 'linux';
|
let runChown = process.platform != 'linux';
|
||||||
if (argv['run-chown']) runChown = true;
|
if (argv['run-chown']) runChown = true;
|
||||||
|
|
||||||
await execP(`docker run --env RUN_CHOWN=${runChown} -d --name salix-db -p 3306:3306 salix-db`);
|
let result = await execP(`docker run --env RUN_CHOWN=${runChown} -d ${dockerArgs} salix-db`);
|
||||||
|
containerId = result.stdout;
|
||||||
|
|
||||||
|
if (argv['random']) {
|
||||||
|
let inspect = await execP(`docker inspect -f "{{json .NetworkSettings.Ports}}" ${containerId}`);
|
||||||
|
let ports = JSON.parse(inspect.stdout);
|
||||||
|
dbConf.port = ports['3306/tcp'][0]['HostPort'];
|
||||||
|
}
|
||||||
|
|
||||||
if (runChown) await dockerWait();
|
if (runChown) await dockerWait();
|
||||||
|
return containerId;
|
||||||
}
|
}
|
||||||
docker.description = `Builds the database image and runs a container`;
|
docker.description = `Builds the database image and runs a container`;
|
||||||
|
|
||||||
|
@ -350,7 +384,7 @@ docker.description = `Builds the database image and runs a container`;
|
||||||
async function dockerStart() {
|
async function dockerStart() {
|
||||||
let state;
|
let state;
|
||||||
try {
|
try {
|
||||||
let result = await execP('docker container inspect -f "{{json .State}}" salix-db');
|
let result = await execP(`docker inspect -f "{{json .State}}" ${containerId}`);
|
||||||
state = JSON.parse(result.stdout);
|
state = JSON.parse(result.stdout);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return await docker();
|
return await docker();
|
||||||
|
@ -360,7 +394,7 @@ async function dockerStart() {
|
||||||
case 'running':
|
case 'running':
|
||||||
return;
|
return;
|
||||||
case 'exited':
|
case 'exited':
|
||||||
await execP('docker start salix-db');
|
await execP(`docker start ${containerId}`);
|
||||||
await dockerWait();
|
await dockerWait();
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
|
@ -377,6 +411,13 @@ function dockerWait() {
|
||||||
let elapsedTime = 0;
|
let elapsedTime = 0;
|
||||||
let maxInterval = 5 * 60 * 1000;
|
let maxInterval = 5 * 60 * 1000;
|
||||||
|
|
||||||
|
let myConf = {
|
||||||
|
user: dbConf.username,
|
||||||
|
password: dbConf.password,
|
||||||
|
host: dbConf.host,
|
||||||
|
port: dbConf.port
|
||||||
|
};
|
||||||
|
|
||||||
log('Waiting for MySQL init process...');
|
log('Waiting for MySQL init process...');
|
||||||
checker();
|
checker();
|
||||||
|
|
||||||
|
@ -385,7 +426,7 @@ function dockerWait() {
|
||||||
let state;
|
let state;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let result = await execP('docker container inspect -f "{{json .State}}" salix-db');
|
let result = await execP(`docker container inspect -f "{{json .State}}" ${containerId}`);
|
||||||
state = JSON.parse(result.stdout);
|
state = JSON.parse(result.stdout);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return reject(new Error(err.message));
|
return reject(new Error(err.message));
|
||||||
|
@ -394,11 +435,7 @@ function dockerWait() {
|
||||||
if (state.Status === 'exited')
|
if (state.Status === 'exited')
|
||||||
return reject(new Error('Docker exited, please see the docker logs for more info'));
|
return reject(new Error('Docker exited, please see the docker logs for more info'));
|
||||||
|
|
||||||
let conn = mysql.createConnection({
|
let conn = mysql.createConnection(myConf);
|
||||||
host: 'localhost',
|
|
||||||
user: 'root',
|
|
||||||
password: 'root'
|
|
||||||
});
|
|
||||||
conn.on('error', () => {});
|
conn.on('error', () => {});
|
||||||
conn.connect(err => {
|
conn.connect(err => {
|
||||||
conn.destroy();
|
conn.destroy();
|
||||||
|
@ -443,21 +480,21 @@ module.exports = {
|
||||||
back,
|
back,
|
||||||
backOnly,
|
backOnly,
|
||||||
backWatch,
|
backWatch,
|
||||||
backendUnitTest,
|
|
||||||
dockerAndBackTest,
|
|
||||||
backTest,
|
backTest,
|
||||||
e2eOnly,
|
backTestOnly,
|
||||||
|
backTestDocker,
|
||||||
e2e,
|
e2e,
|
||||||
smokesOnly,
|
e2eOnly,
|
||||||
smokes,
|
smokes,
|
||||||
install,
|
smokesOnly,
|
||||||
i,
|
i,
|
||||||
|
install,
|
||||||
build,
|
build,
|
||||||
clean,
|
clean,
|
||||||
webpack,
|
webpack,
|
||||||
webpackDevServer,
|
webpackDevServer,
|
||||||
locales,
|
|
||||||
routes,
|
routes,
|
||||||
|
locales,
|
||||||
localesRoutes,
|
localesRoutes,
|
||||||
watch,
|
watch,
|
||||||
docker,
|
docker,
|
||||||
|
|
|
@ -34,98 +34,106 @@ let modulesDir = `${appDir}/modules`;
|
||||||
|
|
||||||
// Internationalization
|
// Internationalization
|
||||||
|
|
||||||
if (fs.existsSync(localeDir)) {
|
|
||||||
i18n.configure({
|
|
||||||
directory: localeDir,
|
|
||||||
defaultLocale: 'es'
|
|
||||||
});
|
|
||||||
|
|
||||||
app.use(i18n.init);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialization
|
|
||||||
|
|
||||||
app.disconnect = async function() {
|
app.disconnect = async function() {
|
||||||
let promises = [];
|
let promises = [];
|
||||||
for (let ds in app.dataSources)
|
for (let ds in this.dataSources)
|
||||||
promises.push(app.dataSources[ds].disconnect());
|
promises.push(this.dataSources[ds].disconnect());
|
||||||
return await Promise.all(promises);
|
return await Promise.all(promises);
|
||||||
};
|
};
|
||||||
|
|
||||||
app.start = function(port) {
|
app.start = function(bootOptions, port, callback) {
|
||||||
function onListen() {
|
let onListen = () => {
|
||||||
let baseUrl = app.get('url').replace(/\/$/, '');
|
let baseUrl = this.get('url').replace(/\/$/, '');
|
||||||
let explorerPath = app.get('loopback-component-explorer').mountPath;
|
let explorerPath = this.get('loopback-component-explorer').mountPath;
|
||||||
console.log(`Browse your REST API at: %s`, `${baseUrl}${explorerPath}`);
|
console.log(`Browse your REST API at: %s`, `${baseUrl}${explorerPath}`);
|
||||||
app.emit('started');
|
this.emit('started');
|
||||||
}
|
callback && callback();
|
||||||
|
};
|
||||||
|
|
||||||
let args = port ? [port, onListen] : [onListen];
|
this.boot(bootOptions, err => {
|
||||||
return app.listen(...args);
|
if (err) throw err;
|
||||||
|
let args = port ? [port, onListen] : [onListen];
|
||||||
|
return this.listen(...args);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
let config = require('./config.json');
|
app.boot = function(myBootOptions, callback) {
|
||||||
|
// Internatinalization
|
||||||
|
|
||||||
for (let key in config)
|
if (fs.existsSync(localeDir)) {
|
||||||
app.set(key, config[key]);
|
i18n.configure({
|
||||||
|
directory: localeDir,
|
||||||
|
defaultLocale: 'es'
|
||||||
|
});
|
||||||
|
|
||||||
let modelConfigFiles = [
|
this.use(i18n.init);
|
||||||
`${__dirname}/model-config.json`
|
}
|
||||||
];
|
|
||||||
let modelSources = [
|
|
||||||
`loopback/common/models`,
|
|
||||||
`loopback/server/models`,
|
|
||||||
`${__dirname}/../common/models`
|
|
||||||
];
|
|
||||||
let mixinDirs = [
|
|
||||||
`loopback/common/mixins`,
|
|
||||||
`loopback/server/mixins`,
|
|
||||||
`${__dirname}/../common/mixins`
|
|
||||||
];
|
|
||||||
let bootDirs = [
|
|
||||||
`${__dirname}/boot`
|
|
||||||
];
|
|
||||||
|
|
||||||
addPath(`${appDir}/back`);
|
// Initialization
|
||||||
|
|
||||||
let modules = fs.readdirSync(modulesDir);
|
let config = require('./config.json');
|
||||||
for (let mod of modules)
|
|
||||||
addPath(`${modulesDir}/${mod}/back`);
|
|
||||||
|
|
||||||
function addPath(path) {
|
for (let key in config)
|
||||||
modelConfigFiles.push(`${path}/model-config.json`);
|
this.set(key, config[key]);
|
||||||
modelSources.push(`${path}/models`);
|
|
||||||
mixinDirs.push(`${path}/mixins`);
|
|
||||||
bootDirs.push(`${path}/boot`);
|
|
||||||
}
|
|
||||||
|
|
||||||
let models = {};
|
let modelConfigFiles = [
|
||||||
for (file of modelConfigFiles) {
|
`${__dirname}/model-config.json`
|
||||||
if (fs.existsSync(file)) {
|
];
|
||||||
let fileModels = require(file);
|
let modelSources = [
|
||||||
for (let key in fileModels) {
|
`loopback/common/models`,
|
||||||
if (models[key])
|
`loopback/server/models`,
|
||||||
console.warn(`Redeclaration of '${key}' at ${file}`);
|
`${__dirname}/../common/models`
|
||||||
|
];
|
||||||
|
let mixinDirs = [
|
||||||
|
`loopback/common/mixins`,
|
||||||
|
`loopback/server/mixins`,
|
||||||
|
`${__dirname}/../common/mixins`
|
||||||
|
];
|
||||||
|
let bootDirs = [
|
||||||
|
`${__dirname}/boot`
|
||||||
|
];
|
||||||
|
|
||||||
|
addPath(`${appDir}/back`);
|
||||||
|
|
||||||
|
let modules = fs.readdirSync(modulesDir);
|
||||||
|
for (let mod of modules)
|
||||||
|
addPath(`${modulesDir}/${mod}/back`);
|
||||||
|
|
||||||
|
function addPath(path) {
|
||||||
|
modelConfigFiles.push(`${path}/model-config.json`);
|
||||||
|
modelSources.push(`${path}/models`);
|
||||||
|
mixinDirs.push(`${path}/mixins`);
|
||||||
|
bootDirs.push(`${path}/boot`);
|
||||||
|
}
|
||||||
|
|
||||||
|
let models = {};
|
||||||
|
for (file of modelConfigFiles) {
|
||||||
|
if (fs.existsSync(file)) {
|
||||||
|
let fileModels = require(file);
|
||||||
|
for (let key in fileModels) {
|
||||||
|
if (models[key])
|
||||||
|
console.warn(`Redeclaration of '${key}' at ${file}`);
|
||||||
|
}
|
||||||
|
Object.assign(models, fileModels);
|
||||||
}
|
}
|
||||||
Object.assign(models, fileModels);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let bootOptions = {
|
let bootOptions = {
|
||||||
appRootDir: __dirname,
|
appRootDir: __dirname,
|
||||||
appConfigRootDir: rootDir,
|
appConfigRootDir: rootDir,
|
||||||
modelsRootDir: rootDir,
|
modelsRootDir: rootDir,
|
||||||
models: models,
|
models: models,
|
||||||
modelSources: modelSources,
|
modelSources: modelSources,
|
||||||
mixinDirs: mixinDirs,
|
mixinDirs: mixinDirs,
|
||||||
bootDirs: bootDirs
|
bootDirs: bootDirs
|
||||||
|
};
|
||||||
|
|
||||||
|
if (fs.existsSync(`/etc/salix`))
|
||||||
|
bootOptions.dsRootDir = `/etc/salix`;
|
||||||
|
|
||||||
|
Object.assign(bootOptions, myBootOptions);
|
||||||
|
boot(this, bootOptions, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (fs.existsSync(`/etc/salix`))
|
if (require.main === module)
|
||||||
bootOptions.dsRootDir = `/etc/salix`;
|
app.start();
|
||||||
|
|
||||||
boot(app, bootOptions, function(err) {
|
|
||||||
if (err) throw err;
|
|
||||||
if (require.main === module)
|
|
||||||
app.start();
|
|
||||||
});
|
|
||||||
|
|
Loading…
Reference in New Issue