-
-
Notifications
You must be signed in to change notification settings - Fork 227
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(v2): added v2 migrate task (#771)
refs #759 - executed new task if you are migrating from v1 to v2 - do not execute the new task if you are migrating from v1 to v1 - do not execute the new task if you are already on v2 - this task will: - scan your theme with GScan 2.0 - load the demo post from your database - show a nice UI and prompts - added unit tests
- Loading branch information
Showing
10 changed files
with
663 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
'use strict'; | ||
|
||
module.exports = function getData(options = {}) { | ||
const path = require('path'); | ||
const errors = require('../../errors'); | ||
|
||
if (!options.dir) { | ||
return Promise.reject(new errors.CliError({ | ||
message: '`dir` is required.' | ||
})) | ||
} | ||
|
||
if (!options.database) { | ||
return Promise.reject(new errors.CliError({ | ||
message: '`database` is required.' | ||
})) | ||
} | ||
|
||
const knexPath = path.resolve(options.dir, options.version, 'node_modules', 'knex'); | ||
const gscanPath = path.resolve(options.dir, options.version, 'node_modules', 'gscan'); | ||
|
||
const knex = require(knexPath); | ||
const gscan = require(gscanPath); | ||
|
||
const connection = knex(Object.assign({useNullAsDefault: true}, options.database)); | ||
|
||
const themeFolder = path.resolve(options.dir, 'content', 'themes'); | ||
let gscanReport; | ||
|
||
return connection.raw('SELECT * FROM settings WHERE `key`="active_theme";') | ||
.then((response) => { | ||
let activeTheme; | ||
|
||
if (options.database.client === 'mysql') { | ||
activeTheme = response[0][0].value; | ||
} else { | ||
activeTheme = response[0].value; | ||
} | ||
|
||
return gscan.check(path.resolve(themeFolder, activeTheme)); | ||
}) | ||
.then((report) => { | ||
gscanReport = gscan.format(report, {sortByFiles: true}); | ||
|
||
return connection.raw('SELECT uuid FROM posts WHERE slug="v2-demo-post";') | ||
}) | ||
.then((response) => { | ||
let demoPost; | ||
|
||
if (options.database.client === 'mysql') { | ||
demoPost = response[0][0]; | ||
} else { | ||
demoPost = response[0]; | ||
} | ||
|
||
return { | ||
gscanReport: gscanReport, | ||
demoPost: demoPost | ||
}; | ||
}) | ||
.then((response) => { | ||
return new Promise((resolve) => { | ||
connection.destroy(() => { | ||
resolve(response); | ||
}); | ||
}); | ||
}) | ||
.catch((err) => { | ||
return new Promise((resolve, reject) => { | ||
connection.destroy(() => { | ||
reject(err); | ||
}); | ||
}); | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
'use strict'; | ||
module.exports = require('./ui'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
'use strict'; | ||
|
||
module.exports = function ui(ctx) { | ||
const chalk = require('chalk'); | ||
const logSymbols = require('log-symbols'); | ||
const each = require('lodash/each'); | ||
const errors = require('../../errors'); | ||
const getData = require('./data'); | ||
let gscanReport; | ||
let demoPost; | ||
|
||
return getData({ | ||
dir: ctx.instance.dir, | ||
database: ctx.instance.config.get('database'), | ||
version: `versions/${ctx.version}` | ||
}).then((response) => { | ||
gscanReport = response.gscanReport; | ||
demoPost = response.demoPost; | ||
|
||
ctx.ui.log(chalk.bold.underline.white(`\n\nChecking theme compatibility for Ghost ${ctx.version}\n`)); | ||
if (!gscanReport.results.error.all.length && !gscanReport.results.warning.all.length) { | ||
ctx.ui.log(`${logSymbols.success} Your theme is compatible.\n`); | ||
|
||
if (demoPost && demoPost.uuid) { | ||
const demoLink = `${ctx.instance.config.get('url')}p/${demoPost.uuid}/`; | ||
ctx.ui.log(`Visit the demo post at ${chalk.cyan(demoLink)} to see how your theme looks like in Ghost 2.0`); | ||
} | ||
|
||
ctx.ui.log(`You can also check theme compatibility at ${chalk.cyan('https://gscan.ghost.org')}\n`); | ||
} else { | ||
let message = ''; | ||
|
||
if (gscanReport.results.warning.all.length && !gscanReport.results.error.all.length) { | ||
message += `${chalk.yellow('⚠')} Your theme has `; | ||
|
||
let text = 'warning'; | ||
|
||
if (gscanReport.results.warning.all.length > 1) { | ||
text = 'warnings'; | ||
} | ||
|
||
message += chalk.bold.yellow(`${gscanReport.results.warning.all.length} ${text}`); | ||
} else if (!gscanReport.results.warning.all.length && gscanReport.results.error.all.length) { | ||
message += `${chalk.red('⚠')} Your theme has `; | ||
|
||
let text = 'error'; | ||
|
||
if (gscanReport.results.error.all.length > 1) { | ||
text = 'errors'; | ||
} | ||
|
||
message += chalk.bold.red(`${gscanReport.results.error.all.length} ${text}`); | ||
} else if (gscanReport.results.warning.all.length && gscanReport.results.error.all.length) { | ||
message += `${chalk.red('⚠')} Your theme has `; | ||
|
||
let text1 = 'error'; | ||
let text2 = 'warning'; | ||
|
||
if (gscanReport.results.error.all.length > 1) { | ||
text1 = 'errors'; | ||
} | ||
|
||
if (gscanReport.results.warning.all.length > 1) { | ||
text2 = 'warnings'; | ||
} | ||
|
||
message += chalk.bold.red(`${gscanReport.results.error.all.length} ${text1}`); | ||
message += ' and '; | ||
message += chalk.bold.yellow(`${gscanReport.results.warning.all.length} ${text2}`); | ||
} | ||
|
||
message += '\n'; | ||
ctx.ui.log(message); | ||
|
||
return ctx.ui.confirm('View error and warning details?', null, {prefix: chalk.cyan('?')}); | ||
} | ||
}).then((answer) => { | ||
if (answer) { | ||
const spaces = ' '; | ||
|
||
if (gscanReport.results.error.all.length) { | ||
ctx.ui.log(chalk.bold.red('\nErrors')); | ||
|
||
each(gscanReport.results.error.byFiles, (errors, fileName) => { | ||
if (!errors.length) { | ||
return; | ||
} | ||
|
||
let message = chalk.bold.white(`${spaces}File: `); | ||
message += chalk.white(`${fileName}`); | ||
message += '\n'; | ||
|
||
errors.forEach((error, index) => { | ||
if (error.fatal) { | ||
message += `${spaces}- ${chalk.bold.red('Fatal error:')} ${error.rule.replace(/(<([^>]+)>)/ig, '')}`; | ||
} else { | ||
message += `${spaces}- ${error.rule.replace(/(<([^>]+)>)/ig, '')}`; | ||
} | ||
|
||
if (index < (errors.length - 1)) { | ||
message += '\n'; | ||
} | ||
}); | ||
|
||
message += '\n'; | ||
ctx.ui.log(message); | ||
}); | ||
} | ||
|
||
if (gscanReport.results.warning.all.length) { | ||
ctx.ui.log(chalk.bold.yellow('\nWarnings')); | ||
|
||
each(gscanReport.results.warning.byFiles, (warnings, fileName) => { | ||
if (!warnings.length) { | ||
return; | ||
} | ||
|
||
let message = chalk.bold.white(`${spaces}File: `); | ||
message += chalk.white(`${fileName}`); | ||
message += '\n'; | ||
|
||
warnings.forEach((warning, index) => { | ||
message += `${spaces}- ${warning.rule.replace(/(<([^>]+)>)/ig, '')}`; | ||
|
||
if (index < (warnings.length - 1)) { | ||
message += '\n'; | ||
} | ||
}); | ||
|
||
message += '\n'; | ||
ctx.ui.log(message); | ||
}); | ||
} | ||
|
||
if (demoPost && demoPost.uuid) { | ||
const demoLink = `${ctx.instance.config.get('url')}p/${demoPost.uuid}/`; | ||
ctx.ui.log(`Visit the demo post at ${chalk.cyan(demoLink)} to see how your theme looks like in Ghost 2.0`); | ||
} | ||
|
||
ctx.ui.log(`You can also check theme compatibility at ${chalk.cyan('https://gscan.ghost.org')}\n`); | ||
} | ||
|
||
if (gscanReport.results.hasFatalErrors) { | ||
return Promise.reject(new errors.CliError({ | ||
message: 'Migration failed. Your theme has fatal errors.\n For additional theme help visit https://themes.ghost.org/docs/changelog', | ||
logMessageOnly: true | ||
})); | ||
} | ||
|
||
return ctx.ui.confirm(`Are you sure you want to proceed with migrating to Ghost ${ctx.version}?`, null, {prefix: chalk.cyan('?')}) | ||
.then((answer) => { | ||
if (!answer) { | ||
return Promise.reject(new errors.CliError({ | ||
message: `Update aborted. Your blog is still on ${ctx.activeVersion}.`, | ||
logMessageOnly: true | ||
})); | ||
} | ||
}); | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.