diff --git a/package-lock.json b/package-lock.json
index a17ccea67660..4965377ba6bb 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7972,6 +7972,17 @@
"find-up": "^1.0.0"
}
},
+ "plist": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.1.tgz",
+ "integrity": "sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ==",
+ "dev": true,
+ "requires": {
+ "base64-js": "^1.2.3",
+ "xmlbuilder": "^9.0.7",
+ "xmldom": "0.1.x"
+ }
+ },
"plur": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/plur/-/plur-2.1.2.tgz",
@@ -9419,9 +9430,9 @@
"optional": true
},
"semver": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
- "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
+ "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
"dev": true
},
"semver-diff": {
@@ -12132,6 +12143,18 @@
"dev": true,
"optional": true
},
+ "xmlbuilder": {
+ "version": "9.0.7",
+ "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
+ "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=",
+ "dev": true
+ },
+ "xmldom": {
+ "version": "0.1.27",
+ "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz",
+ "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=",
+ "dev": true
+ },
"xtend": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
diff --git a/package.json b/package.json
index 2d164d8cafab..5da03af9d324 100644
--- a/package.json
+++ b/package.json
@@ -26,11 +26,12 @@
"node-fetch": "^2.1.2",
"nugget": "^2.0.1",
"octicons": "^7.3.0",
+ "plist": "^3.0.1",
"recursive-readdir": "^2.2.2",
"remark-cli": "^4.0.0",
"remark-preset-lint-markdown-style-guide": "^2.1.1",
"request": "^2.88.0",
- "semver": "^5.5.0",
+ "semver": "^5.6.0",
"serve": "^6.5.8",
"standard-markdown": "^5.0.0",
"sumchecker": "^2.0.2",
diff --git a/script/bump-version.js b/script/bump-version.js
new file mode 100644
index 000000000000..d7e66a509818
--- /dev/null
+++ b/script/bump-version.js
@@ -0,0 +1,184 @@
+#!/usr/bin/env node
+
+const { GitProcess } = require('dugite')
+const utils = require('./lib/version-utils')
+const plist = require('plist')
+const fs = require('fs')
+const semver = require('semver')
+const path = require('path')
+const { promisify } = require('util')
+const minimist = require('minimist')
+
+const writeFile = promisify(fs.writeFile)
+const readFile = promisify(fs.readFile)
+
+function parseCommandLine () {
+ let help
+ const opts = minimist(process.argv.slice(2), {
+ string: [ 'bump', 'version' ],
+ boolean: [ 'dryRun', 'help' ],
+ alias: { 'version': ['v'] },
+ unknown: arg => { help = true }
+ })
+ if (help || opts.help || !opts.bump) {
+ console.log(`
+ Bump release version number. Possible arguments:\n
+ --bump=patch to increment patch version\n
+ --version={version} to set version number directly\n
+ --dryRun to print the next version without updating files
+ Note that you can use both --bump and --stable simultaneously.
+ `)
+ process.exit(0)
+ }
+ return opts
+}
+
+// run the script
+async function main () {
+ const opts = parseCommandLine()
+ const currentVersion = await utils.getElectronVersion()
+ const version = await nextVersion(opts.bump, currentVersion)
+
+ const parsed = semver.parse(version)
+ const components = {
+ major: parsed.major,
+ minor: parsed.minor,
+ patch: parsed.patch,
+ pre: parsed.prerelease
+ }
+
+ // print would-be new version and exit early
+ if (opts.dryRun) {
+ console.log(`new version number would be: ${version}\n`)
+ return 0
+ }
+
+ // update all version-related files
+ await Promise.all([
+ updateVersion(version),
+ updateInfoPlist(version),
+ updatePackageJSON(version),
+ updateVersionH(components),
+ updateWinRC(components)
+ ])
+
+ // commit all updated version-related files
+ await commitVersionBump(version)
+
+ console.log(`Bumped to version: ${version}`)
+}
+
+// get next version for release based on [nightly, beta, stable]
+async function nextVersion (bumpType, version) {
+ if (utils.isNightly(version) || utils.isBeta(version)) {
+ switch (bumpType) {
+ case 'nightly':
+ version = await utils.nextNightly(version)
+ break
+ case 'beta':
+ version = await utils.nextBeta(version)
+ break
+ case 'stable':
+ version = semver.valid(semver.coerce(version))
+ break
+ default:
+ throw new Error('Invalid bump type.')
+ }
+ } else if (utils.isStable(version)) {
+ switch (bumpType) {
+ case 'nightly':
+ version = utils.nextNightly(version)
+ break
+ case 'beta':
+ throw new Error('Cannot bump to beta from stable.')
+ case 'stable':
+ version = semver.inc(version, 'patch')
+ break
+ default:
+ throw new Error('Invalid bump type.')
+ }
+ } else {
+ throw new Error(`Invalid current version: ${version}`)
+ }
+ return version
+}
+
+// update VERSION file with latest release info
+async function updateVersion (version) {
+ const versionPath = path.resolve(__dirname, '..', 'VERSION')
+ await writeFile(versionPath, version, 'utf8')
+}
+
+// update package metadata files with new version
+async function updatePackageJSON (version) {
+ ['package.json', 'package-lock.json'].forEach(async fileName => {
+ const filePath = path.resolve(__dirname, '..', fileName)
+ const file = require(filePath)
+ file.version = version
+ await writeFile(filePath, JSON.stringify(file, null, 2))
+ })
+}
+
+// update CFBundle version information and overwrite pre-existing file
+// TODO(codebytere): provide these version fields at GN build time
+async function updateInfoPlist (version) {
+ const filePath = path.resolve(__dirname, '..', 'atom', 'browser', 'resources', 'mac', 'Info.plist')
+ const file = plist.parse(await readFile(filePath, { encoding: 'utf8' }))
+
+ file.CFBundleVersion = version
+ file.CFBundleShortVersionString = version
+
+ await writeFile(filePath, plist.build(file))
+}
+
+// push bump commit to release branch
+async function commitVersionBump (version) {
+ const gitDir = path.resolve(__dirname, '..')
+ const gitArgs = ['commit', '-a', '-m', `Bump v${version}`, '-n']
+ await GitProcess.exec(gitArgs, gitDir)
+}
+
+// updates atom_version.h file with new semver values
+// TODO(codebytere): auto-generate this
+async function updateVersionH (components) {
+ const filePath = path.resolve(__dirname, '..', 'atom', 'common', 'atom_version.h')
+ const data = await readFile(filePath, 'utf8')
+ const arr = data.split('\n')
+ const pre = components.pre != null ? `-${components.pre[0]}.${components.pre[1]}` : null
+
+ arr.forEach((item, idx) => {
+ if (item.includes('#define ATOM_MAJOR_VERSION')) {
+ arr[idx] = `#define ATOM_MAJOR_VERSION ${components.major}`
+ arr[idx + 1] = `#define ATOM_MINOR_VERSION ${components.minor}`
+ arr[idx + 2] = `#define ATOM_PATCH_VERSION ${components.patch}`
+ arr[idx + 4] = pre ? `#define ATOM_PRE_RELEASE_VERSION ${pre}` : '// #define ATOM_PRE_RELEASE_VERSION'
+ }
+ })
+ await writeFile(filePath, arr.join('\n'))
+}
+
+// updates atom.rc file with new semver values
+async function updateWinRC (components) {
+ const filePath = path.resolve(__dirname, '..', 'atom', 'browser', 'resources', 'win', 'atom.rc')
+ const data = await readFile(filePath, 'utf8')
+ const arr = data.split('\n')
+ arr.forEach((line, idx) => {
+ if (line.includes('FILEVERSION')) {
+ arr[idx] = ` FILEVERSION ${utils.makeVersion(components, ',', true)}`
+ arr[idx + 1] = ` PRODUCTVERSION ${utils.makeVersion(components, ',', true)}`
+ } else if (line.includes('FileVersion')) {
+ arr[idx] = ` VALUE "FileVersion", "${utils.makeVersion(components, '.')}"`
+ arr[idx + 5] = ` VALUE "ProductVersion", "${utils.makeVersion(components, '.')}"`
+ }
+ })
+ await writeFile(filePath, arr.join('\n'))
+}
+
+if (process.mainModule === module) {
+ main().catch((error) => {
+ console.error(error)
+ process.exit(1)
+ })
+}
+
+module.exports = { nextVersion }
diff --git a/script/bump-version.py b/script/bump-version.py
deleted file mode 100755
index 5268bde99034..000000000000
--- a/script/bump-version.py
+++ /dev/null
@@ -1,219 +0,0 @@
-#!/usr/bin/env python
-
-import os
-import re
-import sys
-import argparse
-
-from lib.util import execute, get_electron_version, parse_version, scoped_cwd, \
-is_nightly, is_beta, is_stable, get_next_nightly, get_next_beta, \
-get_next_stable_from_pre, get_next_stable_from_stable, clean_parse_version
-
-SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
-
-def main():
-
- parser = argparse.ArgumentParser(
- description='Bump version numbers. Must specify at least one of the three'
- +' options:\n'
- +' --bump=patch to increment patch version, or\n'
- +' --stable to promote current beta to stable, or\n'
- +' --version={version} to set version number directly\n'
- +'Note that you can use both --bump and --stable '
- +'simultaneously.',
- formatter_class=argparse.RawTextHelpFormatter
- )
- parser.add_argument(
- '--version',
- default=None,
- dest='new_version',
- help='new version number'
- )
- parser.add_argument(
- '--bump',
- action='store',
- default=None,
- dest='bump',
- help='increment [stable | beta | nightly]'
- )
- parser.add_argument(
- '--dry-run',
- action='store_true',
- default= False,
- dest='dry_run',
- help='just to check that version number is correct'
- )
-
- args = parser.parse_args()
- curr_version = get_electron_version()
-
- if args.bump not in ['stable', 'beta', 'nightly']:
- raise Exception('bump must be set to either stable, beta or nightly')
-
- if is_nightly(curr_version):
- if args.bump == 'nightly':
- version = get_next_nightly(curr_version)
- elif args.bump == 'beta':
- version = get_next_beta(curr_version)
- elif args.bump == 'stable':
- version = get_next_stable_from_pre(curr_version)
- else:
- not_reached()
- elif is_beta(curr_version):
- if args.bump == 'nightly':
- version = get_next_nightly(curr_version)
- elif args.bump == 'beta':
- version = get_next_beta(curr_version)
- elif args.bump == 'stable':
- version = get_next_stable_from_pre(curr_version)
- else:
- not_reached()
- elif is_stable(curr_version):
- if args.bump == 'nightly':
- version = get_next_nightly(curr_version)
- elif args.bump == 'beta':
- version = get_next_beta(curr_version)
- elif args.bump == 'stable':
- version = get_next_stable_from_stable(curr_version)
- else:
- not_reached()
- else:
- raise Exception("Invalid current version: " + curr_version)
-
- if args.new_version is None and args.bump is None and not args.stable:
- parser.print_help()
- return 1
-
- versions = clean_parse_version(version)
- suffix = ''
- if '-' in version:
- suffix = '-' + version.split('-')[1]
- versions[3] = parse_version(version)[3]
- version = version.split('-')[0]
-
- if args.dry_run:
- print 'new version number would be: {0}\n'.format(version + suffix)
- return 0
-
- with scoped_cwd(SOURCE_ROOT):
- update_version(version, suffix)
- update_win_rc(version, versions, args.bump == "nightly")
- update_version_h(versions, suffix)
- update_info_plist(version)
- update_package_json(version, suffix)
- tag_version(version, suffix)
-
- print 'Bumped to version: {0}'.format(version + suffix)
-
-def not_reached():
- raise Exception('Unreachable code was reached')
-
-def increase_version(versions, index):
- for i in range(index + 1, 4):
- versions[i] = '0'
- versions[index] = str(int(versions[index]) + 1)
- return versions
-
-
-def update_version(version, suffix):
- with open('VERSION', 'w') as f:
- f.write(version + suffix)
-
-
-def update_win_rc(version, versions, is_nightly_version):
- pattern_fv = re.compile(' FILEVERSION [0-9,]+')
- pattern_pv = re.compile(' PRODUCTVERSION [0-9,]+')
- pattern_fvs = re.compile(' *VALUE "FileVersion", "[0-9.]+"')
- pattern_pvs = re.compile(' *VALUE "ProductVersion", "[0-9.]+"')
-
- win_rc = os.path.join('atom', 'browser', 'resources', 'win', 'atom.rc')
- with open(win_rc, 'r') as f:
- lines = f.readlines()
-
- versions = [str(v) for v in versions]
- for i in range(0, len(lines)):
- line = lines[i]
- if pattern_fv.match(line):
- versions_64_bit = versions[::]
- if is_nightly_version:
- versions_64_bit[3] = '0'
- lines[i] = ' FILEVERSION {0}\r\n'.format(','.join(versions_64_bit))
- elif pattern_pv.match(line):
- lines[i] = ' PRODUCTVERSION {0}\r\n'.format(','.join(versions))
- elif pattern_fvs.match(line):
- lines[i] = ' VALUE "FileVersion", "{0}"\r\n'.format(version)
- elif pattern_pvs.match(line):
- lines[i] = ' VALUE "ProductVersion", "{0}"\r\n'.format(version)
-
- with open(win_rc, 'w') as f:
- f.write(''.join(lines))
-
-
-def update_version_h(versions, suffix):
- version_h = os.path.join('atom', 'common', 'atom_version.h')
- with open(version_h, 'r') as f:
- lines = f.readlines()
-
- for i in range(0, len(lines)):
- line = lines[i]
- if 'ATOM_MAJOR_VERSION' in line:
- lines[i] = '#define ATOM_MAJOR_VERSION {0}\n'.format(versions[0])
- lines[i + 1] = '#define ATOM_MINOR_VERSION {0}\n'.format(versions[1])
- lines[i + 2] = '#define ATOM_PATCH_VERSION {0}\n'.format(versions[2])
-
- # We do +4 here to avoid the clang format comment
- if (suffix):
- lines[i + 4] = '#define ATOM_PRE_RELEASE_VERSION {0}\n'.format(suffix)
- else:
- lines[i + 4] = '// #define ATOM_PRE_RELEASE_VERSION\n'
-
- with open(version_h, 'w') as f:
- f.write(''.join(lines))
- return
-
-
-def update_info_plist(version):
- info_plist = os.path.join('atom', 'browser', 'resources', 'mac', 'Info.plist')
- with open(info_plist, 'r') as f:
- lines = f.readlines()
-
- for i in range(0, len(lines)):
- line = lines[i]
- if 'CFBundleVersion' in line:
- lines[i + 1] = ' {0}\n'.format(version)
- if 'CFBundleShortVersionString' in line:
- lines[i + 1] = ' {0}\n'.format(version)
-
- with open(info_plist, 'w') as f:
- f.write(''.join(lines))
-
-
-def update_package_json(version, suffix):
- metadata_json_files = ['package.json', 'package-lock.json']
- for json_file in metadata_json_files:
- with open(json_file, 'r') as f:
- lines = f.readlines()
-
- for i in range(0, len(lines)):
- line = lines[i];
- if 'version' in line:
- lines[i] = ' "version": "{0}",\n'.format(version + suffix)
- break
-
- with open(json_file, 'w') as f:
- f.write(''.join(lines))
-
-
-def tag_version(version, suffix):
- execute([
- 'git',
- 'commit',
- '-a',
- '-m',
- 'Bump v{0}'.format(version + suffix),
- '-n'
- ])
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/script/get-last-major-for-master.js b/script/get-last-major-for-master.js
index 3b0f20f48632..7e9cfd33910c 100644
--- a/script/get-last-major-for-master.js
+++ b/script/get-last-major-for-master.js
@@ -3,7 +3,7 @@ const path = require('path')
const semver = require('semver')
const gitDir = path.resolve(__dirname, '..')
-async function determineNextMajorForMaster () {
+async function getLastMajorForMaster () {
let branchNames
const result = await GitProcess.exec(['branch', '-a', '--remote', '--list', 'origin/[0-9]-[0-9]-x'], gitDir)
if (result.exitCode === 0) {
@@ -17,13 +17,7 @@ async function determineNextMajorForMaster () {
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)
+ return converted.reduce((v1, v2) => semver.gt(v1, v2) ? v1 : v2)
}
-determineNextMajorForMaster().then(console.info).catch((err) => {
- console.error(err)
- process.exit(1)
-})
+module.exports = { getLastMajorForMaster }
diff --git a/script/lib/util.py b/script/lib/util.py
index 1c40efde9e19..f6d125f32794 100644
--- a/script/lib/util.py
+++ b/script/lib/util.py
@@ -217,85 +217,6 @@ def s3put(bucket, access_key, secret_key, prefix, key_prefix, files):
def add_exec_bit(filename):
os.chmod(filename, os.stat(filename).st_mode | stat.S_IEXEC)
-def parse_version(version):
- if version[0] == 'v':
- version = version[1:]
-
- vs = version.split('.')
- if len(vs) > 4:
- return vs[0:4]
- else:
- return vs + ['0'] * (4 - len(vs))
-
-def clean_parse_version(v):
- return parse_version(v.split("-")[0])
-
-def is_stable(v):
- return len(v.split(".")) == 3
-
-def is_beta(v):
- return 'beta' in v
-
-def is_nightly(v):
- return 'nightly' in v
-
-def get_nightly_date():
- return datetime.datetime.today().strftime('%Y%m%d')
-
-def get_last_major():
- return execute(['node', 'script/get-last-major-for-master.js'])
-
-def get_next_nightly(v):
- pv = clean_parse_version(v)
- (major, minor, patch) = pv[0:3]
-
- if (is_stable(v)):
- patch = str(int(pv[2]) + 1)
-
- if execute(['git', 'rev-parse', '--abbrev-ref', 'HEAD']) == "master":
- major = str(get_last_major() + 1)
- minor = '0'
- patch = '0'
-
- pre = 'nightly.' + get_nightly_date()
- return make_version(major, minor, patch, pre)
-
-def non_empty(thing):
- return thing.strip() != ''
-
-def beta_tag_compare(tag1, tag2):
- p1 = parse_version(tag1)
- p2 = parse_version(tag2)
- return int(p1[3]) - int(p2[3])
-
-def get_next_beta(v):
- pv = clean_parse_version(v)
- tag_pattern = 'v' + pv[0] + '.' + pv[1] + '.' + pv[2] + '-beta.*'
- tag_list = sorted(filter(
- non_empty,
- execute(['git', 'tag', '--list', '-l', tag_pattern]).strip().split('\n')
- ), cmp=beta_tag_compare)
- if len(tag_list) == 0:
- return make_version(pv[0] , pv[1], pv[2], 'beta.1')
-
- lv = parse_version(tag_list[-1])
- return make_version(pv[0] , pv[1], pv[2], 'beta.' + str(int(lv[3]) + 1))
-
-def get_next_stable_from_pre(v):
- pv = clean_parse_version(v)
- (major, minor, patch) = pv[0:3]
- return make_version(major, minor, patch)
-
-def get_next_stable_from_stable(v):
- pv = clean_parse_version(v)
- (major, minor, patch) = pv[0:3]
- return make_version(major, minor, str(int(patch) + 1))
-
-def make_version(major, minor, patch, pre = None):
- if pre is None:
- return major + '.' + minor + '.' + patch
- return major + "." + minor + "." + patch + '-' + pre
-
def get_out_dir():
out_dir = 'Debug'
override = os.environ.get('ELECTRON_OUT_DIR')
diff --git a/script/lib/version-utils.js b/script/lib/version-utils.js
new file mode 100644
index 000000000000..439190ebc6cd
--- /dev/null
+++ b/script/lib/version-utils.js
@@ -0,0 +1,73 @@
+const path = require('path')
+const fs = require('fs')
+const semver = require('semver')
+const { getLastMajorForMaster } = require('../get-last-major-for-master')
+const { GitProcess } = require('dugite')
+const { promisify } = require('util')
+
+const readFile = promisify(fs.readFile)
+const gitDir = path.resolve(__dirname, '..', '..')
+
+const getCurrentDate = () => {
+ const d = new Date()
+ const dd = `${d.getDate()}`.padStart(2, '0')
+ const mm = `${d.getMonth() + 1}`.padStart(2, '0')
+ const yyyy = d.getFullYear()
+ return `${yyyy}${mm}${dd}`
+}
+
+const isNightly = v => v.includes('nightly')
+const isBeta = v => v.includes('beta')
+const isStable = v => {
+ const parsed = semver.parse(v)
+ return !!(parsed && parsed.prerelease.length === 0)
+}
+
+const makeVersion = (components, delim, withPre = false) => {
+ let version = [components.major, components.minor, components.patch].join(delim)
+ if (withPre) {
+ version += `-${components.pre[0]}${delim}${components.pre[1]}`
+ }
+ return version
+}
+
+async function nextBeta (v) {
+ const next = semver.coerce(semver.clean(v))
+
+ const tagBlob = await GitProcess.exec(['tag', '--list', '-l', `v${next}-beta.*`], gitDir)
+ const tags = tagBlob.stdout.split('\n').filter(e => e !== '')
+ tags.sort((t1, t2) => semver.gt(t1, t2))
+
+ // increment the latest existing beta tag or start at beta.1 if it's a new beta line
+ return tags.length === 0 ? semver.inc(next, 'beta', 'prerelease') : semver.inc(tags.pop(), 'prerelease')
+}
+
+async function getElectronVersion () {
+ const versionPath = path.join(__dirname, '..', '..', 'VERSION')
+ const version = await readFile(versionPath, 'utf8')
+ return version.trim()
+}
+
+async function nextNightly (v) {
+ let next = semver.valid(semver.coerce(v))
+ const pre = `nightly.${getCurrentDate()}`
+
+ const branch = await GitProcess.exec(['rev-parse', '--abbrev-ref', 'HEAD'], gitDir)
+ if (branch === 'master') {
+ next = semver.inc(await getLastMajorForMaster(), 'major')
+ } else if (isStable(v)) {
+ next = semver.inc(next, 'patch')
+ }
+
+ return `${next}-${pre}`
+}
+
+module.exports = {
+ isStable,
+ isBeta,
+ isNightly,
+ nextBeta,
+ makeVersion,
+ getElectronVersion,
+ nextNightly
+}
diff --git a/script/prepare-release.js b/script/prepare-release.js
index 408f765fd3eb..def737430b73 100755
--- a/script/prepare-release.js
+++ b/script/prepare-release.js
@@ -13,8 +13,8 @@ const path = require('path')
const readline = require('readline')
const releaseNotesGenerator = require('./release-notes/index.js')
const { getCurrentBranch } = require('./lib/utils.js')
-const versionType = args._[0]
-const targetRepo = versionType === 'nightly' ? 'nightlies' : 'electron'
+const bumpType = args._[0]
+const targetRepo = bumpType === 'nightly' ? 'nightlies' : 'electron'
require('colors')
const pass = '\u2713'.green
@@ -23,8 +23,8 @@ const fail = '\u2717'.red
// TODO (future) automatically determine version based on conventional commits
// via conventional-recommended-bump
-if (!versionType && !args.notesOnly) {
- console.log(`Usage: prepare-release versionType [stable | beta | nightly]` +
+if (!bumpType && !args.notesOnly) {
+ console.log(`Usage: prepare-release [stable | beta | nightly]` +
` (--stable) (--notesOnly) (--automaticRelease) (--branch)`)
process.exit(1)
}
@@ -35,13 +35,11 @@ github.authenticate({ type: 'token', token: process.env.ELECTRON_GITHUB_TOKEN })
async function getNewVersion (dryRun) {
if (!dryRun) {
- console.log(`Bumping for new "${versionType}" version.`)
- }
- const bumpScript = path.join(__dirname, 'bump-version.py')
- const scriptArgs = [bumpScript, '--bump', versionType]
- if (dryRun) {
- scriptArgs.push('--dry-run')
+ console.log(`Bumping for new "${bumpType}" version.`)
}
+ const bumpScript = path.join(__dirname, 'bump-version.js')
+ const scriptArgs = ['node', bumpScript, `--bump=${bumpType}`]
+ if (dryRun) scriptArgs.push('--dry-run')
try {
let bumpVersion = execSync(scriptArgs.join(' '), { encoding: 'UTF-8' })
bumpVersion = bumpVersion.substr(bumpVersion.indexOf(':') + 1).trim()
@@ -57,7 +55,7 @@ async function getNewVersion (dryRun) {
}
async function getReleaseNotes (currentBranch) {
- if (versionType === 'nightly') {
+ if (bumpType === 'nightly') {
return 'Nightlies do not get release notes, please compare tags for info'
}
console.log(`Generating release notes for ${currentBranch}.`)
diff --git a/script/upload.py b/script/upload.py
index 7f5464206801..6dbdc9fccaa3 100755
--- a/script/upload.py
+++ b/script/upload.py
@@ -15,7 +15,7 @@ from io import StringIO
from lib.config import PLATFORM, get_target_arch, get_env_var, s3_config, \
get_zip_name
from lib.util import get_electron_branding, execute, get_electron_version, \
- parse_version, scoped_cwd, s3put, get_electron_exec, \
+ scoped_cwd, s3put, get_electron_exec, \
get_out_dir, SRC_DIR
diff --git a/spec/version-bump-spec.js b/spec/version-bump-spec.js
new file mode 100644
index 000000000000..aae96e7a07fb
--- /dev/null
+++ b/spec/version-bump-spec.js
@@ -0,0 +1,80 @@
+const { expect } = require('chai')
+const { nextVersion } = require('../script/bump-version')
+
+describe('bump-version script', () => {
+ const nightlyPattern = /[0-9.]*(-nightly.(\d{4})(\d{2})(\d{2}))$/g
+ const betaPattern = /[0-9.]*(-beta[0-9.]*)/g
+
+ it('bumps to nightly from stable', async () => {
+ const version = 'v2.0.0'
+ const next = await nextVersion('nightly', version)
+ const matches = next.match(nightlyPattern)
+ expect(matches).to.have.lengthOf(1)
+ })
+
+ it('bumps to nightly from beta', async () => {
+ const version = 'v2.0.0-beta.1'
+ const next = await nextVersion('nightly', version)
+ const matches = next.match(nightlyPattern)
+ expect(matches).to.have.lengthOf(1)
+ })
+
+ it('bumps to nightly from nightly', async () => {
+ const version = 'v2.0.0-nightly.19950901'
+ const next = await nextVersion('nightly', version)
+ const matches = next.match(nightlyPattern)
+ expect(matches).to.have.lengthOf(1)
+ })
+
+ it('throws error when bumping to beta from stable', () => {
+ const version = 'v2.0.0'
+ return expect(
+ nextVersion('beta', version)
+ ).to.be.rejectedWith('Cannot bump to beta from stable.')
+ })
+
+ it('bumps to beta from nightly', async () => {
+ const version = 'v2.0.0-nightly.19950901'
+ const next = await nextVersion('beta', version)
+ const matches = next.match(betaPattern)
+ expect(matches).to.have.lengthOf(1)
+ })
+
+ it('bumps to beta from beta', async () => {
+ const version = 'v2.0.0-beta.8'
+ const next = await nextVersion('beta', version)
+ expect(next).to.equal('2.0.0-beta.9')
+ })
+
+ it('bumps to stable from beta', async () => {
+ const version = 'v2.0.0-beta.1'
+ const next = await nextVersion('stable', version)
+ expect(next).to.equal('2.0.0')
+ })
+
+ it('bumps to stable from stable', async () => {
+ const version = 'v2.0.0'
+ const next = await nextVersion('stable', version)
+ expect(next).to.equal('2.0.1')
+ })
+
+ it('bumps to stable from nightly', async () => {
+ const version = 'v2.0.0-nightly.19950901'
+ const next = await nextVersion('stable', version)
+ expect(next).to.equal('2.0.0')
+ })
+
+ it('throws on an invalid version', () => {
+ const version = 'vI.AM.INVALID'
+ return expect(
+ nextVersion('beta', version)
+ ).to.be.rejectedWith(`Invalid current version: ${version}`)
+ })
+
+ it('throws on an invalid bump type', () => {
+ const version = 'v2.0.0'
+ return expect(
+ nextVersion('WRONG', version)
+ ).to.be.rejectedWith('Invalid bump type.')
+ })
+})