Bug 1477706: [try-select] Let taskgraph know that it is being called from try-select; r=ahal
authorTom Prince <mozilla@hocat.ca>
Fri, 03 Aug 2018 10:25:42 -0600
changeset 485969 8616f91338375095850ced71af2668a7b9ee9c1c
parent 485968 1ac3e522f55fe1d893089d31e0f650a26e7ce332
child 485970 e415755450bb62657834557bfb9b6ab2c4e25c6c
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersahal
bugs1477706
milestone63.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 1477706: [try-select] Let taskgraph know that it is being called from try-select; r=ahal Currently, `mach try fuzzy` generates a taskgraph that is configured exactly like the most recent push to mozilla-central. This isn't always desirabe, so pass some configuration down, to allow the taskgraph to behave differently. Differential Revision: https://phabricator.services.mozilla.com/D2729
taskcluster/docs/parameters.rst
taskcluster/taskgraph/parameters.py
taskcluster/taskgraph/test/test_parameters.py
tools/tryselect/tasks.py
--- a/taskcluster/docs/parameters.rst
+++ b/taskcluster/docs/parameters.rst
@@ -79,19 +79,21 @@ Tree Information
    associated with this tree.  This dictates the names of resources used in the
    generated tasks, and those tasks will fail if it is incorrect.
 
 Try Configuration
 -----------------
 
 ``try_mode``
     The mode in which a try push is operating.  This can be one of
-    ``"try_task_config"``, ``"try_option_syntax"``, or ``None`` meaning no try
+    ``"try_task_config"``, ``"try_option_syntax"``, ``"try_select"`` or ``None`` meaning no try
     input was provided.
 
+    ``"try_select"`` is used by ``mach try fuzzy`` to build a list of tasks to select from.
+
 ``try_options``
     The arguments given as try syntax (as a dictionary), or ``None`` if
     ``try_mode`` is not ``try_option_syntax``.
 
 ``try_task_config``
     The contents of the ``try_task_config.json`` file, or ``None`` if
     ``try_mode`` is not ``try_task_config``.
 
--- a/taskcluster/taskgraph/parameters.py
+++ b/taskcluster/taskgraph/parameters.py
@@ -137,19 +137,20 @@ class Parameters(ReadOnlyDict):
             raise KeyError("no such parameter {!r}".format(k))
         try:
             return super(Parameters, self).__getitem__(k)
         except KeyError:
             raise KeyError("taskgraph parameter {!r} not found".format(k))
 
     def is_try(self):
         """
-        Determine whether this graph is being built on a try project.
+        Determine whether this graph is being built on a try project or for
+        `mach try fuzzy`.
         """
-        return 'try' in self['project']
+        return 'try' in self['project'] or self['try_mode'] == 'try_select'
 
     def file_url(self, path):
         """
         Determine the VCS URL for viewing a file in the tree, suitable for
         viewing by a human.
 
         :param basestring path: The path, relative to the root of the repository.
 
@@ -161,29 +162,32 @@ class Parameters(ReadOnlyDict):
             rev = self['comm_head_rev']
         else:
             repo = self['head_repository']
             rev = self['head_rev']
 
         return '{}/file/{}/{}'.format(repo, rev, path)
 
 
-def load_parameters_file(filename, strict=True):
+def load_parameters_file(filename, strict=True, overrides=None):
     """
     Load parameters from a path, url, decision task-id or project.
 
     Examples:
         task-id=fdtgsD5DQUmAQZEaGMvQ4Q
         project=mozilla-central
     """
     import urllib
     from taskgraph.util.taskcluster import get_artifact_url, find_task_id
 
+    if overrides is None:
+        overrides = {}
+
     if not filename:
-        return Parameters(strict=strict)
+        return Parameters(strict=strict, **overrides)
 
     try:
         # reading parameters from a local parameters.yml file
         f = open(filename)
     except IOError:
         # fetching parameters.yml using task task-id, project or supplied url
         task_id = None
         if filename.startswith("task-id="):
@@ -194,13 +198,17 @@ def load_parameters_file(filename, stric
             )
             task_id = find_task_id(index)
 
         if task_id:
             filename = get_artifact_url(task_id, 'public/parameters.yml')
         f = urllib.urlopen(filename)
 
     if filename.endswith('.yml'):
-        return Parameters(strict=strict, **yaml.safe_load(f))
+        kwargs = yaml.safe_load(f)
     elif filename.endswith('.json'):
-        return Parameters(strict=strict, **json.load(f))
+        kwargs = json.load(f)
     else:
         raise TypeError("Parameters file `{}` is not JSON or YAML".format(filename))
+
+    kwargs.update(overrides)
+
+    return Parameters(strict=strict, **kwargs)
--- a/taskcluster/taskgraph/test/test_parameters.py
+++ b/taskcluster/taskgraph/test/test_parameters.py
@@ -65,16 +65,35 @@ class TestParameters(unittest.TestCase):
                     {'some': 'data'})
 
     def test_load_parameters_file_json(self):
         with MockedOpen({"params.json": '{"some": "data"}'}):
             self.assertEqual(
                     load_parameters_file('params.json'),
                     {'some': 'data'})
 
+    def test_load_parameters_override(self):
+        """
+        When ``load_parameters_file`` is passed overrides, they are included in
+        the generated parameters.
+        """
+        self.assert_equal(
+            load_parameters_file('', overrides={'some': 'data'}),
+            {'some': 'data'})
+
+    def test_load_parameters_override_file(self):
+        """
+        When ``load_parameters_file`` is passed overrides, they overwrite data
+        loaded from a file.
+        """
+        with MockedOpen({"params.json": '{"some": "data"}'}):
+            self.assert_equal(
+                load_parameters_file('params.json', overrides={'some': 'other'}),
+                {'some': 'other'})
+
 
 class TestCommParameters(unittest.TestCase):
     vals = {n: n for n in PARAMETERS.keys() + COMM_PARAMETERS.keys()}
 
     def test_Parameters_check(self):
         """
         Specifying all of the gecko and comm parameters doesn't result in an error.
         """
--- a/tools/tryselect/tasks.py
+++ b/tools/tryselect/tasks.py
@@ -58,17 +58,17 @@ def generate_tasks(params, full, root):
         with open(cache, 'r') as fh:
             return fh.read().splitlines()
 
     if not os.path.isdir(cache_dir):
         os.makedirs(cache_dir)
 
     print("Task configuration changed, generating {}".format(attr.replace('_', ' ')))
     try:
-        params = load_parameters_file(params, strict=False)
+        params = load_parameters_file(params, strict=False, overrides={'try_mode': 'try_select'})
         params.check()
     except ParameterMismatch as e:
         print(PARAMETER_MISMATCH.format(e.args[0]))
         sys.exit(1)
 
     taskgraph.fast = True
     cwd = os.getcwd()
     os.chdir(build.topsrcdir)