Skip to content

Commit f9ab982

Browse files
devversionjelbourn
authored andcommitted
build: changelog should collect deprecations (#17740)
Introduces a new commit note type that can be used for deprecations that should be collected in the changelog. Closes #16307
1 parent 3acd6c1 commit f9ab982

File tree

3 files changed

+48
-6
lines changed

3 files changed

+48
-6
lines changed

CONTRIBUTING.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,12 +237,15 @@ Just as in the **subject**, use the imperative, present tense: "change" not "cha
237237
The body should include the motivation for the change and contrast this with previous behavior.
238238

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

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

246+
**Deprecations** should start with the word `DEPRECATED:`. The rest of the commit message will be
247+
used as content for the note.
248+
246249
A detailed explanation can be found in this [document][commit-message-format].
247250

248251
## <a name="cla"></a> Signing the CLA

tools/release/changelog-root-template.hbs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ _Breaking changes:_
1010
* {{#if commit.scope}}**{{commit.scope}}:** {{/if}}{{text}}
1111
{{/each}}
1212

13+
{{/if}}
14+
{{#if deprecations.length}}
15+
_Deprecations:_
16+
17+
{{#each deprecations}}
18+
* {{#if commit.scope}}**{{commit.scope}}:** {{/if}}{{text}}
19+
{{/each}}
20+
1321
{{/if}}
1422
| | |
1523
| ---------- | --------------------- |

tools/release/changelog.ts

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,20 @@ const conventionalChangelog = require('conventional-changelog');
99
const changelogCompare = require('conventional-changelog-writer/lib/util');
1010
const merge2 = require('merge2');
1111

12+
/**
13+
* Maps a commit note to a string that will be used to match notes of the
14+
* given type in commit messages.
15+
*/
16+
const enum CommitNote {
17+
Deprecation = 'DEPRECATED',
18+
BreakingChange = 'BREAKING CHANGE',
19+
}
20+
1221
/** Interface that describes a package in the changelog. */
1322
interface ChangelogPackage {
1423
commits: any[];
1524
breakingChanges: any[];
25+
deprecations: any[];
1626
}
1727

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

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

120+
// Overwrites the conventional-changelog-angular preset transform function. This is necessary
121+
// because the Angular preset changes every commit note to a breaking change note. Since we
122+
// have a custom note type for deprecations, we need to keep track of the original type.
123+
transform: (commit, context) => {
124+
commit.notes.forEach(n => n.type = n.title);
125+
return presetWriterOptions.transform(commit, context);
126+
},
127+
108128
// Specify a writer option that can be used to modify the content of a new changelog section.
109129
// See: conventional-changelog/tree/master/packages/conventional-changelog-writer
110130
finalizeContext: (context: any) => {
@@ -139,11 +159,21 @@ function createChangelogWriterOptions(changelogPath: string) {
139159
const type = getTypeOfCommitGroupDescription(group.title);
140160

141161
if (!packageGroups[packageName]) {
142-
packageGroups[packageName] = {commits: [], breakingChanges: []};
162+
packageGroups[packageName] = {commits: [], breakingChanges: [], deprecations: []};
143163
}
144164
const packageGroup = packageGroups[packageName];
145165

146-
packageGroup.breakingChanges.push(...commit.notes);
166+
// Collect all notes of the commit. Either breaking change or deprecation notes.
167+
commit.notes.forEach(n => {
168+
if (n.type === CommitNote.Deprecation) {
169+
packageGroup.deprecations.push(n);
170+
} else if (n.type === CommitNote.BreakingChange) {
171+
packageGroup.breakingChanges.push(n);
172+
} else {
173+
throw Error(`Found commit note that is not known: ${JSON.stringify(n, null, 2)}`);
174+
}
175+
});
176+
147177
packageGroup.commits.push({...commit, type});
148178
});
149179
});
@@ -159,6 +189,7 @@ function createChangelogWriterOptions(changelogPath: string) {
159189
title: pkgName,
160190
commits: packageGroup.commits.sort(commitSortFunction),
161191
breakingChanges: packageGroup.breakingChanges,
192+
deprecations: packageGroup.deprecations,
162193
};
163194
});
164195

0 commit comments

Comments
 (0)