Skip to content

Commit 1e562e9

Browse files
authored
Prevent duplicate changelog entries (#10786)
The changelog update script now prevents duplicate entries from being added. Specifically, it will ensure that if a PR has been referenced already in an entry, it will not add it again. This should prevent it from adding duplicate entries for changes that were cherry-picked into hotfix releases. Note that this duplication prevention only works for entries containing a PR number. We don't have any way to prevent duplicate entries yet in cases where we don't know the associated PR. We will be preventing this possibility entirely pretty soon in some upcoming release automation changes though, so I'm not concerned about this omission.
1 parent dc75c18 commit 1e562e9

File tree

1 file changed

+34
-10
lines changed

1 file changed

+34
-10
lines changed

development/auto-changelog.js

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ async function main() {
2727
`${mostRecentTag}..HEAD`,
2828
]);
2929

30-
const changelogEntries = [];
30+
const commitEntries = [];
3131
for (const commit of commitsSinceLastRelease) {
3232
const [subject] = await runCommand('git', [
3333
'show',
@@ -36,20 +36,20 @@ async function main() {
3636
commit,
3737
]);
3838

39-
let prefix;
39+
let prNumber;
4040
let description = subject;
4141

4242
// Squash & Merge: the commit subject is parsed as `<description> (#<PR ID>)`
4343
if (subject.match(/\(#\d+\)/u)) {
44-
const [, prNumber] = subject.match(/\(#(\d+)\)/u);
45-
prefix = `[#${prNumber}](${URL}/pull/${prNumber})`;
44+
const matchResults = subject.match(/\(#(\d+)\)/u);
45+
prNumber = matchResults[1];
4646
description = subject.match(/^(.+)\s\(#\d+\)/u)[1];
4747
// Merge: the PR ID is parsed from the git subject (which is of the form `Merge pull request
4848
// #<PR ID> from <branch>`, and the description is assumed to be the first line of the body.
4949
// If no body is found, the description is set to the commit subject
5050
} else if (subject.match(/#\d+\sfrom/u)) {
51-
const [, prNumber] = subject.match(/#(\d+)\sfrom/u);
52-
prefix = `[#${prNumber}](${URL}/pull/${prNumber})`;
51+
const matchResults = subject.match(/#(\d+)\sfrom/u);
52+
prNumber = matchResults[1];
5353
const [firstLineOfBody] = await runCommand('git', [
5454
'show',
5555
'-s',
@@ -61,10 +61,7 @@ async function main() {
6161
// Otherwise:
6262
// Normal commits: The commit subject is the description, and the PR ID is omitted.
6363

64-
const changelogEntry = prefix
65-
? `- ${prefix}: ${description}`
66-
: `- ${description}`;
67-
changelogEntries.push(changelogEntry);
64+
commitEntries.push({ prNumber, description });
6865
}
6966

7067
const changelogFilename = path.resolve(__dirname, '..', 'CHANGELOG.md');
@@ -93,6 +90,33 @@ async function main() {
9390
}'`,
9491
);
9592
}
93+
94+
const prNumbersWithChangelogEntries = [];
95+
for (const line of changelogLines) {
96+
const matchResults = line.match(/- \[#(\d+)\]/u);
97+
if (matchResults === null) {
98+
continue;
99+
}
100+
const prNumber = matchResults[1];
101+
prNumbersWithChangelogEntries.push(prNumber);
102+
}
103+
104+
const changelogEntries = [];
105+
for (const { prNumber, description } of commitEntries) {
106+
if (prNumbersWithChangelogEntries.includes(prNumber)) {
107+
continue;
108+
}
109+
110+
let changelogEntry;
111+
if (prNumber) {
112+
const prefix = `[#${prNumber}](${URL}/pull/${prNumber})`;
113+
changelogEntry = `- ${prefix}: ${description}`;
114+
} else {
115+
changelogEntry = `- ${description}`;
116+
}
117+
changelogEntries.push(changelogEntry);
118+
}
119+
96120
changelogLines.splice(releaseHeaderIndex + 1, 0, ...changelogEntries);
97121
const updatedChangelog = changelogLines.join('\n');
98122
await fs.writeFile(changelogFilename, updatedChangelog);

0 commit comments

Comments
 (0)