Skip to content

Commit c1aa5e0

Browse files
committed
Added support for major blog update
refs #759 [ci skip]
1 parent 06bc19c commit c1aa5e0

File tree

3 files changed

+139
-3
lines changed

3 files changed

+139
-3
lines changed

lib/commands/update.js

+77-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22
const fs = require('fs-extra');
33
const path = require('path');
4+
const map = require('lodash/map');
45

56
// Utils
67
const errors = require('../errors');
@@ -60,6 +61,18 @@ class UpdateCommand extends Command {
6061

6162
// TODO: add meaningful update checks after this task
6263
const tasks = [{
64+
title: 'Updating to a major version',
65+
task: this.majorSupport.bind(this),
66+
// CASE: Skip if you are already on ^2 or you update from v1 to v1.
67+
enabled: () => {
68+
if (semver.satisfies(instance.cliConfig.get('active-version'), '^2.0.0') ||
69+
!semver.satisfies(context.version, '^2.0.0')) {
70+
return false;
71+
}
72+
73+
return true;
74+
}
75+
}, {
6376
title: 'Downloading and updating Ghost',
6477
skip: (ctx) => ctx.rollback,
6578
task: this.downloadAndUpdate
@@ -75,7 +88,7 @@ class UpdateCommand extends Command {
7588
skip: (ctx) => ctx.rollback,
7689
task: migrate,
7790
// CASE: We have moved the execution of knex-migrator into Ghost 2.0.0.
78-
// If you are already on ^2 or you update from ^1 to ^2, then skip the task.
91+
// If you are already on v2 or you update from v1 to v2, then skip the task.
7992
enabled: () => {
8093
if (semver.satisfies(instance.cliConfig.get('active-version'), '^2.0.0') ||
8194
semver.satisfies(context.version, '^2.0.0')) {
@@ -128,6 +141,69 @@ class UpdateCommand extends Command {
128141
return yarnInstall(ctx.ui, ctx.zip);
129142
}
130143

144+
majorSupport(ctx) {
145+
const majorSupport = require('../utils/major-support');
146+
let gscanReport;
147+
let demoPost;
148+
149+
return majorSupport({
150+
dir: ctx.instance.dir,
151+
database: ctx.instance.config.get('database')
152+
}).then((response) => {
153+
gscanReport = response.gscanReport;
154+
demoPost = response.demoPost;
155+
156+
this.ui.log(`\nYou are about to migrate to Ghost 2.0.0.`, 'green');
157+
158+
this.ui.log(`\n## Theme compatibility`, 'magenta', null, true);
159+
160+
if (!gscanReport.results.error.length && !gscanReport.results.warning.length) {
161+
this.ui.log('\nYour theme is compatible.\n')
162+
} else {
163+
this.ui.log(`\nYour theme has ${gscanReport.results.error.length} errors and ${gscanReport.results.warning.length} warnings.\n`);
164+
this.ui.log('We recommend visiting https://gscan.ghost.org to take a look at the full report.\n');
165+
return this.ui.confirm('Would you like to print the full report anyway?');
166+
}
167+
}).then((answer) => {
168+
if (answer) {
169+
if (gscanReport.results.error.length) {
170+
this.ui.log('\n### Errors\n', 'red');
171+
gscanReport.results.error.forEach((error) => {
172+
this.ui.log(`Rule: ${error.rule}`);
173+
this.ui.log(`File: ${map(error.failures, 'ref').join(',')}`);
174+
});
175+
this.ui.log('\n');
176+
}
177+
178+
if (gscanReport.results.warning.length) {
179+
this.ui.log('\n### Warnings\n', 'yellow');
180+
gscanReport.results.warning.forEach((warning) => {
181+
this.ui.log(`Rule: ${warning.rule}`);
182+
this.ui.log(`File: ${map(warning.failures, 'ref').join(',')}`);
183+
});
184+
this.ui.log('\n');
185+
}
186+
}
187+
188+
return this.ui.confirm('Would you like to look at the demo post?');
189+
}).then((answer) => {
190+
if (answer) {
191+
this.ui.log('\n');
192+
this.ui.log(`${ctx.instance.config.get('url')}p/${demoPost.uuid}/`);
193+
this.ui.log('\n');
194+
}
195+
196+
return this.ui.confirm('Continue with updating to the next major version?')
197+
.then((answer) => {
198+
if (!answer) {
199+
return Promise.reject(new errors.CliError({
200+
message: 'Update aborted. Nothing happens.'
201+
}));
202+
}
203+
});
204+
});
205+
}
206+
131207
stop() {
132208
const StopCommand = require('./stop');
133209

lib/ui/index.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,10 @@ class UI {
258258
* @method log
259259
* @public
260260
*/
261-
log(message, color, stderr) {
262-
if (color) {
261+
log(message, color, stderr, bold) {
262+
if (color && bold) {
263+
message = chalk[color].bold(message);
264+
} else if (color) {
263265
message = chalk[color](message);
264266
}
265267

lib/utils/major-support.js

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
const errors = require('../errors');
2+
3+
module.exports = function majorSupport(options = {}) {
4+
const path = require('path');
5+
6+
if (!options.dir) {
7+
return Promise.reject(new errors.CliError({
8+
message: '`dir` is required.'
9+
}))
10+
}
11+
12+
if (!options.database) {
13+
return Promise.reject(new errors.CliError({
14+
message: '`database` is required.'
15+
}))
16+
}
17+
18+
const knexPath = options.knexPath || path.resolve(options.dir, 'current/node_modules/knex');
19+
const gscanPath = options.gscanPath || path.resolve(options.dir, 'current/node_modules/gscan');
20+
21+
const knex = require(knexPath);
22+
const gscan = require(gscanPath);
23+
24+
const connection = knex(Object.assign({useNullAsDefault: true}, options.database));
25+
26+
const themeFolder = options.contentPath || path.resolve(options.dir, 'content', 'themes');
27+
let activeTheme;
28+
let gscanReport;
29+
30+
return connection.raw('SELECT * FROM settings WHERE `key`="active_theme";')
31+
.then((response) => {
32+
activeTheme = response[0].value;
33+
34+
return gscan.check(path.resolve(themeFolder, activeTheme));
35+
})
36+
.then((report) => {
37+
gscanReport = gscan.format(report);
38+
39+
return connection.raw('SELECT uuid FROM posts WHERE slug="v2-demo-post";')
40+
})
41+
.then((demoPost) => {
42+
if (demoPost.length) {
43+
demoPost = demoPost[0];
44+
}
45+
46+
return {
47+
gscanReport: gscanReport,
48+
demoPost: demoPost
49+
}
50+
})
51+
.finally(() => {
52+
return new Promise((resolve) => {
53+
connection.destroy(() => {
54+
resolve();
55+
});
56+
});
57+
});
58+
};

0 commit comments

Comments
 (0)