Skip to content

Commit

Permalink
feat(check): add check functionality to determine migrations to run
Browse files Browse the repository at this point in the history
Signed-off-by: RandomSeeded <nate@blend.com>
  • Loading branch information
RandomSeeded committed Apr 10, 2018
1 parent 03659d9 commit 56acdb9
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 3 deletions.
25 changes: 25 additions & 0 deletions api.js
Expand Up @@ -227,6 +227,31 @@ dbmigrate.prototype = {
).asCallback(callback);
},

check: function (specification, opts, callback) {
var executeCheck = load('check');

if (arguments.length > 0) {
if (typeof specification === 'number') {
this.internals.argv.count = arguments[0];
} else if (typeof specification === 'function') {
callback = specification;
}

if (typeof opts === 'string') {
this.internals.migrationMode = opts;
this.internals.matching = opts;
} else if (typeof opts === 'function') {
callback = opts;
}
}

return Promise.fromCallback(
function (callback) {
executeCheck(this.internals, this.config, callback);
}.bind(this)
).asCallback(callback);
},

/**
* Executes up a given number of migrations or a specific one.
*
Expand Down
37 changes: 37 additions & 0 deletions lib/commands/check.js
@@ -0,0 +1,37 @@
var path = require('path');
var log = require('db-migrate-shared').log;
var assert = require('./helper/assert.js');
var migrationHook = require('./helper/migration-hook.js');

module.exports = function (internals, config, callback) {
migrationHook(internals)
.then(function () {
var Migrator = require('../migrator.js');
var index = require('../../connect');

if (!internals.argv.count) {
internals.argv.count = Number.MAX_VALUE;
}
index.connect({
config: config.getCurrent().settings,
internals: internals
}, Migrator, function (err, migrator) {
if (!assert(err, callback)) return;

if (internals.locTitle) {
migrator.migrationsDir = path.resolve(internals.argv['migrations-dir'],
internals.locTitle);
} else { migrator.migrationsDir = path.resolve(internals.argv['migrations-dir']); }

internals.migrationsDir = migrator.migrationsDir;

migrator.driver.createMigrationsTable(function (err) {
if (!assert(err, callback)) return;
log.verbose('migration table created');

migrator.check(internals.argv, internals.onComplete.bind(this,
migrator, internals, callback));
});
});
});
};
8 changes: 6 additions & 2 deletions lib/commands/run.js
Expand Up @@ -42,6 +42,7 @@ function run (internals, config) {
break;
case 'up':
case 'down':
case 'check':
case 'reset':
if (action === 'reset') internals.argv.count = Number.MAX_VALUE;

Expand All @@ -62,9 +63,12 @@ function run (internals, config) {
if (action === 'up') {
var executeUp = load('up');
executeUp(internals, config);
} else {
} else if (action === 'down') {
var executeDown = load('down');
executeDown(internals, config);
} else {
var executeCheck = load('check');
executeCheck(internals, config);
}
break;

Expand Down Expand Up @@ -104,7 +108,7 @@ function run (internals, config) {
);
} else {
log.error(
'Invalid Action: Must be [up|down|create|reset|sync|' +
'Invalid Action: Must be [up|down|check|create|reset|sync|' +
'db|transition].'
);
optimist.showHelp();
Expand Down
8 changes: 7 additions & 1 deletion lib/commands/set-default-argv.js
Expand Up @@ -22,7 +22,7 @@ module.exports = function (internals, isModule) {
internals.argv = optimist
.default(defaultConfig)
.usage(
'Usage: db-migrate [up|down|reset|sync|create|db|transition] ' +
'Usage: db-migrate [up|down|check|reset|sync|create|db|transition] ' +
'[[dbname/]migrationName|all] [options]'
)
.describe(
Expand All @@ -42,6 +42,8 @@ module.exports = function (internals, isModule) {
.string('c')
.describe('dry-run', "Prints the SQL but doesn't run it.")
.boolean('dry-run')
.describe('check', 'Prints the migrations to be run without running them.')
.boolean('check')
.describe(
'force-exit',
'Forcibly exit the migration process on completion.'
Expand Down Expand Up @@ -145,8 +147,12 @@ module.exports = function (internals, isModule) {
internals.notransactions = internals.argv['non-transactional'];
internals.dryRun = internals.argv['dry-run'];
global.dryRun = internals.dryRun;
internals.check = internals.argv['check'];

if (internals.dryRun) {
log.info('dry run');
}
if (internals.check) {
log.info('check');
}
};
48 changes: 48 additions & 0 deletions lib/migrator.js
Expand Up @@ -119,6 +119,40 @@ Migrator.prototype = {
}
},

check: function (funcOrOpts, callback) {
var self = this;
Migration.loadFromFilesystem(self.migrationsDir, self.internals, function (
err,
allMigrations
) {
if (err) {
callback(err);
return;
}

Migration.loadFromDatabase(
self.migrationsDir,
self._driver,
self.internals,
function (err, completedMigrations) {
if (err) {
callback(err);
return;
}

// Requires pr to export filterCompleted from db-migrate-shared
var toRun = dbmUtil.filterCompleted(
allMigrations,
completedMigrations
);

log.info('Migrations to run:', toRun.map(migration => migration.name));
callback(null, toRun);
}
);
});
},

sync: function (funcOrOpts, callback) {
var self = this;

Expand Down Expand Up @@ -180,6 +214,13 @@ Migrator.prototype = {
return;
}

if (self.internals.check) {
var toRunNames = toRun.map(migration => migration.name);
log.info('Migrations to run:', toRunNames);
callback(null, toRunNames);
return;
}

return Promise.resolve(toRun)
.each(function (migration) {
log.verbose('preparing to run up migration:', migration.name);
Expand Down Expand Up @@ -234,6 +275,13 @@ Migrator.prototype = {
return;
}

if (self.internals.check) {
var toRunNames = toRun.map(migration => migration.name);
log.info('Migrations to run:', toRunNames);
callback(null, toRunNames);
return;
}

return Promise.resolve(toRun)
.each(function (migration) {
log.verbose('preparing to run down migration:', migration.name);
Expand Down
17 changes: 17 additions & 0 deletions test/integration/api_test.js
Expand Up @@ -168,6 +168,23 @@ lab.experiment('api', function () {
}
);

lab.test(
'should handle all check parameter variations properly',

function () {
return Promise.resolve([
[], // promise
[sinon.spy()],
[1, sinon.spy()], // targeted migration
[1], // promise targeted migration
[1, 'testscope', sinon.spy()], // scoped target
[1, 'testscope'] // promise scope target
])
.each(defaultExecParams('check'))
.each(spyCallback);
}
);

lab.test(
'should handle all reset parameter variations properly',

Expand Down
32 changes: 32 additions & 0 deletions test/migrator_test.js
@@ -0,0 +1,32 @@
var Code = require('code');
var Lab = require('lab');
var proxyquire = require('proxyquire').noPreserveCache();
var lab = (exports.lab = Lab.script());

lab.experiment('migrators', function () {
lab.experiment('check', function () {
lab.test('should return the migrations to be run', function (done) {
var completedMigration = {
name: '20180330020329-thisMigrationIsCompleted'
};
var uncompletedMigration = {
name: '20180330020330-thisMigrationIsNotCompleted'
};
var Migrator = proxyquire('../lib/migrator.js', {
'./migration': {
loadFromFilesystem: (migrationsDir, internals, cb) => {
return cb(null, [completedMigration, uncompletedMigration]);
},
loadFromDatabase: (migrationsDir, driver, internals, cb) => {
return cb(null, [completedMigration]);
}
}
});
Migrator.prototype.check(null, function (err, res) {
Code.expect(res.length).to.equal(1);
Code.expect(res[0].name).to.equal(uncompletedMigration.name);
done(err, res);
});
});
});
});

0 comments on commit 56acdb9

Please sign in to comment.