@@ -15,13 +15,24 @@ class ReleasePreparation {
1515 constructor ( argv , cli , dir ) {
1616 this . cli = cli ;
1717 this . dir = dir ;
18- this . newVersion = semver . clean ( argv . newVersion ) ;
1918 this . isSecurityRelease = argv . security ;
2019 this . isLTS = false ;
2120 this . ltsCodename = '' ;
2221 this . date = '' ;
2322 this . config = getMergedConfig ( this . dir ) ;
2423
24+ // Allow passing optional new version.
25+ if ( argv . newVersion ) {
26+ const newVersion = semver . clean ( argv . newVersion ) ;
27+ if ( ! semver . valid ( newVersion ) ) {
28+ cli . warn ( `${ newVersion } is not a valid semantic version.` ) ;
29+ return ;
30+ }
31+ this . newVersion = newVersion ;
32+ } else {
33+ this . newVersion = this . calculateNewVersion ( ) ;
34+ }
35+
2536 const { upstream, owner, repo, newVersion } = this ;
2637
2738 this . versionComponents = {
@@ -54,17 +65,20 @@ class ReleasePreparation {
5465 await this . updateNodeVersion ( ) ;
5566 cli . stopSpinner ( `Updated 'src/node_version.h' for ${ newVersion } ` ) ;
5667
57- // Check whether to update NODE_MODULE_VERSION (default false).
58- const shouldUpdateNodeModuleVersion = await cli . prompt (
59- 'Update NODE_MODULE_VERSION?' , { defaultAnswer : false } ) ;
60- if ( shouldUpdateNodeModuleVersion ) {
61- const variant = await cli . prompt (
62- 'Specify variant (ex. \'v8_7.9\') for new NODE_MODULE_VERSION:' ,
63- { questionType : 'input' , noSeparator : true } ) ;
64- const versions = await cli . prompt (
65- 'Specify versions (ex. \'14.0.0-pre\') for new NODE_MODULE_VERSION:' ,
66- { questionType : 'input' , noSeparator : true } ) ;
67- this . updateNodeModuleVersion ( 'node' , variant , versions ) ;
68+ // Check whether to update NODE_MODULE_VERSION.
69+ const isSemverMajor = versionComponents . minor === 0 ;
70+ if ( isSemverMajor ) {
71+ const shouldUpdateNodeModuleVersion = await cli . prompt (
72+ 'Update NODE_MODULE_VERSION?' , { defaultAnswer : false } ) ;
73+ if ( shouldUpdateNodeModuleVersion ) {
74+ const variant = await cli . prompt (
75+ 'Specify variant (ex. \'v8_7.9\') for new NODE_MODULE_VERSION:' ,
76+ { questionType : 'input' , noSeparator : true } ) ;
77+ const versions = await cli . prompt (
78+ 'Specify versions (ex. \'14.0.0-pre\') for new NODE_MODULE_VERSION:' ,
79+ { questionType : 'input' , noSeparator : true } ) ;
80+ this . updateNodeModuleVersion ( 'node' , variant , versions ) ;
81+ }
6882 }
6983
7084 // Update any REPLACEME tags in the docs.
@@ -154,6 +168,32 @@ class ReleasePreparation {
154168 return this . config . username ;
155169 }
156170
171+ calculateNewVersion ( ) {
172+ let newVersion ;
173+
174+ const lastTagVersion = semver . clean ( this . getLastRef ( ) ) ;
175+ const lastTag = {
176+ major : semver . major ( lastTagVersion ) ,
177+ minor : semver . minor ( lastTagVersion ) ,
178+ patch : semver . patch ( lastTagVersion )
179+ } ;
180+
181+ const raw = this . getBranchDiff ( {
182+ onlyNotableChanges : false ,
183+ comparisonBranch : `v${ lastTagVersion } `
184+ } ) ;
185+
186+ if ( raw . includes ( 'SEMVER-MAJOR' ) ) {
187+ newVersion = `${ lastTag . major + 1 } .0.0` ;
188+ } else if ( raw . includes ( 'SEMVER-MINOR' ) ) {
189+ newVersion = `${ lastTag . major } .${ lastTag . minor + 1 } .0` ;
190+ } else {
191+ newVersion = `${ lastTag . major } .${ lastTag . minor } .${ lastTag . patch + 1 } ` ;
192+ }
193+
194+ return newVersion ;
195+ }
196+
157197 getCurrentBranch ( ) {
158198 return runSync ( 'git' , [ 'rev-parse' , '--abbrev-ref' , 'HEAD' ] ) . trim ( ) ;
159199 }
@@ -253,14 +293,21 @@ class ReleasePreparation {
253293 ` ${ releaseInfo } , @${ username } \n` ;
254294
255295 for ( let idx = 0 ; idx < arr . length ; idx ++ ) {
256- if ( arr [ idx ] . includes ( `<a id="${ lastRef . substring ( 1 ) } "></a>` ) ) {
296+ const topHeader =
297+ `<a href="#${ lastRef . substring ( 1 ) } ">${ lastRef . substring ( 1 ) } </a><br/>` ;
298+ if ( arr [ idx ] . includes ( topHeader ) ) {
299+ const newHeader =
300+ `<a href="#${ newVersion } ">${ newVersion } </a><br/>` ;
301+ arr . splice ( idx , 1 , newHeader ) ;
302+ } else if ( arr [ idx ] . includes ( `<a id="${ lastRef . substring ( 1 ) } "></a>` ) ) {
257303 const toAppend = [ ] ;
258304 toAppend . push ( `<a id="${ newVersion } "></a>` ) ;
259305 toAppend . push ( releaseHeader ) ;
260306 toAppend . push ( '### Notable Changes\n' ) ;
261307 toAppend . push ( notableChanges ) ;
262308 toAppend . push ( '### Commits\n' ) ;
263309 toAppend . push ( allCommits ) ;
310+ toAppend . push ( '' ) ;
264311
265312 arr . splice ( idx , 0 , ...toAppend ) ;
266313 break ;
@@ -345,23 +392,33 @@ class ReleasePreparation {
345392
346393 cli . log ( `${ messageTitle } \n\n${ messageBody . join ( '' ) } ` ) ;
347394 const useMessage = await cli . prompt (
348- 'Continue with this commit message?' ) ;
395+ 'Continue with this commit message?' , { defaultAnswer : false } ) ;
349396 return useMessage ;
350397 }
351398
352399 getBranchDiff ( opts ) {
353400 const {
354- versionComponents,
355- stagingBranch,
401+ versionComponents = { } ,
356402 upstream,
357403 newVersion,
358404 isLTS
359405 } = this ;
360406
407+ let majorVersion ;
408+ let stagingBranch ;
409+ if ( Object . keys ( versionComponents ) . length !== 0 ) {
410+ majorVersion = versionComponents . major ;
411+ stagingBranch = this . stagingBranch ;
412+ } else {
413+ stagingBranch = this . getCurrentBranch ( ) ;
414+ const stagingBranchSemver = semver . coerce ( stagingBranch ) ;
415+ majorVersion = stagingBranchSemver . major ;
416+ }
417+
361418 let branchDiffOptions ;
362419 if ( opts . onlyNotableChanges ) {
363420 const proposalBranch = `v${ newVersion } -proposal` ;
364- const releaseBranch = `v${ versionComponents . major } .x` ;
421+ const releaseBranch = `v${ majorVersion } .x` ;
365422
366423 const notableLabels = [
367424 'notable-change' ,
@@ -377,21 +434,26 @@ class ReleasePreparation {
377434 } else {
378435 const excludeLabels = [
379436 'semver-major' ,
380- `dont-land-on-v${ versionComponents . major } .x` ,
381- `backport-requested-v${ versionComponents . major } .x` ,
382- `backported-to-v${ versionComponents . major } .x` ,
383- `backport-blocked-v${ versionComponents . major } .x`
437+ `dont-land-on-v${ majorVersion } .x` ,
438+ `backport-requested-v${ majorVersion } .x` ,
439+ `backported-to-v${ majorVersion } .x` ,
440+ `backport-blocked-v${ majorVersion } .x`
384441 ] ;
385442
386443 const isSemverMinor = versionComponents . patch === 0 ;
387444 if ( isLTS && ! isSemverMinor ) {
388445 excludeLabels . push ( 'semver-minor' ) ;
389446 }
390447
448+ let comparisonBranch = 'master' ;
449+ if ( opts . comparisonBranch ) {
450+ comparisonBranch = opts . comparisonBranch ;
451+ }
452+
391453 branchDiffOptions = [
392454 stagingBranch ,
393455 // TODO(codebytere): use Current branch instead of master for LTS
394- 'master' ,
456+ comparisonBranch ,
395457 `--exclude-label=${ excludeLabels . join ( ',' ) } ` ,
396458 '--filter-release' ,
397459 '--format=simple'
0 commit comments