fix: Include Error properties in logs

This commit is contained in:
Pierre Vanduynslager 2017-10-29 01:50:24 -04:00 committed by Gregor Martynus
parent ad2e1d76b7
commit c90765e10d
5 changed files with 35 additions and 13 deletions

View File

@ -52,7 +52,7 @@ module.exports = async () => {
logger.log(`%s ${err.message}`, err.code);
} else {
process.exitCode = 1;
logger.error(err);
logger.error('An error occurred while running semantic-release: %O', err);
}
}
};

View File

@ -6,13 +6,18 @@ const chalk = require('chalk');
module.exports = {
log(...args) {
const [format, ...rest] = args;
console.log(`${chalk.grey('[Semantic release]:')} ${format}`, ...rest.map(arg => chalk.magenta(arg)));
console.log(
`${chalk.grey('[Semantic release]:')}${typeof format === 'string'
? ` ${format.replace(/%[^%]/g, seq => chalk.magenta(seq))}`
: ''}`,
...(typeof format === 'string' ? [] : [format]).concat(rest)
);
},
error(...args) {
const [format, ...rest] = args;
console.error(
`${chalk.grey('[Semantic release]:')} ${chalk.red(format instanceof Error ? format.stack : format)}`,
...rest.map(arg => chalk.red(arg instanceof Error ? arg.stack : arg))
`${chalk.grey('[Semantic release]:')}${typeof format === 'string' ? ` ${chalk.red(format)}` : ''}`,
...(typeof format === 'string' ? [] : [format]).concat(rest)
);
},
};

View File

@ -1,3 +1,5 @@
module.exports = function(config, options, cb) {
cb(new Error('a'));
const error = new Error('a');
error.errorProperty = 'errorProperty';
cb(error);
};

View File

@ -634,8 +634,12 @@ test.serial('Log unexpected errors from plugins and exit with 1', async t => {
await gitCommits(['feat: Initial commit']);
t.log('$ semantic-release');
let {stderr, code} = await execa(cli, [], {env, reject: false});
// Verify the type and message are logged
t.regex(stderr, /Error: a/);
// Verify the the stacktrace is logged
t.regex(stderr, new RegExp(pluginError));
// Verify the Error properties are logged
t.regex(stderr, /errorProperty: 'errorProperty'/);
t.is(code, 1);
});

View File

@ -1,5 +1,5 @@
import test from 'ava';
import {stub} from 'sinon';
import {stub, match} from 'sinon';
import logger from '../src/lib/logger';
test.beforeEach(t => {
@ -20,18 +20,29 @@ test.serial('Basic log', t => {
t.true(t.context.error.calledWithMatch(/.*test error/));
});
test.serial('Log object', t => {
const obj = {a: 1, b: '2'};
logger.log(obj);
logger.error(obj);
t.true(t.context.log.calledWithMatch(match.string, obj));
t.true(t.context.error.calledWithMatch(match.string, obj));
});
test.serial('Log with string formatting', t => {
logger.log('test log %s', 'log value');
logger.error('test error %s', 'error value');
t.true(t.context.log.calledWithMatch(/.*test log %s/, 'log value'));
t.true(t.context.error.calledWithMatch(/.*test error %s/, 'error value'));
t.true(t.context.log.calledWithMatch(/.*test log/, 'log value'));
t.true(t.context.error.calledWithMatch(/.*test error/, 'error value'));
});
test.serial('Log with error stacktrace', t => {
logger.error(new Error('error message'));
logger.error('test error %s', new Error('other error message'));
test.serial('Log with error stacktrace and properties', t => {
const error = new Error('error message');
logger.error(error);
const otherError = new Error('other error message');
logger.error('test error %O', otherError);
t.true(t.context.error.calledWithMatch(/.*test error %s/, /Error: other error message(\s|.)*?logger\.test\.js/));
t.true(t.context.error.calledWithMatch(/Error: error message(\s|.)*?logger\.test\.js/));
t.true(t.context.error.calledWithMatch(match.string, error));
t.true(t.context.error.calledWithMatch(/.*test error/, otherError));
});