Skip to content

Commit

Permalink
cleanup: refactor more commands to use async/await (#1039)
Browse files Browse the repository at this point in the history
  • Loading branch information
acburdine authored Nov 4, 2019
1 parent 4efd35f commit 514ad02
Show file tree
Hide file tree
Showing 8 changed files with 247 additions and 263 deletions.
8 changes: 4 additions & 4 deletions lib/commands/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class ConfigCommand extends Command {
this.instance = this.system.getInstance();
}

run(argv) {
async run(argv) {
const {key, value} = argv;

this.instance.checkEnvironment();
Expand All @@ -32,16 +32,16 @@ class ConfigCommand extends Command {
this.ui.log(this.instance.config.get(key));
}

return Promise.resolve();
return;
} else if (key) {
// setter
this.instance.config.set(key, value).save();
this.ui.log(`Successfully set '${key}' to '${value}'`, 'green');
return Promise.resolve();
return;
}

const configure = require('../tasks/configure');
return configure(this.ui, this.instance.config, argv, this.system.environment, false);
await configure(this.ui, this.instance.config, argv, this.system.environment, false);
}
}

Expand Down
24 changes: 13 additions & 11 deletions lib/commands/ls.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
const Command = require('../command');

class LsCommand extends Command {
run() {
async run() {
const chalk = require('chalk');
const Promise = require('bluebird');

Expand All @@ -16,17 +16,19 @@ class LsCommand extends Command {
return [name, dir, version, `${chalk.green('running')} (${mode})`, url, port, process];
}

return this.system.getAllInstances().then(
instances => Promise.map(instances, instance => instance.summary().then(makeRow))
).then((rows) => {
if (rows.length) {
this.ui.table(['Name', 'Location', 'Version', 'Status', 'URL', 'Port', 'Process Manager'], rows, {
style: {head: ['cyan']}
});
} else {
this.ui.log('No installed ghost instances found', 'cyan');
}
const instances = await this.system.getAllInstances();
const rows = await Promise.map(instances, async (instance) => {
const summary = await instance.summary();
return makeRow(summary);
});

if (rows.length) {
this.ui.table(['Name', 'Location', 'Version', 'Status', 'URL', 'Port', 'Process Manager'], rows, {
style: {head: ['cyan']}
});
} else {
this.ui.log('No installed ghost instances found', 'cyan');
}
}
}

Expand Down
20 changes: 9 additions & 11 deletions lib/commands/restart.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,17 @@
const Command = require('../command');

class RestartCommand extends Command {
run() {
async run() {
const instance = this.system.getInstance();
const isRunning = await instance.running();
if (!isRunning) {
const StartCommand = require('./start');
this.ui.log('Ghost instance is not running! Starting...', 'yellow');
return this.runCommand(StartCommand);
}

return instance.running().then((isRunning) => {
if (!isRunning) {
const StartCommand = require('./start');
this.ui.log('Ghost instance is not running! Starting...', 'yellow');
return this.runCommand(StartCommand);
}

instance.loadRunningEnvironment(true);
return this.ui.run(instance.process.restart(process.cwd(), this.system.environment), 'Restarting Ghost');
});
instance.loadRunningEnvironment(true);
return this.ui.run(instance.process.restart(process.cwd(), this.system.environment), 'Restarting Ghost');
}
}

Expand Down
86 changes: 42 additions & 44 deletions lib/commands/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class SetupCommand extends Command {
return;
}

this.options = Object.assign({}, omit(options, Object.keys(this.options)), this.options);
this.options = {...omit(options, Object.keys(this.options)), ...this.options};
});

yargs = super.configureOptions(commandName, yargs, extensions, onlyOptions);
Expand All @@ -26,14 +26,15 @@ class SetupCommand extends Command {

localArgs(argv) {
const dbpath = argv.db ? null : path.join(process.cwd(), 'content/data/ghost-local.db');
const args = Object.assign({
const args = {
url: 'http://localhost:2368',
pname: 'ghost-local',
process: 'local',
stack: false,
db: 'sqlite3',
start: true
}, argv);
start: true,
...argv
};

if (dbpath) {
args.dbpath = dbpath;
Expand Down Expand Up @@ -107,25 +108,24 @@ class SetupCommand extends Command {

return origEnabled(ctx, ...args);
};
const task = (ctx, task) => {
const task = async (ctx, task) => {
if (ctx.single || step[internal]) {
return step.task(ctx, task);
}

return this.ui.confirm(`Do you wish to set up ${name}?`, true).then((confirmed) => {
if (!confirmed) {
return task.skip();
}
const confirmed = await this.ui.confirm(`Do you wish to set up ${name}?`, true);
if (!confirmed) {
return task.skip();
}

return step.task(ctx, task);
});
return step.task(ctx, task);
};

return Object.assign({}, step, {title, enabled, task});
return {...step, title, enabled, task};
});
}

run(argv) {
async run(argv) {
// Ensure stages is an array
argv.stages = argv.stages || [];

Expand All @@ -148,44 +148,42 @@ class SetupCommand extends Command {
instance.checkEnvironment();
}

return this.system.hook('setup').then((steps) => {
const tasks = this.tasks(steps);
const listr = this.ui.listr(tasks, false, {exitOnError: false});
const taskMap = listr.tasks.reduce(
(map, task, index) => Object.assign({[tasks[index].id]: task}, map),
{}
);

return listr.run({
ui: this.ui,
system: this.system,
instance,
tasks: taskMap,
listr,
argv,
single: Boolean(stages.length)
});
}).then(() => {
if (stages.length) {
// Don't start Ghost if we're running individual setup stages
return false;
}
const steps = await this.system.hook('setup');
const tasks = this.tasks(steps);
const listr = this.ui.listr(tasks, false, {exitOnError: false});
const taskMap = listr.tasks.reduce(
(map, task, index) => ({[tasks[index].id]: task, ...map}),
{}
);

await listr.run({
ui: this.ui,
system: this.system,
instance,
tasks: taskMap,
listr,
argv,
single: Boolean(stages.length)
});

// If argv.start has a value, this means either --start or --no-start were explicitly provided
// In this case, we don't prompt, we use the value of argv.start
if (argv.start || argv.start === false) {
return Promise.resolve(argv.start);
}
if (stages.length || argv.start === false) {
// Don't start Ghost if we're running individual setup stages
return;
}

return this.ui.confirm('Do you want to start Ghost?', true);
}).then(confirmed => confirmed && this.runCommand(StartCommand, argv));
const shouldStart = argv.start || await this.ui.confirm('Do you want to start Ghost?', true);

if (shouldStart) {
await this.runCommand(StartCommand, argv);
}
}
}

SetupCommand.description = 'Setup an installation of Ghost (after it is installed)';
SetupCommand.longDescription = '$0 setup [stages..]\n stages can be one or more of nginx, ssl, mysql, systemd, migrate, linux-user.';
SetupCommand.params = '[stages..]';
SetupCommand.options = Object.assign({}, options, {
SetupCommand.options = {
...options,
start: {
description: '[--no-start] Enable/disable automatically starting Ghost'
},
Expand All @@ -200,7 +198,7 @@ SetupCommand.options = Object.assign({}, options, {
type: 'string',
group: 'Service Options:'
}
});
};
SetupCommand.runPreChecks = true;

module.exports = SetupCommand;
50 changes: 23 additions & 27 deletions test/unit/commands/config-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ describe('Unit: Command > Config', function () {
});

describe('run', function () {
it('outputs key if key defined and value is not', function () {
it('outputs key if key defined and value is not', async function () {
const ConfigCommand = fake();
const log = sinon.stub();
const checkEnvironment = sinon.stub();
Expand All @@ -61,19 +61,17 @@ describe('Unit: Command > Config', function () {

const cmd = new ConfigCommand({log}, {getInstance});

return cmd.run({key: 'url'}).then(() => {
expect(checkEnvironment.calledOnce).to.be.true;
expect(log.calledOnce).to.be.true;
expect(log.args[0][0]).to.equal('http://localhost:2368');
await cmd.run({key: 'url'});
expect(checkEnvironment.calledOnce).to.be.true;
expect(log.calledOnce).to.be.true;
expect(log.args[0][0]).to.equal('http://localhost:2368');

return cmd.run({key: 'nope'});
}).then(() => {
expect(checkEnvironment.calledTwice).to.be.true;
expect(log.calledOnce).to.be.true;
});
await cmd.run({key: 'nope'});
expect(checkEnvironment.calledTwice).to.be.true;
expect(log.calledOnce).to.be.true;
});

it('sets value if both key and value defined', function () {
it('sets value if both key and value defined', async function () {
const ConfigCommand = fake();
const checkEnvironment = sinon.stub();
const config = new Config('config.json');
Expand All @@ -84,16 +82,15 @@ describe('Unit: Command > Config', function () {

const cmd = new ConfigCommand({log}, {getInstance});

return cmd.run({key: 'url', value: 'http://localhost:2368'}).then(() => {
expect(checkEnvironment.calledOnce).to.be.true;
expect(setStub.calledOnce).to.be.true;
expect(saveStub.calledOnce).to.be.true;
expect(setStub.args[0]).to.deep.equal(['url', 'http://localhost:2368']);
expect(log.calledOnce).to.be.true;
});
await cmd.run({key: 'url', value: 'http://localhost:2368'});
expect(checkEnvironment.calledOnce).to.be.true;
expect(setStub.calledOnce).to.be.true;
expect(saveStub.calledOnce).to.be.true;
expect(setStub.args[0]).to.deep.equal(['url', 'http://localhost:2368']);
expect(log.calledOnce).to.be.true;
});

it('calls configure if key and value aren\'t provided', function () {
it('calls configure if key and value aren\'t provided', async function () {
const configureStub = sinon.stub().resolves();
const ConfigCommand = fake({
'../tasks/configure': configureStub
Expand All @@ -105,14 +102,13 @@ describe('Unit: Command > Config', function () {
const argv = {url: 'http://ghost.test', dbhost: 'localhost', dbuser: 'root', db: 'mysql'};
const cmd = new ConfigCommand(ui, {getInstance, environment: 'testing'});

return cmd.run(argv).then(() => {
expect(configureStub.calledOnce).to.be.true;
expect(configureStub.args[0][0]).to.deep.equal(ui);
expect(configureStub.args[0][1]).to.deep.equal(config);
expect(configureStub.args[0][2]).to.deep.equal(argv);
expect(configureStub.args[0][3]).to.equal('testing');
expect(configureStub.args[0][4]).to.equal(false);
});
await cmd.run(argv);
expect(configureStub.calledOnce).to.be.true;
expect(configureStub.args[0][0]).to.deep.equal(ui);
expect(configureStub.args[0][1]).to.deep.equal(config);
expect(configureStub.args[0][2]).to.deep.equal(argv);
expect(configureStub.args[0][3]).to.equal('testing');
expect(configureStub.args[0][4]).to.equal(false);
});
});
});
46 changes: 22 additions & 24 deletions test/unit/commands/ls-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const stripAnsi = require('strip-ansi');
const LsCommand = require('../../../lib/commands/ls');

describe('Unit: Commands > ls', function () {
it('outputs the correct data for instances that are running and not running', function () {
it('outputs the correct data for instances that are running and not running', async function () {
const summaryStub = sinon.stub();
summaryStub.onFirstCall().resolves({
name: 'testa',
Expand Down Expand Up @@ -43,39 +43,37 @@ describe('Unit: Commands > ls', function () {

const instance = new LsCommand({table: tableStub}, {getAllInstances: getAllInstancesStub});

return instance.run().then(() => {
expect(summaryStub.calledThrice).to.be.true;
expect(tableStub.calledOnce).to.be.true;
expect(tableStub.args[0][0]).to.deep
.equal(['Name', 'Location', 'Version', 'Status', 'URL', 'Port', 'Process Manager']);
const rows = tableStub.args[0][1];
expect(rows).to.be.an.instanceof(Array);
expect(rows).to.have.length(3);
await instance.run();
expect(summaryStub.calledThrice).to.be.true;
expect(tableStub.calledOnce).to.be.true;
expect(tableStub.args[0][0]).to.deep
.equal(['Name', 'Location', 'Version', 'Status', 'URL', 'Port', 'Process Manager']);
const rows = tableStub.args[0][1];
expect(rows).to.be.an.instanceof(Array);
expect(rows).to.have.length(3);

const expected = [
['testa', '/var/www/testa', '1.5.0', 'stopped', 'n/a', 'n/a', 'n/a'],
['testb', '/var/www/testb', '1.2.0', 'running (production)', 'https://testa.com', 2369, 'systemd'],
['testc', '/var/www/testc', '1.3.0', 'running (development)', 'http://localhost:2370', 2370, 'local']
];
const expected = [
['testa', '/var/www/testa', '1.5.0', 'stopped', 'n/a', 'n/a', 'n/a'],
['testb', '/var/www/testb', '1.2.0', 'running (production)', 'https://testa.com', 2369, 'systemd'],
['testc', '/var/www/testc', '1.3.0', 'running (development)', 'http://localhost:2370', 2370, 'local']
];

expected.forEach((row, i) => {
row.forEach((prop, j) => {
expect(stripAnsi(rows[i][j])).to.equal(prop);
});
expected.forEach((row, i) => {
row.forEach((prop, j) => {
expect(stripAnsi(rows[i][j])).to.equal(prop);
});
});
});

it('Doesn\'t create a table when no instances exist', function () {
it('Doesn\'t create a table when no instances exist', async function () {
const getAllInstancesStub = sinon.stub().resolves([]);
const tableStub = sinon.stub();
const logStub = sinon.stub();

const instance = new LsCommand({log: logStub, table: tableStub}, {getAllInstances: getAllInstancesStub});
instance.run().then(() => {
expect(tableStub.called).to.be.false;
expect(logStub.calledOnce).to.be.true;
expect(logStub.args[0][0]).to.equal('No installed ghost instances found');
});
await instance.run();
expect(tableStub.called).to.be.false;
expect(logStub.calledOnce).to.be.true;
expect(logStub.args[0][0]).to.equal('No installed ghost instances found');
});
});
Loading

0 comments on commit 514ad02

Please sign in to comment.