forked from mirrors/gecko-dev
This allows thunderbird to be supported. Differential Revision: https://phabricator.services.mozilla.com/D1484
299 lines
11 KiB
Python
299 lines
11 KiB
Python
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
"""
|
|
Add from parameters.yml into bouncer submission tasks.
|
|
"""
|
|
|
|
from __future__ import absolute_import, print_function, unicode_literals
|
|
|
|
import logging
|
|
|
|
from taskgraph.transforms.base import TransformSequence
|
|
from taskgraph.transforms.l10n import parse_locales_file
|
|
from taskgraph.util.schema import resolve_keyed_by
|
|
from taskgraph.util.scriptworker import get_release_config
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
FTP_PLATFORMS_PER_BOUNCER_PLATFORM = {
|
|
'android': 'android-api-16',
|
|
'android-x86': 'android-x86',
|
|
'linux': 'linux-i686',
|
|
'linux64': 'linux-x86_64',
|
|
'osx': 'mac',
|
|
'win': 'win32',
|
|
'win64': 'win64',
|
|
}
|
|
|
|
# :lang is interpolated by bouncer at runtime
|
|
CANDIDATES_PATH_TEMPLATE = '/{ftp_product}/candidates/{version}-candidates/build{build_number}/\
|
|
{update_folder}{ftp_platform}/:lang/{file}'
|
|
RELEASES_PATH_TEMPLATE = '/{ftp_product}/releases/{version}/\
|
|
{update_folder}{ftp_platform}/:lang/{file}'
|
|
|
|
|
|
CONFIG_PER_BOUNCER_PRODUCT = {
|
|
'apk': {
|
|
'path_template': RELEASES_PATH_TEMPLATE,
|
|
'file_names': {
|
|
'android': '{product}-{version}.:lang.android-arm.apk',
|
|
'android-x86': '{product}-{version}.:lang.android-i386.apk',
|
|
},
|
|
},
|
|
'complete-mar': {
|
|
'path_template': RELEASES_PATH_TEMPLATE,
|
|
'file_names': {
|
|
'default': '{product}-{version}.complete.mar',
|
|
},
|
|
},
|
|
'complete-mar-candidates': {
|
|
'path_template': CANDIDATES_PATH_TEMPLATE,
|
|
'file_names': {
|
|
'default': '{product}-{version}.complete.mar',
|
|
},
|
|
},
|
|
'installer': {
|
|
'path_template': RELEASES_PATH_TEMPLATE,
|
|
'file_names': {
|
|
'linux': '{product}-{version}.tar.bz2',
|
|
'linux64': '{product}-{version}.tar.bz2',
|
|
'osx': '{pretty_product}%20{version}.dmg',
|
|
'win': '{pretty_product}%20Setup%20{version}.exe',
|
|
'win64': '{pretty_product}%20Setup%20{version}.exe',
|
|
},
|
|
},
|
|
'partial-mar': {
|
|
'path_template': RELEASES_PATH_TEMPLATE,
|
|
'file_names': {
|
|
'default': '{product}-{previous_version}-{version}.partial.mar',
|
|
},
|
|
},
|
|
'partial-mar-candidates': {
|
|
'path_template': CANDIDATES_PATH_TEMPLATE,
|
|
'file_names': {
|
|
'default': '{product}-{previous_version}-{version}.partial.mar',
|
|
},
|
|
},
|
|
'stub-installer': {
|
|
'path_template': RELEASES_PATH_TEMPLATE,
|
|
'file_names': {
|
|
'win': '{pretty_product}%20Installer.exe',
|
|
'win64': '{pretty_product}%20Installer.exe',
|
|
},
|
|
},
|
|
}
|
|
CONFIG_PER_BOUNCER_PRODUCT['installer-ssl'] = CONFIG_PER_BOUNCER_PRODUCT['installer']
|
|
|
|
transforms = TransformSequence()
|
|
|
|
|
|
@transforms.add
|
|
def make_task_worker(config, jobs):
|
|
for job in jobs:
|
|
resolve_keyed_by(
|
|
job, 'worker-type', item_name=job['name'], project=config.params['project']
|
|
)
|
|
resolve_keyed_by(
|
|
job, 'scopes', item_name=job['name'], project=config.params['project']
|
|
)
|
|
resolve_keyed_by(
|
|
job, 'bouncer-products', item_name=job['name'], project=config.params['project']
|
|
)
|
|
|
|
# No need to filter out ja-JP-mac, we need to upload both; but we do
|
|
# need to filter out the platforms they come with
|
|
all_locales = sorted([
|
|
locale
|
|
for locale in parse_locales_file(job['locales-file']).keys()
|
|
if locale not in ('linux', 'win32', 'osx')
|
|
])
|
|
|
|
job['worker']['locales'] = all_locales
|
|
job['worker']['entries'] = craft_bouncer_entries(config, job)
|
|
|
|
del job['locales-file']
|
|
del job['bouncer-platforms']
|
|
del job['bouncer-products']
|
|
|
|
if job['worker']['entries']:
|
|
# XXX Because rc jobs are defined within the same kind, we need to delete the
|
|
# firefox-rc job at this stage, if we're not building an RC. Otherwise, even if
|
|
# target_tasks.py filters out the rc job, it gets resurected by any kind that depends
|
|
# on the release-bouncer-sub one (release-notify-promote as of time of this writing).
|
|
if config.params['release_type'] == 'rc' or job['name'] != 'firefox-rc':
|
|
yield job
|
|
else:
|
|
logger.warn('No bouncer entries defined in bouncer submission task for "{}". \
|
|
Job deleted.'.format(job['name']))
|
|
|
|
|
|
def craft_bouncer_entries(config, job):
|
|
release_config = get_release_config(config)
|
|
|
|
product = job['shipping-product']
|
|
bouncer_platforms = job['bouncer-platforms']
|
|
|
|
current_version = release_config['version']
|
|
current_build_number = release_config['build_number']
|
|
|
|
bouncer_products = job['bouncer-products']
|
|
previous_versions_string = release_config.get('partial_versions', None)
|
|
if previous_versions_string:
|
|
previous_versions = previous_versions_string.split(', ')
|
|
else:
|
|
logger.warn('No partials defined! Bouncer submission task won\'t send any \
|
|
partial-related entry for "{}"'.format(job['name']))
|
|
bouncer_products = [
|
|
bouncer_product
|
|
for bouncer_product in bouncer_products
|
|
if 'partial' not in bouncer_product
|
|
]
|
|
previous_versions = [None]
|
|
|
|
project = config.params['project']
|
|
|
|
return {
|
|
craft_bouncer_product_name(
|
|
product, bouncer_product, current_version, current_build_number, previous_version
|
|
): {
|
|
'options': {
|
|
'add_locales': craft_add_locales(product),
|
|
'check_uptake': craft_check_uptake(bouncer_product),
|
|
'ssl_only': craft_ssl_only(bouncer_product, project),
|
|
},
|
|
'paths_per_bouncer_platform': craft_paths_per_bouncer_platform(
|
|
product, bouncer_product, bouncer_platforms, current_version,
|
|
current_build_number, previous_version
|
|
),
|
|
}
|
|
for bouncer_product in bouncer_products
|
|
for previous_version in previous_versions
|
|
}
|
|
|
|
|
|
def craft_paths_per_bouncer_platform(product, bouncer_product, bouncer_platforms, current_version,
|
|
current_build_number, previous_version=None):
|
|
paths_per_bouncer_platform = {}
|
|
for bouncer_platform in bouncer_platforms:
|
|
file_names_per_platform = CONFIG_PER_BOUNCER_PRODUCT[bouncer_product]['file_names']
|
|
file_name_template = file_names_per_platform.get(
|
|
bouncer_platform, file_names_per_platform.get('default', None)
|
|
)
|
|
if not file_name_template:
|
|
# Some bouncer product like stub-installer are only meant to be on Windows.
|
|
# Thus no default value is defined there
|
|
continue
|
|
|
|
file_name_product = _craft_filename_product(product)
|
|
file_name = file_name_template.format(
|
|
product=file_name_product,
|
|
pretty_product=file_name_product.capitalize(),
|
|
version=current_version,
|
|
previous_version=strip_build_data(previous_version),
|
|
)
|
|
|
|
path_template = CONFIG_PER_BOUNCER_PRODUCT[bouncer_product]['path_template']
|
|
file_relative_location = path_template.format(
|
|
ftp_product=_craft_ftp_product(product),
|
|
version=current_version,
|
|
build_number=current_build_number,
|
|
update_folder='update/' if '-mar' in bouncer_product else '',
|
|
ftp_platform=_craft_ftp_platform(bouncer_platform, file_name),
|
|
file=file_name,
|
|
)
|
|
|
|
paths_per_bouncer_platform[bouncer_platform] = file_relative_location
|
|
|
|
return paths_per_bouncer_platform
|
|
|
|
|
|
def _craft_ftp_product(product):
|
|
return 'mobile' if product == 'fennec' else product.lower()
|
|
|
|
|
|
def _craft_ftp_platform(bouncer_platform, file_name):
|
|
ftp_platform = FTP_PLATFORMS_PER_BOUNCER_PLATFORM[bouncer_platform]
|
|
# We currently have a sole win32 stub installer that is to be used
|
|
# in both windows platforms to toggle between full installers
|
|
if 'Installer.exe' in file_name and ftp_platform == 'win64':
|
|
return 'win32'
|
|
|
|
return ftp_platform
|
|
|
|
|
|
def _craft_filename_product(product):
|
|
return 'firefox' if product == 'devedition' else product
|
|
|
|
|
|
def craft_bouncer_product_name(product, bouncer_product, current_version,
|
|
current_build_number=None, previous_version=None):
|
|
if '-ssl' in bouncer_product:
|
|
postfix = '-SSL'
|
|
elif 'stub-' in bouncer_product:
|
|
postfix = '-stub'
|
|
elif 'complete-' in bouncer_product:
|
|
postfix = _set_current_build_number_if_needed(bouncer_product, current_build_number)
|
|
postfix = '{}-Complete'.format(postfix)
|
|
elif 'partial-' in bouncer_product:
|
|
if not previous_version:
|
|
raise Exception('Partial is being processed, but no previous version defined.')
|
|
|
|
if '-candidates' in bouncer_product:
|
|
postfix = _set_current_build_number_if_needed(bouncer_product, current_build_number)
|
|
postfix = '{postfix}-Partial-{previous_version_with_build_number}'.format(
|
|
postfix=postfix,
|
|
build_number=current_build_number,
|
|
previous_version_with_build_number=previous_version,
|
|
)
|
|
else:
|
|
postfix = '-Partial-{previous_version}'.format(
|
|
previous_version=strip_build_data(previous_version)
|
|
)
|
|
|
|
elif 'sha1-' in bouncer_product:
|
|
postfix = '-sha1'
|
|
else:
|
|
postfix = ''
|
|
|
|
return '{product}-{version}{postfix}'.format(
|
|
product=product.capitalize(), version=current_version, postfix=postfix
|
|
)
|
|
|
|
|
|
def _set_current_build_number_if_needed(bouncer_product, current_build_number):
|
|
if '-candidates' in bouncer_product:
|
|
if not current_build_number:
|
|
raise Exception('Partial in candidates directory is being processed, \
|
|
but no current build number defined.')
|
|
return 'build{}'.format(current_build_number)
|
|
|
|
return ''
|
|
|
|
|
|
def craft_check_uptake(bouncer_product):
|
|
return bouncer_product != 'complete-mar-candidates'
|
|
|
|
|
|
def craft_ssl_only(bouncer_product, project):
|
|
# XXX ESR is the only channel where we force serve the installer over SSL
|
|
if '-esr' in project and bouncer_product == 'installer':
|
|
return True
|
|
|
|
return bouncer_product not in (
|
|
'complete-mar',
|
|
'complete-mar-candidates',
|
|
'installer',
|
|
'partial-mar',
|
|
'partial-mar-candidates',
|
|
)
|
|
|
|
|
|
def craft_add_locales(product):
|
|
# Do not add locales on Fennec in order to let "multi" work
|
|
return product != 'fennec'
|
|
|
|
|
|
def strip_build_data(version):
|
|
return version.split('build')[0] if version and 'build' in version else version
|