2020-03-20 15:24:12 -04:00
|
|
|
/**
|
|
|
|
* @license
|
2020-05-19 15:08:49 -04:00
|
|
|
* Copyright Google LLC All Rights Reserved.
|
2020-03-20 15:24:12 -04:00
|
|
|
*
|
|
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
|
|
* found in the LICENSE file at https://angular.io/license
|
|
|
|
*/
|
2021-03-24 19:17:15 -04:00
|
|
|
import {error, green, info, red} from '../../utils/console';
|
|
|
|
import {Commit} from '../parse';
|
|
|
|
import {getCommitsInRange} from '../utils';
|
2020-09-14 16:21:31 -04:00
|
|
|
import {printValidationErrors, validateCommitMessage, ValidateCommitMessageOptions} from '../validate';
|
2020-03-20 15:24:12 -04:00
|
|
|
|
|
|
|
// Whether the provided commit is a fixup commit.
|
2021-03-19 15:11:21 -04:00
|
|
|
const isNonFixup = (commit: Commit) => !commit.isFixup;
|
2020-03-20 15:24:12 -04:00
|
|
|
|
2020-04-20 19:50:25 -04:00
|
|
|
// Extracts commit header (first line of commit message).
|
2021-03-19 15:11:21 -04:00
|
|
|
const extractCommitHeader = (commit: Commit) => commit.header;
|
2020-04-20 19:50:25 -04:00
|
|
|
|
2020-03-20 15:24:12 -04:00
|
|
|
/** Validate all commits in a provided git commit range. */
|
2021-03-24 19:17:15 -04:00
|
|
|
export async function validateCommitRange(from: string, to: string) {
|
2020-11-17 14:20:41 -05:00
|
|
|
/** A list of tuples of the commit header string and a list of error messages for the commit. */
|
2020-09-03 17:54:31 -04:00
|
|
|
const errors: [commitHeader: string, errors: string[]][] = [];
|
2021-03-24 19:17:15 -04:00
|
|
|
|
2020-11-17 14:20:41 -05:00
|
|
|
/** A list of parsed commit messages from the range. */
|
2021-03-24 19:17:15 -04:00
|
|
|
const commits = await getCommitsInRange(from, to);
|
|
|
|
info(`Examining ${commits.length} commit(s) in the provided range: ${from}..${to}`);
|
2020-03-20 15:24:12 -04:00
|
|
|
|
2020-11-17 14:20:41 -05:00
|
|
|
/**
|
|
|
|
* Whether all commits in the range are valid, commits are allowed to be fixup commits for other
|
|
|
|
* commits in the provided commit range.
|
|
|
|
*/
|
|
|
|
const allCommitsInRangeValid = commits.every((commit, i) => {
|
2020-03-20 15:24:12 -04:00
|
|
|
const options: ValidateCommitMessageOptions = {
|
|
|
|
disallowSquash: true,
|
2020-11-17 14:20:41 -05:00
|
|
|
nonFixupCommitHeaders: isNonFixup(commit) ?
|
2020-04-20 19:50:25 -04:00
|
|
|
undefined :
|
2021-03-24 19:17:15 -04:00
|
|
|
commits.slice(i + 1).filter(isNonFixup).map(extractCommitHeader)
|
2020-03-20 15:24:12 -04:00
|
|
|
};
|
2020-11-17 14:20:41 -05:00
|
|
|
const {valid, errors: localErrors} = validateCommitMessage(commit, options);
|
2020-09-03 17:54:31 -04:00
|
|
|
if (localErrors.length) {
|
|
|
|
errors.push([commit.header, localErrors]);
|
|
|
|
}
|
|
|
|
return valid;
|
2020-03-20 15:24:12 -04:00
|
|
|
});
|
2020-04-20 13:42:09 -04:00
|
|
|
|
2020-03-20 15:24:12 -04:00
|
|
|
if (allCommitsInRangeValid) {
|
2021-03-24 19:17:15 -04:00
|
|
|
info(green('√ All commit messages in range valid.'));
|
2020-04-20 13:42:09 -04:00
|
|
|
} else {
|
2021-03-24 19:17:15 -04:00
|
|
|
error(red('✘ Invalid commit message'));
|
2020-09-03 17:54:31 -04:00
|
|
|
errors.forEach(([header, validationErrors]) => {
|
|
|
|
error.group(header);
|
|
|
|
printValidationErrors(validationErrors);
|
|
|
|
error.groupEnd();
|
|
|
|
});
|
2020-04-20 13:42:09 -04:00
|
|
|
// Exit with a non-zero exit code if invalid commit messages have
|
|
|
|
// been discovered.
|
|
|
|
process.exit(1);
|
2020-03-20 15:24:12 -04:00
|
|
|
}
|
|
|
|
}
|