Skip to content

Commit 76829e9

Browse files
committed
fix(doctor): refactor doctor command
refs #47 - split doctor checks out into separate files - refactor doctor command to work on a "filtering" basis - refactor usage of doctor command in other commands - fix tests
1 parent b91fe09 commit 76829e9

23 files changed

+1321
-1175
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
'use strict';
2+
const fs = require('fs-extra');
3+
const Mode = require('stat-mode');
4+
const path = require('path');
5+
const isRoot = require('path-is-root');
6+
7+
const errors = require('../../../errors');
8+
9+
module.exports = function checkDirectoryAndAbove(dir, extra) {
10+
if (isRoot(dir)) {
11+
return Promise.resolve();
12+
}
13+
14+
return fs.lstat(dir).then((stats) => {
15+
const mode = new Mode(stats);
16+
17+
if (!mode.others.read) {
18+
return Promise.reject(new errors.SystemError(`The path ${dir} is not readable by other users on the system.
19+
This can cause issues with the CLI, please either make this directory readable by others or ${extra} in another location.`));
20+
}
21+
22+
return checkDirectoryAndAbove(path.join(dir, '../'), extra);
23+
});
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
'use strict';
2+
const fs = require('fs-extra');
3+
const constants = require('constants');
4+
5+
const errors = require('../../../errors');
6+
const checkDirectoryAndAbove = require('./check-directory');
7+
8+
function folderPermissions(ctx) {
9+
return fs.access(process.cwd(), constants.R_OK | constants.W_OK).catch(() => {
10+
return Promise.reject(new errors.SystemError(`The current directory is not writable.
11+
Please fix your directory permissions.`));
12+
}).then(() => {
13+
if (ctx.local || !ctx.system.platform.linux || (ctx.argv && ctx.argv['setup-linux-user'] === false)) {
14+
return Promise.resolve();
15+
}
16+
17+
return checkDirectoryAndAbove(process.cwd(), 'run `ghost install`');
18+
});
19+
}
20+
21+
module.exports = {
22+
title: 'Checking current folder permissions',
23+
task: folderPermissions,
24+
category: ['install']
25+
};

lib/commands/doctor/checks/index.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
'use strict';
2+
const nodeVersion = require('./node-version');
3+
const folderPermissions = require('./folder-permissions');
4+
const systemStack = require('./system-stack');
5+
const mysqlCheck = require('./mysql');
6+
const validateConfig = require('./validate-config');
7+
8+
module.exports = [
9+
nodeVersion,
10+
folderPermissions,
11+
systemStack,
12+
mysqlCheck,
13+
validateConfig
14+
];

lib/commands/doctor/checks/install.js

-167
This file was deleted.

lib/commands/doctor/checks/mysql.js

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
'use strict';
2+
const execa = require('execa');
3+
const chalk = require('chalk');
4+
const includes = require('lodash/includes');
5+
6+
const errors = require('../../../errors');
7+
8+
function mysqlCheck(ctx) {
9+
// On ubuntu, mysqld is in `/usr/sbin` but it's not automatically in the PATH of non-root users
10+
// So, we modify the path env var to make things work
11+
const options = ctx.system.platform.linux ? {env: {PATH: `/usr/sbin:${process.env.PATH}`}} : {};
12+
13+
// Technically this doesn't work on windows, but there's
14+
// not an easy way to do that anyways so ¯\_(ツ)_/¯
15+
return execa.shell('which mysqld', options).catch(() => {
16+
ctx.ui.log(`${chalk.yellow(`Local MySQL install not found. You can ignore this if you are using a remote MySQL host.
17+
Alternatively you could:`)}
18+
${chalk.blue('a)')} install MySQL locally
19+
${chalk.blue('b)')} run ${chalk.cyan('`ghost install --db=sqlite3`')} to use sqlite
20+
${chalk.blue('c)')} run ${chalk.cyan('`ghost install local`')} to get a development install using sqlite3.`);
21+
22+
const confirmPromise = ctx.ui.allowPrompt ?
23+
ctx.ui.confirm(chalk.blue('Continue anyway?'), false) :
24+
Promise.resolve({yes: false});
25+
26+
return confirmPromise.then(answer => answer.yes || Promise.reject(
27+
new errors.SystemError('MySQL check failed.')
28+
));
29+
});
30+
}
31+
32+
module.exports = {
33+
title: 'Checking for a MySQL installation',
34+
task: mysqlCheck,
35+
// Disable this check if:
36+
// a) local install OR
37+
// b) --db sqlite3 is passed OR
38+
// c) --dbhost is passed and IS NOT 'localhost' or '127.0.0.1'
39+
enabled: (ctx) => !ctx.local &&
40+
ctx.argv.db !== 'sqlite3' &&
41+
(!ctx.argv.dbhost || includes(['localhost', '127.0.0.1'], ctx.argv.dbhost)),
42+
category: ['install']
43+
};
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
'use strict';
2+
const chalk = require('chalk');
3+
const semver = require('semver');
4+
5+
const errors = require('../../../errors');
6+
const cliPackage = require('../../../../package');
7+
const checkDirectoryAndAbove = require('./check-directory');
8+
9+
function nodeVersion(ctx) {
10+
if (process.env.GHOST_NODE_VERSION_CHECK !== 'false' && !semver.satisfies(process.versions.node, cliPackage.engines.node)) {
11+
return Promise.reject(new errors.SystemError(`${chalk.red('The version of Node.js you are using is not supported.')}
12+
${chalk.gray('Supported: ')}${cliPackage.engines.node}
13+
${chalk.gray('Installed: ')}${process.versions.node}
14+
See ${chalk.underline.blue('https://docs.ghost.org/v1/docs/supported-node-versions')} for more information`));
15+
}
16+
17+
if (ctx.local || !ctx.system.platform.linux || (ctx.argv && ctx.argv['setup-linux-user'] === false)) {
18+
return Promise.resolve();
19+
}
20+
21+
return checkDirectoryAndAbove(process.argv[0], 'install node and Ghost-CLI');
22+
}
23+
24+
module.exports = {
25+
title: 'Checking system Node.js version',
26+
task: nodeVersion,
27+
category: ['install']
28+
};

lib/commands/doctor/checks/startup.js

-54
This file was deleted.

0 commit comments

Comments
 (0)