Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add subject-exclamation-mark rule to improve error messages
When using the conventional commit feature of an `!` in the commit subject the angular config get really confused and gives some error messages that do not relate to the issue due to the message failing at the parse stage. This overrides the angular parser preset to add in the exclamation mark then uses the new rule to give a better error message. The result is with the message "fix!: the fix" previously the error message would be "subject may not be empty" now the error message is "subject must not have an exclamation mark in the subject to identify a breaking change". This message it more descriptive and will give the user info they need to resolve the issue. This also updates the docs to highlight the difference in angular and conventional configs, and point them in the direction of the conventional config if they want to use the `!` in the commit messages
- Loading branch information
1 parent
81358f9
commit f43433d
Showing
8 changed files
with
197 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import lint from '@commitlint/lint'; | ||
import {rules, parserPreset} from '.'; | ||
|
||
export const testCommit = async ({message, valid, error, warning}) => { | ||
const m = message.replace(/^\s+/, '').trim(); | ||
test(m.split('\n')[0], async () => { | ||
const parserOpts = parserPreset.parserOpts; | ||
const result = await lint(m, rules, {parserOpts}); | ||
|
||
expect(result.valid).toBe(valid); | ||
|
||
if (result.errors.length > 1) { | ||
console.log(errors); | ||
fail( | ||
'Commit test should only have one error message to validate against' | ||
); | ||
} else if (result.errors.length) { | ||
expect(result.errors[0].message).toBe(error); | ||
} | ||
|
||
if (result.warnings.length > 1) { | ||
fail( | ||
'Commit test should only have one warning message to validate against' | ||
); | ||
} else if (result.warnings.length) { | ||
expect(result.warnings[0].message).toBe(warning); | ||
} | ||
}); | ||
}; | ||
|
||
testCommit({ | ||
message: `test: a valid angular commit`, | ||
valid: true, | ||
}); | ||
|
||
testCommit({ | ||
message: `test(scope): a valid angular commit with a scope`, | ||
valid: true, | ||
}); | ||
|
||
testCommit({ | ||
message: ` | ||
test(scope): a valid angular commit with a scope | ||
Some content in the body | ||
`, | ||
valid: true, | ||
}); | ||
|
||
testCommit({ | ||
message: ` | ||
test(scope): a valid angular commit with a scope | ||
Some content in the body | ||
`, | ||
valid: true, | ||
warning: 'body must have leading blank line', | ||
}); | ||
|
||
testCommit({ | ||
message: `no: no is not not an invalid commit type`, | ||
valid: false, | ||
error: | ||
'type must be one of [build, ci, docs, feat, fix, perf, refactor, revert, style, test]', | ||
}); | ||
|
||
testCommit({ | ||
message: `test: that its an error when there is ia realllllllllllllllllllllly long header`, | ||
valid: false, | ||
error: 'header must not be longer than 72 characters, current length is 79', | ||
}); | ||
|
||
testCommit({ | ||
message: `test!: with a breaking change in the type`, | ||
valid: false, | ||
error: | ||
'subject must not have an exclamation mark in the subject to identify a breaking change', | ||
}); | ||
|
||
testCommit({ | ||
message: `test(scope)!: with a breaking change in the type with scope`, | ||
valid: false, | ||
error: | ||
'subject must not have an exclamation mark in the subject to identify a breaking change', | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import parse from '@commitlint/parse'; | ||
import {subjectExclamationMark} from './subject-exclamation-mark'; | ||
|
||
const {parserOpts} = require('@commitlint/config-angular'); | ||
|
||
const messages = { | ||
empty: 'test:\n', | ||
with: `test!: subject\n`, | ||
without: `test: subject\n`, | ||
}; | ||
|
||
const parsed = { | ||
empty: parse(messages.empty, undefined, parserOpts), | ||
with: parse(messages.with, undefined, parserOpts), | ||
without: parse(messages.without, undefined, parserOpts), | ||
}; | ||
|
||
test('empty against "always" should fail', async () => { | ||
const [actual] = subjectExclamationMark(await parsed.empty, 'always'); | ||
const expected = false; | ||
expect(actual).toEqual(expected); | ||
}); | ||
|
||
test('empty against "never" should succeed', async () => { | ||
const [actual] = subjectExclamationMark(await parsed.empty, 'never'); | ||
const expected = true; | ||
expect(actual).toEqual(expected); | ||
}); | ||
|
||
test('with against "always" should succeed', async () => { | ||
const [actual] = subjectExclamationMark(await parsed.with, 'always'); | ||
const expected = true; | ||
expect(actual).toEqual(expected); | ||
}); | ||
|
||
test('with against "never" should fail', async () => { | ||
const [actual] = subjectExclamationMark(await parsed.with, 'never'); | ||
const expected = false; | ||
expect(actual).toEqual(expected); | ||
}); | ||
|
||
test('without against "always" should fail', async () => { | ||
const [actual] = subjectExclamationMark(await parsed.without, 'always'); | ||
const expected = false; | ||
expect(actual).toEqual(expected); | ||
}); | ||
|
||
test('without against "never" should succeed', async () => { | ||
const [actual] = subjectExclamationMark(await parsed.without, 'never'); | ||
const expected = true; | ||
expect(actual).toEqual(expected); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import message from '@commitlint/message'; | ||
import {SyncRule} from '@commitlint/types'; | ||
|
||
export const subjectExclamationMark: SyncRule = (parsed, when = 'always') => { | ||
const input = parsed.header; | ||
if (!input) { | ||
return [true, '']; | ||
} | ||
|
||
const negated = when === 'never'; | ||
const hasExclamationMark = /!:/.test(input); | ||
|
||
return [ | ||
negated ? !hasExclamationMark : hasExclamationMark, | ||
message([ | ||
'subject', | ||
negated ? 'must not' : 'must', | ||
'have an exclamation mark in the subject to identify a breaking change', | ||
]), | ||
]; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters