Skip to content

Commit

Permalink
Add min-body-length option
Browse files Browse the repository at this point in the history
When set an error will be emitted if the body does not contain enough
characters. This is useful to require commit bodies with more
information, like impact, motivation, approach, testing results, new
behavior, etc. Default: no minimum. Suggested: at least 150.
  • Loading branch information
soulseekah committed May 24, 2024
1 parent 8d22319 commit 85936d3
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 1 deletion.
4 changes: 4 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ inputs:
description: 'Maximum length of the commit subject line'
required: false
default: ''
min-body-length:
description: 'Minimum length of the body of the commit message'
required: false
default: ''
max-body-line-length:
description: 'Maximum length of a line in the body of the commit message'
required: false
Expand Down
24 changes: 23 additions & 1 deletion dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29029,6 +29029,7 @@ class Inputs {
this.allowOneLiners = values.allowOneLiners;
this.additionalVerbs = values.additionalVerbs;
this.maxSubjectLength = values.maxSubjectLength;
this.minBodyLength = values.minBodyLength;
this.maxBodyLineLength = values.maxBodyLineLength;
this.enforceSignOff = values.enforceSignOff;
this.validatePullRequestCommits = values.validatePullRequestCommits;
Expand Down Expand Up @@ -29078,7 +29079,7 @@ function parseIntOrInfinity(text) {
return parseInt(text, 10);
}
function parseInputs(rawInputs) {
const { additionalVerbsInput = '', pathToAdditionalVerbsInput = '', allowOneLinersInput = '', maxSubjectLengthInput = '', maxBodyLineLengthInput = '', enforceSignOffInput = '', validatePullRequestCommitsInput = '', skipBodyCheckInput = '', ignoreMergeCommitsInput = '', ignorePatternsInput = '', } = rawInputs;
const { additionalVerbsInput = '', pathToAdditionalVerbsInput = '', allowOneLinersInput = '', maxSubjectLengthInput = '', minBodyLengthInput = '', maxBodyLineLengthInput = '', enforceSignOffInput = '', validatePullRequestCommitsInput = '', skipBodyCheckInput = '', ignoreMergeCommitsInput = '', ignorePatternsInput = '', } = rawInputs;
const additionalVerbs = new Set();
const hasAdditionalVerbsInput = additionalVerbsInput.length > 0;
if (additionalVerbsInput) {
Expand Down Expand Up @@ -29110,6 +29111,13 @@ function parseInputs(rawInputs) {
return new MaybeInputs(null, 'Unexpected value for max-subject-line-length. ' +
`Expected a number or nothing, got ${maxSubjectLengthInput}`);
}
const minBodyLength = !minBodyLengthInput
? 0
: parseInt(minBodyLengthInput, 10);
if (Number.isNaN(minBodyLength)) {
return new MaybeInputs(null, 'Unexpected value for min-body-length. ' +
`Expected a number or nothing, got ${minBodyLengthInput}`);
}
const maxBodyLineLength = !maxBodyLineLengthInput
? 72
: parseIntOrInfinity(maxBodyLineLengthInput);
Expand Down Expand Up @@ -29158,6 +29166,7 @@ function parseInputs(rawInputs) {
allowOneLiners,
additionalVerbs,
maxSubjectLength,
minBodyLength,
maxBodyLineLength,
enforceSignOff,
validatePullRequestCommits,
Expand Down Expand Up @@ -29380,6 +29389,15 @@ function checkBody(subject, bodyLines, inputs) {
errors.push('Unexpected empty body');
return errors;
}
// Minimum character body length
if (inputs.minBodyLength) {
const bodyLength = bodyLines.join(' ').length;
if (bodyLength < inputs.minBodyLength) {
errors.push(`The body must contain at least ${inputs.minBodyLength} characters. ` +
`The body contains ${bodyLength} characters.`);
return errors;
}
}
for (const [i, line] of bodyLines.entries()) {
if (urlLineRe.test(line) || linkDefinitionRe.test(line)) {
continue;
Expand Down Expand Up @@ -29574,6 +29592,9 @@ async function runWithExceptions() {
const maxSubjectLengthInput = core.getInput('max-subject-line-length', {
required: false,
});
const minBodyLengthInput = core.getInput('min-body-length', {
required: false,
});
const maxBodyLineLengthInput = core.getInput('max-body-line-length', {
required: false,
});
Expand All @@ -29597,6 +29618,7 @@ async function runWithExceptions() {
pathToAdditionalVerbsInput,
allowOneLinersInput,
maxSubjectLengthInput,
minBodyLengthInput,
maxBodyLineLengthInput,
enforceSignOffInput,
validatePullRequestCommitsInput,
Expand Down
2 changes: 2 additions & 0 deletions src/__tests__/input.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ it('parses the inputs.', () => {
pathToAdditionalVerbsInput: pathToVerbs,
allowOneLinersInput: 'true',
maxSubjectLengthInput: '90',
minBodyLengthInput: '120',
maxBodyLineLengthInput: '100',
enforceSignOffInput: 'true',
validatePullRequestCommitsInput: 'true',
Expand All @@ -56,6 +57,7 @@ it('parses the inputs.', () => {
);
expect(inputs.allowOneLiners).toBeTruthy();
expect(inputs.maxSubjectLength).toEqual(90);
expect(inputs.minBodyLength).toEqual(120);
expect(inputs.maxBodyLineLength).toEqual(100);
expect(inputs.enforceSignOff).toBeTruthy();
expect(inputs.validatePullRequestCommits).toBeTruthy();
Expand Down
42 changes: 42 additions & 0 deletions src/__tests__/inspection.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ it(
allowOneLiners: false,
additionalVerbs: new Set<string>('table'),
maxSubjectLength: 50,
minBodyLength: 0,
maxBodyLineLength: 72,
enforceSignOff: false,
validatePullRequestCommits: false,
Expand Down Expand Up @@ -318,6 +319,47 @@ it('reports too long a subject line with custom max length.', () => {
]);
});

it('reports too short a body length.', () => {
const message =
'Change SomeClass to OtherClass\n' +
'\n' +
'This replaces the SomeClass with OtherClass in all of the module\n' +
'since Some class was deprecated.';

const inputs = input.parseInputs({minBodyLengthInput: '100'}).mustInputs();

const errors = inspection.check(message, inputs);
expect(errors).toEqual([
`The body must contain at least 100 characters. ` +
`The body contains 97 characters.`
]);
});

it('accepts a body length.', () => {
const message =
'Change SomeClass to OtherClass\n' +
'\n' +
'This replaces the SomeClass with OtherClass in all of the module\n' +
'since Some class was deprecated.';

const inputs = input.parseInputs({minBodyLengthInput: '97'}).mustInputs();

const errors = inspection.check(message, inputs);
expect(errors).toEqual([]);
});

it('accepts a no minimum body length.', () => {
const message =
'Change SomeClass to OtherClass\n' +
'\n' +
'This changes SomeClass to OtherClass';

const inputs = input.parseInputs({}).mustInputs();

const errors = inspection.check(message, inputs);
expect(errors).toEqual([]);
});

it('reports too long a body line.', () => {
const message =
'Change SomeClass to OtherClass\n' +
Expand Down
18 changes: 18 additions & 0 deletions src/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ interface InputValues {
allowOneLiners: boolean;
additionalVerbs: Set<string>;
maxSubjectLength: number;
minBodyLength: number;
maxBodyLineLength: number;
enforceSignOff: boolean;
validatePullRequestCommits: boolean;
Expand All @@ -19,6 +20,7 @@ export class Inputs implements InputValues {
public pathToAdditionalVerbs: string;
public allowOneLiners: boolean;
public maxSubjectLength: number;
public minBodyLength: number;
public maxBodyLineLength: number;
public skipBodyCheck: boolean;
public validatePullRequestCommits: boolean;
Expand All @@ -38,6 +40,7 @@ export class Inputs implements InputValues {
this.allowOneLiners = values.allowOneLiners;
this.additionalVerbs = values.additionalVerbs;
this.maxSubjectLength = values.maxSubjectLength;
this.minBodyLength = values.minBodyLength;
this.maxBodyLineLength = values.maxBodyLineLength;
this.enforceSignOff = values.enforceSignOff;
this.validatePullRequestCommits = values.validatePullRequestCommits;
Expand Down Expand Up @@ -82,6 +85,7 @@ interface RawInputs {
pathToAdditionalVerbsInput?: string;
allowOneLinersInput?: string;
maxSubjectLengthInput?: string;
minBodyLengthInput?: string;
maxBodyLineLengthInput?: string;
enforceSignOffInput?: string;
validatePullRequestCommitsInput?: string;
Expand Down Expand Up @@ -118,6 +122,7 @@ export function parseInputs(rawInputs: RawInputs): MaybeInputs {
pathToAdditionalVerbsInput = '',
allowOneLinersInput = '',
maxSubjectLengthInput = '',
minBodyLengthInput = '',
maxBodyLineLengthInput = '',
enforceSignOffInput = '',
validatePullRequestCommitsInput = '',
Expand Down Expand Up @@ -176,6 +181,18 @@ export function parseInputs(rawInputs: RawInputs): MaybeInputs {
);
}

const minBodyLength: number = !minBodyLengthInput
? 0
: parseInt(minBodyLengthInput, 10);

if (Number.isNaN(minBodyLength)) {
return new MaybeInputs(
null,
'Unexpected value for min-body-length. ' +
`Expected a number or nothing, got ${minBodyLengthInput}`,
);
}

const maxBodyLineLength: number = !maxBodyLineLengthInput
? 72
: parseIntOrInfinity(maxBodyLineLengthInput);
Expand Down Expand Up @@ -253,6 +270,7 @@ export function parseInputs(rawInputs: RawInputs): MaybeInputs {
allowOneLiners,
additionalVerbs,
maxSubjectLength,
minBodyLength,
maxBodyLineLength,
enforceSignOff,
validatePullRequestCommits,
Expand Down
13 changes: 13 additions & 0 deletions src/inspection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,19 @@ function checkBody(
return errors;
}

// Minimum character body length
if (inputs.minBodyLength) {
const bodyLength = bodyLines.join(' ').length;

if (bodyLength < inputs.minBodyLength) {
errors.push(
`The body must contain at least ${inputs.minBodyLength} characters. ` +
`The body contains ${bodyLength} characters.`,
);
return errors;
}
}

for (const [i, line] of bodyLines.entries()) {
if (urlLineRe.test(line) || linkDefinitionRe.test(line)) {
continue;
Expand Down
5 changes: 5 additions & 0 deletions src/mainImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ async function runWithExceptions(): Promise<void> {
required: false,
});

const minBodyLengthInput = core.getInput('min-body-length', {
required: false,
});

const maxBodyLineLengthInput = core.getInput('max-body-line-length', {
required: false,
});
Expand Down Expand Up @@ -57,6 +61,7 @@ async function runWithExceptions(): Promise<void> {
pathToAdditionalVerbsInput,
allowOneLinersInput,
maxSubjectLengthInput,
minBodyLengthInput,
maxBodyLineLengthInput,
enforceSignOffInput,
validatePullRequestCommitsInput,
Expand Down

0 comments on commit 85936d3

Please sign in to comment.