versionLog, push user arg removed, minor version check

This commit is contained in:
Juan Ferrer 2022-01-31 14:07:08 +01:00
parent f1f1f00b5d
commit 7762340e75
6 changed files with 219 additions and 2041 deletions

View File

@ -82,7 +82,7 @@ When *checkout* option is provided, it does the following before export:
Applies versions and routine changes into database. Applies versions and routine changes into database.
```text ```text
$ myvc push [<remote>] [-f|--force] [-u|--user] $ myvc push [<remote>] [-f|--force]
``` ```
### version ### version
@ -209,7 +209,10 @@ start a small project.
## Todo ## Todo
* Don't push (modified) routines whose SQL text is the same in DB.
* Preserve all characteristics on pull: comments, SQL mode, READS SQL DATA...
* Update routines shasum when push. * Update routines shasum when push.
* Undo changes when there is an error applying a version using "undo" files.
* Use a custom *Dockerfile* for local database container. * Use a custom *Dockerfile* for local database container.
* Console logging via events. * Console logging via events.
* Lock version table row when pushing. * Lock version table row when pushing.

View File

@ -11,8 +11,7 @@ class Push {
return { return {
description: 'Apply changes into database', description: 'Apply changes into database',
params: { params: {
force: 'Answer yes to all questions', force: 'Answer yes to all questions'
user: 'Update the user version instead, for shared databases'
}, },
operand: 'remote' operand: 'remote'
}; };
@ -21,8 +20,7 @@ class Push {
get localOpts() { get localOpts() {
return { return {
boolean: { boolean: {
force: 'f', force: 'f'
user: 'u'
} }
}; };
} }
@ -63,28 +61,6 @@ class Push {
if (!/^[0-9]*$/.test(version.number)) if (!/^[0-9]*$/.test(version.number))
throw new Error('Wrong database version'); throw new Error('Wrong database version');
if (opts.user) {
const user = await this.getDbUser();
let [[userVersion]] = await conn.query(
`SELECT number, gitCommit
FROM versionUser
WHERE code = ? AND user = ?`,
[opts.code, user]
);
userVersion = userVersion || {};
console.log(
`User information:`
+ `\n -> User: ${user}`
+ `\n -> Version: ${userVersion.number}`
+ `\n -> Commit: ${userVersion.gitCommit}`
);
if (userVersion.number > version.number)
version.number = userVersion.number;
if (userVersion.gitCommit && userVersion.gitCommit !== version.gitCommit)
version.gitCommit = userVersion.gitCommit;
}
// Prevent push to production by mistake // Prevent push to production by mistake
if (opts.remote == 'production') { if (opts.remote == 'production') {
@ -124,8 +100,11 @@ class Push {
let nChanges = 0; let nChanges = 0;
const versionsDir = `${opts.myvcDir}/versions`; const versionsDir = `${opts.myvcDir}/versions`;
function logVersion(type, version, name) { function logVersion(version, name, error) {
console.log('', type.bold, `[${version.bold}]`, name); console.log('', version.bold, name);
}
function logScript(type, message, error) {
console.log(' ', type.bold, message);
} }
if (await fs.pathExists(versionsDir)) { if (await fs.pathExists(versionsDir)) {
@ -137,7 +116,9 @@ class Push {
const match = versionDir.match(/^([0-9]+)-([a-zA-Z0-9]+)?$/); const match = versionDir.match(/^([0-9]+)-([a-zA-Z0-9]+)?$/);
if (!match) { if (!match) {
logVersion('[W]'.yellow, '?????', versionDir); logVersion('[?????]'.yellow, versionDir,
`Wrong directory name.`
);
continue; continue;
} }
@ -145,26 +126,72 @@ class Push {
const versionName = match[2]; const versionName = match[2];
if (versionNumber.length != version.number.length) { if (versionNumber.length != version.number.length) {
logVersion('[W]'.yellow, '*****', versionDir); logVersion('[*****]'.gray, versionDir,
continue; `Bad version length, should have ${version.number.length} characters.`
} );
if (version.number >= versionNumber) {
logVersion('[I]'.blue, versionNumber, versionName);
continue; continue;
} }
logVersion('[+]'.green, versionNumber, versionName); logVersion(`[${versionNumber}]`.cyan, versionName);
const scriptsDir = `${versionsDir}/${versionDir}`; const scriptsDir = `${versionsDir}/${versionDir}`;
const scripts = await fs.readdir(scriptsDir); const scripts = await fs.readdir(scriptsDir);
for (const script of scripts) { for (const script of scripts) {
if (!/^[0-9]{2}-[a-zA-Z0-9_]+\.sql$/.test(script)) { if (!/^[0-9]{2}-[a-zA-Z0-9_]+(.undo)?\.sql$/.test(script)) {
console.log(` - Ignoring wrong file name: ${script}`); logScript('[W]'.yellow, script, `Wrong file name.`);
continue; continue;
} }
if (/\.undo\.sql$/.test(script))
continue;
console.log(` - ${script}`); const [[row]] = await conn.query(
await this.queryFromFile(pushConn, `${scriptsDir}/${script}`); `SELECT errorNumber FROM versionLog
WHERE code = ?
AND number = ?
AND file = ?`,
[
opts.code,
versionNumber,
script
]
);
const apply = !row || row.errorNumber;
const actionMsg = apply ? '[+]'.green : '[I]'.blue;
logScript(actionMsg, script);
if (!apply) continue;
let err;
try {
await this.queryFromFile(pushConn, `${scriptsDir}/${script}`);
} catch (e) {
err = e;
}
await conn.query(
`INSERT INTO versionLog
SET code = ?,
number = ?,
file = ?,
user = USER(),
updated = NOW(),
errorNumber = ?,
errorMessage = ?
ON DUPLICATE KEY UPDATE
updated = VALUES(updated),
user = VALUES(user),
errorNumber = VALUES(errorNumber),
errorMessage = VALUES(errorMessage)`,
[
opts.code,
versionNumber,
script,
err && err.errno,
err && err.message
]
);
if (err) throw err;
nChanges++; nChanges++;
} }
@ -280,49 +307,24 @@ class Push {
return routines; return routines;
} }
async getDbUser() {
const [[row]] = await this.conn.query('SELECT USER() `user`');
return row.user.substr(0, row.user.indexOf('@'));
}
async updateVersion(nChanges, column, value) { async updateVersion(nChanges, column, value) {
if (nChanges == 0) return; if (nChanges == 0) return;
const {opts} = this; const {opts} = this;
column = this.conn.escapeId(column, true); column = this.conn.escapeId(column, true);
await this.conn.query(
if (opts.user) { `INSERT INTO version
const user = await this.getDbUser(); SET code = ?,
await this.conn.query( ${column} = ?,
`INSERT INTO versionUser updated = NOW()
SET code = ?, ON DUPLICATE KEY UPDATE
user = ?, ${column} = VALUES(${column}),
${column} = ?, updated = VALUES(updated)`,
updated = NOW() [
ON DUPLICATE KEY UPDATE opts.code,
${column} = VALUES(${column}), value
updated = VALUES(updated)`, ]
[ );
opts.code,
user,
value
]
);
} else {
await this.conn.query(
`INSERT INTO version
SET code = ?,
${column} = ?,
updated = NOW()
ON DUPLICATE KEY UPDATE
${column} = VALUES(${column}),
updated = VALUES(updated)`,
[
opts.code,
value
]
);
}
} }
/** /**

View File

@ -103,12 +103,16 @@ class MyVC {
if (depVersion) { if (depVersion) {
const myVersion = packageJson.version.match(versionRegex); const myVersion = packageJson.version.match(versionRegex);
const isSameVersion = const isSameVersion =
depVersion[1] === myVersion[1] && depVersion[1] === myVersion[1] &&
depVersion[2] === myVersion[2]; depVersion[2] === myVersion[2];
if (!isSameVersion) if (!isSameVersion)
throw new Error(`This version of MyVC differs from your package.json`) throw new Error(`This version of MyVC differs from your package.json`);
const isSameMinor = depVersion[3] === myVersion[3];
if (!isSameMinor)
console.warn(`Warning! Minor version of MyVC differs from your package.json`.yellow);
} }
// Load method // Load method

2066
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "myvc", "name": "myvc",
"version": "1.2.3", "version": "1.2.4",
"author": "Verdnatura Levante SL", "author": "Verdnatura Levante SL",
"description": "MySQL Version Control", "description": "MySQL Version Control",
"license": "GPL-3.0", "license": "GPL-3.0",
@ -12,11 +12,11 @@
"dependencies": { "dependencies": {
"@sqltools/formatter": "^1.2.3", "@sqltools/formatter": "^1.2.3",
"colors": "^1.4.0", "colors": "^1.4.0",
"ejs": "^3.1.5", "ejs": "^3.1.6",
"fs-extra": "^8.1.0", "fs-extra": "^8.1.0",
"getopts": "^2.2.5", "getopts": "^2.3.0",
"ini": "^1.3.8", "ini": "^1.3.8",
"mysql2": "^2.2.5", "mysql2": "^2.3.2",
"nodegit": "^0.27.0", "nodegit": "^0.27.0",
"require-yaml": "0.0.1", "require-yaml": "0.0.1",
"sha.js": "^2.4.11" "sha.js": "^2.4.11"

View File

@ -9,14 +9,15 @@ CREATE TABLE `version` (
ALTER TABLE `version` ALTER TABLE `version`
ADD PRIMARY KEY (`code`); ADD PRIMARY KEY (`code`);
CREATE TABLE `versionUser` ( CREATE TABLE `versionLog` (
`code` VARCHAR(255) NOT NULL, `code` VARCHAR(255) NOT NULL,
`user` VARCHAR(255) NOT NULL, `number` CHAR(11) NOT NULL,
`number` CHAR(11) NULL DEFAULT NULL, `file` VARCHAR(255) NOT NULL,
`gitCommit` VARCHAR(255) NULL DEFAULT NULL, `user` VARCHAR(255) NULL,
`updated` DATETIME NOT NULL DEFAULT NULL, `updated` DATETIME NOT NULL,
`lastNumber` CHAR(11) NULL DEFAULT NULL, `errorNumber` INT(10) UNSIGNED DEFAULT NULL,
`errorMessage` VARCHAR(255) DEFAULT NULL
) ENGINE=InnoDB; ) ENGINE=InnoDB;
ALTER TABLE `versionUser` ALTER TABLE `versionLog`
ADD PRIMARY KEY (`code`,`user`); ADD PRIMARY KEY (`code`,`number`,`file`);