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
--- 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', {})