🔥 remove database version (#7894)

refs #7489

- as we are now using a different migration approach (knex-migrator), we don't need to remember the database version anymore
- it was once used to check the state of a database and based on it we decided to migrate or not
- with knex-migrator everything depends on the migration table entries and the current ghost version you are on
- on current master the leftover usage is to add the db version when exporting the database, which can be replaced by reading the ghost version
- removing this solves also an interesting migration case with knex-migrator:
  - you are on 1.0
  - you update to 1.1, but 1.1 has no migrations
  - the db version would remain in 1.0
  - because the db version was only updated when knex migrator executed a migration
This commit is contained in:
Katharina Irrgang 2017-01-26 13:12:00 +01:00 committed by Kevin Ansfield
parent 5c94151e14
commit 584bd15b76
27 changed files with 103 additions and 540 deletions

View File

@ -1,8 +1,8 @@
var config = require('./core/server/config'),
versioning = require('./core/server/data/schema/versioning');
utils = require('./core/server/utils');
module.exports = {
currentVersion: versioning.getNewestDatabaseVersion(),
currentVersion: utils.ghostVersion.safe,
database: config.get('database'),
migrationPath: config.get('paths:migrationPath')
};

View File

@ -2,8 +2,8 @@ var _ = require('lodash'),
Promise = require('bluebird'),
db = require('../../data/db'),
commands = require('../schema').commands,
versioning = require('../schema').versioning,
serverUtils = require('../../utils'),
ghostVersion = require('../../utils/ghost-version'),
errors = require('../../errors'),
logging = require('../../logging'),
settings = require('../../api/settings'),
@ -36,7 +36,7 @@ exportFileName = function exportFileName() {
getVersionAndTables = function getVersionAndTables() {
var props = {
version: versioning.getDatabaseVersion(),
version: ghostVersion.full,
tables: commands.getTables()
};

View File

@ -1,30 +1,18 @@
var errors = require('../../../../errors'),
config = require('../../../../config'),
versioning = require('../../../schema/versioning'),
var config = require('../../../../config'),
database = require('../../../db');
module.exports = function after(options) {
return versioning.getDatabaseVersion(options)
.catch(function (err) {
if (err instanceof errors.DatabaseVersionError && err.code === 'VERSION_DOES_NOT_EXIST') {
return versioning.setDatabaseVersion(options);
}
module.exports = function after() {
// do not close database connection in test mode, because all tests are executed one after another
// this check is not nice, but there is only one other solution i can think of:
// forward a custom object to knex-migrator, which get's forwarded to the hooks
if (config.get('env').match(/testing/g)) {
return;
}
throw err;
})
.finally(function destroyConnection() {
// do not close database connection in test mode, because all tests are executed one after another
// this check is not nice, but there is only one other solution i can think of:
// forward a custom object to knex-migrator, which get's forwarded to the hooks
if (config.get('env').match(/testing/g)) {
return;
}
// we need to close the database connection
// the after hook signals the last step of a knex-migrator command
// Example:
// Ghost-CLI calls knexMigrator.init and afterwards it starts Ghost, but Ghost-CLI can't shutdown
// if Ghost keeps a connection alive
return database.knex.destroy();
});
// we need to close the database connection
// the after hook signals the last step of a knex-migrator command
// Example:
// Ghost-CLI calls knexMigrator.init and afterwards it starts Ghost, but Ghost-CLI can't shutdown
// if Ghost keeps a connection alive
return database.knex.destroy();
};

View File

@ -1,30 +1,18 @@
var errors = require('../../../../errors'),
config = require('../../../../config'),
versioning = require('../../../schema/versioning'),
var config = require('../../../../config'),
database = require('../../../db');
module.exports = function after(options) {
return versioning.getDatabaseVersion(options)
.catch(function (err) {
if (err instanceof errors.DatabaseVersionError && err.code === 'VERSION_DOES_NOT_EXIST') {
return versioning.setDatabaseVersion(options);
}
module.exports = function after() {
// do not close database connection in test mode, because all tests are executed one after another
// this check is not nice, but there is only one other solution i can think of:
// forward a custom object to knex-migrator, which get's forwarded to the hooks
if (config.get('env').match(/testing/g)) {
return;
}
throw err;
})
.finally(function destroyConnection() {
// do not close database connection in test mode, because all tests are executed one after another
// this check is not nice, but there is only one other solution i can think of:
// forward a custom object to knex-migrator, which get's forwarded to the hooks
if (config.get('env').match(/testing/g)) {
return;
}
// we need to close the database connection
// the after hook signals the last step of a knex-migrator command
// Example:
// Ghost-CLI calls knexMigrator.init and afterwards it starts Ghost, but Ghost-CLI can't shutdown
// if Ghost keeps a connection alive
return database.knex.destroy();
});
// we need to close the database connection
// the after hook signals the last step of a knex-migrator command
// Example:
// Ghost-CLI calls knexMigrator.init and afterwards it starts Ghost, but Ghost-CLI can't shutdown
// if Ghost keeps a connection alive
return database.knex.destroy();
};

View File

@ -1,8 +1,5 @@
{
"core": {
"databaseVersion": {
"defaultValue": null
},
"dbHash": {
"defaultValue": null
},

View File

@ -1,5 +1,4 @@
module.exports.tables = require('./schema');
module.exports.checks = require('./checks');
module.exports.commands = require('./commands');
module.exports.versioning = require('./versioning');
module.exports.defaultSettings = require('./default-settings');

View File

@ -1,78 +0,0 @@
var Promise = require('bluebird'),
db = require('../db'),
errors = require('../../errors'),
ghostVersion = require('../../utils/ghost-version');
/**
* Database version has always two digits
* Database version is Ghost Version X.X
*
* @TODO: remove alpha text!
* @TODO: extend database validation
*/
function validateDatabaseVersion(version) {
if (version === null) {
throw new errors.DatabaseVersionError({
code: 'VERSION_DOES_NOT_EXIST'
});
}
if (!version.match(/\d\.\d/gi)) {
throw new errors.DatabaseVersionError({
message: 'Your database version is not compatible with Ghost 1.0.0 Alpha (master branch)',
context: 'Want to keep your DB? Use Ghost < 1.0.0 or the "stable" branch. Otherwise please delete your DB and restart Ghost',
help: 'More information on the Ghost 1.0.0 Alpha at https://support.ghost.org/v1-0-alpha'
});
}
return version;
}
/**
* If the database version is null, the database was never seeded.
* The init migration script will set your database to current Ghost Version.
*/
function getDatabaseVersion(options) {
options = options || {};
return (options.transacting || db.knex).schema.hasTable('settings')
.then(function (exists) {
if (!exists) {
return Promise.reject(new errors.DatabaseVersionError({
code: 'SETTINGS_TABLE_DOES_NOT_EXIST'
}));
}
return (options.transacting || db.knex)('settings')
.where('key', 'databaseVersion')
.first('value')
.then(function (version) {
return validateDatabaseVersion(version ? version.value : null);
});
});
}
function getNewestDatabaseVersion() {
return ghostVersion.safe;
}
/**
* Database version cannot set from outside.
* If this function get called, we set the database version to your current Ghost version.
*/
function setDatabaseVersion(options) {
options = options || {};
return (options.transacting || db.knex)('settings')
.where('key', 'databaseVersion')
.update({
value: getNewestDatabaseVersion()
});
}
module.exports = {
canMigrateFromVersion: '1.0',
getNewestDatabaseVersion: getNewestDatabaseVersion,
getDatabaseVersion: getDatabaseVersion,
setDatabaseVersion: setDatabaseVersion
};

View File

@ -19,6 +19,7 @@ var debug = require('debug')('ghost:boot:init'),
KnexMigrator = require('knex-migrator'),
config = require('./config'),
logging = require('./logging'),
errors = require('./errors'),
i18n = require('./i18n'),
api = require('./api'),
models = require('./models'),
@ -83,7 +84,35 @@ function init(options) {
models.init();
}).then(function () {
return knexMigrator.isDatabaseOK();
return knexMigrator.isDatabaseOK()
.catch(function (outerErr) {
if (outerErr.code === 'DB_NOT_INITIALISED') {
throw outerErr;
}
// CASE: migration table does not exist, figure out if database is compatible
return models.Settings.findOne({key: 'databaseVersion', context: {internal: true}})
.then(function (response) {
// CASE: no db version key, database is compatible
if (!response) {
throw outerErr;
}
throw new errors.DatabaseVersionError({
message: 'Your database version is not compatible with Ghost 1.0.0 Alpha (master branch)',
context: 'Want to keep your DB? Use Ghost < 1.0.0 or the "stable" branch. Otherwise please delete your DB and restart Ghost.',
help: 'More information on the Ghost 1.0.0 Alpha at https://support.ghost.org/v1-0-alpha'
});
})
.catch(function (err) {
// CASE: settings table does not exist
if (err.errno === 1 || err.errno === 1146) {
throw outerErr;
}
throw err;
});
});
}).then(function () {
// Populate any missing default settings
return models.Settings.populateDefaults();

View File

@ -167,10 +167,6 @@ Settings = ghostBookshelf.Model.extend({
_.each(getDefaultSettings(), function each(defaultSetting, defaultSettingKey) {
var isMissingFromDB = usedKeys.indexOf(defaultSettingKey) === -1;
// Temporary code to deal with old databases with currentVersion settings
if (defaultSettingKey === 'databaseVersion' && usedKeys.indexOf('currentVersion') !== -1) {
isMissingFromDB = false;
}
if (isMissingFromDB) {
defaultSetting.value = defaultSetting.defaultValue;
insertOperations.push(Settings.forge(defaultSetting).save(null, options));

View File

@ -448,17 +448,6 @@
}
}
},
"versioning": {
"index": {
"dbVersionNotRecognized": "Database version is not recognized",
"databaseNotPopulated": "Database is not populated.",
"databaseNotSeeded": "Database is not seeded.",
"cannotMigrate": {
"error": "Unable to upgrade from version 0.4.2 or earlier.",
"context": "Please upgrade to 0.7.1 first."
}
}
},
"xml": {
"xmlrpc": {
"pingUpdateFailed": {

View File

@ -107,7 +107,8 @@ utils = {
generateAssetHash: require('./asset-hash'),
url: require('./url'),
tokens: require('./tokens'),
sequence: require('./sequence')
sequence: require('./sequence'),
ghostVersion: require('./ghost-version')
};
module.exports = utils;

View File

@ -88,8 +88,8 @@ describe('Settings API', function () {
});
it('cannot read core settings if not an internal request', function () {
return callApiWithContext(defaultContext, 'read', {key: 'databaseVersion'}).then(function () {
throw new Error('Allowed to read databaseVersion with external request');
return callApiWithContext(defaultContext, 'read', {key: 'dbHash'}).then(function () {
throw new Error('Allowed to read dbHash with external request');
}).catch(function (error) {
should.exist(error);
error.errorType.should.eql('NoPermissionError');
@ -97,7 +97,7 @@ describe('Settings API', function () {
});
it('can read core settings if an internal request', function () {
return callApiWithContext(internalContext, 'read', {key: 'databaseVersion'}).then(function (response) {
return callApiWithContext(internalContext, 'read', {key: 'dbHash'}).then(function (response) {
should.exist(response);
testUtils.API.checkResponse(response, 'settings');
response.settings.length.should.equal(1);
@ -134,7 +134,7 @@ describe('Settings API', function () {
});
it('cannot edit a core setting if not an internal request', function () {
return callApiWithContext(defaultContext, 'edit', {settings: [{key: 'databaseVersion', value: '999'}]}, {})
return callApiWithContext(defaultContext, 'edit', {settings: [{key: 'dbHash', value: 'hash'}]}, {})
.then(function () {
throw new Error('Allowed to edit a core setting as external request');
}).catch(function (err) {
@ -145,7 +145,7 @@ describe('Settings API', function () {
});
it('can edit a core setting with an internal request', function () {
return callApiWithContext(internalContext, 'edit', {settings: [{key: 'databaseVersion', value: '999'}]}, {})
return callApiWithContext(internalContext, 'edit', {settings: [{key: 'dbHash', value: 'hash'}]}, {})
.then(function (response) {
should.exist(response);
testUtils.API.checkResponse(response, 'settings');

View File

@ -1,14 +1,12 @@
var testUtils = require('../utils/index'),
should = require('should'),
sinon = require('sinon'),
Promise = require('bluebird'),
_ = require('lodash'),
// Stuff we are testing
versioning = require('../../server/data/schema').versioning,
exporter = require('../../server/data/export'),
utils = require('../../server/utils'),
DEF_DB_VERSION = versioning.getNewestDatabaseVersion(),
sandbox = sinon.sandbox.create();
describe('Exporter', function () {
@ -22,36 +20,23 @@ describe('Exporter', function () {
should.exist(exporter);
it('exports data', function (done) {
// Stub migrations to return DEF_DB_VERSION as the current database version
var versioningStub = sandbox.stub(versioning, 'getDatabaseVersion', function () {
return Promise.resolve(DEF_DB_VERSION);
});
exporter.doExport().then(function (exportData) {
var tables = ['posts', 'users', 'roles', 'roles_users', 'permissions', 'permissions_roles',
'permissions_users', 'settings', 'tags', 'posts_tags'],
dbVersionSetting;
'permissions_users', 'settings', 'tags', 'posts_tags'];
should.exist(exportData);
should.exist(exportData.meta);
should.exist(exportData.data);
exportData.meta.version.should.equal(DEF_DB_VERSION);
dbVersionSetting = _.find(exportData.data.settings, {key: 'databaseVersion'});
should.exist(dbVersionSetting);
dbVersionSetting.value.should.equal(DEF_DB_VERSION);
exportData.meta.version.should.equal(utils.ghostVersion.full);
_.each(tables, function (name) {
should.exist(exportData.data[name]);
});
// should not export sqlite data
should.not.exist(exportData.data.sqlite_sequence);
versioningStub.restore();
done();
}).catch(done);
});

View File

@ -9,12 +9,10 @@ var testUtils = require('../utils/index'),
// Stuff we are testing
db = require('../../server/data/db'),
versioning = require('../../server/data/schema').versioning,
exporter = require('../../server/data/export'),
importer = require('../../server/data/import'),
DataImporter = require('../../server/data/import/data-importer'),
DEF_DB_VERSION = versioning.getNewestDatabaseVersion(),
knex = db.knex,
sandbox = sinon.sandbox.create();
@ -150,7 +148,6 @@ describe('Import', function () {
// test settings
settings.length.should.be.above(0, 'Wrong number of settings');
_.find(settings, {key: 'databaseVersion'}).value.should.equal(DEF_DB_VERSION, 'Wrong database version');
// test tags
tags.length.should.equal(exportData.data.tags.length, 'no new tags');
@ -204,10 +201,6 @@ describe('Import', function () {
// import no longer requires all data to be dropped, and adds posts
posts.length.should.equal(exportData.data.posts.length, 'Wrong number of posts');
// test settings
settings.length.should.be.above(0, 'Wrong number of settings');
_.find(settings, {key: 'databaseVersion'}).value.should.equal(DEF_DB_VERSION, 'Wrong database version');
// activeTheme should NOT have been overridden
_.find(settings, {key: 'activeTheme'}).value.should.equal('casper', 'Wrong theme');
@ -246,17 +239,15 @@ describe('Import', function () {
Promise.all([
knex('users').select(),
knex('posts').select(),
knex('settings').select(),
knex('tags').select()
]).then(function (importedData) {
should.exist(importedData);
importedData.length.should.equal(4, 'Did not get data successfully');
importedData.length.should.equal(3, 'Did not get data successfully');
var users = importedData[0],
posts = importedData[1],
settings = importedData[2],
tags = importedData[3];
tags = importedData[2];
// we always have 1 user, the default user we added
users.length.should.equal(1, 'There should only be one user');
@ -265,10 +256,6 @@ describe('Import', function () {
posts.length.should.equal(0, 'Wrong number of posts');
tags.length.should.equal(0, 'no new tags');
// test settings
settings.length.should.be.above(0, 'Wrong number of settings');
_.find(settings, {key: 'databaseVersion'}).value.should.equal(DEF_DB_VERSION, 'Wrong database version');
done();
});
}).catch(done);
@ -291,17 +278,15 @@ describe('Import', function () {
Promise.all([
knex('users').select(),
knex('posts').select(),
knex('settings').select(),
knex('tags').select()
]).then(function (importedData) {
should.exist(importedData);
importedData.length.should.equal(4, 'Did not get data successfully');
importedData.length.should.equal(3, 'Did not get data successfully');
var users = importedData[0],
posts = importedData[1],
settings = importedData[2],
tags = importedData[3];
tags = importedData[2];
// we always have 1 user, the default user we added
users.length.should.equal(1, 'There should only be one user');
@ -310,10 +295,6 @@ describe('Import', function () {
posts.length.should.equal(0, 'Wrong number of posts');
tags.length.should.equal(0, 'no new tags');
// test settings
settings.length.should.be.above(0, 'Wrong number of settings');
_.find(settings, {key: 'databaseVersion'}).value.should.equal(DEF_DB_VERSION, 'Wrong database version');
done();
});
}).catch(done);
@ -368,10 +349,6 @@ describe('Import', function () {
// import no longer requires all data to be dropped, and adds posts
posts.length.should.equal(exportData.data.posts.length, 'Wrong number of posts');
// test settings
settings.length.should.be.above(0, 'Wrong number of settings');
_.find(settings, {key: 'databaseVersion'}).value.should.equal(DEF_DB_VERSION, 'Wrong database version');
// activeTheme should NOT have been overridden
_.find(settings, {key: 'activeTheme'}).value.should.equal('casper', 'Wrong theme');
@ -410,17 +387,15 @@ describe('Import', function () {
Promise.all([
knex('users').select(),
knex('posts').select(),
knex('settings').select(),
knex('tags').select()
]).then(function (importedData) {
should.exist(importedData);
importedData.length.should.equal(4, 'Did not get data successfully');
importedData.length.should.equal(3, 'Did not get data successfully');
var users = importedData[0],
posts = importedData[1],
settings = importedData[2],
tags = importedData[3];
tags = importedData[2];
// we always have 1 user, the owner user we added
users.length.should.equal(1, 'There should only be one user');
@ -428,10 +403,6 @@ describe('Import', function () {
posts.length.should.equal(0, 'Wrong number of posts');
tags.length.should.equal(0, 'no new tags');
// test settings
settings.length.should.be.above(0, 'Wrong number of settings');
_.find(settings, {key: 'databaseVersion'}).value.should.equal(DEF_DB_VERSION, 'Wrong database version');
done();
});
}).catch(done);
@ -454,17 +425,15 @@ describe('Import', function () {
Promise.all([
knex('users').select(),
knex('posts').select(),
knex('settings').select(),
knex('tags').select()
]).then(function (importedData) {
should.exist(importedData);
importedData.length.should.equal(4, 'Did not get data successfully');
importedData.length.should.equal(3, 'Did not get data successfully');
var users = importedData[0],
posts = importedData[1],
settings = importedData[2],
tags = importedData[3];
tags = importedData[2];
// we always have 1 user, the owner user we added
users.length.should.equal(1, 'There should only be one user');
@ -472,10 +441,6 @@ describe('Import', function () {
posts.length.should.equal(0, 'Wrong number of posts');
tags.length.should.equal(0, 'no new tags');
// test settings
settings.length.should.be.above(0, 'Wrong number of settings');
_.find(settings, {key: 'databaseVersion'}).value.should.equal(DEF_DB_VERSION, 'Wrong database version');
done();
});
}).catch(done);
@ -496,18 +461,16 @@ describe('Import', function () {
return Promise.all([
knex('users').select(),
knex('posts').select(),
knex('settings').select(),
knex('tags').select()
]);
}).then(function (importedData) {
should.exist(importedData);
importedData.length.should.equal(4, 'Did not get data successfully');
importedData.length.should.equal(3, 'Did not get data successfully');
var users = importedData[0],
posts = importedData[1],
settings = importedData[2],
tags = importedData[3];
tags = importedData[2];
// user should still have the credentials from the original insert, not the import
users[0].email.should.equal(testUtils.DataGenerator.Content.users[0].email);
@ -522,10 +485,6 @@ describe('Import', function () {
// test tags
tags.length.should.equal(1, 'no new tags');
// test settings
settings.length.should.be.above(0, 'Wrong number of settings');
_.find(settings, {key: 'databaseVersion'}).value.should.equal(DEF_DB_VERSION, 'Wrong database version');
done();
}).catch(done);
});
@ -712,10 +671,6 @@ describe('Import (new test structure)', function () {
// test tags
tags.length.should.equal(3, 'should be 3 tags');
// test settings
settings.length.should.be.above(0, 'Wrong number of settings');
_.find(settings, {key: 'databaseVersion'}).value.should.equal(DEF_DB_VERSION, 'Wrong database version');
done();
}).catch(done);
});
@ -937,10 +892,6 @@ describe('Import (new test structure)', function () {
// test tags
tags.length.should.equal(3, 'should be 3 tags');
// test settings
settings.length.should.be.above(0, 'Wrong number of settings');
_.find(settings, {key: 'databaseVersion'}).value.should.equal(DEF_DB_VERSION, 'Wrong database version');
done();
}).catch(done);
});
@ -1174,10 +1125,6 @@ describe('Import (new test structure)', function () {
tags[0].name.should.equal(testUtils.DataGenerator.Content.tags[0].name);
// test settings
settings.length.should.be.above(0, 'Wrong number of settings');
_.find(settings, {key: 'databaseVersion'}).value.should.equal(DEF_DB_VERSION, 'Wrong database version');
done();
}).catch(done);
});

View File

@ -153,7 +153,6 @@ describe('Settings Model', function () {
it('can destroy', function (done) {
SettingsModel.findAll().then(function (allSettings) {
// dont't use index 0, since it will delete databaseversion
SettingsModel.findOne({id: allSettings.models[1].id}).then(function (results) {
should.exist(results);
results.attributes.id.should.equal(allSettings.models[1].id);

View File

@ -1,16 +1,17 @@
var should = require('should'),
sinon = require('sinon'),
rewire = require('rewire'),
Promise = require('bluebird'),
db = require('../../server/data/db'),
errors = require('../../server/errors'),
exporter = require('../../server/data/export'),
exporter = rewire('../../server/data/export'),
schema = require('../../server/data/schema'),
settings = require('../../server/api/settings'),
schemaTables = Object.keys(schema.tables),
sandbox = sinon.sandbox.create();
describe('Exporter', function () {
var versionStub, tablesStub, queryMock, knexMock, knexStub;
var tablesStub, queryMock, knexMock, knexStub;
afterEach(function () {
sandbox.restore();
@ -19,7 +20,10 @@ describe('Exporter', function () {
describe('doExport', function () {
beforeEach(function () {
versionStub = sandbox.stub(schema.versioning, 'getDatabaseVersion').returns(new Promise.resolve('004'));
exporter.__set__('ghostVersion', {
full: '1.0.0'
});
tablesStub = sandbox.stub(schema.commands, 'getTables').returns(schemaTables);
queryMock = {
@ -43,7 +47,8 @@ describe('Exporter', function () {
should.exist(exportData);
versionStub.calledOnce.should.be.true();
exportData.meta.version.should.eql('1.0.0');
tablesStub.calledOnce.should.be.true();
knexStub.get.called.should.be.true();
knexMock.called.should.be.true();

View File

@ -1,5 +1,4 @@
var should = require('should'),
sinon = require('sinon'),
var sinon = require('sinon'),
rewire = require('rewire'),
_ = require('lodash'),
Promise = require('bluebird'),
@ -10,7 +9,6 @@ var should = require('should'),
schema = require('../../server/data/schema'),
backupDatabase = rewire('../../server/data/db/backup'),
fixtures = require('../../server/data/schema/fixtures'),
defaultSettings = schema.defaultSettings,
sandbox = sinon.sandbox.create();
// Check version integrity
@ -38,11 +36,8 @@ describe('DB version integrity', function () {
schemaHash = crypto.createHash('md5').update(JSON.stringify(tablesNoValidation)).digest('hex');
fixturesHash = crypto.createHash('md5').update(JSON.stringify(fixtures)).digest('hex');
// by default the database version is null
should.not.exist(defaultSettings.core.databaseVersion.defaultValue);
schemaHash.should.eql(currentSchemaHash);
fixturesHash.should.eql(currentFixturesHash);
schema.versioning.canMigrateFromVersion.should.eql('1.0');
});
});

View File

@ -1,189 +0,0 @@
var should = require('should'),
sinon = require('sinon'),
Promise = require('bluebird'),
// Stuff we are testing
versioning = require('../../server/data/schema').versioning,
db = require('../../server/data/db'),
errors = require('../../server/errors'),
sandbox = sinon.sandbox.create();
describe('Versioning', function () {
afterEach(function () {
sandbox.restore();
});
describe('getNewestDatabaseVersion', function () {
it('should return the correct version', function () {
var currentVersion = '1.0';
// This function has an internal cache, so we call it twice.
// First, to check that it fetches the correct version from default-settings.json.
versioning.getNewestDatabaseVersion().should.eql(currentVersion);
// Second, to check that it returns the same value from the cache.
versioning.getNewestDatabaseVersion().should.eql(currentVersion);
});
});
describe('getDatabaseVersion', function () {
var knexStub, knexMock, queryMock;
beforeEach(function () {
queryMock = {
where: sandbox.stub().returnsThis(),
first: sandbox.stub()
};
knexMock = sandbox.stub().returns(queryMock);
knexMock.schema = {
hasTable: sandbox.stub()
};
// this MUST use sinon, not sandbox, see sinonjs/sinon#781
knexStub = sinon.stub(db, 'knex', {
get: function () {
return knexMock;
}
});
});
afterEach(function () {
knexStub.restore();
});
it('should throw error if settings table does not exist', function (done) {
// Setup
knexMock.schema.hasTable.returns(new Promise.resolve(false));
// Execute
versioning.getDatabaseVersion().then(function () {
done('Should throw an error if the settings table does not exist');
}).catch(function (err) {
should.exist(err);
(err instanceof errors.DatabaseVersionError).should.eql(true);
knexStub.get.calledOnce.should.be.true();
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('settings').should.be.true();
queryMock.where.called.should.be.false();
queryMock.first.called.should.be.false();
done();
}).catch(done);
});
it('should lookup & return version, if settings table exists', function (done) {
// Setup
knexMock.schema.hasTable.returns(new Promise.resolve(true));
queryMock.first.returns(new Promise.resolve({value: '1.0'}));
// Execute
versioning.getDatabaseVersion().then(function (version) {
should.exist(version);
version.should.eql('1.0');
knexStub.get.calledTwice.should.be.true();
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('settings').should.be.true();
queryMock.where.called.should.be.true();
queryMock.first.called.should.be.true();
done();
}).catch(done);
});
it('should throw error if version does not exist', function (done) {
// Setup
knexMock.schema.hasTable.returns(new Promise.resolve(true));
queryMock.first.returns(new Promise.resolve());
// Execute
versioning.getDatabaseVersion().then(function () {
done('Should throw an error if version does not exist');
}).catch(function (err) {
should.exist(err);
(err instanceof errors.DatabaseVersionError).should.eql(true);
err.code.should.eql('VERSION_DOES_NOT_EXIST');
knexStub.get.calledTwice.should.be.true();
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('settings').should.be.true();
queryMock.where.called.should.be.true();
queryMock.first.called.should.be.true();
done();
}).catch(done);
});
it('should throw error if version is not a number', function (done) {
// Setup
knexMock.schema.hasTable.returns(new Promise.resolve(true));
queryMock.first.returns(new Promise.resolve({value: 'Eyjafjallajökull'}));
// Execute
versioning.getDatabaseVersion().then(function () {
done('Should throw an error if version is not a number');
}).catch(function (err) {
should.exist(err);
(err instanceof errors.DatabaseVersionError).should.eql(true);
knexStub.get.calledTwice.should.be.true();
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('settings').should.be.true();
queryMock.where.called.should.be.true();
queryMock.first.called.should.be.true();
done();
}).catch(done);
});
it('database does exist: expect alpha error', function (done) {
knexMock.schema.hasTable.returns(new Promise.resolve(true));
queryMock.first.returns(new Promise.resolve({value: '008'}));
versioning.getDatabaseVersion()
.then(function () {
done('Should throw an error if version is not a number');
})
.catch(function (err) {
(err instanceof errors.DatabaseVersionError).should.eql(true);
err.message.should.eql('Your database version is not compatible with Ghost 1.0.0 Alpha (master branch)');
done();
});
});
});
describe('setDatabaseVersion', function () {
var knexStub, knexMock, queryMock;
beforeEach(function () {
queryMock = {
where: sandbox.stub().returnsThis(),
update: sandbox.stub().returns(new Promise.resolve())
};
knexMock = sandbox.stub().returns(queryMock);
// this MUST use sinon, not sandbox, see sinonjs/sinon#781
knexStub = sinon.stub(db, 'knex', {
get: function () {
return knexMock;
}
});
});
afterEach(function () {
knexStub.restore();
});
it('should try to update the databaseVersion', function (done) {
versioning.setDatabaseVersion().then(function () {
knexStub.get.calledOnce.should.be.true();
queryMock.where.called.should.be.true();
queryMock.update.called.should.be.true();
done();
}).catch(done);
});
});
});

View File

@ -119,17 +119,6 @@
}
],
"settings": [
{
"id": 1,
"uuid": "f90aa810-4fa2-49fe-a39b-7c0d2ebb473e",
"key": "databaseVersion",
"value": "000",
"type": "core",
"created_at": 1388318310829,
"created_by": 1,
"updated_at": 1388318310829,
"updated_by": 1
},
{
"id": 3,
"uuid": "c356fbde-0bc5-4fe1-9309-2510291aa34d",

View File

@ -149,17 +149,6 @@
}
],
"settings": [
{
"id": 1,
"uuid": "f90aa810-4fa2-49fe-a39b-7c0d2ebb473e",
"key": "databaseVersion",
"value": "001",
"type": "core",
"created_at": 1388318310829,
"created_by": 1,
"updated_at": 1388318310829,
"updated_by": 1
},
{
"id": 2,
"uuid": "95ce1c53-69b0-4f5f-be91-d3aeb39046b5",
@ -328,4 +317,4 @@
}
]
}
}
}

View File

@ -149,17 +149,6 @@
}
],
"settings": [
{
"id": 1,
"uuid": "f90aa810-4fa2-49fe-a39b-7c0d2ebb473e",
"key": "databaseVersion",
"value": "001",
"type": "core",
"created_at": 1388318310829,
"created_by": 1,
"updated_at": 1388318310829,
"updated_by": 1
},
{
"id": 2,
"uuid": "95ce1c53-69b0-4f5f-be91-d3aeb39046b5",
@ -328,4 +317,4 @@
}
]
}
}
}

View File

@ -171,17 +171,6 @@
}
],
"settings": [
{
"id": 1,
"uuid": "f90aa810-4fa2-49fe-a39b-7c0d2ebb473e",
"key": "databaseVersion",
"value": "001",
"type": "core",
"created_at": 1388318310829,
"created_by": 1,
"updated_at": 1388318310829,
"updated_by": 1
},
{
"id": 2,
"uuid": "95ce1c53-69b0-4f5f-be91-d3aeb39046b5",
@ -388,4 +377,4 @@
}
]
}
}
}

View File

@ -149,17 +149,6 @@
}
],
"settings": [
{
"id": 1,
"uuid": "f90aa810-4fa2-49fe-a39b-7c0d2ebb473e",
"key": "databaseVersion",
"value": "001",
"type": "core",
"created_at": 1388318310829,
"created_by": 1,
"updated_at": 1388318310829,
"updated_by": 1
},
{
"id": 2,
"uuid": "95ce1c53-69b0-4f5f-be91-d3aeb39046b5",

View File

@ -157,17 +157,6 @@
}
],
"settings": [
{
"id": 1,
"uuid": "f90aa810-4fa2-49fe-a39b-7c0d2ebb473e",
"key": "databaseVersion",
"value": "001",
"type": "core",
"created_at": 1388318310829,
"created_by": 1,
"updated_at": 1388318310829,
"updated_by": 1
},
{
"id": 2,
"uuid": "95ce1c53-69b0-4f5f-be91-d3aeb39046b5",

View File

@ -235,17 +235,6 @@
}
],
"settings": [
{
"id": 1,
"uuid": "f90aa810-4fa2-49fe-a39b-7c0d2ebb473e",
"key": "databaseVersion",
"value": "001",
"type": "core",
"created_at": 1388318310829,
"created_by": 1,
"updated_at": 1388318310829,
"updated_by": 1
},
{
"id": 2,
"uuid": "95ce1c53-69b0-4f5f-be91-d3aeb39046b5",
@ -477,4 +466,4 @@
}
]
}
}
}

View File

@ -149,17 +149,6 @@
}
],
"settings": [
{
"id": 1,
"uuid": "f90aa810-4fa2-49fe-a39b-7c0d2ebb473e",
"key": "databaseVersion",
"value": "001",
"type": "core",
"created_at": 1388318310829,
"created_by": 1,
"updated_at": 1388318310829,
"updated_by": 1
},
{
"id": 2,
"uuid": "95ce1c53-69b0-4f5f-be91-d3aeb39046b5",
@ -366,4 +355,4 @@
}
]
}
}
}

View File

@ -22,15 +22,15 @@ ghost().then(function (ghostServer) {
process.send({started: true});
}
});
}).catch(function (error) {
if (!(error instanceof errors.IgnitionError)) {
error = new errors.GhostError({err: error});
}).catch(function (err) {
if (!errors.utils.isIgnitionError(err)) {
err = new errors.GhostError({err: err});
}
if (process.send) {
process.send({started: false, error: error.message});
process.send({started: false, error: err.message});
}
logging.error(error);
logging.error(err);
process.exit(-1);
});