chore: introduce concept of nightly builds to release scripts (#14130)
* chore: introduce concept of nightly builds to release scripts * build: publish nightly releases to dedicated repo
This commit is contained in:
		
					parent
					
						
							
								22a2d9bd44
							
						
					
				
			
			
				commit
				
					
						b9afc68c35
					
				
			
		
					 7 changed files with 89 additions and 23 deletions
				
			
		| 
						 | 
				
			
			@ -72,10 +72,17 @@ def main():
 | 
			
		|||
    versions[3] = '0'
 | 
			
		||||
 | 
			
		||||
  if args.new_version != None:
 | 
			
		||||
    versions = parse_version(re.sub('-beta', '', args.new_version))
 | 
			
		||||
    clean_version = re.sub('-beta', '', args.new_version)
 | 
			
		||||
    clean_version = re.sub('-nightly', '', clean_version)
 | 
			
		||||
    versions = parse_version(clean_version)
 | 
			
		||||
 | 
			
		||||
  version = '.'.join(versions[:3])
 | 
			
		||||
  suffix = '' if versions[3] == '0' else '-beta.' + versions[3]
 | 
			
		||||
  suffix = ''
 | 
			
		||||
 | 
			
		||||
  if args.new_version != None and '-nightly' in args.new_version:
 | 
			
		||||
    suffix = '-nightly.' + versions[3]
 | 
			
		||||
  elif versions[3] != '0':
 | 
			
		||||
    suffix = '-beta.' + versions[3]
 | 
			
		||||
 | 
			
		||||
  if args.dry_run:
 | 
			
		||||
    print 'new version number would be: {0}\n'.format(version + suffix)
 | 
			
		||||
| 
						 | 
				
			
			@ -192,7 +199,14 @@ def update_package_json(version, suffix):
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
def tag_version(version, suffix):
 | 
			
		||||
  execute(['git', 'commit', '-a', '-m', 'Bump v{0}'.format(version + suffix)])
 | 
			
		||||
  execute([
 | 
			
		||||
    'git',
 | 
			
		||||
    'commit',
 | 
			
		||||
    '-a',
 | 
			
		||||
    '-m',
 | 
			
		||||
    'Bump v{0}'.format(version + suffix),
 | 
			
		||||
    '-n'
 | 
			
		||||
  ])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,7 +14,7 @@ async function findRelease () {
 | 
			
		|||
  github.authenticate({type: 'token', token: process.env.ELECTRON_GITHUB_TOKEN})
 | 
			
		||||
  let releases = await github.repos.getReleases({
 | 
			
		||||
    owner: 'electron',
 | 
			
		||||
    repo: 'electron'
 | 
			
		||||
    repo: version.indexOf('nightly') > 0 ? 'nightlies' : 'electron'
 | 
			
		||||
  })
 | 
			
		||||
  let targetRelease = releases.data.find(release => {
 | 
			
		||||
    return release.tag_name === version
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,13 +14,14 @@ const pass = '\u2713'.green
 | 
			
		|||
const path = require('path')
 | 
			
		||||
const pkg = require('../package.json')
 | 
			
		||||
const readline = require('readline')
 | 
			
		||||
const semver = require('semver')
 | 
			
		||||
const versionType = args._[0]
 | 
			
		||||
 | 
			
		||||
// TODO (future) automatically determine version based on conventional commits
 | 
			
		||||
// via conventional-recommended-bump
 | 
			
		||||
 | 
			
		||||
if (!versionType && !args.notesOnly) {
 | 
			
		||||
  console.log(`Usage: prepare-release versionType [major | minor | patch | beta]` +
 | 
			
		||||
  console.log(`Usage: prepare-release versionType [major | minor | patch | beta | nightly]` +
 | 
			
		||||
     ` (--stable) (--notesOnly) (--automaticRelease) (--branch)`)
 | 
			
		||||
  process.exit(1)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -29,10 +30,15 @@ const github = new GitHub()
 | 
			
		|||
const gitDir = path.resolve(__dirname, '..')
 | 
			
		||||
github.authenticate({type: 'token', token: process.env.ELECTRON_GITHUB_TOKEN})
 | 
			
		||||
 | 
			
		||||
function getNewVersion (dryRun) {
 | 
			
		||||
async function getNewVersion (dryRun) {
 | 
			
		||||
  console.log(`Bumping for new "${versionType}" version.`)
 | 
			
		||||
  let bumpScript = path.join(__dirname, 'bump-version.py')
 | 
			
		||||
  let scriptArgs = [bumpScript, `--bump ${versionType}`]
 | 
			
		||||
  let scriptArgs = [bumpScript]
 | 
			
		||||
  if (versionType === 'nightly') {
 | 
			
		||||
    scriptArgs.push(`--version ${await determineNextNightly(await getCurrentBranch())}`)
 | 
			
		||||
  } else {
 | 
			
		||||
    scriptArgs.push(`--bump ${versionType}`)
 | 
			
		||||
  }
 | 
			
		||||
  if (args.stable) {
 | 
			
		||||
    scriptArgs.push('--stable')
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -49,9 +55,47 @@ function getNewVersion (dryRun) {
 | 
			
		|||
    return newVersion
 | 
			
		||||
  } catch (err) {
 | 
			
		||||
    console.log(`${fail} Could not bump version, error was:`, err)
 | 
			
		||||
    throw err
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function determineNextNightly (currentBranch) {
 | 
			
		||||
  const twoPad = (n) => n < 10 ? `0${n}` : `${n}`
 | 
			
		||||
  const d = new Date()
 | 
			
		||||
  const date = `${d.getFullYear()}${twoPad(d.getMonth() + 1)}${twoPad(d.getDate())}`
 | 
			
		||||
 | 
			
		||||
  let version
 | 
			
		||||
 | 
			
		||||
  if (currentBranch === 'master') {
 | 
			
		||||
    version = await determineNextNightlyForMaster()
 | 
			
		||||
  }
 | 
			
		||||
  if (!version) {
 | 
			
		||||
    throw new Error(`not yet implemented for release branch: ${currentBranch}`)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return `${version}-nightly.${date}`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function determineNextNightlyForMaster () {
 | 
			
		||||
  let branchNames
 | 
			
		||||
  let result = await GitProcess.exec(['branch', '-a', '--remote', '--list', 'origin/[0-9]-[0-9]-x'], gitDir)
 | 
			
		||||
  if (result.exitCode === 0) {
 | 
			
		||||
    branchNames = result.stdout.trim().split('\n')
 | 
			
		||||
    const filtered = branchNames.map(b => b.replace('origin/', ''))
 | 
			
		||||
    return getNextReleaseBranch(filtered)
 | 
			
		||||
  } else {
 | 
			
		||||
    throw new Error('Release branches could not be fetched.')
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getNextReleaseBranch (branches) {
 | 
			
		||||
  const converted = branches.map(b => b.replace(/-/g, '.').replace('x', '0'))
 | 
			
		||||
  const next = converted.reduce((v1, v2) => {
 | 
			
		||||
    return semver.gt(v1, v2) ? v1 : v2
 | 
			
		||||
  })
 | 
			
		||||
  return `${parseInt(next.split('.')[0], 10) + 1}.0.0`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function getCurrentBranch (gitDir) {
 | 
			
		||||
  console.log(`Determining current git branch`)
 | 
			
		||||
  let gitArgs = ['rev-parse', '--abbrev-ref', 'HEAD']
 | 
			
		||||
| 
						 | 
				
			
			@ -70,6 +114,9 @@ async function getCurrentBranch (gitDir) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
async function getReleaseNotes (currentBranch) {
 | 
			
		||||
  if (versionType === 'nightly') {
 | 
			
		||||
    return 'Nightlies do not get release notes, please compare tags for info'
 | 
			
		||||
  }
 | 
			
		||||
  console.log(`Generating release notes for ${currentBranch}.`)
 | 
			
		||||
  let githubOpts = {
 | 
			
		||||
    owner: 'electron',
 | 
			
		||||
| 
						 | 
				
			
			@ -135,7 +182,7 @@ async function getReleaseNotes (currentBranch) {
 | 
			
		|||
 | 
			
		||||
async function createRelease (branchToTarget, isBeta) {
 | 
			
		||||
  let releaseNotes = await getReleaseNotes(branchToTarget)
 | 
			
		||||
  let newVersion = getNewVersion()
 | 
			
		||||
  let newVersion = await getNewVersion()
 | 
			
		||||
  await tagRelease(newVersion)
 | 
			
		||||
  const githubOpts = {
 | 
			
		||||
    owner: 'electron',
 | 
			
		||||
| 
						 | 
				
			
			@ -208,7 +255,7 @@ async function tagRelease (version) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
async function verifyNewVersion () {
 | 
			
		||||
  let newVersion = getNewVersion(true)
 | 
			
		||||
  let newVersion = await getNewVersion(true)
 | 
			
		||||
  let response
 | 
			
		||||
  if (args.automaticRelease) {
 | 
			
		||||
    response = 'y'
 | 
			
		||||
| 
						 | 
				
			
			@ -238,8 +285,8 @@ async function promptForVersion (version) {
 | 
			
		|||
 | 
			
		||||
async function prepareRelease (isBeta, notesOnly) {
 | 
			
		||||
  if (args.automaticRelease && (pkg.version.indexOf('beta') === -1 ||
 | 
			
		||||
      versionType !== 'beta')) {
 | 
			
		||||
    console.log(`${fail} Automatic release is only supported for beta releases`)
 | 
			
		||||
      versionType !== 'beta') && versionType !== 'nightly') {
 | 
			
		||||
    console.log(`${fail} Automatic release is only supported for beta and nightly releases`)
 | 
			
		||||
    process.exit(1)
 | 
			
		||||
  }
 | 
			
		||||
  let currentBranch
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,7 +68,7 @@ new Promise((resolve, reject) => {
 | 
			
		|||
 | 
			
		||||
  return github.repos.getReleases({
 | 
			
		||||
    owner: 'electron',
 | 
			
		||||
    repo: 'electron'
 | 
			
		||||
    repo: rootPackageJson.version.indexOf('nightly') > 0 ? 'nightlies' : 'electron'
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
.then((releases) => {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,6 +16,7 @@ const fail = '\u2717'.red
 | 
			
		|||
const sumchecker = require('sumchecker')
 | 
			
		||||
const temp = require('temp').track()
 | 
			
		||||
const { URL } = require('url')
 | 
			
		||||
const targetRepo = pkgVersion.indexOf('nightly') > 0 ? 'nightlies' : 'electron'
 | 
			
		||||
let failureCount = 0
 | 
			
		||||
 | 
			
		||||
const github = new GitHub({
 | 
			
		||||
| 
						 | 
				
			
			@ -24,7 +25,7 @@ const github = new GitHub({
 | 
			
		|||
github.authenticate({type: 'token', token: process.env.ELECTRON_GITHUB_TOKEN})
 | 
			
		||||
 | 
			
		||||
async function getDraftRelease (version, skipValidation) {
 | 
			
		||||
  let releaseInfo = await github.repos.getReleases({owner: 'electron', repo: 'electron'})
 | 
			
		||||
  let releaseInfo = await github.repos.getReleases({owner: 'electron', repo: targetRepo})
 | 
			
		||||
  let drafts
 | 
			
		||||
  let versionToCheck
 | 
			
		||||
  if (version) {
 | 
			
		||||
| 
						 | 
				
			
			@ -197,7 +198,7 @@ async function createReleaseShasums (release) {
 | 
			
		|||
    console.log(`${fileName} already exists on GitHub; deleting before creating new file.`)
 | 
			
		||||
    await github.repos.deleteAsset({
 | 
			
		||||
      owner: 'electron',
 | 
			
		||||
      repo: 'electron',
 | 
			
		||||
      repo: targetRepo,
 | 
			
		||||
      id: existingAssets[0].id
 | 
			
		||||
    }).catch(err => {
 | 
			
		||||
      console.log(`${fail} Error deleting ${fileName} on GitHub:`, err)
 | 
			
		||||
| 
						 | 
				
			
			@ -216,7 +217,7 @@ async function createReleaseShasums (release) {
 | 
			
		|||
async function uploadShasumFile (filePath, fileName, release) {
 | 
			
		||||
  let githubOpts = {
 | 
			
		||||
    owner: 'electron',
 | 
			
		||||
    repo: 'electron',
 | 
			
		||||
    repo: targetRepo,
 | 
			
		||||
    id: release.id,
 | 
			
		||||
    filePath,
 | 
			
		||||
    name: fileName
 | 
			
		||||
| 
						 | 
				
			
			@ -251,7 +252,7 @@ function saveShaSumFile (checksums, fileName) {
 | 
			
		|||
async function publishRelease (release) {
 | 
			
		||||
  let githubOpts = {
 | 
			
		||||
    owner: 'electron',
 | 
			
		||||
    repo: 'electron',
 | 
			
		||||
    repo: targetRepo,
 | 
			
		||||
    id: release.id,
 | 
			
		||||
    tag_name: release.tag_name,
 | 
			
		||||
    draft: false
 | 
			
		||||
| 
						 | 
				
			
			@ -305,7 +306,7 @@ async function verifyAssets (release) {
 | 
			
		|||
  let downloadDir = await makeTempDir()
 | 
			
		||||
  let githubOpts = {
 | 
			
		||||
    owner: 'electron',
 | 
			
		||||
    repo: 'electron',
 | 
			
		||||
    repo: targetRepo,
 | 
			
		||||
    headers: {
 | 
			
		||||
      Accept: 'application/octet-stream'
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,17 +4,20 @@ const GitHub = require('github')
 | 
			
		|||
const github = new GitHub()
 | 
			
		||||
github.authenticate({type: 'token', token: process.env.ELECTRON_GITHUB_TOKEN})
 | 
			
		||||
 | 
			
		||||
if (process.argv.length < 5) {
 | 
			
		||||
if (process.argv.length < 6) {
 | 
			
		||||
  console.log('Usage: upload-to-github filePath fileName releaseId')
 | 
			
		||||
  process.exit(1)
 | 
			
		||||
}
 | 
			
		||||
let filePath = process.argv[2]
 | 
			
		||||
let fileName = process.argv[3]
 | 
			
		||||
let releaseId = process.argv[4]
 | 
			
		||||
let releaseVersion = process.argv[5]
 | 
			
		||||
 | 
			
		||||
const targetRepo = releaseVersion.indexOf('nightly') > 0 ? 'nightlies' : 'electron'
 | 
			
		||||
 | 
			
		||||
let githubOpts = {
 | 
			
		||||
  owner: 'electron',
 | 
			
		||||
  repo: 'electron',
 | 
			
		||||
  repo: targetRepo,
 | 
			
		||||
  id: releaseId,
 | 
			
		||||
  filePath: filePath,
 | 
			
		||||
  name: fileName
 | 
			
		||||
| 
						 | 
				
			
			@ -36,7 +39,7 @@ function uploadToGitHub () {
 | 
			
		|||
          console.log(`${fileName} already exists; will delete before retrying upload.`)
 | 
			
		||||
          github.repos.deleteAsset({
 | 
			
		||||
            owner: 'electron',
 | 
			
		||||
            repo: 'electron',
 | 
			
		||||
            repo: targetRepo,
 | 
			
		||||
            id: existingAssets[0].id
 | 
			
		||||
          }).then(uploadToGitHub).catch(uploadToGitHub)
 | 
			
		||||
        } else {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -165,17 +165,18 @@ def upload_electron(release, file_path, args):
 | 
			
		|||
    return
 | 
			
		||||
 | 
			
		||||
  # Upload the file.
 | 
			
		||||
  upload_io_to_github(release, filename, file_path)
 | 
			
		||||
  upload_io_to_github(release, filename, file_path, args.version)
 | 
			
		||||
 | 
			
		||||
  # Upload the checksum file.
 | 
			
		||||
  upload_sha256_checksum(args.version, file_path)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def upload_io_to_github(release, filename, filepath):
 | 
			
		||||
def upload_io_to_github(release, filename, filepath, version):
 | 
			
		||||
  print 'Uploading %s to Github' % \
 | 
			
		||||
      (filename)
 | 
			
		||||
  script_path = os.path.join(SOURCE_ROOT, 'script', 'upload-to-github.js')
 | 
			
		||||
  execute(['node', script_path, filepath, filename, str(release['id'])])
 | 
			
		||||
  execute(['node', script_path, filepath, filename, str(release['id']),
 | 
			
		||||
          version])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def upload_sha256_checksum(version, file_path, key_prefix=None):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue