Bug 1624859 - [taskgraph] Always optimize build tasks with ./mach try auto, r=tomprince
authorAndrew Halberstadt <ahalberstadt@mozilla.com>
Wed, 22 Apr 2020 15:51:35 +0000
changeset 525400 ff704e8cb0ea14330dc27c863e3619bd39e4e1fe
parent 525399 9f55382156dd8ec0298d3b5c6942229891a9d1fa
child 525401 d82de935b08b371a07dfa1322c70981456633a17
push id37339
push usernerli@mozilla.com
push dateThu, 23 Apr 2020 09:52:48 +0000
treeherdermozilla-central@47426d145e24 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstomprince
bugs1624859
milestone77.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1624859 - [taskgraph] Always optimize build tasks with ./mach try auto, r=tomprince This ensures we don't run every build with every push via ./mach try auto. It introduces a new 'optimization-overrides' try_config that can be used to replace optimizations. For now, there is no user interface to pass this in via the 'mach try' command line. Differential Revision: https://phabricator.services.mozilla.com/D68207
taskcluster/taskgraph/optimize/__init__.py
taskcluster/taskgraph/transforms/build_attrs.py
taskcluster/taskgraph/util/schema.py
tools/tryselect/selectors/auto.py
tools/tryselect/task_config.py
tools/tryselect/test/test_auto.t
tools/tryselect/test/test_task_configs.py
--- a/taskcluster/taskgraph/optimize/__init__.py
+++ b/taskcluster/taskgraph/optimize/__init__.py
@@ -254,16 +254,22 @@ class OptimizationStrategy(object):
 
     def should_replace_task(self, task, params, arg):
         """Determine whether to optimize this task by replacing it.  Returns a
         taskId to replace this task, True to replace with nothing, or False to
         keep the task."""
         return False
 
 
+@register_strategy('always')
+class Always(OptimizationStrategy):
+    def should_remove_task(self, task, params, arg):
+        return True
+
+
 @six.add_metaclass(ABCMeta)
 class CompositeStrategy(OptimizationStrategy):
 
     def __init__(self, *substrategies, **kwargs):
         self.substrategies = []
         missing = set()
         for sub in substrategies:
             if isinstance(sub, six.text_type):
@@ -364,22 +370,25 @@ class Alias(CompositeStrategy):
         return next(results)
 
 
 # Trigger registration in sibling modules.
 import_sibling_modules()
 
 
 # Register composite strategies.
+register_strategy('build', args=('skip-unless-schedules',))(Alias)
 register_strategy('test', args=(Any('skip-unless-schedules', 'seta'), 'backstop'))(All)
 register_strategy('test-inclusive', args=('skip-unless-schedules',))(Alias)
 register_strategy('test-try', args=('skip-unless-schedules',))(Alias)
 register_strategy('fuzzing-builds', args=('skip-unless-schedules', 'seta'))(Any)
 
 
+# Strategy overrides used by |mach try| and/or shadow-scheduler tasks.
+
 class experimental(object):
     """Experimental strategies either under development or used as benchmarks.
 
     These run as "shadow-schedulers" on each autoland push (tier 3) and/or can be used
     with `./mach try auto`.  E.g:
 
         ./mach try auto --strategy relevant_tests
     """
@@ -420,8 +429,35 @@ class experimental(object):
     }
     """Runs task containing tests in the same directories as modified files."""
 
     seta = {
         'test': Any('skip-unless-schedules', 'seta'),
     }
     """Provides a stable history of SETA's performance in the event we make it
     non-default in the future. Only useful as a benchmark."""
+
+
+class ExperimentalOverride(object):
+    """Overrides dictionaries that are stored in a container with new values.
+
+    This can be used to modify all strategies in a collection the same way,
+    presumably with strategies affecting kinds of tasks tangential to the
+    current context.
+
+    Args:
+        base (object): A container class supporting attribute access.
+        overrides (dict): Values to update any accessed dictionaries with.
+    """
+    def __init__(self, base, overrides):
+        self.base = base
+        self.overrides = overrides
+
+    def __getattr__(self, name):
+        val = getattr(self.base, name).copy()
+        val.update(self.overrides)
+        return val
+
+
+tryselect = ExperimentalOverride(experimental, {
+    'build': Alias('always'),
+    'fuzzing-builds': Alias('always'),
+})
--- a/taskcluster/taskgraph/transforms/build_attrs.py
+++ b/taskcluster/taskgraph/transforms/build_attrs.py
@@ -40,10 +40,10 @@ def set_schedules_optimization(config, j
     for job in jobs:
         # don't add skip-unless-schedules if there's already a when defined
         if 'when' in job:
             yield job
             continue
 
         build_platform = job['attributes']['build_platform']
         job.setdefault('optimization',
-                       {'skip-unless-schedules': [platform_family(build_platform)]})
+                       {'build': [platform_family(build_platform)]})
         yield job
