Files
tubestation/testing/mozharness/scripts/fx_desktop_build.py
Chris Manchester aecb7edab9 Bug 1357562 - Specify artifact build replacement via mozharness for non-variant builds. r=nalexander
No builds other than vanilla opt and debug builds are supported by the artifact
code currently, so prevent variant builds from being replaced by artifact builds
by modifying mozharness' replacement logic to replace a build with an artifact
build only when it is a regular opt or debug build or when specified by a
config.

MozReview-Commit-ID: KUUgrbga53l
2017-04-25 15:54:24 -07:00

261 lines
11 KiB
Python
Executable File

#!/usr/bin/env python
# ***** BEGIN LICENSE BLOCK *****
# 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/.
# ***** END LICENSE BLOCK *****
"""fx_desktop_build.py.
script harness to build nightly firefox within Mozilla's build environment
and developer machines alike
author: Jordan Lund
"""
import copy
import pprint
import sys
import os
# load modules from parent dir
sys.path.insert(1, os.path.dirname(sys.path[0]))
import mozharness.base.script as script
from mozharness.mozilla.building.buildbase import BUILD_BASE_CONFIG_OPTIONS, \
BuildingConfig, BuildOptionParser, BuildScript
from mozharness.base.config import parse_config_file
from mozharness.mozilla.testing.try_tools import TryToolsMixin, try_config_options
class FxDesktopBuild(BuildScript, TryToolsMixin, object):
def __init__(self):
buildscript_kwargs = {
'config_options': BUILD_BASE_CONFIG_OPTIONS + copy.deepcopy(try_config_options),
'all_actions': [
'get-secrets',
'clobber',
'clone-tools',
'checkout-sources',
'setup-mock',
'build',
'upload-files', # upload from BB to TC
'sendchange',
'check-test',
'valgrind-test',
'package-source',
'generate-source-signing-manifest',
'multi-l10n',
'generate-build-stats',
'update',
],
'require_config_file': True,
# Default configuration
'config': {
'is_automation': True,
"pgo_build": False,
"debug_build": False,
"pgo_platforms": ['linux', 'linux64', 'win32', 'win64'],
# nightly stuff
"nightly_build": False,
'balrog_credentials_file': 'oauth.txt',
'taskcluster_credentials_file': 'oauth.txt',
'periodic_clobber': 168,
# hg tool stuff
"tools_repo": "https://hg.mozilla.org/build/tools",
# Seed all clones with mozilla-unified. This ensures subsequent
# jobs have a minimal `hg pull`.
"clone_upstream_url": "https://hg.mozilla.org/mozilla-unified",
"repo_base": "https://hg.mozilla.org",
'tooltool_url': 'https://api.pub.build.mozilla.org/tooltool/',
"graph_selector": "/server/collect.cgi",
# only used for make uploadsymbols
'old_packages': [
"%(objdir)s/dist/firefox-*",
"%(objdir)s/dist/fennec*",
"%(objdir)s/dist/seamonkey*",
"%(objdir)s/dist/thunderbird*",
"%(objdir)s/dist/install/sea/*.exe"
],
'stage_product': 'firefox',
'platform_supports_post_upload_to_latest': True,
'build_resources_path': '%(abs_src_dir)s/obj-firefox/.mozbuild/build_resources.json',
'nightly_promotion_branches': ['mozilla-central', 'mozilla-aurora'],
# try will overwrite these
'clone_with_purge': False,
'clone_by_revision': False,
'tinderbox_build_dir': None,
'to_tinderbox_dated': True,
'release_to_try_builds': False,
'include_post_upload_builddir': False,
'use_clobberer': True,
'stage_username': 'ffxbld',
'stage_ssh_key': 'ffxbld_rsa',
'virtualenv_modules': [
'requests==2.8.1',
'PyHawk-with-a-single-extra-commit==0.1.5',
'taskcluster==0.0.26',
],
'virtualenv_path': 'venv',
#
},
'ConfigClass': BuildingConfig,
}
super(FxDesktopBuild, self).__init__(**buildscript_kwargs)
def _pre_config_lock(self, rw_config):
"""grab buildbot props if we are running this in automation"""
super(FxDesktopBuild, self)._pre_config_lock(rw_config)
c = self.config
if c['is_automation']:
# parse buildbot config and add it to self.config
self.info("We are running this in buildbot, grab the build props")
self.read_buildbot_config()
###
if c.get('stage_platform'):
platform_for_log_url = c['stage_platform']
if c.get('pgo_build'):
platform_for_log_url += '-pgo'
# postrun.py uses stage_platform buildbot prop as part of the log url
self.set_buildbot_property('stage_platform',
platform_for_log_url,
write_to_file=True)
else:
self.fatal("'stage_platform' not determined and is required in your config")
if self.try_message_has_flag('artifact'):
# Not all jobs that look like builds can be made into artifact
# builds (for example, various SAN builds will not make sense as
# artifact builds). By default, only a vanilla debug or opt build
# will be replaced by an artifact build.
#
# In addition, some jobs want to specify their artifact equivalent.
# Use `artifact_flag_build_variant_in_try` to specify that variant.
#
# This is temporary, until we find a way to introduce an "artifact
# build dimension" like "opt"/"debug" into the CI configurations.
self.info('Artifact build requested in try syntax.')
variant = None
if 'artifact_flag_build_variant_in_try' in c:
variant = c['artifact_flag_build_variant_in_try']
if not variant:
self.info('Build variant has falsy `artifact_flag_build_variant_in_try`; '
'ignoring artifact build request and performing original build.')
return
self.info('Build variant has `artifact_build_variant_in_try`: "%s".' % variant)
else:
if not c.get('build_variant'):
variant = 'artifact'
elif c.get('build_variant') in ['debug', 'cross-debug']:
variant = 'debug-artifact'
if variant:
self.info('Using artifact build variant "%s".' % variant)
self._update_build_variant(rw_config, variant)
# helpers
def _update_build_variant(self, rw_config, variant='artifact'):
""" Intended for use in _pre_config_lock """
c = self.config
variant_cfg_path, _ = BuildOptionParser.find_variant_cfg_path(
'--custom-build-variant-cfg',
variant,
rw_config.config_parser
)
if not variant_cfg_path:
self.fatal('Could not find appropriate config file for variant %s' % variant)
# Update other parts of config to keep dump-config accurate
# Only dump-config is affected because most config info is set during
# initial parsing
variant_cfg_dict = parse_config_file(variant_cfg_path)
rw_config.all_cfg_files_and_dicts.append((variant_cfg_path, variant_cfg_dict))
c.update({
'build_variant': variant,
'config_files': c['config_files'] + [variant_cfg_path]
})
self.info("Updating self.config with the following from {}:".format(variant_cfg_path))
self.info(pprint.pformat(variant_cfg_dict))
c.update(variant_cfg_dict)
c['forced_artifact_build'] = True
# Bug 1231320 adds MOZHARNESS_ACTIONS in TaskCluster tasks to override default_actions
# We don't want that when forcing an artifact build.
if rw_config.volatile_config['actions']:
self.info("Updating volatile_config to include default_actions "
"from {}.".format(variant_cfg_path))
# add default actions in correct order
combined_actions = []
for a in rw_config.all_actions:
if a in c['default_actions'] or a in rw_config.volatile_config['actions']:
combined_actions.append(a)
rw_config.volatile_config['actions'] = combined_actions
self.info("Actions in volatile_config are now: {}".format(
rw_config.volatile_config['actions'])
)
# replace rw_config as well to set actions as in BaseScript
rw_config.set_config(c, overwrite=True)
rw_config.update_actions()
self.actions = tuple(rw_config.actions)
self.all_actions = tuple(rw_config.all_actions)
def query_abs_dirs(self):
if self.abs_dirs:
return self.abs_dirs
c = self.config
abs_dirs = super(FxDesktopBuild, self).query_abs_dirs()
if not c.get('app_ini_path'):
self.fatal('"app_ini_path" is needed in your config for this '
'script.')
dirs = {
# BuildFactories in factory.py refer to a 'build' dir on the slave.
# This contains all the source code/objdir to compile. However,
# there is already a build dir in mozharness for every mh run. The
# 'build' that factory refers to I named: 'src' so
# there is a seperation in mh. for example, rather than having
# '{mozharness_repo}/build/build/', I have '{
# mozharness_repo}/build/src/'
'abs_src_dir': os.path.join(abs_dirs['abs_work_dir'],
'src'),
'abs_obj_dir': os.path.join(abs_dirs['abs_work_dir'],
'src',
self._query_objdir()),
'abs_tools_dir': os.path.join(abs_dirs['abs_work_dir'], 'tools'),
'abs_app_ini_path': c['app_ini_path'] % {
'obj_dir': os.path.join(abs_dirs['abs_work_dir'],
'src',
self._query_objdir())
},
}
abs_dirs.update(dirs)
self.abs_dirs = abs_dirs
return self.abs_dirs
# Actions {{{2
# read_buildbot_config in BuildingMixin
# clobber in BuildingMixin -> PurgeMixin
# if Linux config:
# reset_mock in BuildingMixing -> MockMixin
# setup_mock in BuildingMixing (overrides MockMixin.mock_setup)
def set_extra_try_arguments(self, action, success=None):
""" Override unneeded method from TryToolsMixin """
pass
@script.PreScriptRun
def suppress_windows_modal_dialogs(self, *args, **kwargs):
if self._is_windows():
# Suppress Windows modal dialogs to avoid hangs
import ctypes
ctypes.windll.kernel32.SetErrorMode(0x8001)
if __name__ == '__main__':
fx_desktop_build = FxDesktopBuild()
fx_desktop_build.run_and_exit()