diff --git a/script/lib/omaha.py b/script/lib/omaha.py index 406deb77ef8..1c4504f3028 100644 --- a/script/lib/omaha.py +++ b/script/lib/omaha.py @@ -28,27 +28,40 @@ platform_id = { def get_channel_id(channel, host, headers, logging): channel_json = get_channel_ids_from_omaha_server(host, headers, logging) - id = next(item["id"] for item in channel_json if item["name"] == channel) + id = next(item['id'] for item in channel_json if item['name'] == channel) return id def get_channel_ids_from_omaha_server(host, headers, logging): - """ + ''' Channel IDs can change between Omaha servers and over time may even change on the same Omaha server. Get all IDs from the server versus hardcoding in an enum like we do above with Event IDs or Platform IDs. - """ + ''' url = 'https://' + host + '/api/channel' response = get(url, headers) if response.status_code != 200: - logging.error("ERROR: Cannot GET /api/channel from Omaha host {}! " - "response.status_code: {}".format(host, response.status_code)) + logging.error('ERROR: Cannot GET /api/channel from Omaha host {}! ' + 'response.status_code: {}'.format(host, response.status_code)) logging.error(response.raise_for_status()) exit(1) return response.json() +def get_omaha_version_id(channel, version, host, headers, logging): + channel_id = get_channel_id(channel, host, headers, logging) + url = 'https://' + host + '/api/omaha/version?version=' + version + response = get(url, headers) + if response.status_code != 200: + logging.error('ERROR: Cannot GET /api/omaha/version from Omaha host {}! ' + 'response.status_code: {}'.format(host, response.status_code)) + logging.error(response.raise_for_status()) + exit(1) + id = next(item['id'] for item in response.json() if (item['channel'] == channel_id and item['version'] == version)) + return id + + def get_event_id(event): return event_id[event] @@ -62,9 +75,9 @@ def get_platform_id(platform): def get_base64_authorization(omahaid, omahapw): - """ + ''' Returns a base64 encoded string created from the Omaha ID and PW - """ + ''' concatstr = omahaid + ':' + omahapw return base64.b64encode(concatstr.encode()) @@ -83,55 +96,64 @@ def get_appguid(channel, platform): def get_app_info(appinfo, args): - """ + ''' Returns a dict with all the info about the omaha app that we will need to perform the upload - """ + ''' - changelog_url = "https://github.com/brave/brave-browser/blob/master/CHANGELOG_DESKTOP.md" - chrome_major = get_chrome_version().split('.')[0] - chrome_minor = get_chrome_version().split('.')[1] + changelog_url = 'https://github.com/brave/brave-browser/blob/master/CHANGELOG_DESKTOP.md' + + if args.version: + version_values = args.version.split('.') + chrome_major = version_values[0] + brave_version = '.'.join(version_values[1:3]) + version = args.version + else: + chrome_major = get_chrome_version().split('.')[0] + brave_version = get_upload_version() + version = chrome_major + '.' + brave_version + version_values = version.split('.') # The Sparkle CFBundleVersion is no longer tied to the Chrome version, # instead we derive it from the package.json['version'] string. The 2nd # digit is adjusted, and then we utilize that combined with the 3rd digit as # the CFBundleVersion. (This is also used in build/mac/tweak_info_plist.py) - version_values = get_upload_version().split('.') - if int(version_values[0]) >= 1: - adjusted_minor = int(version_values[1]) + (100 * int(version_values[0])) + if int(version_values[1]) >= 1: + adjusted_minor = int(version_values[2]) + (100 * int(version_values[1])) else: # Fall back to returning the actual minor value - adjusted_minor = int(version_values[1]) + adjusted_minor = int(version_values[2]) + appinfo['platform'] = 'darwin' if 'darwin' in args.platform else 'win32' + appinfo['arch'] = 'ia32' if 'win32' in args.platform else 'x64' appinfo['appguid'] = get_appguid(release_channel(), appinfo['platform']) appinfo['channel'] = release_channel() - appinfo['chrome_version'] = get_chrome_version() appinfo['platform_id'] = get_platform_id(appinfo['platform']) - appinfo['preview'] = args.preview + appinfo['internal'] = args.internal appinfo['full'] = args.full + appinfo['previous'] = args.previous if appinfo['platform'] in 'win32': # By default enable the win32 version on upload appinfo['is_enabled'] = True # The win32 version is the equivalent of the 'short_version' on darwin - appinfo['version'] = chrome_major + '.' + get_upload_version() + appinfo['version'] = version if appinfo['platform'] in 'darwin': - appinfo['short_version'] = chrome_major + '.' + get_upload_version() - appinfo['version'] = str(adjusted_minor) + \ - '.' + version_values[2] + appinfo['short_version'] = version + appinfo['version'] = str(adjusted_minor) + '.' + version_values[3] appinfo['release_notes'] = 'Release notes at {0}'.format(changelog_url) return appinfo def get_upload_version(): - """ + ''' Returns the version of brave-browser - """ + ''' return get_raw_version() def sign_update_sparkle(dmg, dsaprivpem): - """ + ''' Signs the Darwin dmg and returns the base64 encoded hash. This replaces the functionality in: @@ -139,7 +161,7 @@ def sign_update_sparkle(dmg, dsaprivpem): Need to run the equivalent of the command: `$openssl dgst -sha1 -binary < "$1" | $openssl dgst -sha1 -sign "$2" | $openssl enc -base64` - """ + ''' import base64 from cryptography.hazmat.backends import default_backend diff --git a/script/lib/util.py b/script/lib/util.py index b400bd0975c..f01dfc27efa 100644 --- a/script/lib/util.py +++ b/script/lib/util.py @@ -251,9 +251,9 @@ def get_platform(): return PLATFORM -def omaha_channel(platform, arch, preview, full=False): +def omaha_channel(platform, arch, internal, full=False): if platform == 'darwin': - if preview: + if internal: if release_channel() in ['nightly']: chan = 'test-nite' if release_channel() in ['beta']: @@ -265,10 +265,10 @@ def omaha_channel(platform, arch, preview, full=False): else: chan = 'stable' if release_channel() in ['release'] else release_channel() elif platform == 'win32': - arch = ('86' if preview else 'x86') if (arch in ['ia32']) else ('64' if preview else 'x64') + arch = ('86' if internal else 'x86') if (arch in ['ia32']) else ('64' if internal else 'x64') if release_channel() in ['nightly', 'beta']: - chan = '{}-{}{}'.format(arch, release_channel()[0:2], '-test' if preview else '') - elif preview: + chan = '{}-{}{}'.format(arch, release_channel()[0:2], '-test' if internal else '') + elif internal: if release_channel() in ['dev']: chan = '{}-dv-test'.format(arch) elif release_channel() in ['release']: diff --git a/script/omaha-upload.py b/script/omaha-upload.py index 72c77f5f57b..0361666ecff 100644 --- a/script/omaha-upload.py +++ b/script/omaha-upload.py @@ -17,8 +17,8 @@ from lib.connect import post, get, post_with_file from lib.github import GitHub from lib.helpers import * from lib.util import get_host_arch, omaha_channel -from lib.omaha import get_app_info, get_base64_authorization, get_channel_id, get_upload_version, get_event_id, \ - get_channel_ids_from_omaha_server, sign_update_sparkle +from lib.omaha import get_app_info, get_base64_authorization, get_channel_id, get_omaha_version_id, \ + get_upload_version, get_event_id, get_channel_ids_from_omaha_server, sign_update_sparkle # TODO: # 1. write tests @@ -196,19 +196,16 @@ def parse_args(): " in the parent dir)" parser = argparse.ArgumentParser( description=desc, formatter_class=RawTextHelpFormatter) - parser.add_argument('-d', '--debug', help='Print debug statements', action='store_true') - parser.add_argument('-f', '--file', help='Windows or Mac install file to upload to' - ' omaha/sparkle (cannot be combined with --github)') - parser.add_argument('-p', '--preview', help='Preview channels for testing' - ' omaha/sparkle uploads by QA before production release', action='store_true') - parser.add_argument('--full', help='Upload to "-full" channels', action='store_true') - parser.add_argument('--platform', help='Platform(s) to upload to Omaha (separated by spaces)', - nargs='*', choices=['win32', 'win64', 'darwin']) - parser.add_argument('--uploaded', help='Upload all the platform(s) that are already in the GitHub release', - action='store_true') - parser.add_argument('-g', '--github', help='Download Win and Mac install files' - ' from Github before uploading to Omaha (cannot be combined with --file)', action='store_true') - parser.add_argument('-t', '--tag', help='Version tag to download from Github') + parser.add_argument('--version', help='full brave version to upload') + parser.add_argument('--previous', help='previous version') + parser.add_argument('--platform', help='platforms (spaced)', nargs='*', choices=['win32', 'win64', 'darwin']) + parser.add_argument('--internal', help='upload to internal test channels', action='store_true') + parser.add_argument('--full', help='upload to "-full" channels', action='store_true') + parser.add_argument('--file', help='installer file to upload (cannot be combined with --github)') + parser.add_argument('--tag', help='GitHub version tag to upload') + parser.add_argument('--github', help='download from GitHub (cannot be combined with --file)', action='store_true') + parser.add_argument('--uploaded', help='upload all the platforms from the GitHub release', action='store_true') + parser.add_argument('--debug', help='debug', action='store_true') return parser.parse_args() @@ -219,6 +216,10 @@ def main(): logging.basicConfig(stream=sys.stderr, level=logging.DEBUG) logging.debug('brave_version: {}'.format(get_upload_version())) + if args.version and args.previous: + if args.version == args.previous: + exit("Error: version and previous have to be different") + if args.uploaded and args.platform: exit("Error: --platform and --uploaded are mutually exclusive, only one allowed") @@ -247,37 +248,38 @@ def main(): if args.debug: logging.debug("source_file: {}".format(source_file)) - if re.match(r'.*\.dmg$', source_file): - app_info['platform'] = 'darwin' - app_info['arch'] = 'x64' - elif re.match(r'.*brave_installer-ia32\.exe$', source_file): - app_info['platform'] = 'win32' - app_info['arch'] = 'ia32' - elif re.match(r'.*brave_installer-x64\.exe$', source_file): - app_info['platform'] = 'win32' - app_info['arch'] = 'x64' + if args.github: + if re.match(r'.*\.dmg$', source_file): + app_info['platform'] = 'darwin' + app_info['arch'] = 'x64' + elif re.match(r'.*brave_installer-ia32\.exe$', source_file): + app_info['platform'] = 'win32' + app_info['arch'] = 'ia32' + elif re.match(r'.*brave_installer-x64\.exe$', source_file): + app_info['platform'] = 'win32' + app_info['arch'] = 'x64' app_info = get_app_info(app_info, args) app_info['omahahost'] = os.environ.get('OMAHA_HOST') - app_info['auth'] = get_base64_authorization( - os.environ.get('OMAHA_USER'), os.environ.get('OMAHA_PASS')) + app_info['auth'] = get_base64_authorization(os.environ.get('OMAHA_USER'), os.environ.get('OMAHA_PASS')) app_info['headers'] = headers = { 'Authorization': 'Basic %s' % app_info['auth'] } - if app_info['platform'] in 'darwin': - app_info['version_url'] = '/api/sparkle/version/' - if not os.environ.get('DSA_PRIVATE_PEM'): - exit('Error: Please set the $DSA_PRIVATE_PEM environment variable') - elif app_info['platform'] in 'win32': - app_info['version_url'] = '/api/omaha/version/' - - app_info['version_post_url'] = 'https://' + \ - app_info['omahahost'] + app_info['version_url'] + if app_info['previous']: + app_info['version_url'] = '/api/deltaupdate/' + else: + if app_info['platform'] in 'darwin': + app_info['version_url'] = '/api/sparkle/version/' + if not os.environ.get('DSA_PRIVATE_PEM'): + exit('Error: Please set the $DSA_PRIVATE_PEM environment variable') + elif app_info['platform'] in 'win32': + app_info['version_url'] = '/api/omaha/version/' + app_info['version_post_url'] = 'https://' + app_info['omahahost'] + app_info['version_url'] app_info['size'] = os.path.getsize(source_file) - channel = omaha_channel(app_info['platform'], app_info['arch'], app_info['preview'], app_info['full']) + channel = omaha_channel(app_info['platform'], app_info['arch'], app_info['internal'], app_info['full']) channel_id = get_channel_id(channel, app_info['omahahost'], app_info['headers'], logging) if args.debug: @@ -296,49 +298,53 @@ def main(): with open(source_file, 'rb') as f: files = {'file': f} - params = { - 'app': app_info['appguid'], - 'channel': channel_id, - 'version': app_info['version'], - 'release_notes': app_info['release_notes'] - } - if app_info['platform'] in 'win32': - params['is_enabled'] = app_info['is_enabled'] - params['platform'] = app_info['platform_id'] - else: - app_info['darwindsasig'] = sign_update_sparkle( - source_file, os.environ.get('DSA_PRIVATE_PEM')).rstrip('\n') - params['dsa_signature'] = app_info['darwindsasig'] - params['short_version'] = app_info['short_version'] + if not app_info['previous']: + params = { + 'app': app_info['appguid'], + 'channel': channel_id, + 'version': app_info['version'], + 'release_notes': app_info['release_notes'] + } + + if app_info['platform'] in 'win32': + params['is_enabled'] = app_info['is_enabled'] + params['platform'] = app_info['platform_id'] + else: + app_info['darwindsasig'] = sign_update_sparkle( + source_file, os.environ.get('DSA_PRIVATE_PEM')).rstrip('\n') + params['dsa_signature'] = app_info['darwindsasig'] + params['short_version'] = app_info['short_version'] + elif 'win64' in args.platform: + target_version_id = get_omaha_version_id(channel, args.version, app_info['omahahost'], + app_info['headers'], logging) + source_version_id = get_omaha_version_id(channel, args.previous, app_info['omahahost'], + app_info['headers'], logging) + params = { + 'target': target_version_id, + 'source': source_version_id + } + + response = post_with_file(app_info['version_post_url'], files, params, headers) - response = post_with_file( - app_info['version_post_url'], files, params, headers) if response.status_code != 201: - logging.error("ERROR: Version not created! response.status_code : {}".format( - response.status_code)) + logging.error("ERROR: Version not created! response.status_code : {}".format(response.status_code)) logging.error("response.text : {}".format(response.text)) if response.status_code == 400 and 'version must make a unique set' in response.text: logging.error("ERROR: This version({}), channel({}), appguid({}) set has already been " - "uploaded to the Omaha server!".format(params['version'], app_info['channel'], - params['app'])) - - remove_github_downloaded_files(file_list, logging) - + "uploaded!".format(params['version'], app_info['channel'], params['app'])) exit(1) - if app_info['platform'] in 'win32': + if not app_info['previous'] and (app_info['platform'] in 'win32'): # When uploading windows builds, add actions to version just created rjson = response.json() if args.debug: logging.debug("response['id']: {}".format(rjson['id'])) - post_action(app_info['omahahost'], rjson['id'], - 'install', headers, args) - post_action(app_info['omahahost'], - rjson['id'], 'update', headers, args) + post_action(app_info['omahahost'], rjson['id'], 'install', headers, args) + post_action(app_info['omahahost'], rjson['id'], 'update', headers, args) # if downloading from github, remove files after upload if args.github: