Skip to content

Commit

Permalink
build: changelog should collect deprecations (#17740)
Browse files Browse the repository at this point in the history
Introduces a new commit note type that can be
used for deprecations that should be collected
in the changelog.

Closes #16307
  • Loading branch information
devversion authored and jelbourn committed Nov 18, 2019
1 parent 3acd6c1 commit f9ab982
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 6 deletions.
7 changes: 5 additions & 2 deletions CONTRIBUTING.md
Expand Up @@ -237,12 +237,15 @@ Just as in the **subject**, use the imperative, present tense: "change" not "cha
The body should include the motivation for the change and contrast this with previous behavior.

### Footer
The footer should contain any information about **Breaking Changes** and is also the place to
reference GitHub issues that this commit **Closes**.
The footer should contain any information about **Breaking Changes** or **Deprecations** and
is also the place to reference GitHub issues that this commit **Closes**.

**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines.
The rest of the commit message is then used for this.

**Deprecations** should start with the word `DEPRECATED:`. The rest of the commit message will be
used as content for the note.

A detailed explanation can be found in this [document][commit-message-format].

## <a name="cla"></a> Signing the CLA
Expand Down
8 changes: 8 additions & 0 deletions tools/release/changelog-root-template.hbs
Expand Up @@ -10,6 +10,14 @@ _Breaking changes:_
* {{#if commit.scope}}**{{commit.scope}}:** {{/if}}{{text}}
{{/each}}

{{/if}}
{{#if deprecations.length}}
_Deprecations:_

{{#each deprecations}}
* {{#if commit.scope}}**{{commit.scope}}:** {{/if}}{{text}}
{{/each}}

{{/if}}
| | |
| ---------- | --------------------- |
Expand Down
39 changes: 35 additions & 4 deletions tools/release/changelog.ts
Expand Up @@ -9,10 +9,20 @@ const conventionalChangelog = require('conventional-changelog');
const changelogCompare = require('conventional-changelog-writer/lib/util');
const merge2 = require('merge2');

/**
* Maps a commit note to a string that will be used to match notes of the
* given type in commit messages.
*/
const enum CommitNote {
Deprecation = 'DEPRECATED',
BreakingChange = 'BREAKING CHANGE',
}

/** Interface that describes a package in the changelog. */
interface ChangelogPackage {
commits: any[];
breakingChanges: any[];
deprecations: any[];
}

/** Hardcoded order of packages shown in the changelog. */
Expand Down Expand Up @@ -41,6 +51,7 @@ export async function promptAndGenerateChangelog(changelogPath: string) {
* @param releaseName Name of the release that should show up in the changelog.
*/
export async function prependChangelogFromLatestTag(changelogPath: string, releaseName: string) {
const angularPresetWriterOptions = await require('conventional-changelog-angular/writer-opts');
const outputStream: Readable = conventionalChangelog(
/* core options */ {preset: 'angular'},
/* context options */ {title: releaseName},
Expand All @@ -50,8 +61,9 @@ export async function prependChangelogFromLatestTag(changelogPath: string, relea
// name from the commit message.
headerPattern: /^(\w*)(?:\((?:([^/]+)\/)?(.*)\))?: (.*)$/,
headerCorrespondence: ['type', 'package', 'scope', 'subject'],
noteKeywords: [CommitNote.BreakingChange, CommitNote.Deprecation],
},
/* writer options */ createChangelogWriterOptions(changelogPath));
/* writer options */ createChangelogWriterOptions(changelogPath, angularPresetWriterOptions));

// Stream for reading the existing changelog. This is necessary because we want to
// actually prepend the new changelog to the existing one.
Expand Down Expand Up @@ -93,7 +105,7 @@ export async function promptChangelogReleaseName(): Promise<string> {
* build the changelog from last major version to master's HEAD when a new major version is being
* published from the "master" branch.
*/
function createChangelogWriterOptions(changelogPath: string) {
function createChangelogWriterOptions(changelogPath: string, presetWriterOptions: any) {
const existingChangelogContent = readFileSync(changelogPath, 'utf8');
const commitSortFunction = changelogCompare.functionify(['type', 'scope', 'subject']);
const allPackages = [...orderedChangelogPackages, ...excludedChangelogPackages];
Expand All @@ -105,6 +117,14 @@ function createChangelogWriterOptions(changelogPath: string) {
mainTemplate: readFileSync(join(__dirname, 'changelog-root-template.hbs'), 'utf8'),
commitPartial: readFileSync(join(__dirname, 'changelog-commit-template.hbs'), 'utf8'),

// Overwrites the conventional-changelog-angular preset transform function. This is necessary
// because the Angular preset changes every commit note to a breaking change note. Since we
// have a custom note type for deprecations, we need to keep track of the original type.
transform: (commit, context) => {
commit.notes.forEach(n => n.type = n.title);
return presetWriterOptions.transform(commit, context);
},

// Specify a writer option that can be used to modify the content of a new changelog section.
// See: conventional-changelog/tree/master/packages/conventional-changelog-writer
finalizeContext: (context: any) => {
Expand Down Expand Up @@ -139,11 +159,21 @@ function createChangelogWriterOptions(changelogPath: string) {
const type = getTypeOfCommitGroupDescription(group.title);

if (!packageGroups[packageName]) {
packageGroups[packageName] = {commits: [], breakingChanges: []};
packageGroups[packageName] = {commits: [], breakingChanges: [], deprecations: []};
}
const packageGroup = packageGroups[packageName];

packageGroup.breakingChanges.push(...commit.notes);
// Collect all notes of the commit. Either breaking change or deprecation notes.
commit.notes.forEach(n => {
if (n.type === CommitNote.Deprecation) {
packageGroup.deprecations.push(n);
} else if (n.type === CommitNote.BreakingChange) {
packageGroup.breakingChanges.push(n);
} else {
throw Error(`Found commit note that is not known: ${JSON.stringify(n, null, 2)}`);
}
});

packageGroup.commits.push({...commit, type});
});
});
Expand All @@ -159,6 +189,7 @@ function createChangelogWriterOptions(changelogPath: string) {
title: pkgName,
commits: packageGroup.commits.sort(commitSortFunction),
breakingChanges: packageGroup.breakingChanges,
deprecations: packageGroup.deprecations,
};
});

Expand Down

0 comments on commit f9ab982

Please sign in to comment.