diff --git a/commitlint.config.ts b/commitlint.config.ts index 6df5f392b..0e147c568 100644 --- a/commitlint.config.ts +++ b/commitlint.config.ts @@ -356,7 +356,11 @@ module.exports = { 'too-many-spaces': [RuleStatus.Error, 'always'], 'commit-hash-alone': [RuleStatus.Error, 'always'], 'title-uppercase': [RuleStatus.Error, 'always'], + 'proper-revert-message': [RuleStatus.Error, 'always'], }, + // Commitlint automatically ignores some kinds of commits like Revert commit messages. + // We need to set this value to false to apply our rules on these messages. + defaultIgnores: false, plugins: [ // TODO (ideas for more rules): // * Detect if paragraphs in body have been cropped too shortly (less than 64 chars), and suggest same auto-wrap command that body-soft-max-line-length suggests, since it unwraps and wraps (both). @@ -602,6 +606,28 @@ module.exports = { `Please use full URLs instead of #XYZ refs.` ]; }, + + 'proper-revert-message': ({header, body}: {header: any, body: any}) => { + let offence = false; + + if (header.match(/^[Rr]evert ".+"$/) !== null) { + + // does msg have a body? + if (body !== null) { + let bodyStr = convertAnyToString(body, "body").trim(); + let lines = bodyStr.split('\n'); + offence = lines[0].match(/^This reverts commit [^ ]{40}\.$/) !== null && lines.length == 1; + } + else { + offence = true; + } + } + + return [ + !offence, + `Please explain why you're reverting` + ]; + }, 'title-uppercase': ({header}: {header:any}) => { let headerStr = convertAnyToString(header, "header"); @@ -625,6 +651,7 @@ module.exports = { `Please watch out for too many whitespaces in the text` ]; }, + 'type-space-after-colon': ({header}: {header:any}) => { let headerStr = convertAnyToString(header, "header"); diff --git a/commitlintplugins.test.ts b/commitlintplugins.test.ts index 2ff758c54..6ca200434 100644 --- a/commitlintplugins.test.ts +++ b/commitlintplugins.test.ts @@ -422,6 +422,58 @@ test('proper-issue-refs3', () => { }); +test('proper-revert-message1', () => { + let commitMsgWithoutProperRevertMessage = + 'Revert "add abbreviations.ts"\n\n' + + 'This reverts commit 0272f587c7eece147e8d1756116b0b43e11c34ac.'; + let properRevertMessage1 = runCommitLintOnMsg(commitMsgWithoutProperRevertMessage); + expect(properRevertMessage1.status).not.toBe(0); +}); + + +test('proper-revert-message2', () => { + let commitMsgWithProperRevertMessage = + 'Revert "add abbreviations.ts"\n\n' + + 'This reverts commit 0272f587c7eece147e8d1756116b0b43e11c34ac\n' + + 'because/otherwise bla bla.' + let properRevertMessage2 = runCommitLintOnMsg(commitMsgWithProperRevertMessage); + expect(properRevertMessage2.status).toBe(0); +}); + + +test('proper-revert-message3', () => { + let commitMsgWithoutProperRevertMessage = 'Revert "add abbreviations.ts"'; + let properRevertMessage3 = runCommitLintOnMsg(commitMsgWithoutProperRevertMessage); + expect(properRevertMessage3.status).not.toBe(0); +}); + + +test('proper-revert-message4', () => { + let commitMsgWithProperRevertMessage = 'Revert .NET6 upd as it broke CI'; + let properRevertMessage4 = runCommitLintOnMsg(commitMsgWithProperRevertMessage); + expect(properRevertMessage4.status).toBe(0); +}); + + +test('proper-revert-message5', () => { + let commitMsgWithoutProperRevertMessage = + 'Revert "add abbreviations.ts"\n\n' + + 'This reverts commit 0272f587 because bla bla.\n'; + + let properRevertMessage5 = runCommitLintOnMsg(commitMsgWithoutProperRevertMessage); + expect(properRevertMessage5.status).toBe(0); +}); + + +test('proper-revert-message6', () => { + let commitMsgWithProperRevertMessage = + 'Revert "process overhaul" to fix CI\n\n'; + + let properRevertMessage6 = runCommitLintOnMsg(commitMsgWithProperRevertMessage); + expect(properRevertMessage6.status).toBe(0); +}); + + test('subject-lowercase1', () => { let commitMsgWithUppercaseAfterColon = "foo: Bar baz"; let subjectLowerCase1 = runCommitLintOnMsg(commitMsgWithUppercaseAfterColon);