X Tutup
Skip to content

Commit cc2cd95

Browse files
John Kleinschmidtckerr
authored andcommitted
Release updates in prep for 3-0-x releases (electron#12916)
* Add autorelease logic * Fix UnboundLocalError when using s3 upload
1 parent d5dfb19 commit cc2cd95

File tree

4 files changed

+110
-33
lines changed

4 files changed

+110
-33
lines changed

script/ci-release-build.js

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const circleCIJobs = [
66
'electron-linux-arm',
77
'electron-linux-arm64',
88
'electron-linux-ia32',
9-
'electron-linux-mips64el',
9+
// 'electron-linux-mips64el',
1010
'electron-linux-x64'
1111
]
1212

@@ -32,7 +32,7 @@ async function makeRequest (requestOptions, parseResponse) {
3232
})
3333
}
3434

35-
async function circleCIcall (buildUrl, targetBranch, job, ghRelease) {
35+
async function circleCIcall (buildUrl, targetBranch, job, options) {
3636
assert(process.env.CIRCLE_TOKEN, 'CIRCLE_TOKEN not found in environment')
3737
console.log(`Triggering CircleCI to run build job: ${job} on branch: ${targetBranch} with release flag.`)
3838
let buildRequest = {
@@ -41,12 +41,16 @@ async function circleCIcall (buildUrl, targetBranch, job, ghRelease) {
4141
}
4242
}
4343

44-
if (ghRelease) {
44+
if (options.ghRelease) {
4545
buildRequest.build_parameters.ELECTRON_RELEASE = 1
4646
} else {
4747
buildRequest.build_parameters.RUN_RELEASE_BUILD = 'true'
4848
}
4949

50+
if (options.automaticRelease) {
51+
buildRequest.build_parameters.AUTO_RELEASE = 'true'
52+
}
53+
5054
let circleResponse = await makeRequest({
5155
method: 'POST',
5256
url: buildUrl,
@@ -61,17 +65,21 @@ async function circleCIcall (buildUrl, targetBranch, job, ghRelease) {
6165
console.log(`Check ${circleResponse.build_url} for status. (${job})`)
6266
}
6367

64-
async function buildAppVeyor (targetBranch, ghRelease) {
68+
async function buildAppVeyor (targetBranch, options) {
6569
console.log(`Triggering AppVeyor to run build on branch: ${targetBranch} with release flag.`)
6670
assert(process.env.APPVEYOR_TOKEN, 'APPVEYOR_TOKEN not found in environment')
6771
let environmentVariables = {}
6872

69-
if (ghRelease) {
73+
if (options.ghRelease) {
7074
environmentVariables.ELECTRON_RELEASE = 1
7175
} else {
7276
environmentVariables.RUN_RELEASE_BUILD = 'true'
7377
}
7478

79+
if (options.automaticRelease) {
80+
environmentVariables.AUTO_RELEASE = 'true'
81+
}
82+
7583
const requestOpts = {
7684
url: buildAppVeyorURL,
7785
auth: {
@@ -95,42 +103,44 @@ async function buildAppVeyor (targetBranch, ghRelease) {
95103
console.log(`AppVeyor release build request successful. Check build status at ${buildUrl}`)
96104
}
97105

98-
function buildCircleCI (targetBranch, ghRelease, job) {
106+
function buildCircleCI (targetBranch, options) {
99107
const circleBuildUrl = `https://circleci.com/api/v1.1/project/github/electron/electron/tree/${targetBranch}?circle-token=${process.env.CIRCLE_TOKEN}`
100-
if (job) {
101-
assert(circleCIJobs.includes(job), `Unknown CI job name: ${job}.`)
102-
circleCIcall(circleBuildUrl, targetBranch, job, ghRelease)
108+
if (options.job) {
109+
assert(circleCIJobs.includes(options.job), `Unknown CI job name: ${options.job}.`)
110+
circleCIcall(circleBuildUrl, targetBranch, options.job, options)
103111
} else {
104-
circleCIJobs.forEach((job) => circleCIcall(circleBuildUrl, targetBranch, job, ghRelease))
112+
circleCIJobs.forEach((job) => circleCIcall(circleBuildUrl, targetBranch, job, options))
105113
}
106114
}
107115

108116
function runRelease (targetBranch, options) {
109117
if (options.ci) {
110118
switch (options.ci) {
111119
case 'CircleCI': {
112-
buildCircleCI(targetBranch, options.ghRelease, options.job)
120+
buildCircleCI(targetBranch, options)
113121
break
114122
}
115123
case 'AppVeyor': {
116-
buildAppVeyor(targetBranch, options.ghRelease)
124+
buildAppVeyor(targetBranch, options)
117125
break
118126
}
119127
}
120128
} else {
121-
buildCircleCI(targetBranch, options.ghRelease, options.job)
122-
buildAppVeyor(targetBranch, options.ghRelease)
129+
buildCircleCI(targetBranch, options)
130+
buildAppVeyor(targetBranch, options)
123131
}
124132
}
125133

126134
module.exports = runRelease
127135

128136
if (require.main === module) {
129-
const args = require('minimist')(process.argv.slice(2), { boolean: 'ghRelease' })
137+
const args = require('minimist')(process.argv.slice(2), {
138+
boolean: ['ghRelease', 'automaticRelease']
139+
})
130140
const targetBranch = args._[0]
131141
if (args._.length < 1) {
132142
console.log(`Trigger CI to build release builds of electron.
133-
Usage: ci-release-build.js [--job=CI_JOB_NAME] [--ci=CircleCI|AppVeyor] [--ghRelease] TARGET_BRANCH
143+
Usage: ci-release-build.js [--job=CI_JOB_NAME] [--ci=CircleCI|AppVeyor] [--ghRelease] [--automaticRelease] TARGET_BRANCH
134144
`)
135145
process.exit(0)
136146
}

script/prepare-release.js

Lines changed: 68 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#!/usr/bin/env node
22

33
require('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+
})
57
const assert = require('assert')
68
const ciReleaseBuild = require('./ci-release-build')
79
const { execSync } = require('child_process')
@@ -20,7 +22,7 @@ const versionType = args._[0]
2022
assert(process.env.ELECTRON_GITHUB_TOKEN, 'ELECTRON_GITHUB_TOKEN not found in environment')
2123
if (!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 = /Merge pull request #(\d+) from .*\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

153192
async 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

171211
async 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

195240
async 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
}

script/release.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ function assetsForVersion (version, validatingRelease) {
9797
`electron-${version}-linux-armv7l.zip`,
9898
`electron-${version}-linux-ia32-symbols.zip`,
9999
`electron-${version}-linux-ia32.zip`,
100-
`electron-${version}-linux-mips64el.zip`,
100+
// `electron-${version}-linux-mips64el.zip`,
101101
`electron-${version}-linux-x64-symbols.zip`,
102102
`electron-${version}-linux-x64.zip`,
103103
`electron-${version}-mas-x64-dsym.zip`,
@@ -116,7 +116,7 @@ function assetsForVersion (version, validatingRelease) {
116116
`ffmpeg-${version}-linux-arm64.zip`,
117117
`ffmpeg-${version}-linux-armv7l.zip`,
118118
`ffmpeg-${version}-linux-ia32.zip`,
119-
`ffmpeg-${version}-linux-mips64el.zip`,
119+
// `ffmpeg-${version}-linux-mips64el.zip`,
120120
`ffmpeg-${version}-linux-x64.zip`,
121121
`ffmpeg-${version}-mas-x64.zip`,
122122
`ffmpeg-${version}-win32-ia32.zip`,
@@ -148,7 +148,11 @@ function s3UrlsForVersion (version) {
148148
function checkVersion () {
149149
console.log(`Verifying that app version matches package version ${pkgVersion}.`)
150150
let startScript = path.join(__dirname, 'start.py')
151-
let appVersion = runScript(startScript, ['--version']).trim()
151+
let scriptArgs = ['--version']
152+
if (args.automaticRelease) {
153+
scriptArgs.unshift('-R')
154+
}
155+
let appVersion = runScript(startScript, scriptArgs).trim()
152156
check((pkgVersion.indexOf(appVersion) === 0), `App version ${appVersion} matches ` +
153157
`package version ${pkgVersion}.`, true)
154158
}
@@ -179,7 +183,11 @@ function uploadNodeShasums () {
179183
function uploadIndexJson () {
180184
console.log('Uploading index.json to S3.')
181185
let scriptPath = path.join(__dirname, 'upload-index-json.py')
182-
runScript(scriptPath, [])
186+
let scriptArgs = []
187+
if (args.automaticRelease) {
188+
scriptArgs.push('-R')
189+
}
190+
runScript(scriptPath, scriptArgs)
183191
console.log(`${pass} Done uploading index.json to S3.`)
184192
}
185193

script/upload.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ def main():
5050
github = GitHub(auth_token())
5151
releases = github.repos(ELECTRON_REPO).releases.get()
5252
tag_exists = False
53+
release = None
5354
for r in releases:
5455
if not r['draft'] and r['tag_name'] == args.version:
5556
release = r
@@ -62,6 +63,9 @@ def main():
6263
if not args.overwrite:
6364
release = create_or_get_release_draft(github, releases, args.version,
6465
tag_exists)
66+
elif release is None:
67+
release = dict(tag_name=args.version)
68+
6569

6670
# Upload Electron with GitHub Releases API.
6771
upload_electron(github, release, os.path.join(DIST_DIR, DIST_NAME),

0 commit comments

Comments
 (0)
X Tutup