diff --git a/dev-infra/commit-message/config.ts b/dev-infra/commit-message/config.ts index 7a84edc488..2d9739cecf 100644 --- a/dev-infra/commit-message/config.ts +++ b/dev-infra/commit-message/config.ts @@ -11,6 +11,7 @@ import {assertNoErrors, getConfig, NgDevConfig} from '../utils/config'; export interface CommitMessageConfig { maxLineLength: number; minBodyLength: number; + minBodyLengthTypeExcludes?: string[]; types: string[]; scopes: string[]; } @@ -19,7 +20,7 @@ export interface CommitMessageConfig { export function getCommitMessageConfig() { // List of errors encountered validating the config. const errors: string[] = []; - // The unvalidated config object. + // The non-validated config object. const config: Partial> = getConfig(); if (config.commitMessage === undefined) { diff --git a/dev-infra/commit-message/validate.spec.ts b/dev-infra/commit-message/validate.spec.ts index e745fa7158..ad1bf5b1e9 100644 --- a/dev-infra/commit-message/validate.spec.ts +++ b/dev-infra/commit-message/validate.spec.ts @@ -10,19 +10,22 @@ import * as validateConfig from './config'; import {validateCommitMessage} from './validate'; +type CommitMessageConfig = validateConfig.CommitMessageConfig; + + // Constants -const config = { - 'commitMessage': { - 'maxLineLength': 120, - 'minBodyLength': 0, - 'types': [ +const config: {commitMessage: CommitMessageConfig} = { + commitMessage: { + maxLineLength: 120, + minBodyLength: 0, + types: [ 'feat', 'fix', 'refactor', 'release', 'style', ], - 'scopes': [ + scopes: [ 'common', 'compiler', 'core', @@ -224,5 +227,42 @@ describe('validate-commit-message.js', () => { }); }); }); + + describe('minBodyLength', () => { + const minBodyLengthConfig: {commitMessage: CommitMessageConfig} = { + commitMessage: { + maxLineLength: 120, + minBodyLength: 30, + minBodyLengthTypeExcludes: ['docs'], + types: ['fix', 'docs'], + scopes: ['core'] + } + }; + + beforeEach(() => { + (validateConfig.getCommitMessageConfig as jasmine.Spy).and.returnValue(minBodyLengthConfig); + }); + + it('should fail validation if the body is shorter than `minBodyLength`', () => { + expect(validateCommitMessage( + 'fix(core): something\n\n Explanation of the motivation behind this change')) + .toBe(VALID); + expect(validateCommitMessage('fix(core): something\n\n too short')).toBe(INVALID); + expect(lastError).toContain( + 'The commit message body does not meet the minimum length of 30 characters'); + expect(validateCommitMessage('fix(core): something')).toBe(INVALID); + expect(lastError).toContain( + 'The commit message body does not meet the minimum length of 30 characters'); + }); + + it('should pass validation if the body is shorter than `minBodyLength` but the commit type is in the `minBodyLengthTypeExclusions` list', + () => { + expect(validateCommitMessage('docs: just fixing a typo')).toBe(VALID); + expect(validateCommitMessage('docs(core): just fixing a typo')).toBe(VALID); + expect(validateCommitMessage( + 'docs(core): just fixing a typo\n\nThis was just a silly typo.')) + .toBe(VALID); + }); + }); }); }); diff --git a/dev-infra/commit-message/validate.ts b/dev-infra/commit-message/validate.ts index 6148f6dfe2..a9b01f1c4d 100644 --- a/dev-infra/commit-message/validate.ts +++ b/dev-infra/commit-message/validate.ts @@ -148,7 +148,8 @@ export function validateCommitMessage( // Checking commit body // ////////////////////////// - if (commit.bodyWithoutLinking.trim().length < config.minBodyLength) { + if (!config.minBodyLengthTypeExcludes?.includes(commit.type) && + commit.bodyWithoutLinking.trim().length < config.minBodyLength) { printError(`The commit message body does not meet the minimum length of ${ config.minBodyLength} characters`); return false; @@ -157,7 +158,7 @@ export function validateCommitMessage( const bodyByLine = commit.body.split('\n'); if (bodyByLine.some(line => line.length > config.maxLineLength)) { printError( - `The commit messsage body contains lines greater than ${config.maxLineLength} characters`); + `The commit message body contains lines greater than ${config.maxLineLength} characters`); return false; }