Merge pull request #6017 from brave/mplesa-omaha-upload-delta

added upload for delta installers
This commit is contained in:
Mihai PLESA
2020-07-08 18:34:59 +01:00
committed by GitHub
3 changed files with 123 additions and 95 deletions
+48 -26
View File
@@ -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 <a href="{0}">{0}</a>'.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
+5 -5
View File
@@ -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']:
+70 -64
View File
@@ -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: