Bug 1249091 - Make generic tasks disabled by default; r?garndt draft
authorGregory Szorc <gps@mozilla.com>
Wed, 17 Feb 2016 14:23:01 -0800
changeset 331694 c559632cdaa2b24252bfc0380c7ee5ad0bc1d2e8
parent 331693 91b09cb2bbae5560ed8ab5a906d4f025b8892ff9
child 331695 5fdc0244e2e9363fbcac80eb604c84adcdf2f75f
push id11040
push usergszorc@mozilla.com
push dateWed, 17 Feb 2016 22:51:37 +0000
reviewersgarndt
bugs1249091
milestone47.0a1
Bug 1249091 - Make generic tasks disabled by default; r?garndt We want to encourage tasks to only run when necessary. This commit changes the default behavior of generic tasks to not run unless their conditions are met. This is accomplished by the introduction of the "always" condition flag. We set this flag on old-style tasks to mimic existing behavior. All new generic tasks will need to set this flag or define conditions to trigger task scheduling. While we're here, we also add an "explicitly-added" property to denote that a task was explicitly requested to be run. This prevents such tasks from getting filtered. The filtering logic for tasks is kind of wonky and occurs in multiple locations. The code should definitely be unified someday. MozReview-Commit-ID: 7tQbd0GMUs0
testing/taskcluster/docs/index.rst
testing/taskcluster/mach_commands.py
testing/taskcluster/taskcluster_graph/commit_parser.py
--- a/testing/taskcluster/docs/index.rst
+++ b/testing/taskcluster/docs/index.rst
@@ -196,16 +196,20 @@ file_patterns
 
    Values use the ``mozpack`` matching code. ``*`` is a wildcard for
    all path characters except ``/``. ``**`` matches all directories. To
    e.g. match against all ``.js`` files, one would use ``**/*.js``.
 
    If a single pattern matches a single changed file, the task will be
    scheduled.
 
+always
+   Boolean that indicates to always schedule a task. By default, tasks aren't
+   enabled unless their conditions are met.
+
 Developing
 ==========
 
 Running commands via mach is the best way to invoke commands testing
 works a little differently (I have not figured out how to invoke
 python-test without running install steps first)::
 
    mach python-test tests/
--- a/testing/taskcluster/mach_commands.py
+++ b/testing/taskcluster/mach_commands.py
@@ -395,46 +395,43 @@ class Graph(object):
             'owner': params['owner'],
             # TODO: Add full mach commands to this example?
             'description': 'Task graph generated via ./mach taskcluster-graph',
             'name': 'task graph local'
         }
 
         # Filter the job graph according to conditions met by this invocation run.
         def should_run(task):
-            # Old style build or test task that doesn't define conditions. Always runs.
-            if 'when' not in task:
-                return True
-
             # Command line override to not filter.
             if params['ignore_conditions']:
                 return True
 
             when = task['when']
 
+            if when.get('always', False):
+                return True
+
+            if task.get('explicitly-added', False):
+                return True
+
             # If the task defines file patterns and we have a set of changed
             # files to compare against, only run if a file pattern matches one
             # of the changed files.
             file_patterns = when.get('file_patterns', None)
             if file_patterns and changed_files:
                 for pattern in file_patterns:
                     for path in changed_files:
                         if mozpackmatch(path, pattern):
                             sys.stderr.write('scheduling %s because pattern %s '
                                              'matches %s\n' % (task['task'],
                                                                pattern,
                                                                path))
                             return True
 
-                # No file patterns matched. Discard task.
-                sys.stderr.write('discarding %s because no relevant files changed\n' %
-                                 task['task'])
-                return False
-
-            return True
+            return False
 
         job_graph = filter(should_run, job_graph)
 
         all_routes = {}
 
         for build in job_graph:
             interactive = cmdline_interactive or build["interactive"]
             build_parameters = merge_dicts(parameters, build['additional-parameters']);
--- a/testing/taskcluster/taskcluster_graph/commit_parser.py
+++ b/testing/taskcluster/taskcluster_graph/commit_parser.py
@@ -324,44 +324,49 @@ def parse_commit(message, jobs):
                 'post-build': post_build_jobs,
                 'dependents': extract_tests_from_platform(
                     jobs['tests'], platform_builds, build_task, tests
                 ),
                 'additional-parameters': additional_parameters,
                 'build_name': platform,
                 'build_type': build_type,
                 'interactive': args.interactive,
+                # Non-generic tasks are always scheduled because that's how
+                # they worked when they were invented.
+                'when': {'always': True},
             })
 
     # Process miscellaneous tasks.
 
     def filtertask(name, task):
         # args.jobs == None implies all tasks.
         if args.jobs is None:
-            return True
+            return True, False
 
         if name in args.jobs:
-            return True
+            return True, True
 
         for tag in task.get('tags', []):
             if tag in args.jobs:
-                return True
+                return True, True
 
-        return False
+        return False, False
 
     for name, task in sorted(jobs.get('tasks', {}).items()):
-        if not filtertask(name, task):
+        run, explicit = filtertask(name, task)
+        if not run:
             continue
 
         # TODO support tasks that are defined as dependent on another one.
         if not task.get('root', False):
             continue
 
         result.append({
             'task': task['task'],
+            'explicitly-added': explicit,
             'post-build': [],
             'dependents': [],
             'additional-parameters': task.get('additional-parameters', {}),
             'build_name': name,
             # TODO support declaring a different build type
             'build_type': name,
             'interactive': args.interactive,
             'when': task.get('when', {})