mirror of
https://github.com/balena-io/balena-cli.git
synced 2025-01-23 04:48:15 +00:00
Merge pull request #1806 from balena-io/errors-improvements
Improve presentation of errors, help
This commit is contained in:
commit
c2561938c1
@ -73,8 +73,8 @@ const manuallySortedPrimaryCommands = [
|
||||
|
||||
const general = function(_params, options, done) {
|
||||
console.log('Usage: balena [COMMAND] [OPTIONS]\n');
|
||||
console.log(messages.reachingOut);
|
||||
console.log('\nPrimary commands:\n');
|
||||
|
||||
console.log('Primary commands:\n');
|
||||
|
||||
// We do not want the wildcard command
|
||||
// to be printed in the help screen.
|
||||
@ -123,6 +123,9 @@ const general = function(_params, options, done) {
|
||||
console.log('\nGlobal Options:\n');
|
||||
print(parse(capitano.state.globalOptions).sort());
|
||||
}
|
||||
console.log(indent('--debug\n'));
|
||||
|
||||
console.log(messages.help);
|
||||
|
||||
return done();
|
||||
})
|
||||
@ -152,6 +155,8 @@ const commandHelp = (params, _options, done) =>
|
||||
print(parse(command.options).sort());
|
||||
}
|
||||
|
||||
console.log();
|
||||
|
||||
return done();
|
||||
});
|
||||
|
||||
|
@ -28,7 +28,7 @@ export class NotLoggedInError extends ExpectedError {}
|
||||
export class InsufficientPrivilegesError extends ExpectedError {}
|
||||
|
||||
/**
|
||||
* instanceOf is a more reliable implemention of the plain `instanceof`
|
||||
* instanceOf is a more reliable implementation of the plain `instanceof`
|
||||
* typescript operator, for use with TypedError errors when the error
|
||||
* classes may be defined in external packages/dependencies.
|
||||
* Sample usage:
|
||||
@ -126,56 +126,81 @@ const messages: {
|
||||
`,
|
||||
|
||||
BalenaExpiredToken: () => stripIndent`
|
||||
Looks like your session token is expired.
|
||||
Looks like your session token has expired.
|
||||
Please try logging in again with:
|
||||
$ balena login`,
|
||||
};
|
||||
|
||||
const EXPECTED_ERROR_REGEXES = [
|
||||
/^BalenaApplicationNotFound:/, // balena-sdk
|
||||
/^BalenaDeviceNotFound:/, // balena-sdk
|
||||
/^Missing \w+$/, // Capitano, oclif parser: RequiredArgsError, RequiredFlagError
|
||||
/^Unexpected arguments?:/, // oclif parser: UnexpectedArgsError
|
||||
/to be one of/, // oclif parser: FlagInvalidOptionError, ArgInvalidOptionError
|
||||
];
|
||||
|
||||
export async function handleError(error: any) {
|
||||
// Set appropriate exitCode
|
||||
process.exitCode =
|
||||
error.exitCode === 0
|
||||
? 0
|
||||
: parseInt(error.exitCode, 10) || process.exitCode || 1;
|
||||
|
||||
// Handle non-Error objects (probably strings)
|
||||
if (!(error instanceof Error)) {
|
||||
printErrorMessage(String(error));
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare message
|
||||
const message = [interpret(error)];
|
||||
|
||||
if (process.env.DEBUG && error.stack) {
|
||||
message.push('\n' + error.stack);
|
||||
if (error.stack) {
|
||||
if (process.env.DEBUG) {
|
||||
message.push('\n' + error.stack);
|
||||
} else {
|
||||
// Include first line of stacktrace
|
||||
message.push('\n' + error.stack.split(`\n`)[0]);
|
||||
}
|
||||
}
|
||||
printErrorMessage(message.join('\n'));
|
||||
|
||||
const expectedErrorREs = [
|
||||
/^BalenaApplicationNotFound:/, // balena-sdk
|
||||
/^BalenaDeviceNotFound:/, // balena-sdk
|
||||
/^Missing \w+$/, // Capitano's command line parsing error
|
||||
/^Unexpected arguments?:/, // oclif's command line parsing error
|
||||
];
|
||||
|
||||
if (
|
||||
// Expected?
|
||||
const isExpectedError =
|
||||
error instanceof ExpectedError ||
|
||||
expectedErrorREs.some(re => re.test(message[0]))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
EXPECTED_ERROR_REGEXES.some(re => re.test(message[0]));
|
||||
|
||||
// Report "unexpected" errors via Sentry.io
|
||||
const Sentry = await import('@sentry/node');
|
||||
Sentry.captureException(error);
|
||||
await Sentry.close(1000);
|
||||
// Unhandled/unexpected error: ensure that the process terminates.
|
||||
// The exit error code was set above through `process.exitCode`.
|
||||
process.exit();
|
||||
// Output/report error
|
||||
if (isExpectedError) {
|
||||
printExpectedErrorMessage(message.join('\n'));
|
||||
} else {
|
||||
printErrorMessage(message.join('\n'));
|
||||
|
||||
// Report "unexpected" errors via Sentry.io
|
||||
const Sentry = await import('@sentry/node');
|
||||
Sentry.captureException(error);
|
||||
await Sentry.close(1000);
|
||||
// Unhandled/unexpected error: ensure that the process terminates.
|
||||
// The exit error code was set above through `process.exitCode`.
|
||||
process.exit();
|
||||
}
|
||||
}
|
||||
|
||||
export function printErrorMessage(message: string) {
|
||||
const chalk = getChalk();
|
||||
console.error(chalk.red(message));
|
||||
console.error(chalk.red(`\n${getHelp}\n`));
|
||||
|
||||
// Only first line should be red
|
||||
const messageLines = message.split('\n');
|
||||
console.error(chalk.red(messageLines.shift()));
|
||||
|
||||
messageLines.forEach(line => {
|
||||
console.error(line);
|
||||
});
|
||||
|
||||
console.error(`\n${getHelp}\n`);
|
||||
}
|
||||
|
||||
export function printExpectedErrorMessage(message: string) {
|
||||
console.error(`${message}\n`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -9,19 +9,16 @@ create a new one at: https://github.com/balena-io/balena-cli/issues/\
|
||||
`;
|
||||
|
||||
const debugHint = `\
|
||||
Additional information may be available by setting a DEBUG=1 environment
|
||||
variable: "set DEBUG=1" on a Windows command prompt, "$env:DEBUG = 1" on
|
||||
powershell, or "export DEBUG=1" on Linux or macOS.\n
|
||||
Additional information may be available with the \`--debug\` flag.
|
||||
`;
|
||||
|
||||
export const getHelp = `${DEBUG_MODE ? '' : debugHint}\
|
||||
If you need help, don't hesitate in contacting our support forums at
|
||||
https://forums.balena.io
|
||||
|
||||
For CLI bug reports or feature requests, have a look at the GitHub issues or
|
||||
create a new one at: https://github.com/balena-io/balena-cli/issues/\
|
||||
export const help = `\
|
||||
For help, visit our support forums: https://forums.balena.io
|
||||
For bug reports or feature requests, see: https://github.com/balena-io/balena-cli/issues/
|
||||
`;
|
||||
|
||||
export const getHelp = (DEBUG_MODE ? '' : debugHint) + help;
|
||||
|
||||
export const balenaAsciiArt = `\
|
||||
_ _
|
||||
| |__ __ _ | | ____ _ __ __ _
|
||||
|
@ -4,12 +4,6 @@ import { cleanOutput, runCommand } from '../helpers';
|
||||
const SIMPLE_HELP = `
|
||||
Usage: balena [COMMAND] [OPTIONS]
|
||||
|
||||
If you need help, or just want to say hi, don't hesitate in reaching out
|
||||
through our discussion and support forums at https://forums.balena.io
|
||||
|
||||
For bug reports or feature requests, have a look at the GitHub issues or
|
||||
create a new one at: https://github.com/balena-io/balena-cli/issues/
|
||||
|
||||
Primary commands:
|
||||
|
||||
help [command...] show help
|
||||
@ -84,33 +78,33 @@ Additional commands:
|
||||
|
||||
`;
|
||||
|
||||
const LIST_ADDITIONAL = `
|
||||
Run \`balena help --verbose\` to list additional commands
|
||||
`;
|
||||
|
||||
const GLOBAL_OPTIONS = `
|
||||
Global Options:
|
||||
|
||||
--help, -h
|
||||
--version, -v
|
||||
--debug
|
||||
`;
|
||||
|
||||
const ONLINE_RESOURCES = `
|
||||
For help, visit our support forums: https://forums.balena.io
|
||||
For bug reports or feature requests, see: https://github.com/balena-io/balena-cli/issues/
|
||||
`;
|
||||
|
||||
describe('balena help', function() {
|
||||
it('should list primary command summaries', async () => {
|
||||
const { out, err } = await runCommand('help');
|
||||
|
||||
console.log('ONE');
|
||||
console.log(cleanOutput(out));
|
||||
console.log(
|
||||
cleanOutput([
|
||||
SIMPLE_HELP,
|
||||
'Run `balena help --verbose` to list additional commands',
|
||||
GLOBAL_OPTIONS,
|
||||
]),
|
||||
);
|
||||
console.log();
|
||||
|
||||
expect(cleanOutput(out)).to.deep.equal(
|
||||
cleanOutput([
|
||||
SIMPLE_HELP,
|
||||
'Run `balena help --verbose` to list additional commands',
|
||||
LIST_ADDITIONAL,
|
||||
GLOBAL_OPTIONS,
|
||||
ONLINE_RESOURCES,
|
||||
]),
|
||||
);
|
||||
|
||||
@ -121,7 +115,12 @@ describe('balena help', function() {
|
||||
const { out, err } = await runCommand('help -v');
|
||||
|
||||
expect(cleanOutput(out)).to.deep.equal(
|
||||
cleanOutput([SIMPLE_HELP, ADDITIONAL_HELP, GLOBAL_OPTIONS]),
|
||||
cleanOutput([
|
||||
SIMPLE_HELP,
|
||||
ADDITIONAL_HELP,
|
||||
GLOBAL_OPTIONS,
|
||||
ONLINE_RESOURCES,
|
||||
]),
|
||||
);
|
||||
|
||||
expect(err.join('')).to.equal('');
|
||||
@ -135,8 +134,9 @@ describe('balena help', function() {
|
||||
expect(cleanOutput(out)).to.deep.equal(
|
||||
cleanOutput([
|
||||
SIMPLE_HELP,
|
||||
'Run `balena help --verbose` to list additional commands',
|
||||
LIST_ADDITIONAL,
|
||||
GLOBAL_OPTIONS,
|
||||
ONLINE_RESOURCES,
|
||||
]),
|
||||
);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user