Skip to content

Commit 931a5e5

Browse files
committed
Add setup hook and sanityCheck. cf. #1
1 parent d6c7cd0 commit 931a5e5

File tree

6 files changed

+138
-75
lines changed

6 files changed

+138
-75
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ refer to the [Plugin Documentation][2].
118118
* `didDeploy`
119119
* `fetchInitialRevisions`
120120
* `fetchRevisions`
121+
* `setup`
121122
* `upload`
122123
* `willActivate`
123124
@@ -152,7 +153,7 @@ A file matching this pattern will be uploaded to the database table.
152153
153154
The name of the database table in which to store the revision keys and file
154155
contents. By default this option will use the `project.name()` property from
155-
the deployment context.
156+
the deployment context, snake-cased and suffixed with `_bootstrap`.
156157
157158
The table is created in your database automatically on the initial deploy, so
158159
your database user will need `CREATE TABLE` privileges—at least
@@ -171,7 +172,7 @@ The table looks something like this (e.g. in MySQL):
171172
| is_active | tinyint(1) | NO | | 0 | |
172173
| created_at | timestamp | NO | | CURRENT_TIMESTAMP | |
173174
174-
*Default:* `${projectNameSnakeCased}_bootstrap`
175+
*Default:* `${projectName}_bootstrap`
175176
176177
### allowOverwrite
177178

