fix(CLI): don't print stack traces by default (#1206)

Currently, the Etcher CLI will print scary stack traces for every single
error (e.g: if you forgot to pass an image to the tool), given that
`errors.getDescription()` will return a stack trace if no other
description could be found.

This commit introduces an `ETCHER_CLI_DEBUG` environment variable, which
when set, it will cause the Etcher CLI to output stack traces, plus a
boolean `userFriendlyDescriptionsOnly` option to
`errors.getDescription()`, so we can control whether
`errors.getDescription()` returns things like stack traces, or
stringified error objects.

Change-Type: minor
Changelog-Entry: Don't print stack traces by default in the CLI.
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
This commit is contained in:
Juan Cruz Viotti 2017-03-28 09:43:15 -04:00 committed by GitHub
parent 396145d625
commit 57952f6f55
4 changed files with 79 additions and 2 deletions

View File

@ -43,3 +43,9 @@ Options
--yes, -y confirm non-interactively --yes, -y confirm non-interactively
--unmount, -u unmount on success --unmount, -u unmount on success
``` ```
Debug mode
----------
You can set the `ETCHER_CLI_DEBUG` environment variable to make the Etcher CLI
print error stack traces.

View File

@ -31,10 +31,17 @@ const errors = require('../shared/errors');
*/ */
exports.printError = (error) => { exports.printError = (error) => {
const title = errors.getTitle(error); const title = errors.getTitle(error);
const description = errors.getDescription(error); const description = errors.getDescription(error, {
userFriendlyDescriptionsOnly: true
});
console.error(chalk.red(title)); console.error(chalk.red(title));
if (description) { if (description) {
console.error(`\n${chalk.red(description)}`); console.error(`\n${chalk.red(description)}`);
} }
if (process.env.ETCHER_CLI_DEBUG && error.stack) {
console.error(`\n${chalk.red(error.stack)}`);
}
}; };

View File

@ -206,6 +206,8 @@ exports.getTitle = (error) => {
* @public * @public
* *
* @param {Error} error - error * @param {Error} error - error
* @param {Object} options - options
* @param {Boolean} [options.userFriendlyDescriptionsOnly=false] - only return user friendly descriptions
* @returns {String} error description * @returns {String} error description
* *
* @example * @example
@ -213,7 +215,11 @@ exports.getTitle = (error) => {
* const description = errors.getDescription(error); * const description = errors.getDescription(error);
* console.log(description); * console.log(description);
*/ */
exports.getDescription = (error) => { exports.getDescription = (error, options = {}) => {
_.defaults(options, {
userFriendlyDescriptionsOnly: false
});
if (!_.isError(error) && !_.isPlainObject(error)) { if (!_.isError(error) && !_.isPlainObject(error)) {
return ''; return '';
} }
@ -227,6 +233,10 @@ exports.getDescription = (error) => {
return codeDescription; return codeDescription;
} }
if (options.userFriendlyDescriptionsOnly) {
return '';
}
if (error.stack) { if (error.stack) {
return error.stack; return error.stack;
} }

View File

@ -422,6 +422,60 @@ describe('Shared: Errors', function() {
m.chai.expect(errors.getDescription(error)).to.equal('Memory error'); m.chai.expect(errors.getDescription(error)).to.equal('Memory error');
}); });
describe('given userFriendlyDescriptionsOnly is false', function() {
it('should return the stack for a basic error', function() {
const error = new Error('Foo');
m.chai.expect(errors.getDescription(error, {
userFriendlyDescriptionsOnly: false
})).to.equal(error.stack);
});
it('should return the stack if the description is an empty string', function() {
const error = new Error('Foo');
error.description = '';
m.chai.expect(errors.getDescription(error, {
userFriendlyDescriptionsOnly: false
})).to.equal(error.stack);
});
it('should return the stack if the description is a blank string', function() {
const error = new Error('Foo');
error.description = ' ';
m.chai.expect(errors.getDescription(error, {
userFriendlyDescriptionsOnly: false
})).to.equal(error.stack);
});
});
describe('given userFriendlyDescriptionsOnly is true', function() {
it('should return an empty string for a basic error', function() {
const error = new Error('Foo');
m.chai.expect(errors.getDescription(error, {
userFriendlyDescriptionsOnly: true
})).to.equal('');
});
it('should return an empty string if the description is an empty string', function() {
const error = new Error('Foo');
error.description = '';
m.chai.expect(errors.getDescription(error, {
userFriendlyDescriptionsOnly: true
})).to.equal('');
});
it('should return an empty string if the description is a blank string', function() {
const error = new Error('Foo');
error.description = ' ';
m.chai.expect(errors.getDescription(error, {
userFriendlyDescriptionsOnly: true
})).to.equal('');
});
});
}); });
describe('.createError()', function() { describe('.createError()', function() {