diff --git a/@commitlint/lint/src/index.js b/@commitlint/lint/src/index.js index 25e2fd64c95..8b10253c5a2 100644 --- a/@commitlint/lint/src/index.js +++ b/@commitlint/lint/src/index.js @@ -28,6 +28,19 @@ export default async (message, rules = {}, opts = {}) => { // Parse the commit message const parsed = await parse(message, undefined, opts.parserOpts); + if ( + parsed.header === null && + parsed.body === null && + parsed.footer === null + ) { + // Commit is empty, skip + return { + valid: true, + errors: [], + warnings: [], + input: message + }; + } const mergedImplementations = Object.assign({}, implementations); if (opts.plugins) { diff --git a/@commitlint/lint/src/index.test.js b/@commitlint/lint/src/index.test.js index 80ac3d8e8b4..8c3702d27fc 100644 --- a/@commitlint/lint/src/index.test.js +++ b/@commitlint/lint/src/index.test.js @@ -66,6 +66,37 @@ test('positive on custom ignored message and broken rule', async t => { t.is(actual.input, ignoredMessage); }); +test('positive on comment-only commit message', async t => { + const actual = await lint( + // '# This is empty\n#This is also a comment', + '# comment!', + { + 'header-max-length': [2, 'always', 72] + }, + { + parserOpts: { + commentChar: '#' + } + } + ); + t.true(actual.valid); +}); + +test('positive on blank lines and comment commit message', async t => { + const actual = await lint( + '\n# Comment\n# Another comment\n', + { + 'header-max-length': [2, 'always', 72] + }, + { + parserOpts: { + commentChar: '#' + } + } + ); + t.true(actual.valid); +}); + test('positive on stub message and opts', async t => { const actual = await lint( 'foo-bar',