--- a/taskcluster/taskgraph/util/schema.py
+++ b/taskcluster/taskgraph/util/schema.py
@@ -192,16 +192,20 @@ class Schema(voluptuous.Schema):
 
     def __getitem__(self, item):
         return self.schema[item]
 
 
 OptimizationSchema = voluptuous.Any(
     # always run this task (default)
     None,
+    # always optimize this task
+    {'always': None},
+    # optimize strategy aliases for build kind
+    {'build': list(schedules.ALL_COMPONENTS)},
     # search the index for the given index namespaces, and replace this task if found
     # the search occurs in order, with the first match winning
     {'index-search': [text_type]},
     # consult SETA and skip this task if it is low-value
     {'seta': None},
     # skip this task if none of the given file patterns match
     {'skip-unless-changed': [text_type]},
     # skip this task if unless the change files' SCHEDULES contains any of these components
--- a/tools/tryselect/selectors/auto.py
+++ b/tools/tryselect/selectors/auto.py
@@ -24,17 +24,17 @@ class AutoParser(BaseTryParser):
 def run(message='{msg}', push=True, closed_tree=False, try_config=None):
     print("warning: 'mach try auto' is experimental, results may vary!")
     msg = message.format(msg='Tasks automatically selected.')
     try_config = try_config or {}
 
     # XXX Remove once an intelligent scheduling algorithm is running on
     # autoland by default. This ensures `mach try auto` doesn't run SETA.
     try_config.setdefault('optimize-strategies',
-                          'taskgraph.optimize:experimental.bugbug_debug')
+                          'taskgraph.optimize:tryselect.bugbug_debug')
 
     task_config = {
         'version': 2,
         'parameters': {
             'optimize_target_tasks': True,
             'target_tasks_method': 'try_auto',
             'try_mode': 'try_auto',
             'try_task_config': try_config or {},
--- a/tools/tryselect/task_config.py
+++ b/tools/tryselect/task_config.py
@@ -313,17 +313,17 @@ class OptimizeStrategies(TryConfig):
                   'are the experimental strategies defined at the bottom of '
                   '`taskcluster/taskgraph/optimize/__init__.py`.'
           }],
     ]
 
     def try_config(self, strategy, **kwargs):
         if strategy:
             if ':' not in strategy:
-                strategy = "taskgraph.optimize:experimental.{}".format(strategy)
+                strategy = "taskgraph.optimize:tryselect.{}".format(strategy)
 
             try:
                 obj = find_object(strategy)
             except (ImportError, AttributeError):
                 print("error: invalid module path '{}'".format(strategy))
                 sys.exit(1)
 
             if not isinstance(obj, dict):
--- a/tools/tryselect/test/test_auto.t
+++ b/tools/tryselect/test/test_auto.t
@@ -12,17 +12,17 @@ Test auto selector
   Pushed via `mach try auto`
   Calculated try_task_config.json:
   {
       "parameters": {
           "optimize_target_tasks": true,
           "target_tasks_method": "try_auto",
           "try_mode": "try_auto",
           "try_task_config": {
-              "optimize-strategies": "taskgraph.optimize:experimental.bugbug_debug"
+              "optimize-strategies": "taskgraph.optimize:tryselect.bugbug_debug"
           }
       },
       "version": 2
   }
   
 
   $ ./mach try auto $testargs --closed-tree
   warning: 'mach try auto' is experimental, results may vary!
@@ -32,17 +32,17 @@ Test auto selector
   Pushed via `mach try auto`
   Calculated try_task_config.json:
   {
       "parameters": {
           "optimize_target_tasks": true,
           "target_tasks_method": "try_auto",
           "try_mode": "try_auto",
           "try_task_config": {
-              "optimize-strategies": "taskgraph.optimize:experimental.bugbug_debug"
+              "optimize-strategies": "taskgraph.optimize:tryselect.bugbug_debug"
           }
       },
       "version": 2
   }
   
   $ ./mach try auto $testargs --closed-tree -m "foo {msg} bar"
   warning: 'mach try auto' is experimental, results may vary!
   Commit message:
@@ -51,14 +51,14 @@ Test auto selector
   Pushed via `mach try auto`
   Calculated try_task_config.json:
   {
       "parameters": {
           "optimize_target_tasks": true,
           "target_tasks_method": "try_auto",
           "try_mode": "try_auto",
           "try_task_config": {
-              "optimize-strategies": "taskgraph.optimize:experimental.bugbug_debug"
+              "optimize-strategies": "taskgraph.optimize:tryselect.bugbug_debug"
           }
       },
       "version": 2
   }
   
--- a/tools/tryselect/test/test_task_configs.py
+++ b/tools/tryselect/test/test_task_configs.py
@@ -37,19 +37,19 @@ TASK_CONFIG_TESTS = {
     'rebuild': [
         ([], None),
         (['--rebuild', '10'], {'rebuild': 10}),
         (['--rebuild', '1'], SystemExit),
         (['--rebuild', '21'], SystemExit),
     ],
     'strategy': [
         ([], None),
-        (['--strategy', 'seta'], {'optimize-strategies': 'taskgraph.optimize:experimental.seta'}),
+        (['--strategy', 'seta'], {'optimize-strategies': 'taskgraph.optimize:tryselect.seta'}),
         (['--strategy', 'taskgraph.optimize:experimental.seta'], {'optimize-strategies': 'taskgraph.optimize:experimental.seta'}),  # noqa
-        (['--strategy', 'taskgraph.optimize:experimental'], SystemExit),
+        (['--strategy', 'taskgraph.optimize:tryselect'], SystemExit),
         (['--strategy', 'foo'], SystemExit),
         (['--strategy', 'foo:bar'], SystemExit),
     ],
     'worker-overrides': [
         ([], None),
         (['--worker-override', 'alias=worker/pool'],
          {'worker-overrides': {'alias': 'worker/pool'}}),
         (['--worker-override', 'alias=worker/pool', '--worker-override', 'alias=other/pool'],