11import path from 'node:path' ;
22import { promises as fs } from 'node:fs' ;
3+ import { createInterface } from 'node:readline' ;
4+ import { spawn } from 'node:child_process' ;
35
46import semver from 'semver' ;
57import { replaceInFile } from 'replace-in-file' ;
@@ -19,8 +21,9 @@ import Session from './session.js';
1921const isWindows = process . platform === 'win32' ;
2022
2123export 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 - f 0 - 9 ] + ) ` \] \( h t t p s : \/ \/ g i t h u b \. c o m \/ ( [ ^ / ] + ) \/ ( [ ^ / ] + ) \/ c o m m i t \/ \1\) \] - (?: \* \* \( S E M V E R - M I N O R \) \* \* ) ? ( .+ ) \( ( .+ ) \) \[ # ( \d + ) \] \( h t t p s : \/ \/ g i t h u b \. c o m \/ \2\/ \3\/ p u l l \/ \6\) $ / ;
424+ const detailsPattern = / (?: ^ | \r ? \n \r ? \n ) < d e t a i l s [ ^ > ] + > < s u m m a r y > N o t a b l e c h a n g e s ? < \/ s u m m a r y > \r ? \n \r ? \n (?: # + ( [ ^ \r \n ] + ) \r ? \n ) ? ( .+ ) \r ? \n \r ? \n < \/ d e t a i l s > (?: \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 ) {
0 commit comments