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.
```text
$ myvc push [<remote>] [-f|--force] [-u|--user]
$ myvc push [<remote>] [-f|--force]
```
### version
@ -209,7 +209,10 @@ start a small project.
## 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.
* Undo changes when there is an error applying a version using "undo" files.
* Use a custom *Dockerfile* for local database container.
* Console logging via events.
* Lock version table row when pushing.

View File

@ -11,8 +11,7 @@ class Push {
return {
description: 'Apply changes into database',
params: {
force: 'Answer yes to all questions',
user: 'Update the user version instead, for shared databases'
force: 'Answer yes to all questions'
},
operand: 'remote'
};
@ -21,8 +20,7 @@ class Push {
get localOpts() {
return {
boolean: {
force: 'f',
user: 'u'
force: 'f'
}
};
}
@ -63,28 +61,6 @@ class Push {
if (!/^[0-9]*$/.test(version.number))
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
if (opts.remote == 'production') {
@ -124,8 +100,11 @@ class Push {
let nChanges = 0;
const versionsDir = `${opts.myvcDir}/versions`;
function logVersion(type, version, name) {
console.log('', type.bold, `[${version.bold}]`, name);
function logVersion(version, name, error) {
console.log('', version.bold, name);
}
function logScript(type, message, error) {
console.log(' ', type.bold, message);
}
if (await fs.pathExists(versionsDir)) {
@ -137,7 +116,9 @@ class Push {
const match = versionDir.match(/^([0-9]+)-([a-zA-Z0-9]+)?$/);
if (!match) {
logVersion('[W]'.yellow, '?????', versionDir);
logVersion('[?????]'.yellow, versionDir,
`Wrong directory name.`
);
continue;
}
@ -145,26 +126,72 @@ class Push {
const versionName = match[2];
if (versionNumber.length != version.number.length) {
logVersion('[W]'.yellow, '*****', versionDir);
continue;
}
if (version.number >= versionNumber) {
logVersion('[I]'.blue, versionNumber, versionName);
logVersion('[*****]'.gray, versionDir,
`Bad version length, should have ${version.number.length} characters.`
);
continue;
}
logVersion('[+]'.green, versionNumber, versionName);
logVersion(`[${versionNumber}]`.cyan, versionName);
const scriptsDir = `${versionsDir}/${versionDir}`;
const scripts = await fs.readdir(scriptsDir);
for (const script of scripts) {
if (!/^[0-9]{2}-[a-zA-Z0-9_]+\.sql$/.test(script)) {
console.log(` - Ignoring wrong file name: ${script}`);
if (!/^[0-9]{2}-[a-zA-Z0-9_]+(.undo)?\.sql$/.test(script)) {
logScript('[W]'.yellow, script, `Wrong file name.`);
continue;
}
if (/\.undo\.sql$/.test(script))
continue;
console.log(` - ${script}`);
await this.queryFromFile(pushConn, `${scriptsDir}/${script}`);
const [[row]] = await conn.query(
`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++;
}
@ -280,49 +307,24 @@ class Push {
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) {
if (nChanges == 0) return;
const {opts} = this;
column = this.conn.escapeId(column, true);
if (opts.user) {
const user = await this.getDbUser();
await this.conn.query(
`INSERT INTO versionUser
SET code = ?,
user = ?,
${column} = ?,
updated = NOW()
ON DUPLICATE KEY UPDATE
${column} = VALUES(${column}),
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
]
);
}
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) {
const myVersion = packageJson.version.match(versionRegex);
const isSameVersion =
depVersion[1] === myVersion[1] &&
depVersion[2] === myVersion[2];
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

2066
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

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

View File

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