versionLog, push user arg removed, minor version check
This commit is contained in:
parent
f1f1f00b5d
commit
7762340e75
|
@ -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.
|
||||
|
|
156
myvc-push.js
156
myvc-push.js
|
@ -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
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
8
myvc.js
8
myvc.js
|
@ -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
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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"
|
||||
|
|
|
@ -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`);
|
||||
|
|
Loading…
Reference in New Issue