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.
|
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.
|
||||||
|
|
156
myvc-push.js
156
myvc-push.js
|
@ -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
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
8
myvc.js
8
myvc.js
|
@ -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
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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"
|
||||||
|
|
|
@ -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`);
|
||||||
|
|
Loading…
Reference in New Issue