Skip to content

Commit 5a75986

Browse files
author
Duarte Amorim
committed
feat: print commit message when the message is invalid
When using the CLI, if the message is invalid we lose all its content (using a custom message in VIM mode), which might be a little frustrating when we a have a long commit body. This feature prints the full message when there are linting errors. Closes conventional-changelog#222
1 parent b1454d1 commit 5a75986

File tree

5 files changed

+408
-32
lines changed

5 files changed

+408
-32
lines changed

@commitlint/cli/src/cli.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,13 @@ async function main(options) {
114114
messages.map(async message => {
115115
const report = await lint(message, loaded.rules, opts);
116116
const formatted = format(report, {color: flags.color});
117+
const input =
118+
report.errors.length > 0
119+
? `\n${report.input}\n`
120+
: message.split('\n')[0];
117121

118122
if (!flags.quiet) {
119-
console.log(
120-
`${fmt.grey('⧗')} input: ${fmt.bold(message.split('\n')[0])}`
121-
);
123+
console.log(`${fmt.grey('⧗')} input: ${fmt.bold(input)}`);
122124
console.log(formatted.join('\n'));
123125
}
124126

@commitlint/cli/src/cli.test.js

+19
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,25 @@ test('should handle linting with issue prefixes', async t => {
196196
t.is(actual.code, 0);
197197
});
198198

199+
test('should print full commit message when input from stdin fails', async t => {
200+
const cwd = await git.bootstrap('fixtures/simple');
201+
const input = 'foo: bar\n\nFoo bar bizz buzz.\n\nCloses #123.';
202+
const actual = await cli([], {cwd})(input);
203+
204+
t.true(actual.stdout.includes(input));
205+
t.is(actual.code, 1);
206+
});
207+
208+
test('should not print full commit message when input succeeds', async t => {
209+
const cwd = await git.bootstrap('fixtures/empty');
210+
const message = 'foo: bar\n\nFoo bar bizz buzz.\n\nCloses #123.';
211+
const actual = await cli([], {cwd})(message);
212+
213+
t.false(actual.stdout.includes(message));
214+
t.true(actual.stdout.includes(message.split('\n')[0]));
215+
t.is(actual.code, 0);
216+
});
217+
199218
async function writePkg(payload, options) {
200219
const pkgPath = path.join(options.cwd, 'package.json');
201220
const pkg = JSON.parse(await sander.readFile(pkgPath));

@commitlint/lint/src/index.js

+13-2
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,23 @@ import parse from '@commitlint/parse';
44
import implementations from '@commitlint/rules';
55
import entries from 'lodash.topairs';
66

7+
const buildCommitMesage = ({header, body, footer}) => {
8+
let message = header;
9+
10+
message = body ? `${message}\n\n${body}` : message;
11+
message = footer ? `${message}\n\n${footer}` : message;
12+
13+
return message;
14+
};
15+
716
export default async (message, rules = {}, opts = {}) => {
817
// Found a wildcard match, skip
918
if (isIgnored(message)) {
1019
return {
1120
valid: true,
1221
errors: [],
13-
warnings: []
22+
warnings: [],
23+
input: message
1424
};
1525
}
1626

@@ -133,6 +143,7 @@ export default async (message, rules = {}, opts = {}) => {
133143
return {
134144
valid,
135145
errors,
136-
warnings
146+
warnings,
147+
input: buildCommitMesage(parsed)
137148
};
138149
};

@commitlint/lint/src/index.test.js

+40
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ test('positive on ignored message and broken rule', async t => {
3535
'type-empty': [2, 'never']
3636
});
3737
t.true(actual.valid);
38+
t.is(actual.input, 'Revert "some bogus commit"');
3839
});
3940

4041
test('positive on stub message and opts', async t => {
@@ -182,3 +183,42 @@ test('fails for custom issue prefix', async t => {
182183

183184
t.false(report.valid);
184185
});
186+
187+
test('returns original message only with commit header', async t => {
188+
const message = 'foo: bar';
189+
const report = await lint(message);
190+
191+
t.is(report.input, message);
192+
});
193+
194+
test('returns original message with commit header and body', async t => {
195+
const message = 'foo: bar/n/nFoo bar bizz buzz.';
196+
const report = await lint(message);
197+
198+
t.is(report.input, message);
199+
});
200+
201+
test('returns original message with commit header, body and footer', async t => {
202+
const message = 'foo: bar/n/nFoo bar bizz buzz./n/nCloses #1';
203+
const report = await lint(message);
204+
205+
t.is(report.input, message);
206+
});
207+
208+
test('returns original message with commit header, body and footer, parsing comments', async t => {
209+
const expected = 'foo: bar/n/nFoo bar bizz buzz./n/nCloses #1';
210+
const message = `${expected}\n\n# Some comment to ignore`;
211+
const report = await lint(
212+
message,
213+
{
214+
'references-empty': [2, 'never']
215+
},
216+
{
217+
parserOpts: {
218+
commentChar: '#'
219+
}
220+
}
221+
);
222+
223+
t.is(report.input, expected);
224+
});

0 commit comments

Comments
 (0)