fix(dev-infra): use commit message validation from @angular/dev-infra-private (#36172)

Prior to this change we manage a local version of commit message validation
in addition to the commit message validation tool contained in the ng-dev
tooling.  By adding the ability to validate a range of commit messages
together, the remaining piece of commit message validation that is in the
local version is replicated.

We use both commands provided by the `ng-dev commit-message` tooling:
- pre-commit-validate: Set to automatically run on an git hook to validate
    commits as they are created locally.
- validate-range: Run by CI for every PR, testing that all of the commits
    added by the PR are valid when considered together.  Ensuring that all
    fixups are matched to another commit in the change.

PR Close #36172
This commit is contained in:
Joey Perrott
2020-03-20 12:24:12 -07:00
committed by Kara Erickson
parent 4894220acf
commit 61db817eed
18 changed files with 129 additions and 569 deletions

View File

@ -8,6 +8,12 @@
import {getAngularDevConfig} from '../utils/config';
import {CommitMessageConfig} from './config';
/** Options for commit message validation. */
export interface ValidateCommitMessageOptions {
disallowSquash?: boolean;
nonFixupCommitHeaders?: string[];
}
const FIXUP_PREFIX_RE = /^fixup! /i;
const GITHUB_LINKING_RE = /((closed?s?)|(fix(es)?(ed)?)|(resolved?s?))\s\#(\d+)/ig;
const SQUASH_PREFIX_RE = /^squash! /i;
@ -26,17 +32,17 @@ export function parseCommitMessage(commitMsg: string) {
let subject = '';
if (COMMIT_HEADER_RE.test(commitMsg)) {
header = COMMIT_HEADER_RE.exec(commitMsg) ![1]
header = COMMIT_HEADER_RE.exec(commitMsg)![1]
.replace(FIXUP_PREFIX_RE, '')
.replace(SQUASH_PREFIX_RE, '');
}
if (COMMIT_BODY_RE.test(commitMsg)) {
body = COMMIT_BODY_RE.exec(commitMsg) ![1];
body = COMMIT_BODY_RE.exec(commitMsg)![1];
bodyWithoutLinking = body.replace(GITHUB_LINKING_RE, '');
}
if (TYPE_SCOPE_RE.test(header)) {
const parsedCommitHeader = TYPE_SCOPE_RE.exec(header) !;
const parsedCommitHeader = TYPE_SCOPE_RE.exec(header)!;
type = parsedCommitHeader[1];
scope = parsedCommitHeader[2];
subject = parsedCommitHeader[3];
@ -54,10 +60,9 @@ export function parseCommitMessage(commitMsg: string) {
};
}
/** Validate a commit message against using the local repo's config. */
export function validateCommitMessage(
commitMsg: string, disallowSquash: boolean = false, nonFixupCommitHeaders?: string[]) {
commitMsg: string, options: ValidateCommitMessageOptions = {}) {
function error(errorMessage: string) {
console.error(
`INVALID COMMIT MSG: \n` +
@ -78,7 +83,7 @@ export function validateCommitMessage(
return true;
}
if (commit.isSquash && disallowSquash) {
if (commit.isSquash && options.disallowSquash) {
error('The commit must be manually squashed into the target commit');
return false;
}
@ -86,11 +91,11 @@ export function validateCommitMessage(
// If it is a fixup commit and `nonFixupCommitHeaders` is not empty, we only care to check whether
// there is a corresponding non-fixup commit (i.e. a commit whose header is identical to this
// commit's header after stripping the `fixup! ` prefix).
if (commit.isFixup && nonFixupCommitHeaders) {
if (!nonFixupCommitHeaders.includes(commit.header)) {
if (commit.isFixup && options.nonFixupCommitHeaders) {
if (!options.nonFixupCommitHeaders.includes(commit.header)) {
error(
'Unable to find match for fixup commit among prior commits: ' +
(nonFixupCommitHeaders.map(x => `\n ${x}`).join('') || '-'));
(options.nonFixupCommitHeaders.map(x => `\n ${x}`).join('') || '-'));
return false;
}
@ -118,8 +123,8 @@ export function validateCommitMessage(
}
if (commit.bodyWithoutLinking.trim().length < config.minBodyLength) {
error(
`The commit message body does not meet the minimum length of ${config.minBodyLength} characters`);
error(`The commit message body does not meet the minimum length of ${
config.minBodyLength} characters`);
return false;
}