feat(dev-infra): update commit-message functions to properly type commits from git log (#41458)
For commits from git log entries additional fields are available such as the reference hash and author name, update the utility functions in commit-message to include the parsed fields. Additionally define, per commit message type, whether to include the commit in a release notes entry. PR Close #41458
This commit is contained in:
parent
ba3344ddbe
commit
c63d00e5b0
|
@ -38,11 +38,17 @@ export enum ScopeRequirement {
|
||||||
Forbidden,
|
Forbidden,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum ReleaseNotesLevel {
|
||||||
|
Hidden,
|
||||||
|
Visible,
|
||||||
|
}
|
||||||
|
|
||||||
/** A commit type */
|
/** A commit type */
|
||||||
export interface CommitType {
|
export interface CommitType {
|
||||||
description: string;
|
description: string;
|
||||||
name: string;
|
name: string;
|
||||||
scope: ScopeRequirement;
|
scope: ScopeRequirement;
|
||||||
|
releaseNotesLevel: ReleaseNotesLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The valid commit types for Angular commit messages. */
|
/** The valid commit types for Angular commit messages. */
|
||||||
|
@ -51,45 +57,54 @@ export const COMMIT_TYPES: {[key: string]: CommitType} = {
|
||||||
name: 'build',
|
name: 'build',
|
||||||
description: 'Changes to local repository build system and tooling',
|
description: 'Changes to local repository build system and tooling',
|
||||||
scope: ScopeRequirement.Optional,
|
scope: ScopeRequirement.Optional,
|
||||||
|
releaseNotesLevel: ReleaseNotesLevel.Hidden,
|
||||||
},
|
},
|
||||||
ci: {
|
ci: {
|
||||||
name: 'ci',
|
name: 'ci',
|
||||||
description: 'Changes to CI configuration and CI specific tooling',
|
description: 'Changes to CI configuration and CI specific tooling',
|
||||||
scope: ScopeRequirement.Forbidden,
|
scope: ScopeRequirement.Forbidden,
|
||||||
|
releaseNotesLevel: ReleaseNotesLevel.Hidden,
|
||||||
},
|
},
|
||||||
docs: {
|
docs: {
|
||||||
name: 'docs',
|
name: 'docs',
|
||||||
description: 'Changes which exclusively affects documentation.',
|
description: 'Changes which exclusively affects documentation.',
|
||||||
scope: ScopeRequirement.Optional,
|
scope: ScopeRequirement.Optional,
|
||||||
|
releaseNotesLevel: ReleaseNotesLevel.Hidden,
|
||||||
},
|
},
|
||||||
feat: {
|
feat: {
|
||||||
name: 'feat',
|
name: 'feat',
|
||||||
description: 'Creates a new feature',
|
description: 'Creates a new feature',
|
||||||
scope: ScopeRequirement.Required,
|
scope: ScopeRequirement.Required,
|
||||||
|
releaseNotesLevel: ReleaseNotesLevel.Visible,
|
||||||
},
|
},
|
||||||
fix: {
|
fix: {
|
||||||
name: 'fix',
|
name: 'fix',
|
||||||
description: 'Fixes a previously discovered failure/bug',
|
description: 'Fixes a previously discovered failure/bug',
|
||||||
scope: ScopeRequirement.Required,
|
scope: ScopeRequirement.Required,
|
||||||
|
releaseNotesLevel: ReleaseNotesLevel.Visible,
|
||||||
},
|
},
|
||||||
perf: {
|
perf: {
|
||||||
name: 'perf',
|
name: 'perf',
|
||||||
description: 'Improves performance without any change in functionality or API',
|
description: 'Improves performance without any change in functionality or API',
|
||||||
scope: ScopeRequirement.Required,
|
scope: ScopeRequirement.Required,
|
||||||
|
releaseNotesLevel: ReleaseNotesLevel.Visible,
|
||||||
},
|
},
|
||||||
refactor: {
|
refactor: {
|
||||||
name: 'refactor',
|
name: 'refactor',
|
||||||
description: 'Refactor without any change in functionality or API (includes style changes)',
|
description: 'Refactor without any change in functionality or API (includes style changes)',
|
||||||
scope: ScopeRequirement.Required,
|
scope: ScopeRequirement.Required,
|
||||||
|
releaseNotesLevel: ReleaseNotesLevel.Hidden,
|
||||||
},
|
},
|
||||||
release: {
|
release: {
|
||||||
name: 'release',
|
name: 'release',
|
||||||
description: 'A release point in the repository',
|
description: 'A release point in the repository',
|
||||||
scope: ScopeRequirement.Forbidden,
|
scope: ScopeRequirement.Forbidden,
|
||||||
|
releaseNotesLevel: ReleaseNotesLevel.Hidden,
|
||||||
},
|
},
|
||||||
test: {
|
test: {
|
||||||
name: 'test',
|
name: 'test',
|
||||||
description: 'Improvements or corrections made to the project\'s test suite',
|
description: 'Improvements or corrections made to the project\'s test suite',
|
||||||
scope: ScopeRequirement.Required,
|
scope: ScopeRequirement.Required,
|
||||||
|
releaseNotesLevel: ReleaseNotesLevel.Hidden,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -41,6 +41,13 @@ export interface Commit {
|
||||||
isRevert: boolean;
|
isRevert: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** A parsed commit which originated from a Git Log entry */
|
||||||
|
export interface CommitFromGitLog extends Commit {
|
||||||
|
author: string;
|
||||||
|
hash: string;
|
||||||
|
shortHash: string;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of tuples expressing the fields to extract from each commit log entry. The tuple contains
|
* A list of tuples expressing the fields to extract from each commit log entry. The tuple contains
|
||||||
* two values, the first is the key for the property and the second is the template shortcut for the
|
* two values, the first is the key for the property and the second is the template shortcut for the
|
||||||
|
@ -107,9 +114,16 @@ const parseOptions: Options&{notesPattern: (keywords: string) => RegExp} = {
|
||||||
notesPattern: (keywords: string) => new RegExp(`(${keywords})(?:: ?)(.*)`),
|
notesPattern: (keywords: string) => new RegExp(`(${keywords})(?:: ?)(.*)`),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Parse a commit message into its composite parts. */
|
||||||
|
export const parseCommitMessage: (fullText: string) => Commit = parseInternal;
|
||||||
|
|
||||||
|
/** Parse a commit message from a git log entry into its composite parts. */
|
||||||
|
export const parseCommitFromGitLog: (fullText: Buffer) => CommitFromGitLog = parseInternal;
|
||||||
|
|
||||||
/** Parse a full commit message into its composite parts. */
|
/** Parse a full commit message into its composite parts. */
|
||||||
export function parseCommitMessage(fullText: string|Buffer): Commit {
|
function parseInternal(fullText: string): Commit;
|
||||||
|
function parseInternal(fullText: Buffer): CommitFromGitLog;
|
||||||
|
function parseInternal(fullText: string|Buffer): CommitFromGitLog|Commit {
|
||||||
// Ensure the fullText symbol is a `string`, even if a Buffer was provided.
|
// Ensure the fullText symbol is a `string`, even if a Buffer was provided.
|
||||||
fullText = fullText.toString();
|
fullText = fullText.toString();
|
||||||
/** The commit message text with the fixup and squash markers stripped out. */
|
/** The commit message text with the fixup and squash markers stripped out. */
|
||||||
|
@ -148,5 +162,8 @@ export function parseCommitMessage(fullText: string|Buffer): Commit {
|
||||||
isFixup: FIXUP_PREFIX_RE.test(fullText),
|
isFixup: FIXUP_PREFIX_RE.test(fullText),
|
||||||
isSquash: SQUASH_PREFIX_RE.test(fullText),
|
isSquash: SQUASH_PREFIX_RE.test(fullText),
|
||||||
isRevert: REVERT_PREFIX_RE.test(fullText),
|
isRevert: REVERT_PREFIX_RE.test(fullText),
|
||||||
|
author: commit.author || undefined,
|
||||||
|
hash: commit.hash || undefined,
|
||||||
|
shortHash: commit.shortHash || undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
import * as gitCommits_ from 'git-raw-commits';
|
import * as gitCommits_ from 'git-raw-commits';
|
||||||
|
|
||||||
import {Commit, gitLogFormatForParsing, parseCommitMessage} from './parse';
|
import {CommitFromGitLog, gitLogFormatForParsing, parseCommitFromGitLog} from './parse';
|
||||||
|
|
||||||
// Set `gitCommits` as this imported value to address "Cannot call a namespace" error.
|
// Set `gitCommits` as this imported value to address "Cannot call a namespace" error.
|
||||||
const gitCommits = gitCommits_;
|
const gitCommits = gitCommits_;
|
||||||
|
@ -16,16 +16,16 @@ const gitCommits = gitCommits_;
|
||||||
/**
|
/**
|
||||||
* Find all commits within the given range and return an object describing those.
|
* Find all commits within the given range and return an object describing those.
|
||||||
*/
|
*/
|
||||||
export function getCommitsInRange(from: string, to: string = 'HEAD'): Promise<Commit[]> {
|
export function getCommitsInRange(from: string, to: string = 'HEAD'): Promise<CommitFromGitLog[]> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
/** List of parsed commit objects. */
|
/** List of parsed commit objects. */
|
||||||
const commits: Commit[] = [];
|
const commits: CommitFromGitLog[] = [];
|
||||||
/** Stream of raw git commit strings in the range provided. */
|
/** Stream of raw git commit strings in the range provided. */
|
||||||
const commitStream = gitCommits({from, to, format: gitLogFormatForParsing});
|
const commitStream = gitCommits({from, to, format: gitLogFormatForParsing});
|
||||||
|
|
||||||
// Accumulate the parsed commits for each commit from the Readable stream into an array, then
|
// Accumulate the parsed commits for each commit from the Readable stream into an array, then
|
||||||
// resolve the promise with the array when the Readable stream ends.
|
// resolve the promise with the array when the Readable stream ends.
|
||||||
commitStream.on('data', (commit: Buffer) => commits.push(parseCommitMessage(commit)));
|
commitStream.on('data', (commit: Buffer) => commits.push(parseCommitFromGitLog(commit)));
|
||||||
commitStream.on('error', (err: Error) => reject(err));
|
commitStream.on('error', (err: Error) => reject(err));
|
||||||
commitStream.on('end', () => resolve(commits));
|
commitStream.on('end', () => resolve(commits));
|
||||||
});
|
});
|
||||||
|
|
|
@ -1670,52 +1670,66 @@ var ScopeRequirement;
|
||||||
ScopeRequirement[ScopeRequirement["Optional"] = 1] = "Optional";
|
ScopeRequirement[ScopeRequirement["Optional"] = 1] = "Optional";
|
||||||
ScopeRequirement[ScopeRequirement["Forbidden"] = 2] = "Forbidden";
|
ScopeRequirement[ScopeRequirement["Forbidden"] = 2] = "Forbidden";
|
||||||
})(ScopeRequirement || (ScopeRequirement = {}));
|
})(ScopeRequirement || (ScopeRequirement = {}));
|
||||||
|
var ReleaseNotesLevel;
|
||||||
|
(function (ReleaseNotesLevel) {
|
||||||
|
ReleaseNotesLevel[ReleaseNotesLevel["Hidden"] = 0] = "Hidden";
|
||||||
|
ReleaseNotesLevel[ReleaseNotesLevel["Visible"] = 1] = "Visible";
|
||||||
|
})(ReleaseNotesLevel || (ReleaseNotesLevel = {}));
|
||||||
/** The valid commit types for Angular commit messages. */
|
/** The valid commit types for Angular commit messages. */
|
||||||
const COMMIT_TYPES = {
|
const COMMIT_TYPES = {
|
||||||
build: {
|
build: {
|
||||||
name: 'build',
|
name: 'build',
|
||||||
description: 'Changes to local repository build system and tooling',
|
description: 'Changes to local repository build system and tooling',
|
||||||
scope: ScopeRequirement.Optional,
|
scope: ScopeRequirement.Optional,
|
||||||
|
releaseNotesLevel: ReleaseNotesLevel.Hidden,
|
||||||
},
|
},
|
||||||
ci: {
|
ci: {
|
||||||
name: 'ci',
|
name: 'ci',
|
||||||
description: 'Changes to CI configuration and CI specific tooling',
|
description: 'Changes to CI configuration and CI specific tooling',
|
||||||
scope: ScopeRequirement.Forbidden,
|
scope: ScopeRequirement.Forbidden,
|
||||||
|
releaseNotesLevel: ReleaseNotesLevel.Hidden,
|
||||||
},
|
},
|
||||||
docs: {
|
docs: {
|
||||||
name: 'docs',
|
name: 'docs',
|
||||||
description: 'Changes which exclusively affects documentation.',
|
description: 'Changes which exclusively affects documentation.',
|
||||||
scope: ScopeRequirement.Optional,
|
scope: ScopeRequirement.Optional,
|
||||||
|
releaseNotesLevel: ReleaseNotesLevel.Hidden,
|
||||||
},
|
},
|
||||||
feat: {
|
feat: {
|
||||||
name: 'feat',
|
name: 'feat',
|
||||||
description: 'Creates a new feature',
|
description: 'Creates a new feature',
|
||||||
scope: ScopeRequirement.Required,
|
scope: ScopeRequirement.Required,
|
||||||
|
releaseNotesLevel: ReleaseNotesLevel.Visible,
|
||||||
},
|
},
|
||||||
fix: {
|
fix: {
|
||||||
name: 'fix',
|
name: 'fix',
|
||||||
description: 'Fixes a previously discovered failure/bug',
|
description: 'Fixes a previously discovered failure/bug',
|
||||||
scope: ScopeRequirement.Required,
|
scope: ScopeRequirement.Required,
|
||||||
|
releaseNotesLevel: ReleaseNotesLevel.Visible,
|
||||||
},
|
},
|
||||||
perf: {
|
perf: {
|
||||||
name: 'perf',
|
name: 'perf',
|
||||||
description: 'Improves performance without any change in functionality or API',
|
description: 'Improves performance without any change in functionality or API',
|
||||||
scope: ScopeRequirement.Required,
|
scope: ScopeRequirement.Required,
|
||||||
|
releaseNotesLevel: ReleaseNotesLevel.Visible,
|
||||||
},
|
},
|
||||||
refactor: {
|
refactor: {
|
||||||
name: 'refactor',
|
name: 'refactor',
|
||||||
description: 'Refactor without any change in functionality or API (includes style changes)',
|
description: 'Refactor without any change in functionality or API (includes style changes)',
|
||||||
scope: ScopeRequirement.Required,
|
scope: ScopeRequirement.Required,
|
||||||
|
releaseNotesLevel: ReleaseNotesLevel.Hidden,
|
||||||
},
|
},
|
||||||
release: {
|
release: {
|
||||||
name: 'release',
|
name: 'release',
|
||||||
description: 'A release point in the repository',
|
description: 'A release point in the repository',
|
||||||
scope: ScopeRequirement.Forbidden,
|
scope: ScopeRequirement.Forbidden,
|
||||||
|
releaseNotesLevel: ReleaseNotesLevel.Hidden,
|
||||||
},
|
},
|
||||||
test: {
|
test: {
|
||||||
name: 'test',
|
name: 'test',
|
||||||
description: 'Improvements or corrections made to the project\'s test suite',
|
description: 'Improvements or corrections made to the project\'s test suite',
|
||||||
scope: ScopeRequirement.Required,
|
scope: ScopeRequirement.Required,
|
||||||
|
releaseNotesLevel: ReleaseNotesLevel.Hidden,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1790,8 +1804,11 @@ const parseOptions = {
|
||||||
noteKeywords: [NoteSections.BREAKING_CHANGE, NoteSections.DEPRECATED],
|
noteKeywords: [NoteSections.BREAKING_CHANGE, NoteSections.DEPRECATED],
|
||||||
notesPattern: (keywords) => new RegExp(`(${keywords})(?:: ?)(.*)`),
|
notesPattern: (keywords) => new RegExp(`(${keywords})(?:: ?)(.*)`),
|
||||||
};
|
};
|
||||||
/** Parse a full commit message into its composite parts. */
|
/** Parse a commit message into its composite parts. */
|
||||||
function parseCommitMessage(fullText) {
|
const parseCommitMessage = parseInternal;
|
||||||
|
/** Parse a commit message from a git log entry into its composite parts. */
|
||||||
|
const parseCommitFromGitLog = parseInternal;
|
||||||
|
function parseInternal(fullText) {
|
||||||
// Ensure the fullText symbol is a `string`, even if a Buffer was provided.
|
// Ensure the fullText symbol is a `string`, even if a Buffer was provided.
|
||||||
fullText = fullText.toString();
|
fullText = fullText.toString();
|
||||||
/** The commit message text with the fixup and squash markers stripped out. */
|
/** The commit message text with the fixup and squash markers stripped out. */
|
||||||
|
@ -1828,6 +1845,9 @@ function parseCommitMessage(fullText) {
|
||||||
isFixup: FIXUP_PREFIX_RE.test(fullText),
|
isFixup: FIXUP_PREFIX_RE.test(fullText),
|
||||||
isSquash: SQUASH_PREFIX_RE.test(fullText),
|
isSquash: SQUASH_PREFIX_RE.test(fullText),
|
||||||
isRevert: REVERT_PREFIX_RE.test(fullText),
|
isRevert: REVERT_PREFIX_RE.test(fullText),
|
||||||
|
author: commit.author || undefined,
|
||||||
|
hash: commit.hash || undefined,
|
||||||
|
shortHash: commit.shortHash || undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2083,7 +2103,7 @@ function getCommitsInRange(from, to = 'HEAD') {
|
||||||
const commitStream = gitCommits({ from, to, format: gitLogFormatForParsing });
|
const commitStream = gitCommits({ from, to, format: gitLogFormatForParsing });
|
||||||
// Accumulate the parsed commits for each commit from the Readable stream into an array, then
|
// Accumulate the parsed commits for each commit from the Readable stream into an array, then
|
||||||
// resolve the promise with the array when the Readable stream ends.
|
// resolve the promise with the array when the Readable stream ends.
|
||||||
commitStream.on('data', (commit) => commits.push(parseCommitMessage(commit)));
|
commitStream.on('data', (commit) => commits.push(parseCommitFromGitLog(commit)));
|
||||||
commitStream.on('error', (err) => reject(err));
|
commitStream.on('error', (err) => reject(err));
|
||||||
commitStream.on('end', () => resolve(commits));
|
commitStream.on('end', () => resolve(commits));
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue