Skip to content

Commit 569468e

Browse files
committed
feat(git-node): add support for auto-fill Notable Changes section
Allows PR author (or repo maintainers) to define themselves the Notable Change using a `<details>` section in the PR description.
1 parent 4bd6820 commit 569468e

File tree

3 files changed

+64
-15
lines changed

3 files changed

+64
-15
lines changed

components/git/release.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,10 @@ async function main(state, argv, cli, dir) {
116116
if (prID) {
117117
argv.prid = Number(prID[1]);
118118
}
119+
const credentials = await auth({ github: true });
120+
const request = new Request(credentials);
119121
if (state === PREPARE) {
120-
const release = new ReleasePreparation(argv, cli, dir);
122+
const release = new ReleasePreparation(argv, request, cli, dir);
121123

122124
await release.prepareLocalBranch();
123125

@@ -137,8 +139,6 @@ async function main(state, argv, cli, dir) {
137139

138140
return release.prepare();
139141
} else if (state === PROMOTE) {
140-
const credentials = await auth({ github: true });
141-
const request = new Request(credentials);
142142
const release = new ReleasePromotion(argv, request, cli, dir);
143143

144144
cli.startSpinner('Verifying Releaser status');

lib/prepare_release.js

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import path from 'node:path';
22
import { promises as fs } from 'node:fs';
3+
import { createInterface } from 'node:readline';
4+
import { spawn } from 'node:child_process';
35

46
import semver from 'semver';
57
import { replaceInFile } from 'replace-in-file';
@@ -19,8 +21,9 @@ import Session from './session.js';
1921
const isWindows = process.platform === 'win32';
2022

2123
export default class ReleasePreparation extends Session {
22-
constructor(argv, cli, dir) {
24+
constructor(argv, request, cli, dir) {
2325
super(cli, dir);
26+
this.req = request;
2427
this.isSecurityRelease = argv.security;
2528
this.isLTS = false;
2629
this.isLTSTransition = argv.startLTS;
@@ -176,10 +179,10 @@ export default class ReleasePreparation extends Session {
176179
// Check the branch diff to determine if the releaser
177180
// wants to backport any more commits before proceeding.
178181
cli.startSpinner('Fetching branch-diff');
179-
const raw = await this.getBranchDiff({
182+
const raw = runSync(...await this.getBranchDiff({
180183
onlyNotableChanges: false,
181184
comparisonBranch: newVersion
182-
});
185+
}));
183186

184187
const diff = raw.split('*');
185188
cli.stopSpinner('Got branch diff');
@@ -414,6 +417,38 @@ export default class ReleasePreparation extends Session {
414417
});
415418
}
416419

420+
async fetchNotableChanges(commitListCmd) {
421+
const commitListProcess = spawn(...commitListCmd);
422+
const commitList = createInterface({ input: commitListProcess.stdout });
423+
const commitPattern = /^\* \\\[\[`([a-f0-9]+)`\]\(https:\/\/github\.com\/([^/]+)\/([^/]+)\/commit\/\1\)\] -(?: \*\*\(SEMVER-MINOR\)\*\*)? (.+) \((.+)\) \[#(\d+)\]\(https:\/\/github\.com\/\2\/\3\/pull\/\6\)$/;
424+
const detailsPattern = /(?:^|\r?\n\r?\n)<details[^>]+><summary>Notable changes?<\/summary>\r?\n\r?\n(?:#+ ([^\r\n]+)\r?\n)?(.+)\r?\n\r?\n<\/details>(?:\r?\n\r?\n|$)/s;
425+
let notableChangesSections = '';
426+
let otherNotableChanges = '';
427+
for await (const line of commitList) {
428+
const { 2: owner, 3: repo, 4: title, 5: author, 6: prId } = commitPattern.exec(line);
429+
const { repository: { pullRequest: { body, labels } } } = await this.req.gql(
430+
'PRNotableChange',
431+
{ owner, repo, prId: Number(prId) });
432+
const notableChangeMd =
433+
labels.nodes.some(({ name }) => name === 'notable-change') &&
434+
detailsPattern.exec(body);
435+
if (notableChangeMd) {
436+
notableChangesSections +=
437+
`\n#### ${notableChangeMd[1] || title}\n${notableChangeMd[2]}\nContributed by ${author} in [#${prId}](https://github.com/${owner}/${repo}/pull/${prId}).\n`;
438+
} else {
439+
otherNotableChanges += line + '\n';
440+
}
441+
}
442+
443+
if (notableChangesSections.length === 0) {
444+
return otherNotableChanges;
445+
}
446+
if (otherNotableChanges.length !== 0) {
447+
notableChangesSections += `\n#### Other notable changes\n\n${otherNotableChanges}`;
448+
}
449+
return notableChangesSections.slice(1);
450+
}
451+
417452
async updateMainChangelog() {
418453
const { date, isLTSTransition, versionComponents, newVersion } = this;
419454

@@ -476,7 +511,8 @@ export default class ReleasePreparation extends Session {
476511
const data = await fs.readFile(majorChangelogPath, 'utf8');
477512
const arr = data.split('\n');
478513
const allCommits = this.getChangelog();
479-
const notableChanges = await this.getBranchDiff({ onlyNotableChanges: true });
514+
const notableChanges =
515+
await this.fetchNotableChanges(await this.getBranchDiff({ onlyNotableChanges: true }));
480516
let releaseHeader = `## ${date}, Version ${newVersion}` +
481517
` ${releaseInfo}, @${username}\n`;
482518
if (isSecurityRelease) {
@@ -612,10 +648,10 @@ export default class ReleasePreparation extends Session {
612648
messageBody.push('This is a security release.\n\n');
613649
}
614650

615-
const notableChanges = await this.getBranchDiff({
651+
const notableChanges = runSync(...await this.getBranchDiff({
616652
onlyNotableChanges: true,
617653
format: 'plaintext'
618-
});
654+
}));
619655
messageBody.push('Notable changes:\n\n');
620656
if (isLTSTransition) {
621657
messageBody.push(`${getStartLTSBlurb(this)}\n\n`);
@@ -735,12 +771,13 @@ export default class ReleasePreparation extends Session {
735771
];
736772
}
737773

738-
const branchDiff = new URL(
739-
'../node_modules/.bin/branch-diff' + (isWindows ? '.cmd' : ''),
740-
import.meta.url
741-
);
742-
743-
return runSync(branchDiff, branchDiffOptions);
774+
return [
775+
path.join(
776+
import.meta.dirname,
777+
'../node_modules/.bin/branch-diff' + (isWindows ? '.cmd' : '')
778+
),
779+
branchDiffOptions
780+
];
744781
}
745782

746783
async getLastRelease(major) {

lib/queries/PRNotableChange.gql

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
query PR($prId: Int!, $owner: String!, $repo: String!) {
2+
repository(owner: $owner, name: $repo) {
3+
pullRequest(number: $prId) {
4+
body,
5+
labels(first: 100) {
6+
nodes {
7+
name
8+
}
9+
}
10+
}
11+
}
12+
}

0 commit comments

Comments
 (0)