Reviewed-on: #3
This commit is contained in:
commit
44957a2275
|
@ -276,7 +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
|
||||||
dump has been modified.
|
when dump have been modified.
|
||||||
|
|
||||||
```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,37 @@
|
||||||
/**
|
/**
|
||||||
* Base class for Myt commands.
|
* Base class for Myt commands.
|
||||||
*/
|
*/
|
||||||
module.exports = class MytCommand {
|
module.exports = class MytCommand{
|
||||||
constructor(myt, opts) {
|
constructor(myt, opts) {
|
||||||
this.myt = myt;
|
this.myt = myt;
|
||||||
this.opts = opts;
|
this.opts = opts;
|
||||||
|
this.handlers = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
on(event, handler) {
|
||||||
const messages = this.constructor.messages;
|
this.handlers[event] = handler;
|
||||||
if (messages && messages[event])
|
}
|
||||||
console.log(messages[event]);
|
|
||||||
|
emit(event, ...args) {
|
||||||
|
const handler = this.handlers[event];
|
||||||
|
if (handler) handler (...args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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`));
|
||||||
|
|
26
myt-clean.js
26
myt-clean.js
|
@ -26,6 +26,21 @@ class Clean extends Command {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static reporter = {
|
||||||
|
versionsArchived: function(nVersions) {
|
||||||
|
if (nVersions)
|
||||||
|
console.log(` -> ${oldVersions.length} versions archived.`);
|
||||||
|
else
|
||||||
|
console.log(` -> No versions archived.`);
|
||||||
|
},
|
||||||
|
versionLogPurged: function(nPurged) {
|
||||||
|
if (nPurged)
|
||||||
|
console.log(` -> ${nPurged} changes purged from log.`);
|
||||||
|
else
|
||||||
|
console.log(` -> No logs purged.`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
async run(myt, opts) {
|
async run(myt, opts) {
|
||||||
const conn = await myt.dbConnect();
|
const conn = await myt.dbConnect();
|
||||||
const archiveDir = path.join(opts.versionsDir, '.archive');
|
const archiveDir = path.join(opts.versionsDir, '.archive');
|
||||||
|
@ -71,9 +86,9 @@ class Clean extends Command {
|
||||||
await fs.rmdir(srcDir);
|
await fs.rmdir(srcDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(` -> ${oldVersions.length} versions archived.`);
|
this.emit('versionsArchived', oldVersions.length);
|
||||||
} else
|
} else
|
||||||
console.log(` -> No versions archived.`);
|
this.emit('versionsArchived');
|
||||||
|
|
||||||
if (opts.purge) {
|
if (opts.purge) {
|
||||||
const versionDb = new VersionDb(myt, opts.versionsDir);
|
const versionDb = new VersionDb(myt, opts.versionsDir);
|
||||||
|
@ -104,10 +119,7 @@ class Clean extends Command {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nPurged)
|
this.emit('versionLogPurged', nPurged);
|
||||||
console.log(` -> ${nPurged} versions purged from log.`);
|
|
||||||
else
|
|
||||||
console.log(` -> No versions purged from log.`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,4 +158,4 @@ class VersionDb {
|
||||||
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);
|
||||||
|
|
226
myt-push.js
226
myt-push.js
|
@ -37,6 +37,95 @@ 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(version, error) {
|
||||||
|
let actionMsg;
|
||||||
|
let number, color;
|
||||||
|
|
||||||
|
if (!error) {
|
||||||
|
actionMsg = version.apply
|
||||||
|
? '[A]'.green
|
||||||
|
: '[I]'.blue;
|
||||||
|
number = version.number;
|
||||||
|
color = 'cyan';
|
||||||
|
} else {
|
||||||
|
actionMsg = '[W]'.yellow;
|
||||||
|
switch(action) {
|
||||||
|
case 'badVersion':
|
||||||
|
number = '?????';
|
||||||
|
color = 'yellow';
|
||||||
|
break;
|
||||||
|
case 'wrongDirectory':
|
||||||
|
number = '*****';
|
||||||
|
color = 'gray';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const numberMsg = `[${number}]`[color];
|
||||||
|
console.log('', `${actionMsg}${numberMsg}`.bold, version.name);
|
||||||
|
},
|
||||||
|
logScript(script) {
|
||||||
|
let actionMsg;
|
||||||
|
if (script.apply)
|
||||||
|
actionMsg = '[+]'.green;
|
||||||
|
else if (!script.matchRegex)
|
||||||
|
actionMsg = '[W]'.yellow;
|
||||||
|
else
|
||||||
|
actionMsg = '[I]'.blue;
|
||||||
|
|
||||||
|
console.log(' ', actionMsg.bold, script.file);
|
||||||
|
},
|
||||||
|
change(status, ignore, change) {
|
||||||
|
let actionMsg;
|
||||||
|
if (ignore)
|
||||||
|
actionMsg = '[I]'.blue;
|
||||||
|
else
|
||||||
|
actionMsg = '[A]'.green;
|
||||||
|
|
||||||
|
let statusMsg;
|
||||||
|
switch(status) {
|
||||||
|
case 'added':
|
||||||
|
statusMsg = '[+]'.green;
|
||||||
|
break;
|
||||||
|
case 'deleted':
|
||||||
|
statusMsg = '[-]'.red;
|
||||||
|
break;
|
||||||
|
case 'modified':
|
||||||
|
statusMsg = '[·]'.yellow;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const typeMsg = `[${change.type.abbr}]`[change.type.color];
|
||||||
|
console.log('',
|
||||||
|
(actionMsg + statusMsg).bold,
|
||||||
|
typeMsg.bold,
|
||||||
|
change.fullName
|
||||||
|
);
|
||||||
|
},
|
||||||
|
versionsApplied: function(nVersions, nChanges) {
|
||||||
|
if (nVersions) {
|
||||||
|
console.log(` -> ${nVersions} versions with ${nChanges} changes applied.`);
|
||||||
|
} else
|
||||||
|
console.log(` -> No versions applied.`);
|
||||||
|
},
|
||||||
|
routinesApplied: function(nRoutines) {
|
||||||
|
if (nRoutines) {
|
||||||
|
console.log(` -> ${nRoutines} routines 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 +174,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 dbVersion = await myt.fetchDbVersion() || {};
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`Database information:`
|
|
||||||
+ `\n -> Version: ${dbVersion.number}`
|
|
||||||
+ `\n -> Commit: ${dbVersion.gitCommit}`
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!dbVersion.number)
|
|
||||||
dbVersion.number = String('0').padStart(opts.versionDigits, '0');
|
|
||||||
if (!/^[0-9]*$/.test(dbVersion.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,34 +206,31 @@ class Push extends Command {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await super.cli(myt, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
async push(myt, opts, conn) {
|
||||||
|
const pushConn = await myt.createConnection();
|
||||||
|
|
||||||
|
// Get database version
|
||||||
|
|
||||||
|
const dbVersion = await myt.fetchDbVersion() || {};
|
||||||
|
this.emit('dbInfo', dbVersion);
|
||||||
|
|
||||||
|
if (!dbVersion.number)
|
||||||
|
dbVersion.number = String('0').padStart(opts.versionDigits, '0');
|
||||||
|
if (!/^[0-9]*$/.test(dbVersion.number))
|
||||||
|
throw new Error('Wrong database version');
|
||||||
|
|
||||||
// Apply versions
|
// Apply versions
|
||||||
|
|
||||||
console.log('Applying versions.');
|
this.emit('applyingVersions');
|
||||||
|
|
||||||
let nVersions = 0;
|
let nVersions = 0;
|
||||||
let nChanges = 0;
|
let nChanges = 0;
|
||||||
let silent = true;
|
let showLog = false;
|
||||||
const versionsDir = opts.versionsDir;
|
const versionsDir = opts.versionsDir;
|
||||||
|
|
||||||
function logVersion(version, name, action, error) {
|
|
||||||
let actionMsg;
|
|
||||||
switch(action) {
|
|
||||||
case 'apply':
|
|
||||||
actionMsg = '[A]'.green;
|
|
||||||
break;
|
|
||||||
case 'ignore':
|
|
||||||
actionMsg = '[I]'.blue;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
actionMsg = '[W]'.yellow;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('', (actionMsg + version).bold, name);
|
|
||||||
}
|
|
||||||
function logScript(type, message, error) {
|
|
||||||
console.log(' ', type.bold, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
const skipFiles = new Set([
|
const skipFiles = new Set([
|
||||||
'README.md',
|
'README.md',
|
||||||
'.archive'
|
'.archive'
|
||||||
|
@ -173,44 +242,27 @@ class Push extends Command {
|
||||||
if (skipFiles.has(versionDir)) continue;
|
if (skipFiles.has(versionDir)) continue;
|
||||||
const version = await myt.loadVersion(versionDir);
|
const version = await myt.loadVersion(versionDir);
|
||||||
|
|
||||||
if (!version) {
|
let apply = false;
|
||||||
logVersion('[?????]'.yellow, versionDir, 'warn',
|
|
||||||
`Wrong directory name.`
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (version.number.length != dbVersion.number.length) {
|
|
||||||
logVersion('[*****]'.gray, versionDir, 'warn'
|
|
||||||
`Bad version length, should have ${dbVersion.number.length} characters.`
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const {apply} = version;
|
if (!version)
|
||||||
if (apply) silent = false;
|
this.emit('version', version, 'wrongDirectory');
|
||||||
if (silent) continue;
|
else if (version.number.length != dbVersion.number.length)
|
||||||
|
this.emit('version', version, 'badVersion');
|
||||||
|
else
|
||||||
|
apply = version.apply;
|
||||||
|
|
||||||
const action = apply ? 'apply' : 'ignore';
|
if (apply) showLog = true;
|
||||||
logVersion(`[${version.number}]`.cyan, version.name, action);
|
if (showLog) this.emit('version', version);
|
||||||
if (!apply) continue;
|
if (!apply) continue;
|
||||||
|
|
||||||
for (const script of version.scripts) {
|
for (const script of version.scripts) {
|
||||||
const scriptFile = script.file;
|
this.emit('logScript', script);
|
||||||
|
|
||||||
if (!script.matchRegex) {
|
|
||||||
logScript('[W]'.yellow, scriptFile, `Wrong file name.`);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const actionMsg = script.apply ? '[+]'.green : '[I]'.blue;
|
|
||||||
logScript(actionMsg, scriptFile);
|
|
||||||
|
|
||||||
if (!script.apply) continue;
|
if (!script.apply) continue;
|
||||||
|
|
||||||
let err;
|
let err;
|
||||||
try {
|
try {
|
||||||
await connExt.queryFromFile(pushConn,
|
await connExt.queryFromFile(pushConn,
|
||||||
`${versionsDir}/${versionDir}/${scriptFile}`);
|
`${versionsDir}/${versionDir}/${script.file}`);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
err = e;
|
err = e;
|
||||||
}
|
}
|
||||||
|
@ -232,7 +284,7 @@ class Push extends Command {
|
||||||
[
|
[
|
||||||
opts.code,
|
opts.code,
|
||||||
version.number,
|
version.number,
|
||||||
scriptFile,
|
script.file,
|
||||||
err && err.errno,
|
err && err.errno,
|
||||||
err && err.message
|
err && err.message
|
||||||
]
|
]
|
||||||
|
@ -247,16 +299,11 @@ class Push extends Command {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nVersions) {
|
this.emit('versionsApplied', nVersions, nChanges);
|
||||||
console.log(` -> ${nVersions} versions with ${nChanges} changes applied.`);
|
|
||||||
} else
|
|
||||||
console.log(` -> No versions applied.`);
|
|
||||||
|
|
||||||
// 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(dbVersion.gitCommit);
|
const changes = await this.changedRoutines(dbVersion.gitCommit);
|
||||||
|
@ -320,26 +367,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('',
|
|
||||||
(actionMsg + statusMsg).bold,
|
|
||||||
typeMsg.bold,
|
|
||||||
change.fullName
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!ignore) {
|
if (!ignore) {
|
||||||
const scapedSchema = SqlString.escapeId(schema, true);
|
const scapedSchema = SqlString.escapeId(schema, true);
|
||||||
|
@ -387,11 +423,9 @@ class Push extends Command {
|
||||||
|
|
||||||
await finalize();
|
await finalize();
|
||||||
|
|
||||||
if (nRoutines) {
|
this.emit('routinesApplied', nRoutines);
|
||||||
console.log(` -> ${nRoutines} routines changed.`);
|
|
||||||
} else
|
|
||||||
console.log(` -> No routines changed.`);
|
|
||||||
|
|
||||||
|
const gitExists = await fs.pathExists(`${opts.workspace}/.git`);
|
||||||
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);
|
||||||
const head = await repo.getHeadCommit();
|
const head = await repo.getHeadCommit();
|
||||||
|
@ -558,4 +592,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,7 +10,7 @@ const SqlString = require('sqlstring');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the database image and runs a container. It only rebuilds the image
|
* Builds the database image and runs a container. It only rebuilds the image
|
||||||
* when dump has been modified. Some workarounds have been used to avoid a bug
|
* when dump have been modified. Some workarounds have been used to avoid a bug
|
||||||
* with OverlayFS driver on MacOS.
|
* with OverlayFS driver on MacOS.
|
||||||
*/
|
*/
|
||||||
class Run extends Command {
|
class Run extends Command {
|
||||||
|
@ -33,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');
|
||||||
|
@ -43,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');
|
||||||
|
|
||||||
|
@ -73,8 +84,10 @@ 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 = opts.dbConfig;
|
||||||
|
|
||||||
let runOptions;
|
let runOptions;
|
||||||
|
|
||||||
|
@ -117,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) {
|
||||||
|
@ -143,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',
|
||||||
|
@ -166,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`;
|
||||||
|
@ -179,6 +193,7 @@ class Run extends Command {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await conn.end();
|
||||||
return server;
|
return server;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,4 +201,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);
|
||||||
|
|
24
myt.js
24
myt.js
|
@ -40,7 +40,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
|
||||||
|
@ -144,9 +146,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);
|
||||||
|
@ -164,12 +166,16 @@ class Myt {
|
||||||
process.exit();
|
process.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
async runCommand(Command, opts) {
|
async run(Command, opts) {
|
||||||
|
if (!opts) opts = this.opts;
|
||||||
const command = new Command(this, opts);
|
const command = new Command(this, opts);
|
||||||
return await command.run(this, opts);
|
if (this.cliMode)
|
||||||
|
return await command.cli(this, opts);
|
||||||
|
else
|
||||||
|
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`);
|
||||||
|
@ -265,7 +271,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();
|
||||||
}
|
}
|
||||||
|
@ -434,4 +440,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.27",
|
"version": "1.5.28",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@verdnatura/myt",
|
"name": "@verdnatura/myt",
|
||||||
"version": "1.5.27",
|
"version": "1.5.28",
|
||||||
"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.27",
|
"version": "1.5.28",
|
||||||
"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