diff --git a/commitlint.config.ts b/commitlint.config.ts index e66f89378..7d6a14d68 100644 --- a/commitlint.config.ts +++ b/commitlint.config.ts @@ -50,11 +50,15 @@ module.exports = { // disabled because most of the time it doesn't work, due to https://github.com/conventional-changelog/commitlint/issues/3404 // and anyway we were using this rule only as a warning, not an error (because a scope is not required, e.g. when too broad) "type-empty": [RuleConfigSeverity.Disabled, "never"], + "default-revert-message": [RuleConfigSeverity.Error, "never"], }, + + // 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). - // * Detect reverts which have not been elaborated. // * Reject some stupid obvious words: change, update, modify (if first word after colon, error; otherwise warning). // * Think of how to reject this shitty commit message: https://github.com/nblockchain/NOnion/pull/34/commits/9ffcb373a1147ed1c729e8aca4ffd30467255594 // * Workflow: detect if wip commit in a branch not named "wip/*" or whose name contains "squashed". @@ -139,6 +143,32 @@ module.exports = { return Plugins.properIssueRefs(rawStr); }, + "default-revert-message": ( + { + header, + body, + }: { + header: any; + body: any; + }, + when: string + ) => { + let bodyStr = Helpers.convertAnyToString(body, "body"); + let headerUncastedStr = Helpers.convertAnyToString( + header, + "header" + ); + let headerStr = Helpers.assertNotNull( + headerUncastedStr, + notNullStringErrorMessage("header") + ); + return Plugins.defaultRevertMessage( + headerStr, + bodyStr, + when + ); + }, + "title-uppercase": ({ header }: { header: any }) => { let headerStr = Helpers.assertNotNull( Helpers.convertAnyToString(header, "header"), diff --git a/commitlint/plugins.ts b/commitlint/plugins.ts index 250ed9202..49a0f5ff8 100644 --- a/commitlint/plugins.ts +++ b/commitlint/plugins.ts @@ -262,6 +262,44 @@ export abstract class Plugins { ]; } + public static defaultRevertMessage( + headerStr: string, + bodyStr: string | null, + when: string + ) { + let offence = false; + let isRevertCommitMessage = headerStr.toLowerCase().includes("revert"); + + const negated = when === "never"; + + if (isRevertCommitMessage) { + let isDefaultRevertHeader = + headerStr.match(/^[Rr]evert ".+"$/) !== null; + + if (isDefaultRevertHeader) { + if (bodyStr !== null) { + let lines = bodyStr.split("\n"); + offence = + // 40 is the length of git commit hash. + lines.length == 1 && + lines[0].match(/^This reverts commit [^ ]{40}\.$/) !== + null; + } else { + offence = true; + } + } + + offence = negated ? offence : !offence; + } + return [ + !offence, + (negated + ? `Please explain why you're reverting` + : `Please don't change the default revert commit message`) + + Helpers.errMessageSuffix, + ]; + } + public static titleUppercase(headerStr: string) { let firstWord = headerStr.split(" ")[0]; let offence =