| 
									
										
										
										
											2017-10-23 11:02:50 -04:00
										 |  |  | #!/usr/bin/env node
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-19 11:48:13 -07:00
										 |  |  | if (!process.env.CI) require('dotenv-safe').load() | 
					
						
							| 
									
										
										
										
											2018-05-14 17:21:51 -04:00
										 |  |  | const args = require('minimist')(process.argv.slice(2), { | 
					
						
							|  |  |  |   boolean: ['automaticRelease', 'notesOnly', 'stable'] | 
					
						
							|  |  |  | }) | 
					
						
							| 
									
										
										
										
											2017-11-17 15:13:30 -05:00
										 |  |  | const ciReleaseBuild = require('./ci-release-build') | 
					
						
							| 
									
										
										
										
											2019-05-07 18:48:40 -07:00
										 |  |  | const octokit = require('@octokit/rest')({ | 
					
						
							|  |  |  |   auth: process.env.ELECTRON_GITHUB_TOKEN | 
					
						
							|  |  |  | }) | 
					
						
							| 
									
										
										
										
											2017-10-23 11:02:50 -04:00
										 |  |  | const { execSync } = require('child_process') | 
					
						
							| 
									
										
										
										
											2018-02-12 11:01:50 -05:00
										 |  |  | const { GitProcess } = require('dugite') | 
					
						
							| 
									
										
										
										
											2018-12-03 13:28:10 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-23 11:02:50 -04:00
										 |  |  | const path = require('path') | 
					
						
							| 
									
										
										
										
											2018-01-31 16:40:38 -07:00
										 |  |  | const readline = require('readline') | 
					
						
							| 
									
										
										
										
											2019-06-24 10:18:04 -07:00
										 |  |  | const releaseNotesGenerator = require('./notes/index.js') | 
					
						
							|  |  |  | const { getCurrentBranch, ELECTRON_DIR } = require('../lib/utils.js') | 
					
						
							| 
									
										
										
										
											2018-12-06 11:00:10 -08:00
										 |  |  | const bumpType = args._[0] | 
					
						
							|  |  |  | const targetRepo = bumpType === 'nightly' ? 'nightlies' : 'electron' | 
					
						
							| 
									
										
										
										
											2017-10-23 11:02:50 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 13:28:10 -08:00
										 |  |  | require('colors') | 
					
						
							| 
									
										
										
										
											2019-08-29 07:46:54 -07:00
										 |  |  | const pass = '✓'.green | 
					
						
							|  |  |  | const fail = '✗'.red | 
					
						
							| 
									
										
										
										
											2018-12-03 13:28:10 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-06 11:00:10 -08:00
										 |  |  | if (!bumpType && !args.notesOnly) { | 
					
						
							| 
									
										
										
										
											2019-10-23 14:07:10 -04:00
										 |  |  |   console.log(`Usage: prepare-release [stable | minor | beta | nightly]` + | 
					
						
							| 
									
										
										
										
											2018-05-14 17:21:51 -04:00
										 |  |  |      ` (--stable) (--notesOnly) (--automaticRelease) (--branch)`) | 
					
						
							| 
									
										
										
										
											2017-10-23 11:02:50 -04:00
										 |  |  |   process.exit(1) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-16 08:57:12 -07:00
										 |  |  | async function getNewVersion (dryRun) { | 
					
						
							| 
									
										
										
										
											2018-08-20 08:17:47 -07:00
										 |  |  |   if (!dryRun) { | 
					
						
							| 
									
										
										
										
											2018-12-06 11:00:10 -08:00
										 |  |  |     console.log(`Bumping for new "${bumpType}" version.`) | 
					
						
							| 
									
										
										
										
											2018-01-31 16:40:38 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-06-24 10:18:04 -07:00
										 |  |  |   const bumpScript = path.join(__dirname, 'version-bumper.js') | 
					
						
							| 
									
										
										
										
											2018-12-06 11:00:10 -08:00
										 |  |  |   const scriptArgs = ['node', bumpScript, `--bump=${bumpType}`] | 
					
						
							| 
									
										
										
										
											2019-01-08 18:09:42 -08:00
										 |  |  |   if (dryRun) scriptArgs.push('--dryRun') | 
					
						
							| 
									
										
										
										
											2017-10-23 11:02:50 -04:00
										 |  |  |   try { | 
					
						
							| 
									
										
										
										
											2018-09-14 02:10:51 +10:00
										 |  |  |     let bumpVersion = execSync(scriptArgs.join(' '), { encoding: 'UTF-8' }) | 
					
						
							| 
									
										
										
										
											2017-10-23 11:02:50 -04:00
										 |  |  |     bumpVersion = bumpVersion.substr(bumpVersion.indexOf(':') + 1).trim() | 
					
						
							| 
									
										
										
										
											2018-10-02 03:56:31 +02:00
										 |  |  |     const newVersion = `v${bumpVersion}` | 
					
						
							| 
									
										
										
										
											2018-01-31 16:40:38 -07:00
										 |  |  |     if (!dryRun) { | 
					
						
							|  |  |  |       console.log(`${pass} Successfully bumped version to ${newVersion}`) | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-10-23 11:02:50 -04:00
										 |  |  |     return newVersion | 
					
						
							|  |  |  |   } catch (err) { | 
					
						
							|  |  |  |     console.log(`${fail} Could not bump version, error was:`, err) | 
					
						
							| 
									
										
										
										
											2018-08-16 08:57:12 -07:00
										 |  |  |     throw err | 
					
						
							| 
									
										
										
										
											2017-10-23 11:02:50 -04:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 14:01:38 -06:00
										 |  |  | async function getReleaseNotes (currentBranch, newVersion) { | 
					
						
							| 
									
										
										
										
											2018-12-06 11:00:10 -08:00
										 |  |  |   if (bumpType === 'nightly') { | 
					
						
							| 
									
										
										
										
											2019-01-07 16:00:36 -08:00
										 |  |  |     return { text: 'Nightlies do not get release notes, please compare tags for info.' } | 
					
						
							| 
									
										
										
										
											2018-08-16 08:57:12 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-10-23 11:02:50 -04:00
										 |  |  |   console.log(`Generating release notes for ${currentBranch}.`) | 
					
						
							| 
									
										
										
										
											2019-01-10 14:01:38 -06:00
										 |  |  |   const releaseNotes = await releaseNotesGenerator(currentBranch, newVersion) | 
					
						
							| 
									
										
										
										
											2018-11-06 14:06:11 -06:00
										 |  |  |   if (releaseNotes.warning) { | 
					
						
							|  |  |  |     console.warn(releaseNotes.warning) | 
					
						
							| 
									
										
										
										
											2018-05-14 17:21:51 -04:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-10-23 11:02:50 -04:00
										 |  |  |   return releaseNotes | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | async function createRelease (branchToTarget, isBeta) { | 
					
						
							| 
									
										
										
										
											2018-10-02 03:56:31 +02:00
										 |  |  |   const newVersion = await getNewVersion() | 
					
						
							| 
									
										
										
										
											2019-01-10 14:01:38 -06:00
										 |  |  |   const releaseNotes = await getReleaseNotes(branchToTarget, newVersion) | 
					
						
							| 
									
										
										
										
											2018-02-12 11:01:50 -05:00
										 |  |  |   await tagRelease(newVersion) | 
					
						
							| 
									
										
										
										
											2019-01-08 12:05:58 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   console.log(`Checking for existing draft release.`) | 
					
						
							|  |  |  |   const releases = await octokit.repos.listReleases({ | 
					
						
							| 
									
										
										
										
											2017-10-23 11:02:50 -04:00
										 |  |  |     owner: 'electron', | 
					
						
							| 
									
										
										
										
											2018-08-16 09:12:06 -07:00
										 |  |  |     repo: targetRepo | 
					
						
							| 
									
										
										
										
											2019-01-08 12:05:58 -08:00
										 |  |  |   }).catch(err => { | 
					
						
							|  |  |  |     console.log(`${fail} Could not get releases. Error was: `, err) | 
					
						
							|  |  |  |   }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-02 03:56:31 +02:00
										 |  |  |   const drafts = releases.data.filter(release => release.draft && | 
					
						
							| 
									
										
										
										
											2018-01-30 17:35:16 -07:00
										 |  |  |     release.tag_name === newVersion) | 
					
						
							| 
									
										
										
										
											2017-10-23 11:02:50 -04:00
										 |  |  |   if (drafts.length > 0) { | 
					
						
							|  |  |  |     console.log(`${fail} Aborting because draft release for
 | 
					
						
							| 
									
										
										
										
											2017-11-06 16:11:34 -05:00
										 |  |  |       ${drafts[0].tag_name} already exists.`)
 | 
					
						
							| 
									
										
										
										
											2017-10-23 11:02:50 -04:00
										 |  |  |     process.exit(1) | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   console.log(`${pass} A draft release does not exist; creating one.`) | 
					
						
							| 
									
										
										
										
											2019-01-08 12:05:58 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   let releaseBody | 
					
						
							|  |  |  |   let releaseIsPrelease = false | 
					
						
							| 
									
										
										
										
											2017-10-23 11:02:50 -04:00
										 |  |  |   if (isBeta) { | 
					
						
							| 
									
										
										
										
											2018-08-17 10:42:45 -07:00
										 |  |  |     if (newVersion.indexOf('nightly') > 0) { | 
					
						
							| 
									
										
										
										
											2019-01-08 12:05:58 -08:00
										 |  |  |       releaseBody = `Note: This is a nightly release.  Please file new issues ` + | 
					
						
							| 
									
										
										
										
											2018-08-16 09:12:06 -07:00
										 |  |  |         `for any bugs you find in it.\n \n This release is published to npm ` + | 
					
						
							| 
									
										
										
										
											2018-08-16 09:28:17 -07:00
										 |  |  |         `under the nightly tag and can be installed via npm install electron@nightly, ` + | 
					
						
							| 
									
										
										
										
											2019-08-12 13:01:52 -07:00
										 |  |  |         `or npm i electron-nightly@${newVersion.substr(1)}.\n \n ${releaseNotes.text}` | 
					
						
							| 
									
										
										
										
											2018-08-16 09:12:06 -07:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2019-01-08 12:05:58 -08:00
										 |  |  |       releaseBody = `Note: This is a beta release.  Please file new issues ` + | 
					
						
							| 
									
										
										
										
											2018-08-16 09:12:06 -07:00
										 |  |  |         `for any bugs you find in it.\n \n This release is published to npm ` + | 
					
						
							| 
									
										
										
										
											2018-08-16 09:28:17 -07:00
										 |  |  |         `under the beta tag and can be installed via npm install electron@beta, ` + | 
					
						
							| 
									
										
										
										
											2018-11-06 14:06:11 -06:00
										 |  |  |         `or npm i electron@${newVersion.substr(1)}.\n \n ${releaseNotes.text}` | 
					
						
							| 
									
										
										
										
											2018-08-16 09:12:06 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-01-08 12:05:58 -08:00
										 |  |  |     releaseIsPrelease = true | 
					
						
							| 
									
										
										
										
											2018-01-31 16:40:38 -07:00
										 |  |  |   } else { | 
					
						
							| 
									
										
										
										
											2019-04-30 11:36:39 -07:00
										 |  |  |     releaseBody = releaseNotes.text | 
					
						
							| 
									
										
										
										
											2017-10-23 11:02:50 -04:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-01-08 12:05:58 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   const release = await octokit.repos.createRelease({ | 
					
						
							|  |  |  |     owner: 'electron', | 
					
						
							|  |  |  |     repo: targetRepo, | 
					
						
							|  |  |  |     tag_name: newVersion, | 
					
						
							|  |  |  |     draft: true, | 
					
						
							|  |  |  |     name: `electron ${newVersion}`, | 
					
						
							|  |  |  |     body: releaseBody, | 
					
						
							|  |  |  |     prerelease: releaseIsPrelease, | 
					
						
							|  |  |  |     target_commitish: newVersion.indexOf('nightly') !== -1 ? 'master' : branchToTarget | 
					
						
							|  |  |  |   }).catch(err => { | 
					
						
							|  |  |  |     console.log(`${fail} Error creating new release: `, err) | 
					
						
							|  |  |  |     process.exit(1) | 
					
						
							|  |  |  |   }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-18 19:51:38 -07:00
										 |  |  |   console.log(`Release has been created with id: ${release.data.id}.`) | 
					
						
							| 
									
										
										
										
											2018-11-27 23:12:01 -05:00
										 |  |  |   console.log(`${pass} Draft release for ${newVersion} successful.`) | 
					
						
							| 
									
										
										
										
											2017-10-23 11:02:50 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-14 17:21:51 -04:00
										 |  |  | async function pushRelease (branch) { | 
					
						
							| 
									
										
										
										
											2019-06-24 10:18:04 -07:00
										 |  |  |   const pushDetails = await GitProcess.exec(['push', 'origin', `HEAD:${branch}`, '--follow-tags'], ELECTRON_DIR) | 
					
						
							| 
									
										
										
										
											2017-10-23 11:02:50 -04:00
										 |  |  |   if (pushDetails.exitCode === 0) { | 
					
						
							| 
									
										
										
										
											2018-02-12 11:01:50 -05:00
										 |  |  |     console.log(`${pass} Successfully pushed the release.  Wait for ` + | 
					
						
							| 
									
										
										
										
											2017-10-23 11:02:50 -04:00
										 |  |  |       `release builds to finish before running "npm run release".`) | 
					
						
							|  |  |  |   } else { | 
					
						
							| 
									
										
										
										
											2019-01-08 12:05:58 -08:00
										 |  |  |     console.log(`${fail} Error pushing the release: ${pushDetails.stderr}`) | 
					
						
							| 
									
										
										
										
											2017-10-23 11:02:50 -04:00
										 |  |  |     process.exit(1) | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-12 11:01:50 -05:00
										 |  |  | async function runReleaseBuilds (branch) { | 
					
						
							|  |  |  |   await ciReleaseBuild(branch, { | 
					
						
							| 
									
										
										
										
											2018-05-14 17:21:51 -04:00
										 |  |  |     ghRelease: true, | 
					
						
							|  |  |  |     automaticRelease: args.automaticRelease | 
					
						
							| 
									
										
										
										
											2017-11-17 15:13:30 -05:00
										 |  |  |   }) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-12 11:01:50 -05:00
										 |  |  | async function tagRelease (version) { | 
					
						
							|  |  |  |   console.log(`Tagging release ${version}.`) | 
					
						
							| 
									
										
										
										
											2019-06-24 10:18:04 -07:00
										 |  |  |   const checkoutDetails = await GitProcess.exec([ 'tag', '-a', '-m', version, version ], ELECTRON_DIR) | 
					
						
							| 
									
										
										
										
											2018-02-12 11:01:50 -05:00
										 |  |  |   if (checkoutDetails.exitCode === 0) { | 
					
						
							|  |  |  |     console.log(`${pass} Successfully tagged ${version}.`) | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     console.log(`${fail} Error tagging ${version}: ` + | 
					
						
							|  |  |  |       `${checkoutDetails.stderr}`) | 
					
						
							|  |  |  |     process.exit(1) | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-31 16:40:38 -07:00
										 |  |  | async function verifyNewVersion () { | 
					
						
							| 
									
										
										
										
											2018-10-02 03:56:31 +02:00
										 |  |  |   const newVersion = await getNewVersion(true) | 
					
						
							| 
									
										
										
										
											2018-05-14 17:21:51 -04:00
										 |  |  |   let response | 
					
						
							|  |  |  |   if (args.automaticRelease) { | 
					
						
							|  |  |  |     response = 'y' | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     response = await promptForVersion(newVersion) | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-01-31 16:40:38 -07:00
										 |  |  |   if (response.match(/^y/i)) { | 
					
						
							|  |  |  |     console.log(`${pass} Starting release of ${newVersion}`) | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     console.log(`${fail} Aborting release of ${newVersion}`) | 
					
						
							|  |  |  |     process.exit() | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | async function promptForVersion (version) { | 
					
						
							|  |  |  |   return new Promise((resolve, reject) => { | 
					
						
							|  |  |  |     const rl = readline.createInterface({ | 
					
						
							|  |  |  |       input: process.stdin, | 
					
						
							|  |  |  |       output: process.stdout | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     rl.question(`Do you want to create the release ${version.green} (y/N)? `, (answer) => { | 
					
						
							|  |  |  |       rl.close() | 
					
						
							|  |  |  |       resolve(answer) | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |   }) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-18 17:36:16 -07:00
										 |  |  | // function to determine if there have been commits to master since the last release
 | 
					
						
							|  |  |  | async function changesToRelease () { | 
					
						
							| 
									
										
										
										
											2018-10-02 03:56:31 +02:00
										 |  |  |   const lastCommitWasRelease = new RegExp(`^Bump v[0-9.]*(-beta[0-9.]*)?(-nightly[0-9.]*)?$`, 'g') | 
					
						
							| 
									
										
										
										
											2019-06-24 10:18:04 -07:00
										 |  |  |   const lastCommit = await GitProcess.exec(['log', '-n', '1', `--pretty=format:'%s'`], ELECTRON_DIR) | 
					
						
							| 
									
										
										
										
											2018-08-18 17:36:16 -07:00
										 |  |  |   return !lastCommitWasRelease.test(lastCommit.stdout) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-23 11:02:50 -04:00
										 |  |  | async function prepareRelease (isBeta, notesOnly) { | 
					
						
							| 
									
										
										
										
											2018-08-20 08:17:47 -07:00
										 |  |  |   if (args.dryRun) { | 
					
						
							| 
									
										
										
										
											2018-10-02 03:56:31 +02:00
										 |  |  |     const newVersion = await getNewVersion(true) | 
					
						
							| 
									
										
										
										
											2018-08-20 08:17:47 -07:00
										 |  |  |     console.log(newVersion) | 
					
						
							| 
									
										
										
										
											2017-10-23 11:02:50 -04:00
										 |  |  |   } else { | 
					
						
							| 
									
										
										
										
											2019-06-24 10:18:04 -07:00
										 |  |  |     const currentBranch = (args.branch) ? args.branch : await getCurrentBranch(ELECTRON_DIR) | 
					
						
							| 
									
										
										
										
											2018-08-20 08:17:47 -07:00
										 |  |  |     if (notesOnly) { | 
					
						
							| 
									
										
										
										
											2019-01-10 14:01:38 -06:00
										 |  |  |       const newVersion = await getNewVersion(true) | 
					
						
							|  |  |  |       const releaseNotes = await getReleaseNotes(currentBranch, newVersion) | 
					
						
							| 
									
										
										
										
											2018-11-06 14:06:11 -06:00
										 |  |  |       console.log(`Draft release notes are: \n${releaseNotes.text}`) | 
					
						
							| 
									
										
										
										
											2018-08-18 17:36:16 -07:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2018-08-20 08:17:47 -07:00
										 |  |  |       const changes = await changesToRelease(currentBranch) | 
					
						
							|  |  |  |       if (changes) { | 
					
						
							|  |  |  |         await verifyNewVersion() | 
					
						
							|  |  |  |         await createRelease(currentBranch, isBeta) | 
					
						
							|  |  |  |         await pushRelease(currentBranch) | 
					
						
							|  |  |  |         await runReleaseBuilds(currentBranch) | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         console.log(`There are no new changes to this branch since the last release, aborting release.`) | 
					
						
							|  |  |  |         process.exit(1) | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2018-08-18 17:36:16 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-10-23 11:02:50 -04:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | prepareRelease(!args.stable, args.notesOnly) |