11#!/usr/bin/env node
22
33require ( 'colors' )
4- const args = require ( 'minimist' ) ( process . argv . slice ( 2 ) )
4+ const args = require ( 'minimist' ) ( process . argv . slice ( 2 ) , {
5+ boolean : [ 'automaticRelease' , 'notesOnly' , 'stable' ]
6+ } )
57const assert = require ( 'assert' )
68const ciReleaseBuild = require ( './ci-release-build' )
79const { execSync } = require ( 'child_process' )
@@ -20,7 +22,7 @@ const versionType = args._[0]
2022assert ( process . env . ELECTRON_GITHUB_TOKEN , 'ELECTRON_GITHUB_TOKEN not found in environment' )
2123if ( ! versionType && ! args . notesOnly ) {
2224 console . log ( `Usage: prepare-release versionType [major | minor | patch | beta]` +
23- ` (--stable) (--notesOnly)` )
25+ ` (--stable) (--notesOnly) (--automaticRelease) (--branch) ` )
2426 process . exit ( 1 )
2527}
2628
@@ -76,7 +78,12 @@ async function getReleaseNotes (currentBranch) {
7678 base : `v${ pkg . version } ` ,
7779 head : currentBranch
7880 }
79- let releaseNotes = '(placeholder)\n'
81+ let releaseNotes
82+ if ( args . automaticRelease ) {
83+ releaseNotes = '## Bug Fixes/Changes \n\n'
84+ } else {
85+ releaseNotes = '(placeholder)\n'
86+ }
8087 console . log ( `Checking for commits from ${ pkg . version } to ${ currentBranch } ` )
8188 let commitComparison = await github . repos . compareCommits ( githubOpts )
8289 . catch ( err => {
@@ -85,13 +92,45 @@ async function getReleaseNotes (currentBranch) {
8592 process . exit ( 1 )
8693 } )
8794
95+ if ( commitComparison . data . commits . length === 0 ) {
96+ console . log ( `${ pass } There are no commits from ${ pkg . version } to ` +
97+ `${ currentBranch } , skipping release.` )
98+ process . exit ( 0 )
99+ }
100+
101+ let prCount = 0
102+ const mergeRE = / M e r g e p u l l r e q u e s t # ( \d + ) f r o m .* \n /
103+ const newlineRE = / ( .* ) \n * .* /
104+ const prRE = / ( .* ) \( # ( \d + ) \) (?: .* ) /
88105 commitComparison . data . commits . forEach ( commitEntry => {
89106 let commitMessage = commitEntry . commit . message
90- if ( commitMessage . toLowerCase ( ) . indexOf ( 'merge' ) > - 1 ) {
91- releaseNotes += `${ commitMessage } \n`
107+ if ( commitMessage . indexOf ( '#' ) > - 1 ) {
108+ let prMatch = commitMessage . match ( mergeRE )
109+ let prNumber
110+ if ( prMatch ) {
111+ commitMessage = commitMessage . replace ( mergeRE , '' ) . replace ( '\n' , '' )
112+ let newlineMatch = commitMessage . match ( newlineRE )
113+ if ( newlineMatch ) {
114+ commitMessage = newlineMatch [ 1 ]
115+ }
116+ prNumber = prMatch [ 1 ]
117+ } else {
118+ prMatch = commitMessage . match ( prRE )
119+ if ( prMatch ) {
120+ commitMessage = prMatch [ 1 ] . trim ( )
121+ prNumber = prMatch [ 2 ]
122+ }
123+ }
124+ if ( prMatch ) {
125+ if ( commitMessage . substr ( commitMessage . length - 1 , commitMessage . length ) !== '.' ) {
126+ commitMessage += '.'
127+ }
128+ releaseNotes += `* ${ commitMessage } #${ prNumber } \n\n`
129+ prCount ++
130+ }
92131 }
93132 } )
94- console . log ( `${ pass } Done generating release notes for ${ currentBranch } .` )
133+ console . log ( `${ pass } Done generating release notes for ${ currentBranch } . Found ${ prCount } PRs. ` )
95134 return releaseNotes
96135}
97136
@@ -138,8 +177,8 @@ async function createRelease (branchToTarget, isBeta) {
138177 console . log ( `${ pass } Draft release for ${ newVersion } has been created.` )
139178}
140179
141- async function pushRelease ( ) {
142- let pushDetails = await GitProcess . exec ( [ 'push' , 'origin' , ' HEAD' , '--follow-tags' ] , gitDir )
180+ async function pushRelease ( branch ) {
181+ let pushDetails = await GitProcess . exec ( [ 'push' , 'origin' , ` HEAD: ${ branch } ` , '--follow-tags' ] , gitDir )
143182 if ( pushDetails . exitCode === 0 ) {
144183 console . log ( `${ pass } Successfully pushed the release. Wait for ` +
145184 `release builds to finish before running "npm run release".` )
@@ -152,7 +191,8 @@ async function pushRelease () {
152191
153192async function runReleaseBuilds ( branch ) {
154193 await ciReleaseBuild ( branch , {
155- ghRelease : true
194+ ghRelease : true ,
195+ automaticRelease : args . automaticRelease
156196 } )
157197}
158198
@@ -170,7 +210,12 @@ async function tagRelease (version) {
170210
171211async function verifyNewVersion ( ) {
172212 let newVersion = getNewVersion ( true )
173- let response = await promptForVersion ( newVersion )
213+ let response
214+ if ( args . automaticRelease ) {
215+ response = 'y'
216+ } else {
217+ response = await promptForVersion ( newVersion )
218+ }
174219 if ( response . match ( / ^ y / i) ) {
175220 console . log ( `${ pass } Starting release of ${ newVersion } ` )
176221 } else {
@@ -193,14 +238,24 @@ async function promptForVersion (version) {
193238}
194239
195240async function prepareRelease ( isBeta , notesOnly ) {
196- let currentBranch = await getCurrentBranch ( gitDir )
241+ if ( args . automaticRelease && ( pkg . version . indexOf ( 'beta' ) === - 1 ||
242+ versionType !== 'beta' ) ) {
243+ console . log ( `${ fail } Automatic release is only supported for beta releases` )
244+ process . exit ( 1 )
245+ }
246+ let currentBranch
247+ if ( args . branch ) {
248+ currentBranch = args . branch
249+ } else {
250+ currentBranch = await getCurrentBranch ( gitDir )
251+ }
197252 if ( notesOnly ) {
198253 let releaseNotes = await getReleaseNotes ( currentBranch )
199- console . log ( `Draft release notes are: ${ releaseNotes } ` )
254+ console . log ( `Draft release notes are: \n ${ releaseNotes } ` )
200255 } else {
201256 await verifyNewVersion ( )
202257 await createRelease ( currentBranch , isBeta )
203- await pushRelease ( )
258+ await pushRelease ( currentBranch )
204259 await runReleaseBuilds ( currentBranch )
205260 }
206261}
0 commit comments