index.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,15 @@ const DeployPlugin = DeployPluginBase.extend({
9999
//
100100
// Pipeline hooks
101101
//
102+
setup() {
103+
const
104+
deployClient = this.readConfig('deployClient'),
105+
tableName = this.readConfig('tableName');
106+
107+
return deployClient.sanityCheck({ tableName })
108+
.catch(errorMessage.bind(this));
109+
},
110+
102111
fetchInitialRevisions() {
103112
const
104113
deployClient = this.readConfig('deployClient'),

lib/deploy-client.js

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,6 @@ const
99
//
1010
// Private functions
1111
//
12-
function conditionallyCreateTable(tableName) {
13-
return this.knex.schema.hasTable(tableName)
14-
.then(exists => {
15-
if (!exists) {
16-
return createTable.call(this, tableName);
17-
}
18-
});
19-
}
20-
2112
function createTable(tableName) {
2213
return this.knex.schema.createTable(tableName, tbl => {
2314
tbl.increments();
@@ -142,6 +133,18 @@ module.exports = CoreObject.extend({
142133
this.knex.destroy();
143134
},
144135

136+
sanityCheck(args) {
137+
// TODO: replace let with destructured args
138+
let tableName = args.tableName;
139+
140+
return this.knex.schema.hasTable(tableName)
141+
.then(exists => {
142+
if (!exists) {
143+
return createTable.call(this, tableName);
144+
}
145+
});
146+
},
147+
145148
upload(args) {
146149
// TODO: replace lets with destructured args
147150
let
@@ -151,8 +154,7 @@ module.exports = CoreObject.extend({
151154

152155
revisionKey = revisionKey || 'default';
153156

154-
return conditionallyCreateTable.call(this, tableName)
155-
.then(() => conditionallyCreateRevision.call(this, tableName, revisionKey, value))
157+
return conditionallyCreateRevision.call(this, tableName, revisionKey, value)
156158
.then(() => listRevisions.call(this, tableName))
157159
.then(trimRevisions.bind(this, tableName))
158160
.then(() => ({ tableName, revisionKey }));

tests/unit/deploy-client-test.js

Lines changed: 53 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -6,59 +6,26 @@ const assert = require('../helpers/assert');
66
const rewire = require('rewire');
77
const subject = rewire('../../lib/deploy-client');
88

9-
describe('DeployClient private "constructor" method', function() {
9+
describe('DeployClient private methods', function() {
10+
const rewire = require('rewire');
11+
const subject = rewire('../../lib/deploy-client');
12+
1013
const knex = require('knex')({
1114
client: 'sqlite3',
1215
connection: { filename: ':memory:' },
1316
useNullAsDefault: true,
1417
//debug: true
1518
});
1619

20+
beforeEach(subject.__get__('createTable').bind({ knex }, 'test'));
21+
afterEach(() => knex.schema.dropTable('test'));
22+
1723
// Tear down the connection pool after all the tests have completed.
1824
after(() => knex.destroy());
1925

20-
describe('#conditionallyCreateTable()', function() {
21-
const conditionallyCreateTable = subject.__get__('conditionallyCreateTable');
22-
23-
it('creates a table if none exists', function() {
24-
return conditionallyCreateTable.call({ knex }, 'foo')
25-
.then(() => knex('foo').columnInfo())
26-
.then(info => {
27-
assert.isObject(info);
28-
29-
assert.deepPropertyVal(info, 'id.type', 'integer');
30-
assert.deepPropertyVal(info, 'key.type', 'varchar');
31-
assert.deepPropertyVal(info, 'value.type', 'text');
32-
assert.deepPropertyVal(info, 'is_active.type', 'boolean');
33-
assert.deepPropertyVal(info, 'created_at.type', 'datetime');
34-
})
35-
.finally(() => knex.schema.dropTable('foo'));
36-
});
37-
38-
it('does not create a table if one exists', function() {
39-
return knex.schema.createTable('bar', tbl => {
40-
tbl.increments();
41-
tbl.string('key').notNullable().unique();
42-
tbl.timestamps();
43-
}).then(() => conditionallyCreateTable.call({ knex }, 'bar'))
44-
.then(() => knex('bar').columnInfo())
45-
.then(info => {
46-
assert.isObject(info);
47-
48-
assert.deepPropertyVal(info, 'id.type', 'integer');
49-
assert.deepPropertyVal(info, 'key.type', 'varchar');
50-
assert.deepPropertyVal(info, 'created_at.type', 'datetime');
51-
assert.deepPropertyVal(info, 'updated_at.type', 'datetime');
52-
53-
assert.notProperty(info, 'value');
54-
assert.notProperty(info, 'is_active');
55-
})
56-
.finally(() => knex.schema.dropTable('bar'));
57-
});
58-
26+
describe('#createTable()', function() {
5927
it('sets appropriate column defaults', function() {
60-
return conditionallyCreateTable.call({ knex }, 'test')
61-
.then(() => knex('test').insert({ key: 'foo', value: 'bar' }))
28+
return knex('test').insert({ key: 'foo', value: 'bar' })
6229
.then(() => knex('test').first())
6330
.then(row => {
6431
assert.isObject(row);
@@ -76,24 +43,6 @@ describe('DeployClient private "constructor" method', function() {
7643
});
7744
});
7845
});
79-
});
80-
81-
describe('DeployClient private methods', function() {
82-
const rewire = require('rewire');
83-
const subject = rewire('../../lib/deploy-client');
84-
85-
const knex = require('knex')({
86-
client: 'sqlite3',
87-
connection: { filename: ':memory:' },
88-
useNullAsDefault: true,
89-
//debug: true
90-
});
91-
92-
beforeEach(subject.__get__('createTable').bind({ knex }, 'test'));
93-
afterEach(() => knex.schema.dropTable('test'));
94-
95-
// Tear down the connection pool after all the tests have completed.
96-
after(() => knex.destroy());
9746

9847
describe('#conditionallyCreateRevision()', function() {
9948
const createRevision = subject.__get__('conditionallyCreateRevision');
@@ -384,6 +333,46 @@ describe('DeployClient public API', function() {
384333
}
385334
});
386335

336+
describe('#sanityCheck()', function() {
337+
it('creates a table if none exists', function() {
338+
deployClient = new subject(baseOptions);
339+
340+
return deployClient.sanityCheck({ tableName: 'foo' })
341+
.then(() => deployClient.knex('foo').columnInfo())
342+
.then(info => {
343+
assert.isObject(info);
344+
345+
assert.deepPropertyVal(info, 'id.type', 'integer');
346+
assert.deepPropertyVal(info, 'key.type', 'varchar');
347+
assert.deepPropertyVal(info, 'value.type', 'text');
348+
assert.deepPropertyVal(info, 'is_active.type', 'boolean');
349+
assert.deepPropertyVal(info, 'created_at.type', 'datetime');
350+
});
351+
});
352+
353+
it('does not create a table if one exists', function() {
354+
deployClient = new subject(baseOptions);
355+
356+
return deployClient.knex.schema.createTable('bar', tbl => {
357+
tbl.increments();
358+
tbl.string('key').notNullable().unique();
359+
tbl.timestamps();
360+
}).then(() => deployClient.sanityCheck({ tableName: 'bar' }))
361+
.then(() => deployClient.knex('bar').columnInfo())
362+
.then(info => {
363+
assert.isObject(info);
364+
365+
assert.deepPropertyVal(info, 'id.type', 'integer');
366+
assert.deepPropertyVal(info, 'key.type', 'varchar');
367+
assert.deepPropertyVal(info, 'created_at.type', 'datetime');
368+
assert.deepPropertyVal(info, 'updated_at.type', 'datetime');
369+
370+
assert.notProperty(info, 'value');
371+
assert.notProperty(info, 'is_active');
372+
});
373+
});
374+
});
375+
387376
describe('#fetchRevisions()', function() {
388377
it('returns successfully', function() {
389378
deployClient = new subject(baseOptions);
@@ -456,7 +445,8 @@ describe('DeployClient public API', function() {
456445
it('uploads a new revision with a payload', function() {
457446
deployClient = new subject(baseOptions);
458447

459-
return deployClient.upload({ tableName: 'foo', value: 'bar' })
448+
return deployClient.sanityCheck({ tableName: 'foo' })
449+
.then(() => deployClient.upload({ tableName: 'foo', value: 'bar' }))
460450
.then(() => deployClient.knex('foo').select('key', 'value'))
461451
.then(revisions => {
462452
assert.isArray(revisions);
@@ -473,7 +463,8 @@ describe('DeployClient public API', function() {
473463
it('returns the table name and revision key', function() {
474464
deployClient = new subject(baseOptions);
475465

476-
return deployClient.upload({ tableName: 'foo', value: 'bar' })
466+
return deployClient.sanityCheck({ tableName: 'foo' })
467+
.then(() => deployClient.upload({ tableName: 'foo', value: 'bar' }))
477468
.then(result => {
478469
assert.propertyVal(result, 'tableName', 'foo');
479470
assert.propertyVal(result, 'revisionKey', 'default');

tests/unit/deploy-plugin-test.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ describe('DeployPlugin', function() {
2121
assert.isDefined(plugin.configure);
2222
assert.isFunction(plugin.configure);
2323

24+
assert.isDefined(plugin.setup);
25+
assert.isFunction(plugin.setup);
26+
2427
assert.isDefined(plugin.fetchInitialRevisions);
2528
assert.isFunction(plugin.fetchInitialRevisions);
2629

tests/unit/setup-hook-test.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*global Promise*/
2+
/*eslint-env node*/
3+
'use strict';
4+
5+
const subject = require('../../index');
6+
const assert = require('../helpers/assert');
7+
8+
describe('DeployPlugin | setup hook', function() {
9+
const mockUi = {
10+
verbose: true,
11+
messages: [],
12+
write: function() {},
13+
writeLine: function(message) {
14+
this.messages.push(message);
15+
}
16+
};
17+
18+
let sanityCheckCalled;
19+
20+
const mockClient = () => ({
21+
sanityCheck(args) {
22+
// TODO: replace let with destructured args
23+
let tableName = args.tableName;
24+
25+
sanityCheckCalled = true;
26+
27+
return Promise.resolve(tableName);
28+
}
29+
});
30+
31+
it('calls sanityCheck', function() {
32+
const instance = subject.createDeployPlugin({
33+
name: 'sql'
34+
});
35+
36+
const context = {
37+
ui: mockUi,
38+
distDir: 'tests',
39+
config: {
40+
sql: {
41+
client: 'mock',
42+
deployClient: mockClient,
43+
tableName: 'foo'
44+
}
45+
}
46+
};
47+
48+
instance.beforeHook(context);
49+
instance.configure(context);
50+
51+
return instance.setup(context)
52+
.then(result => {
53+
assert.ok(sanityCheckCalled);
54+
assert.equal(result, 'foo');
55+
});
56+
});
57+
});

0 commit comments

Comments
 (0)