Release updates in prep for 3-0-x releases (#12916)
* Add autorelease logic * Fix UnboundLocalError when using s3 upload
This commit is contained in:
parent
d5dfb19508
commit
cc2cd95ec5
4 changed files with 110 additions and 33 deletions
|
@ -6,7 +6,7 @@ const circleCIJobs = [
|
||||||
'electron-linux-arm',
|
'electron-linux-arm',
|
||||||
'electron-linux-arm64',
|
'electron-linux-arm64',
|
||||||
'electron-linux-ia32',
|
'electron-linux-ia32',
|
||||||
'electron-linux-mips64el',
|
// 'electron-linux-mips64el',
|
||||||
'electron-linux-x64'
|
'electron-linux-x64'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ async function makeRequest (requestOptions, parseResponse) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function circleCIcall (buildUrl, targetBranch, job, ghRelease) {
|
async function circleCIcall (buildUrl, targetBranch, job, options) {
|
||||||
assert(process.env.CIRCLE_TOKEN, 'CIRCLE_TOKEN not found in environment')
|
assert(process.env.CIRCLE_TOKEN, 'CIRCLE_TOKEN not found in environment')
|
||||||
console.log(`Triggering CircleCI to run build job: ${job} on branch: ${targetBranch} with release flag.`)
|
console.log(`Triggering CircleCI to run build job: ${job} on branch: ${targetBranch} with release flag.`)
|
||||||
let buildRequest = {
|
let buildRequest = {
|
||||||
|
@ -41,12 +41,16 @@ async function circleCIcall (buildUrl, targetBranch, job, ghRelease) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ghRelease) {
|
if (options.ghRelease) {
|
||||||
buildRequest.build_parameters.ELECTRON_RELEASE = 1
|
buildRequest.build_parameters.ELECTRON_RELEASE = 1
|
||||||
} else {
|
} else {
|
||||||
buildRequest.build_parameters.RUN_RELEASE_BUILD = 'true'
|
buildRequest.build_parameters.RUN_RELEASE_BUILD = 'true'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.automaticRelease) {
|
||||||
|
buildRequest.build_parameters.AUTO_RELEASE = 'true'
|
||||||
|
}
|
||||||
|
|
||||||
let circleResponse = await makeRequest({
|
let circleResponse = await makeRequest({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: buildUrl,
|
url: buildUrl,
|
||||||
|
@ -61,17 +65,21 @@ async function circleCIcall (buildUrl, targetBranch, job, ghRelease) {
|
||||||
console.log(`Check ${circleResponse.build_url} for status. (${job})`)
|
console.log(`Check ${circleResponse.build_url} for status. (${job})`)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function buildAppVeyor (targetBranch, ghRelease) {
|
async function buildAppVeyor (targetBranch, options) {
|
||||||
console.log(`Triggering AppVeyor to run build on branch: ${targetBranch} with release flag.`)
|
console.log(`Triggering AppVeyor to run build on branch: ${targetBranch} with release flag.`)
|
||||||
assert(process.env.APPVEYOR_TOKEN, 'APPVEYOR_TOKEN not found in environment')
|
assert(process.env.APPVEYOR_TOKEN, 'APPVEYOR_TOKEN not found in environment')
|
||||||
let environmentVariables = {}
|
let environmentVariables = {}
|
||||||
|
|
||||||
if (ghRelease) {
|
if (options.ghRelease) {
|
||||||
environmentVariables.ELECTRON_RELEASE = 1
|
environmentVariables.ELECTRON_RELEASE = 1
|
||||||
} else {
|
} else {
|
||||||
environmentVariables.RUN_RELEASE_BUILD = 'true'
|
environmentVariables.RUN_RELEASE_BUILD = 'true'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.automaticRelease) {
|
||||||
|
environmentVariables.AUTO_RELEASE = 'true'
|
||||||
|
}
|
||||||
|
|
||||||
const requestOpts = {
|
const requestOpts = {
|
||||||
url: buildAppVeyorURL,
|
url: buildAppVeyorURL,
|
||||||
auth: {
|
auth: {
|
||||||
|
@ -95,13 +103,13 @@ async function buildAppVeyor (targetBranch, ghRelease) {
|
||||||
console.log(`AppVeyor release build request successful. Check build status at ${buildUrl}`)
|
console.log(`AppVeyor release build request successful. Check build status at ${buildUrl}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildCircleCI (targetBranch, ghRelease, job) {
|
function buildCircleCI (targetBranch, options) {
|
||||||
const circleBuildUrl = `https://circleci.com/api/v1.1/project/github/electron/electron/tree/${targetBranch}?circle-token=${process.env.CIRCLE_TOKEN}`
|
const circleBuildUrl = `https://circleci.com/api/v1.1/project/github/electron/electron/tree/${targetBranch}?circle-token=${process.env.CIRCLE_TOKEN}`
|
||||||
if (job) {
|
if (options.job) {
|
||||||
assert(circleCIJobs.includes(job), `Unknown CI job name: ${job}.`)
|
assert(circleCIJobs.includes(options.job), `Unknown CI job name: ${options.job}.`)
|
||||||
circleCIcall(circleBuildUrl, targetBranch, job, ghRelease)
|
circleCIcall(circleBuildUrl, targetBranch, options.job, options)
|
||||||
} else {
|
} else {
|
||||||
circleCIJobs.forEach((job) => circleCIcall(circleBuildUrl, targetBranch, job, ghRelease))
|
circleCIJobs.forEach((job) => circleCIcall(circleBuildUrl, targetBranch, job, options))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,28 +117,30 @@ function runRelease (targetBranch, options) {
|
||||||
if (options.ci) {
|
if (options.ci) {
|
||||||
switch (options.ci) {
|
switch (options.ci) {
|
||||||
case 'CircleCI': {
|
case 'CircleCI': {
|
||||||
buildCircleCI(targetBranch, options.ghRelease, options.job)
|
buildCircleCI(targetBranch, options)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'AppVeyor': {
|
case 'AppVeyor': {
|
||||||
buildAppVeyor(targetBranch, options.ghRelease)
|
buildAppVeyor(targetBranch, options)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
buildCircleCI(targetBranch, options.ghRelease, options.job)
|
buildCircleCI(targetBranch, options)
|
||||||
buildAppVeyor(targetBranch, options.ghRelease)
|
buildAppVeyor(targetBranch, options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = runRelease
|
module.exports = runRelease
|
||||||
|
|
||||||
if (require.main === module) {
|
if (require.main === module) {
|
||||||
const args = require('minimist')(process.argv.slice(2), { boolean: 'ghRelease' })
|
const args = require('minimist')(process.argv.slice(2), {
|
||||||
|
boolean: ['ghRelease', 'automaticRelease']
|
||||||
|
})
|
||||||
const targetBranch = args._[0]
|
const targetBranch = args._[0]
|
||||||
if (args._.length < 1) {
|
if (args._.length < 1) {
|
||||||
console.log(`Trigger CI to build release builds of electron.
|
console.log(`Trigger CI to build release builds of electron.
|
||||||
Usage: ci-release-build.js [--job=CI_JOB_NAME] [--ci=CircleCI|AppVeyor] [--ghRelease] TARGET_BRANCH
|
Usage: ci-release-build.js [--job=CI_JOB_NAME] [--ci=CircleCI|AppVeyor] [--ghRelease] [--automaticRelease] TARGET_BRANCH
|
||||||
`)
|
`)
|
||||||
process.exit(0)
|
process.exit(0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
require('colors')
|
require('colors')
|
||||||
const args = require('minimist')(process.argv.slice(2))
|
const args = require('minimist')(process.argv.slice(2), {
|
||||||
|
boolean: ['automaticRelease', 'notesOnly', 'stable']
|
||||||
|
})
|
||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const ciReleaseBuild = require('./ci-release-build')
|
const ciReleaseBuild = require('./ci-release-build')
|
||||||
const { execSync } = require('child_process')
|
const { execSync } = require('child_process')
|
||||||
|
@ -20,7 +22,7 @@ const versionType = args._[0]
|
||||||
assert(process.env.ELECTRON_GITHUB_TOKEN, 'ELECTRON_GITHUB_TOKEN not found in environment')
|
assert(process.env.ELECTRON_GITHUB_TOKEN, 'ELECTRON_GITHUB_TOKEN not found in environment')
|
||||||
if (!versionType && !args.notesOnly) {
|
if (!versionType && !args.notesOnly) {
|
||||||
console.log(`Usage: prepare-release versionType [major | minor | patch | beta]` +
|
console.log(`Usage: prepare-release versionType [major | minor | patch | beta]` +
|
||||||
` (--stable) (--notesOnly)`)
|
` (--stable) (--notesOnly) (--automaticRelease) (--branch)`)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +78,12 @@ async function getReleaseNotes (currentBranch) {
|
||||||
base: `v${pkg.version}`,
|
base: `v${pkg.version}`,
|
||||||
head: currentBranch
|
head: currentBranch
|
||||||
}
|
}
|
||||||
let releaseNotes = '(placeholder)\n'
|
let releaseNotes
|
||||||
|
if (args.automaticRelease) {
|
||||||
|
releaseNotes = '## Bug Fixes/Changes \n\n'
|
||||||
|
} else {
|
||||||
|
releaseNotes = '(placeholder)\n'
|
||||||
|
}
|
||||||
console.log(`Checking for commits from ${pkg.version} to ${currentBranch}`)
|
console.log(`Checking for commits from ${pkg.version} to ${currentBranch}`)
|
||||||
let commitComparison = await github.repos.compareCommits(githubOpts)
|
let commitComparison = await github.repos.compareCommits(githubOpts)
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
|
@ -85,13 +92,45 @@ async function getReleaseNotes (currentBranch) {
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (commitComparison.data.commits.length === 0) {
|
||||||
|
console.log(`${pass} There are no commits from ${pkg.version} to ` +
|
||||||
|
`${currentBranch}, skipping release.`)
|
||||||
|
process.exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
let prCount = 0
|
||||||
|
const mergeRE = /Merge pull request #(\d+) from .*\n/
|
||||||
|
const newlineRE = /(.*)\n*.*/
|
||||||
|
const prRE = /(.* )\(#(\d+)\)(?:.*)/
|
||||||
commitComparison.data.commits.forEach(commitEntry => {
|
commitComparison.data.commits.forEach(commitEntry => {
|
||||||
let commitMessage = commitEntry.commit.message
|
let commitMessage = commitEntry.commit.message
|
||||||
if (commitMessage.toLowerCase().indexOf('merge') > -1) {
|
if (commitMessage.indexOf('#') > -1) {
|
||||||
releaseNotes += `${commitMessage} \n`
|
let prMatch = commitMessage.match(mergeRE)
|
||||||
|
let prNumber
|
||||||
|
if (prMatch) {
|
||||||
|
commitMessage = commitMessage.replace(mergeRE, '').replace('\n', '')
|
||||||
|
let newlineMatch = commitMessage.match(newlineRE)
|
||||||
|
if (newlineMatch) {
|
||||||
|
commitMessage = newlineMatch[1]
|
||||||
|
}
|
||||||
|
prNumber = prMatch[1]
|
||||||
|
} else {
|
||||||
|
prMatch = commitMessage.match(prRE)
|
||||||
|
if (prMatch) {
|
||||||
|
commitMessage = prMatch[1].trim()
|
||||||
|
prNumber = prMatch[2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (prMatch) {
|
||||||
|
if (commitMessage.substr(commitMessage.length - 1, commitMessage.length) !== '.') {
|
||||||
|
commitMessage += '.'
|
||||||
|
}
|
||||||
|
releaseNotes += `* ${commitMessage} #${prNumber} \n\n`
|
||||||
|
prCount++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
console.log(`${pass} Done generating release notes for ${currentBranch}.`)
|
console.log(`${pass} Done generating release notes for ${currentBranch}. Found ${prCount} PRs.`)
|
||||||
return releaseNotes
|
return releaseNotes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,8 +177,8 @@ async function createRelease (branchToTarget, isBeta) {
|
||||||
console.log(`${pass} Draft release for ${newVersion} has been created.`)
|
console.log(`${pass} Draft release for ${newVersion} has been created.`)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function pushRelease () {
|
async function pushRelease (branch) {
|
||||||
let pushDetails = await GitProcess.exec(['push', 'origin', 'HEAD', '--follow-tags'], gitDir)
|
let pushDetails = await GitProcess.exec(['push', 'origin', `HEAD:${branch}`, '--follow-tags'], gitDir)
|
||||||
if (pushDetails.exitCode === 0) {
|
if (pushDetails.exitCode === 0) {
|
||||||
console.log(`${pass} Successfully pushed the release. Wait for ` +
|
console.log(`${pass} Successfully pushed the release. Wait for ` +
|
||||||
`release builds to finish before running "npm run release".`)
|
`release builds to finish before running "npm run release".`)
|
||||||
|
@ -152,7 +191,8 @@ async function pushRelease () {
|
||||||
|
|
||||||
async function runReleaseBuilds (branch) {
|
async function runReleaseBuilds (branch) {
|
||||||
await ciReleaseBuild(branch, {
|
await ciReleaseBuild(branch, {
|
||||||
ghRelease: true
|
ghRelease: true,
|
||||||
|
automaticRelease: args.automaticRelease
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,7 +210,12 @@ async function tagRelease (version) {
|
||||||
|
|
||||||
async function verifyNewVersion () {
|
async function verifyNewVersion () {
|
||||||
let newVersion = getNewVersion(true)
|
let newVersion = getNewVersion(true)
|
||||||
let response = await promptForVersion(newVersion)
|
let response
|
||||||
|
if (args.automaticRelease) {
|
||||||
|
response = 'y'
|
||||||
|
} else {
|
||||||
|
response = await promptForVersion(newVersion)
|
||||||
|
}
|
||||||
if (response.match(/^y/i)) {
|
if (response.match(/^y/i)) {
|
||||||
console.log(`${pass} Starting release of ${newVersion}`)
|
console.log(`${pass} Starting release of ${newVersion}`)
|
||||||
} else {
|
} else {
|
||||||
|
@ -193,14 +238,24 @@ async function promptForVersion (version) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function prepareRelease (isBeta, notesOnly) {
|
async function prepareRelease (isBeta, notesOnly) {
|
||||||
let currentBranch = await getCurrentBranch(gitDir)
|
if (args.automaticRelease && (pkg.version.indexOf('beta') === -1 ||
|
||||||
|
versionType !== 'beta')) {
|
||||||
|
console.log(`${fail} Automatic release is only supported for beta releases`)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
let currentBranch
|
||||||
|
if (args.branch) {
|
||||||
|
currentBranch = args.branch
|
||||||
|
} else {
|
||||||
|
currentBranch = await getCurrentBranch(gitDir)
|
||||||
|
}
|
||||||
if (notesOnly) {
|
if (notesOnly) {
|
||||||
let releaseNotes = await getReleaseNotes(currentBranch)
|
let releaseNotes = await getReleaseNotes(currentBranch)
|
||||||
console.log(`Draft release notes are: ${releaseNotes}`)
|
console.log(`Draft release notes are: \n${releaseNotes}`)
|
||||||
} else {
|
} else {
|
||||||
await verifyNewVersion()
|
await verifyNewVersion()
|
||||||
await createRelease(currentBranch, isBeta)
|
await createRelease(currentBranch, isBeta)
|
||||||
await pushRelease()
|
await pushRelease(currentBranch)
|
||||||
await runReleaseBuilds(currentBranch)
|
await runReleaseBuilds(currentBranch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ function assetsForVersion (version, validatingRelease) {
|
||||||
`electron-${version}-linux-armv7l.zip`,
|
`electron-${version}-linux-armv7l.zip`,
|
||||||
`electron-${version}-linux-ia32-symbols.zip`,
|
`electron-${version}-linux-ia32-symbols.zip`,
|
||||||
`electron-${version}-linux-ia32.zip`,
|
`electron-${version}-linux-ia32.zip`,
|
||||||
`electron-${version}-linux-mips64el.zip`,
|
// `electron-${version}-linux-mips64el.zip`,
|
||||||
`electron-${version}-linux-x64-symbols.zip`,
|
`electron-${version}-linux-x64-symbols.zip`,
|
||||||
`electron-${version}-linux-x64.zip`,
|
`electron-${version}-linux-x64.zip`,
|
||||||
`electron-${version}-mas-x64-dsym.zip`,
|
`electron-${version}-mas-x64-dsym.zip`,
|
||||||
|
@ -116,7 +116,7 @@ function assetsForVersion (version, validatingRelease) {
|
||||||
`ffmpeg-${version}-linux-arm64.zip`,
|
`ffmpeg-${version}-linux-arm64.zip`,
|
||||||
`ffmpeg-${version}-linux-armv7l.zip`,
|
`ffmpeg-${version}-linux-armv7l.zip`,
|
||||||
`ffmpeg-${version}-linux-ia32.zip`,
|
`ffmpeg-${version}-linux-ia32.zip`,
|
||||||
`ffmpeg-${version}-linux-mips64el.zip`,
|
// `ffmpeg-${version}-linux-mips64el.zip`,
|
||||||
`ffmpeg-${version}-linux-x64.zip`,
|
`ffmpeg-${version}-linux-x64.zip`,
|
||||||
`ffmpeg-${version}-mas-x64.zip`,
|
`ffmpeg-${version}-mas-x64.zip`,
|
||||||
`ffmpeg-${version}-win32-ia32.zip`,
|
`ffmpeg-${version}-win32-ia32.zip`,
|
||||||
|
@ -148,7 +148,11 @@ function s3UrlsForVersion (version) {
|
||||||
function checkVersion () {
|
function checkVersion () {
|
||||||
console.log(`Verifying that app version matches package version ${pkgVersion}.`)
|
console.log(`Verifying that app version matches package version ${pkgVersion}.`)
|
||||||
let startScript = path.join(__dirname, 'start.py')
|
let startScript = path.join(__dirname, 'start.py')
|
||||||
let appVersion = runScript(startScript, ['--version']).trim()
|
let scriptArgs = ['--version']
|
||||||
|
if (args.automaticRelease) {
|
||||||
|
scriptArgs.unshift('-R')
|
||||||
|
}
|
||||||
|
let appVersion = runScript(startScript, scriptArgs).trim()
|
||||||
check((pkgVersion.indexOf(appVersion) === 0), `App version ${appVersion} matches ` +
|
check((pkgVersion.indexOf(appVersion) === 0), `App version ${appVersion} matches ` +
|
||||||
`package version ${pkgVersion}.`, true)
|
`package version ${pkgVersion}.`, true)
|
||||||
}
|
}
|
||||||
|
@ -179,7 +183,11 @@ function uploadNodeShasums () {
|
||||||
function uploadIndexJson () {
|
function uploadIndexJson () {
|
||||||
console.log('Uploading index.json to S3.')
|
console.log('Uploading index.json to S3.')
|
||||||
let scriptPath = path.join(__dirname, 'upload-index-json.py')
|
let scriptPath = path.join(__dirname, 'upload-index-json.py')
|
||||||
runScript(scriptPath, [])
|
let scriptArgs = []
|
||||||
|
if (args.automaticRelease) {
|
||||||
|
scriptArgs.push('-R')
|
||||||
|
}
|
||||||
|
runScript(scriptPath, scriptArgs)
|
||||||
console.log(`${pass} Done uploading index.json to S3.`)
|
console.log(`${pass} Done uploading index.json to S3.`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,7 @@ def main():
|
||||||
github = GitHub(auth_token())
|
github = GitHub(auth_token())
|
||||||
releases = github.repos(ELECTRON_REPO).releases.get()
|
releases = github.repos(ELECTRON_REPO).releases.get()
|
||||||
tag_exists = False
|
tag_exists = False
|
||||||
|
release = None
|
||||||
for r in releases:
|
for r in releases:
|
||||||
if not r['draft'] and r['tag_name'] == args.version:
|
if not r['draft'] and r['tag_name'] == args.version:
|
||||||
release = r
|
release = r
|
||||||
|
@ -62,6 +63,9 @@ def main():
|
||||||
if not args.overwrite:
|
if not args.overwrite:
|
||||||
release = create_or_get_release_draft(github, releases, args.version,
|
release = create_or_get_release_draft(github, releases, args.version,
|
||||||
tag_exists)
|
tag_exists)
|
||||||
|
elif release is None:
|
||||||
|
release = dict(tag_name=args.version)
|
||||||
|
|
||||||
|
|
||||||
# Upload Electron with GitHub Releases API.
|
# Upload Electron with GitHub Releases API.
|
||||||
upload_electron(github, release, os.path.join(DIST_DIR, DIST_NAME),
|
upload_electron(github, release, os.path.join(DIST_DIR, DIST_NAME),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue