feat: refs #5483 Split logging from logic #3
|
@ -276,8 +276,7 @@ $ myt fixtures [<remote>]
|
||||||
### run
|
### run
|
||||||
|
|
||||||
Builds and starts local database server container. It only rebuilds the image
|
Builds and starts local database server container. It only rebuilds the image
|
||||||
when fixtures have been modified or when the day on which the image was built
|
when dump have been modified.
|
||||||
is different to today.
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
$ myt run [-c|--ci] [-r|--random]
|
$ myt run [-c|--ci] [-r|--random]
|
||||||
|
|
2
cli.js
2
cli.js
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
const Myt = require('./myt');
|
const Myt = require('./myt');
|
||||||
new Myt().run();
|
new Myt().cli();
|
||||||
|
|
|
@ -1,19 +1,30 @@
|
||||||
|
const EventEmitter = require('node:events');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for Myt commands.
|
* Base class for Myt commands.
|
||||||
*/
|
*/
|
||||||
module.exports = class MytCommand {
|
module.exports = class MytCommand extends EventEmitter {
|
||||||
constructor(myt, opts) {
|
constructor(myt, opts) {
|
||||||
|
super();
|
||||||
this.myt = myt;
|
this.myt = myt;
|
||||||
this.opts = opts;
|
this.opts = opts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async cli(myt, opts) {
|
||||||
|
const reporter = this.constructor.reporter;
|
||||||
|
if (reporter)
|
||||||
|
for (const event in reporter) {
|
||||||
|
const handler = reporter[event];
|
||||||
|
if (typeof handler == 'string') {
|
||||||
|
this.on(event, () => console.log(handler));
|
||||||
|
} else if (handler instanceof Function)
|
||||||
|
this.on(event, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.run(myt, opts);
|
||||||
|
}
|
||||||
|
|
||||||
async run(myt, opts) {
|
async run(myt, opts) {
|
||||||
throw new Error('run command not defined');
|
throw new Error('run command not defined');
|
||||||
}
|
}
|
||||||
|
|
||||||
emit(event) {
|
|
||||||
const messages = this.constructor.messages;
|
|
||||||
if (messages && messages[event])
|
|
||||||
console.log(messages[event]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,6 @@ module.exports = class Server {
|
||||||
port: dbConfig.port
|
port: dbConfig.port
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('Waiting for MySQL init process...');
|
|
||||||
|
|
||||||
async function checker() {
|
async function checker() {
|
||||||
elapsedTime += interval;
|
elapsedTime += interval;
|
||||||
let status;
|
let status;
|
||||||
|
@ -46,10 +44,7 @@ module.exports = class Server {
|
||||||
conn.on('error', () => {});
|
conn.on('error', () => {});
|
||||||
conn.connect(err => {
|
conn.connect(err => {
|
||||||
conn.destroy();
|
conn.destroy();
|
||||||
if (!err) {
|
if (!err) return resolve();
|
||||||
console.log('MySQL process ready.');
|
|
||||||
return resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (elapsedTime >= maxInterval)
|
if (elapsedTime >= maxInterval)
|
||||||
reject(new Error(`MySQL not initialized whithin ${elapsedTime / 1000} secs`));
|
reject(new Error(`MySQL not initialized whithin ${elapsedTime / 1000} secs`));
|
||||||
|
|
13
myt-clean.js
13
myt-clean.js
|
@ -17,6 +17,13 @@ class Clean extends Command {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static reporter = {
|
||||||
|
versionsDeleted: function(nVersions) {
|
||||||
|
console.log(`Old versions deleted: ${nVersions}`);
|
||||||
|
},
|
||||||
|
noVersionsDeleted: 'No versions to delete.'
|
||||||
|
};
|
||||||
|
|
||||||
async run(myt, opts) {
|
async run(myt, opts) {
|
||||||
await myt.dbConnect();
|
await myt.dbConnect();
|
||||||
const version = await myt.fetchDbVersion() || {};
|
const version = await myt.fetchDbVersion() || {};
|
||||||
|
@ -46,13 +53,13 @@ class Clean extends Command {
|
||||||
path.join(archiveDir, oldVersion)
|
path.join(archiveDir, oldVersion)
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log(`Old versions deleted: ${oldVersions.length}`);
|
this.emit('versionsDeleted', oldVersions.length);
|
||||||
} else
|
} else
|
||||||
console.log(`No versions to delete.`);
|
this.emit('noVersionsDeleted');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Clean;
|
module.exports = Clean;
|
||||||
|
|
||||||
if (require.main === module)
|
if (require.main === module)
|
||||||
new Myt().run(Clean);
|
new Myt().cli(Clean);
|
||||||
|
|
|
@ -27,6 +27,11 @@ class Create extends Command {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
async cli(myt, opts) {
|
||||||
|
await super.cli(myt, opts);
|
||||||
|
console.log('Routine created.');
|
||||||
|
}
|
||||||
|
|
||||||
async run(myt, opts) {
|
async run(myt, opts) {
|
||||||
const match = opts.name.match(/^(\w+)\.(\w+)$/);
|
const match = opts.name.match(/^(\w+)\.(\w+)$/);
|
||||||
if (!match)
|
if (!match)
|
||||||
|
@ -63,12 +68,10 @@ class Create extends Command {
|
||||||
|
|
||||||
const routineFile = `${routineDir}/${name}.sql`;
|
const routineFile = `${routineDir}/${name}.sql`;
|
||||||
await fs.writeFile(routineFile, sql);
|
await fs.writeFile(routineFile, sql);
|
||||||
|
|
||||||
console.log('Routine created.');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Create;
|
module.exports = Create;
|
||||||
|
|
||||||
if (require.main === module)
|
if (require.main === module)
|
||||||
new Myt().run(Create);
|
new Myt().cli(Create);
|
||||||
|
|
|
@ -28,7 +28,7 @@ class Dump extends Command {
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
static messages = {
|
static reporter = {
|
||||||
dumpStructure: 'Dumping structure.',
|
dumpStructure: 'Dumping structure.',
|
||||||
dumpData: 'Dumping data.',
|
dumpData: 'Dumping data.',
|
||||||
dumpPrivileges: 'Dumping privileges.',
|
dumpPrivileges: 'Dumping privileges.',
|
||||||
|
@ -128,5 +128,4 @@ class Dump extends Command {
|
||||||
module.exports = Dump;
|
module.exports = Dump;
|
||||||
|
|
||||||
if (require.main === module)
|
if (require.main === module)
|
||||||
new Myt().run(Dump);
|
new Myt().cli(Dump);
|
||||||
|
|
||||||
|
|
|
@ -25,4 +25,4 @@ class Fixtures extends Command {
|
||||||
module.exports = Fixtures;
|
module.exports = Fixtures;
|
||||||
|
|
||||||
if (require.main === module)
|
if (require.main === module)
|
||||||
new Myt().run(Fixtures);
|
new Myt().cli(Fixtures);
|
||||||
|
|
|
@ -33,4 +33,4 @@ class Init extends Command {
|
||||||
module.exports = Init;
|
module.exports = Init;
|
||||||
|
|
||||||
if (require.main === module)
|
if (require.main === module)
|
||||||
new Myt().run(Init);
|
new Myt().cli(Init);
|
||||||
|
|
13
myt-pull.js
13
myt-pull.js
|
@ -32,6 +32,13 @@ class Pull extends Command {
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static reporter = {
|
||||||
|
creatingBranch: function(branchName) {
|
||||||
|
console.log(`Creating branch '${branchName}' from database commit.`);
|
||||||
|
},
|
||||||
|
routineChanges: 'Incorporating routine changes.'
|
||||||
|
};
|
||||||
|
|
||||||
async run(myt, opts) {
|
async run(myt, opts) {
|
||||||
const conn = await myt.dbConnect();
|
const conn = await myt.dbConnect();
|
||||||
const repo = await myt.openRepo();
|
const repo = await myt.openRepo();
|
||||||
|
@ -73,7 +80,7 @@ class Pull extends Command {
|
||||||
if (version && version.gitCommit) {
|
if (version && version.gitCommit) {
|
||||||
const now = parseInt(new Date().toJSON());
|
const now = parseInt(new Date().toJSON());
|
||||||
const branchName = `myt-pull_${now}`;
|
const branchName = `myt-pull_${now}`;
|
||||||
console.log(`Creating branch '${branchName}' from database commit.`);
|
this.emit('creatingBranch', branchName);
|
||||||
const commit = await repo.getCommit(version.gitCommit);
|
const commit = await repo.getCommit(version.gitCommit);
|
||||||
const branch = await nodegit.Branch.create(repo,
|
const branch = await nodegit.Branch.create(repo,
|
||||||
`myt-pull_${now}`, commit, () => {});
|
`myt-pull_${now}`, commit, () => {});
|
||||||
|
@ -83,7 +90,7 @@ class Pull extends Command {
|
||||||
|
|
||||||
// Export routines to SQL files
|
// Export routines to SQL files
|
||||||
|
|
||||||
console.log(`Incorporating routine changes.`);
|
this.emit('routineChanges', branchName);
|
||||||
|
|
||||||
const engine = new ExporterEngine(conn, opts);
|
const engine = new ExporterEngine(conn, opts);
|
||||||
await engine.init();
|
await engine.init();
|
||||||
|
@ -180,4 +187,4 @@ class Pull extends Command {
|
||||||
module.exports = Pull;
|
module.exports = Pull;
|
||||||
|
|
||||||
if (require.main === module)
|
if (require.main === module)
|
||||||
new Myt().run(Pull);
|
new Myt().cli(Pull);
|
||||||
|
|
189
myt-push.js
189
myt-push.js
|
@ -37,6 +37,88 @@ class Push extends Command {
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static reporter = {
|
||||||
|
applyingVersions: 'Applying versions.',
|
||||||
|
applyingRoutines: 'Applying changed routines.',
|
||||||
|
dbInfo: function(version) {
|
||||||
|
console.log(
|
||||||
|
`Database information:`
|
||||||
|
+ `\n -> Version: ${version.number}`
|
||||||
|
+ `\n -> Commit: ${version.gitCommit}`
|
||||||
|
);
|
||||||
|
},
|
||||||
|
version(data, action) {
|
||||||
|
let {version} = data;
|
||||||
|
let name = data.dir;
|
||||||
|
let num, color;
|
||||||
|
switch(action) {
|
||||||
|
case 'apply':
|
||||||
|
num = version.number;
|
||||||
|
name = version.name;
|
||||||
|
color = 'cyan';
|
||||||
|
break;
|
||||||
|
case 'badVersion':
|
||||||
|
num = '?????';
|
||||||
|
color = 'yellow';
|
||||||
|
break;
|
||||||
|
case 'wrongDirectory':
|
||||||
|
num = '*****';
|
||||||
|
color = 'gray';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
console.log('', `[${num[color].bold}]`, name);
|
||||||
|
},
|
||||||
|
logScript(script, action, error) {
|
||||||
|
let actionMsg;
|
||||||
|
switch(action) {
|
||||||
|
case 'apply':
|
||||||
|
actionMsg = '[+]'.green;
|
||||||
|
break;
|
||||||
|
case 'ignore':
|
||||||
|
actionMsg = '[I]'.blue;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
actionMsg = '[W]'.yellow;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
console.log(' ', actionMsg.bold, script);
|
||||||
|
},
|
||||||
|
change(status, ignore, change) {
|
||||||
|
let statusMsg;
|
||||||
|
switch(status) {
|
||||||
|
case 'added':
|
||||||
|
statusMsg = '[+]'.green;
|
||||||
|
break;
|
||||||
|
case 'deleted':
|
||||||
|
statusMsg = '[-]'.red;
|
||||||
|
break;
|
||||||
|
case 'modified':
|
||||||
|
statusMsg = '[·]'.yellow;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let actionMsg;
|
||||||
|
if (ignore)
|
||||||
|
actionMsg = '[I]'.blue;
|
||||||
|
else
|
||||||
|
actionMsg = '[A]'.green;
|
||||||
|
|
||||||
|
const typeMsg = `[${change.type.abbr}]`[change.type.color];
|
||||||
|
console.log('',
|
||||||
|
(statusMsg + actionMsg).bold,
|
||||||
|
typeMsg.bold,
|
||||||
|
change.fullName
|
||||||
|
);
|
||||||
|
},
|
||||||
|
routinesApplied: function(nRoutines) {
|
||||||
|
if (nRoutines > 0) {
|
||||||
|
console.log(` -> ${nRoutines} routines have changed.`);
|
||||||
|
} else {
|
||||||
|
console.log(` -> No routines changed.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
async run(myt, opts) {
|
async run(myt, opts) {
|
||||||
const conn = await myt.dbConnect();
|
const conn = await myt.dbConnect();
|
||||||
this.conn = conn;
|
this.conn = conn;
|
||||||
|
@ -85,24 +167,7 @@ class Push extends Command {
|
||||||
await releaseLock();
|
await releaseLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
async push(myt, opts, conn) {
|
async cli(myt, opts) {
|
||||||
const pushConn = await myt.createConnection();
|
|
||||||
|
|
||||||
// Get database version
|
|
||||||
|
|
||||||
const version = await myt.fetchDbVersion() || {};
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`Database information:`
|
|
||||||
+ `\n -> Version: ${version.number}`
|
|
||||||
+ `\n -> Commit: ${version.gitCommit}`
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!version.number)
|
|
||||||
version.number = String('0').padStart(opts.versionDigits, '0');
|
|
||||||
if (!/^[0-9]*$/.test(version.number))
|
|
||||||
throw new Error('Wrong database version');
|
|
||||||
|
|
||||||
// Prevent push to production by mistake
|
// Prevent push to production by mistake
|
||||||
|
|
||||||
if (opts.remote == 'production') {
|
if (opts.remote == 'production') {
|
||||||
|
@ -134,20 +199,30 @@ class Push extends Command {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await super.cli(myt, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
async push(myt, opts, conn) {
|
||||||
|
const pushConn = await myt.createConnection();
|
||||||
|
|
||||||
|
// Get database version
|
||||||
|
|
||||||
|
const version = await myt.fetchDbVersion() || {};
|
||||||
|
this.emit('dbInfo', version);
|
||||||
|
|
||||||
|
if (!version.number)
|
||||||
|
version.number = String('0').padStart(opts.versionDigits, '0');
|
||||||
|
if (!/^[0-9]*$/.test(version.number))
|
||||||
|
throw new Error('Wrong database version');
|
||||||
|
|
||||||
// Apply versions
|
// Apply versions
|
||||||
|
|
||||||
console.log('Applying versions.');
|
this.emit('applyingVersions');
|
||||||
|
|
||||||
let nChanges = 0;
|
let nChanges = 0;
|
||||||
let silent = true;
|
let silent = true;
|
||||||
const versionsDir = opts.versionsDir;
|
const versionsDir = opts.versionsDir;
|
||||||
|
|
||||||
function logVersion(version, name, error) {
|
|
||||||
console.log('', version.bold, name);
|
|
||||||
}
|
|
||||||
function logScript(type, message, error) {
|
|
||||||
console.log(' ', type.bold, message);
|
|
||||||
}
|
|
||||||
function isUndoScript(script) {
|
function isUndoScript(script) {
|
||||||
return /\.undo\.sql$/.test(script);
|
return /\.undo\.sql$/.test(script);
|
||||||
}
|
}
|
||||||
|
@ -159,29 +234,28 @@ class Push extends Command {
|
||||||
|
|
||||||
if (await fs.pathExists(versionsDir)) {
|
if (await fs.pathExists(versionsDir)) {
|
||||||
const versionDirs = await fs.readdir(versionsDir);
|
const versionDirs = await fs.readdir(versionsDir);
|
||||||
const [[realm]] = await this.conn.query(
|
const [[row]] = await this.conn.query(
|
||||||
`SELECT realm
|
`SELECT realm FROM versionConfig`
|
||||||
FROM versionConfig`
|
|
||||||
);
|
);
|
||||||
|
const realm = row?.realm;
|
||||||
|
|
||||||
for (const versionDir of versionDirs) {
|
for (const versionDir of versionDirs) {
|
||||||
if (skipFiles.has(versionDir)) continue;
|
if (skipFiles.has(versionDir)) continue;
|
||||||
|
|
||||||
const dirVersion = myt.parseVersionDir(versionDir);
|
const dirVersion = myt.parseVersionDir(versionDir);
|
||||||
|
const versionData = {
|
||||||
|
version: dirVersion,
|
||||||
|
current: version
|
||||||
|
};
|
||||||
|
|
||||||
if (!dirVersion) {
|
if (!dirVersion) {
|
||||||
logVersion('[?????]'.yellow, versionDir,
|
this.emit('version', versionData, 'wrongDirectory');
|
||||||
`Wrong directory name.`
|
|
||||||
);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const versionNumber = dirVersion.number;
|
const versionNumber = dirVersion.number;
|
||||||
const versionName = dirVersion.name;
|
|
||||||
|
|
||||||
if (versionNumber.length != version.number.length) {
|
if (versionNumber.length != version.number.length) {
|
||||||
logVersion('[*****]'.gray, versionDir,
|
this.emit('version', versionData, 'badVersion');
|
||||||
`Bad version length, should have ${version.number.length} characters.`
|
|
||||||
);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,18 +278,17 @@ class Push extends Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (silent) continue;
|
if (silent) continue;
|
||||||
logVersion(`[${versionNumber}]`.cyan, versionName);
|
this.emit('version', versionData, 'apply');
|
||||||
|
|
||||||
for (const script of scripts) {
|
for (const script of scripts) {
|
||||||
const match = script.match(/^[0-9]{2}-[a-zA-Z0-9_]+(?:\.(?!undo)([a-zA-Z0-9_]+))?(?:\.undo)?\.sql$/);
|
const match = script.match(/^[0-9]{2}-[a-zA-Z0-9_]+(?:\.(?!undo)([a-zA-Z0-9_]+))?(?:\.undo)?\.sql$/);
|
||||||
|
|
||||||
if (!match) {
|
if (!match) {
|
||||||
logScript('[W]'.yellow, script, `Wrong file name.`);
|
this.emit('logScript', script, 'warn', 'wrongFile');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const skipRealm = match[1] && match[1] !== realm;
|
const skipRealm = match[1] && match[1] !== realm;
|
||||||
|
|
||||||
if (isUndoScript(script) || skipRealm)
|
if (isUndoScript(script) || skipRealm)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -231,9 +304,7 @@ class Push extends Command {
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
const apply = !row || row.errorNumber;
|
const apply = !row || row.errorNumber;
|
||||||
const actionMsg = apply ? '[+]'.green : '[I]'.blue;
|
this.emit('logScript', script, apply ? 'apply' : 'ignore');
|
||||||
|
|
||||||
logScript(actionMsg, script);
|
|
||||||
if (!apply) continue;
|
if (!apply) continue;
|
||||||
|
|
||||||
let err;
|
let err;
|
||||||
|
@ -277,9 +348,7 @@ class Push extends Command {
|
||||||
|
|
||||||
// Apply routines
|
// Apply routines
|
||||||
|
|
||||||
console.log('Applying changed routines.');
|
this.emit('applyingRoutines');
|
||||||
|
|
||||||
const gitExists = await fs.pathExists(`${opts.workspace}/.git`);
|
|
||||||
|
|
||||||
let nRoutines = 0;
|
let nRoutines = 0;
|
||||||
const changes = await this.changedRoutines(version.gitCommit);
|
const changes = await this.changedRoutines(version.gitCommit);
|
||||||
|
@ -343,26 +412,15 @@ class Push extends Command {
|
||||||
&& opts.mockFunctions.indexOf(name) !== -1;
|
&& opts.mockFunctions.indexOf(name) !== -1;
|
||||||
const ignore = newSql == oldSql || isMockFn;
|
const ignore = newSql == oldSql || isMockFn;
|
||||||
|
|
||||||
let statusMsg;
|
let status;
|
||||||
if (exists && !oldSql)
|
if (exists && !oldSql)
|
||||||
statusMsg = '[+]'.green;
|
status = 'added';
|
||||||
else if (!exists)
|
else if (!exists)
|
||||||
statusMsg = '[-]'.red;
|
status = 'deleted';
|
||||||
else
|
else
|
||||||
statusMsg = '[·]'.yellow;
|
status = 'modified';
|
||||||
|
|
||||||
let actionMsg;
|
this.emit('change', status, ignore, change);
|
||||||
if (ignore)
|
|
||||||
actionMsg = '[I]'.blue;
|
|
||||||
else
|
|
||||||
actionMsg = '[A]'.green;
|
|
||||||
|
|
||||||
const typeMsg = `[${change.type.abbr}]`[change.type.color];
|
|
||||||
console.log('',
|
|
||||||
(statusMsg + actionMsg).bold,
|
|
||||||
typeMsg.bold,
|
|
||||||
change.fullName
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!ignore) {
|
if (!ignore) {
|
||||||
const scapedSchema = SqlString.escapeId(schema, true);
|
const scapedSchema = SqlString.escapeId(schema, true);
|
||||||
|
@ -410,10 +468,9 @@ class Push extends Command {
|
||||||
|
|
||||||
await finalize();
|
await finalize();
|
||||||
|
|
||||||
if (nRoutines > 0) {
|
this.emit('routinesApplied', nRoutines);
|
||||||
console.log(` -> ${nRoutines} routines have changed.`);
|
|
||||||
} else
|
const gitExists = await fs.pathExists(`${opts.workspace}/.git`);
|
||||||
console.log(` -> No routines changed.`);
|
|
||||||
|
|
||||||
if (gitExists && opts.commit) {
|
if (gitExists && opts.commit) {
|
||||||
const repo = await nodegit.Repository.open(this.opts.workspace);
|
const repo = await nodegit.Repository.open(this.opts.workspace);
|
||||||
|
@ -581,4 +638,4 @@ class Routine {
|
||||||
module.exports = Push;
|
module.exports = Push;
|
||||||
|
|
||||||
if (require.main === module)
|
if (require.main === module)
|
||||||
new Myt().run(Push);
|
new Myt().cli(Push);
|
||||||
|
|
29
myt-run.js
29
myt-run.js
|
@ -10,9 +10,8 @@ const SqlString = require('sqlstring');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the database image and runs a container. It only rebuilds the
|
* Builds the database image and runs a container. It only rebuilds the
|
||||||
* image when fixtures have been modified or when the day on which the
|
* image when dump have been modified. Some workarounds have been used to avoid
|
||||||
* image was built is different to today. Some workarounds have been used
|
* a bug with OverlayFS driver on MacOS.
|
||||||
* to avoid a bug with OverlayFS driver on MacOS.
|
|
||||||
*/
|
*/
|
||||||
class Run extends Command {
|
class Run extends Command {
|
||||||
static usage = {
|
static usage = {
|
||||||
|
@ -34,6 +33,15 @@ class Run extends Command {
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static reporter = {
|
||||||
|
buildingImage: 'Building container image.',
|
||||||
|
runningContainer: 'Running container.',
|
||||||
|
waitingDb: 'Waiting for MySQL init process.',
|
||||||
|
mockingDate: 'Mocking date functions.',
|
||||||
|
applyingFixtures: 'Applying fixtures.',
|
||||||
|
creatingTriggers: 'Creating triggers.'
|
||||||
|
};
|
||||||
|
|
||||||
async run(myt, opts) {
|
async run(myt, opts) {
|
||||||
const dumpDir = opts.dumpDir;
|
const dumpDir = opts.dumpDir;
|
||||||
const dumpDataDir = path.join(dumpDir, '.dump');
|
const dumpDataDir = path.join(dumpDir, '.dump');
|
||||||
|
@ -44,6 +52,8 @@ class Run extends Command {
|
||||||
|
|
||||||
// Build base image
|
// Build base image
|
||||||
|
|
||||||
|
this.emit('buildingImage');
|
||||||
|
|
||||||
let basePath = dumpDir;
|
let basePath = dumpDir;
|
||||||
let baseDockerfile = path.join(dumpDir, 'Dockerfile');
|
let baseDockerfile = path.join(dumpDir, 'Dockerfile');
|
||||||
|
|
||||||
|
@ -74,6 +84,8 @@ class Run extends Command {
|
||||||
|
|
||||||
// Run container
|
// Run container
|
||||||
|
|
||||||
|
this.emit('runningContainer');
|
||||||
|
|
||||||
const isRandom = opts.random;
|
const isRandom = opts.random;
|
||||||
const dbConfig = Object.assign({}, opts.dbConfig);
|
const dbConfig = Object.assign({}, opts.dbConfig);
|
||||||
|
|
||||||
|
@ -118,12 +130,13 @@ class Run extends Command {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.emit('waitingDb');
|
||||||
await server.wait();
|
await server.wait();
|
||||||
const conn = await myt.createConnection();
|
const conn = await myt.createConnection();
|
||||||
|
|
||||||
// Mock date functions
|
// Mock date functions
|
||||||
|
|
||||||
console.log('Mocking date functions.');
|
this.emit('mockingDate');
|
||||||
const mockDateScript = path.join(dumpDir, 'mockDate.sql');
|
const mockDateScript = path.join(dumpDir, 'mockDate.sql');
|
||||||
|
|
||||||
if (opts.mockDate) {
|
if (opts.mockDate) {
|
||||||
|
@ -144,11 +157,11 @@ class Run extends Command {
|
||||||
commit: true,
|
commit: true,
|
||||||
dbConfig
|
dbConfig
|
||||||
});
|
});
|
||||||
await myt.runCommand(Push, opts);
|
await myt.run(Push, opts);
|
||||||
|
|
||||||
// Apply fixtures
|
// Apply fixtures
|
||||||
|
|
||||||
console.log('Applying fixtures.');
|
this.emit('applyingFixtures');
|
||||||
const fixturesFiles = [
|
const fixturesFiles = [
|
||||||
'fixtures.before',
|
'fixtures.before',
|
||||||
'.fixtures',
|
'.fixtures',
|
||||||
|
@ -167,7 +180,7 @@ class Run extends Command {
|
||||||
// Create triggers
|
// Create triggers
|
||||||
|
|
||||||
if (!hasTriggers) {
|
if (!hasTriggers) {
|
||||||
console.log('Creating triggers.');
|
this.emit('creatingTriggers');
|
||||||
|
|
||||||
for (const schema of opts.schemas) {
|
for (const schema of opts.schemas) {
|
||||||
const triggersPath = `${opts.routinesDir}/${schema}/triggers`;
|
const triggersPath = `${opts.routinesDir}/${schema}/triggers`;
|
||||||
|
@ -187,4 +200,4 @@ class Run extends Command {
|
||||||
module.exports = Run;
|
module.exports = Run;
|
||||||
|
|
||||||
if (require.main === module)
|
if (require.main === module)
|
||||||
new Myt().run(Run);
|
new Myt().cli(Run);
|
||||||
|
|
|
@ -15,6 +15,10 @@ class Start extends Command {
|
||||||
description: 'Start local database server container'
|
description: 'Start local database server container'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static reporter = {
|
||||||
|
startingContainer: 'Starting container.'
|
||||||
|
};
|
||||||
|
|
||||||
async run(myt, opts) {
|
async run(myt, opts) {
|
||||||
const ct = new Container(opts.code);
|
const ct = new Container(opts.code);
|
||||||
let status;
|
let status;
|
||||||
|
@ -27,7 +31,7 @@ class Start extends Command {
|
||||||
});
|
});
|
||||||
exists = true;
|
exists = true;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
server = await myt.runCommand(Run, opts);
|
server = await myt.run(Run, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exists) {
|
if (exists) {
|
||||||
|
@ -35,6 +39,7 @@ class Start extends Command {
|
||||||
case 'running':
|
case 'running':
|
||||||
break;
|
break;
|
||||||
case 'exited':
|
case 'exited':
|
||||||
|
this.emit('startingContainer');
|
||||||
await ct.start();
|
await ct.start();
|
||||||
server = new Server(ct, opts.dbConfig);
|
server = new Server(ct, opts.dbConfig);
|
||||||
await server.wait();
|
await server.wait();
|
||||||
|
@ -51,4 +56,4 @@ class Start extends Command {
|
||||||
module.exports = Start;
|
module.exports = Start;
|
||||||
|
|
||||||
if (require.main === module)
|
if (require.main === module)
|
||||||
new Myt().run(Start);
|
new Myt().cli(Start);
|
||||||
|
|
|
@ -26,6 +26,19 @@ class Version extends Command {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static reporter = {
|
||||||
|
dbInfo: function(number, lastNumber) {
|
||||||
|
console.log(
|
||||||
|
`Database information:`
|
||||||
|
+ `\n -> Version: ${number}`
|
||||||
|
+ `\n -> Last version: ${lastNumber}`
|
||||||
|
);
|
||||||
|
},
|
||||||
|
versionCreated: function(versionName) {
|
||||||
|
console.log(`New version created: ${versionName}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
async run(myt, opts) {
|
async run(myt, opts) {
|
||||||
let newVersionDir;
|
let newVersionDir;
|
||||||
|
|
||||||
|
@ -45,12 +58,7 @@ class Version extends Command {
|
||||||
);
|
);
|
||||||
const number = row && row.number;
|
const number = row && row.number;
|
||||||
const lastNumber = row && row.lastNumber;
|
const lastNumber = row && row.lastNumber;
|
||||||
|
this.emit('dbInfo', number, lastNumber);
|
||||||
console.log(
|
|
||||||
`Database information:`
|
|
||||||
+ `\n -> Version: ${number}`
|
|
||||||
+ `\n -> Last version: ${lastNumber}`
|
|
||||||
);
|
|
||||||
|
|
||||||
let newVersion;
|
let newVersion;
|
||||||
if (lastNumber)
|
if (lastNumber)
|
||||||
|
@ -117,7 +125,7 @@ class Version extends Command {
|
||||||
`${newVersionDir}/00-firstScript.sql`,
|
`${newVersionDir}/00-firstScript.sql`,
|
||||||
'-- Place your SQL code here\n'
|
'-- Place your SQL code here\n'
|
||||||
);
|
);
|
||||||
console.log(`New version created: ${versionFolder}`);
|
this.emit('versionCreated', versionFolder);
|
||||||
|
|
||||||
await conn.query('COMMIT');
|
await conn.query('COMMIT');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -215,4 +223,4 @@ const plants = [
|
||||||
module.exports = Version;
|
module.exports = Version;
|
||||||
|
|
||||||
if (require.main === module)
|
if (require.main === module)
|
||||||
new Myt().run(Version);
|
new Myt().cli(Version);
|
||||||
|
|
21
myt.js
21
myt.js
|
@ -38,7 +38,9 @@ class Myt {
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
async run(Command) {
|
async cli(Command) {
|
||||||
|
this.cliMode = true;
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
'Myt'.green,
|
'Myt'.green,
|
||||||
`v${packageJson.version}`.magenta
|
`v${packageJson.version}`.magenta
|
||||||
|
@ -142,9 +144,9 @@ class Myt {
|
||||||
parameter('Workspace:', opts.workspace);
|
parameter('Workspace:', opts.workspace);
|
||||||
parameter('Remote:', opts.remote || 'local');
|
parameter('Remote:', opts.remote || 'local');
|
||||||
|
|
||||||
await this.load(opts);
|
await this.init(opts);
|
||||||
await this.runCommand(Command, opts);
|
await this.run(Command, opts);
|
||||||
await this.unload();
|
await this.deinit();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.name == 'Error' && !opts.debug) {
|
if (err.name == 'Error' && !opts.debug) {
|
||||||
console.error('Error:'.gray, err.message.red);
|
console.error('Error:'.gray, err.message.red);
|
||||||
|
@ -162,12 +164,15 @@ class Myt {
|
||||||
process.exit();
|
process.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
async runCommand(Command, opts) {
|
async run(Command, opts) {
|
||||||
const command = new Command(this, opts);
|
const command = new Command(this, opts);
|
||||||
|
if (this.cliMode)
|
||||||
|
return await command.cli(this, opts);
|
||||||
|
else
|
||||||
return await command.run(this, opts);
|
return await command.run(this, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
async load(opts) {
|
async init(opts) {
|
||||||
// Configuration file
|
// Configuration file
|
||||||
|
|
||||||
const defaultConfig = require(`${__dirname}/assets/myt.default.yml`);
|
const defaultConfig = require(`${__dirname}/assets/myt.default.yml`);
|
||||||
|
@ -263,7 +268,7 @@ class Myt {
|
||||||
this.opts = opts;
|
this.opts = opts;
|
||||||
}
|
}
|
||||||
|
|
||||||
async unload() {
|
async deinit() {
|
||||||
if (this.conn)
|
if (this.conn)
|
||||||
await this.conn.end();
|
await this.conn.end();
|
||||||
}
|
}
|
||||||
|
@ -375,4 +380,4 @@ class Myt {
|
||||||
module.exports = Myt;
|
module.exports = Myt;
|
||||||
|
|
||||||
if (require.main === module)
|
if (require.main === module)
|
||||||
new Myt().run();
|
new Myt().cli();
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "@verdnatura/myt",
|
"name": "@verdnatura/myt",
|
||||||
"version": "1.5.22",
|
"version": "1.5.23",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@verdnatura/myt",
|
"name": "@verdnatura/myt",
|
||||||
"version": "1.5.22",
|
"version": "1.5.23",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sqltools/formatter": "^1.2.5",
|
"@sqltools/formatter": "^1.2.5",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@verdnatura/myt",
|
"name": "@verdnatura/myt",
|
||||||
"version": "1.5.23",
|
"version": "1.5.24",
|
||||||
"author": "Verdnatura Levante SL",
|
"author": "Verdnatura Levante SL",
|
||||||
"description": "MySQL version control",
|
"description": "MySQL version control",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
|
|
Loading…
Reference in New Issue