Bug 1385055 - Add some taskgraph parameters for dealing with comm-central and related repositories. draft
authorTom Prince <mozilla@hocat.ca>
Thu, 27 Jul 2017 12:26:48 -0600
changeset 676748 6741015b8a24d3a844b3dc43ee56d011ff47d5fb
parent 675508 53bbdaaa2b8c1819061be26101b075c081b23260
child 676749 1ed7335f330de5a42f9fafc386518f7bb2900e3e
push id83623
push userbmo:mozilla@hocat.ca
push dateMon, 09 Oct 2017 16:33:09 +0000
bugs1385055
milestone58.0a1
Bug 1385055 - Add some taskgraph parameters for dealing with comm-central and related repositories. MozReview-Commit-ID: 4tdxfJcx8Fz
taskcluster/docs/parameters.rst
taskcluster/mach_commands.py
taskcluster/taskgraph/decision.py
taskcluster/taskgraph/parameters.py
taskcluster/taskgraph/test/test_parameters.py
--- a/taskcluster/docs/parameters.rst
+++ b/taskcluster/docs/parameters.rst
@@ -119,8 +119,21 @@ syntax or reading a project-specific con
 ``include_nightly``
     If true, then nightly tasks are eligible for optimization.
 
 ``release_history``
    History of recent releases by platform and locale, used when generating
    partial updates for nightly releases.
    Suitable contents can be generated with ``mach release-history``,
    which will print to the console by default.
+
+Comm Push Information
+---------------------
+
+These parameters correspond to the repository and revision of the comm-central
+repository to checkout. Their meaning is the same as the corresponding
+parameters for the gecko repository above. They are optional, but if any of
+them are specified, they must all be specified.
+
+``comm_base_repository``
+``comm_head_repository``
+``comm_head_rev``
+``comm_head_ref``
--- a/taskcluster/mach_commands.py
+++ b/taskcluster/mach_commands.py
@@ -113,16 +113,28 @@ class MachCommands(MachCommandBase):
                      required=True,
                      help='URL for "head" repository to fetch revision from')
     @CommandArgument('--head-ref',
                      required=True,
                      help='Reference (this is same as rev usually for hg)')
     @CommandArgument('--head-rev',
                      required=True,
                      help='Commit revision to use from head repository')
+    @CommandArgument('--comm-base-repository',
+                     required=False,
+                     help='URL for "base" comm-* repository to clone')
+    @CommandArgument('--comm-head-repository',
+                     required=False,
+                     help='URL for "head" comm-* repository to fetch revision from')
+    @CommandArgument('--comm-head-ref',
+                     required=False,
+                     help='comm-* Reference (this is same as rev usually for hg)')
+    @CommandArgument('--comm-head-rev',
+                     required=False,
+                     help='Commit revision to use from head comm-* repository')
     @CommandArgument('--message',
                      required=True,
                      help='Commit message to be parsed. Example: "try: -b do -p all -u all"')
     @CommandArgument('--project',
                      required=True,
                      help='Project to use for creating task graph. Example: --project=try')
     @CommandArgument('--pushlog-id',
                      dest='pushlog_id',
--- a/taskcluster/taskgraph/decision.py
+++ b/taskcluster/taskgraph/decision.py
@@ -154,16 +154,25 @@ def get_decision_parameters(options):
         'project',
         'pushlog_id',
         'pushdate',
         'owner',
         'level',
         'target_tasks_method',
     ] if n in options}
 
+    for n in (
+        'comm_base_repository',
+        'comm_head_repository',
+        'comm_head_rev',
+        'comm_head_ref',
+    ):
+        if n in options and options[n] is not None:
+            parameters[n] = options[n]
+
     # Define default filter list, as most configurations shouldn't need
     # custom filters.
     parameters['filters'] = [
         'check_servo',
         'target_tasks_method',
     ]
 
     # owner must be an email, but sometimes (e.g., for ffxbld) it is not, in which
--- a/taskcluster/taskgraph/parameters.py
+++ b/taskcluster/taskgraph/parameters.py
@@ -46,51 +46,74 @@ PARAMETERS = {
     'pushlog_id': '0',
     'release_history': {},
     'target_tasks_method': 'default',
     'try_mode': None,
     'try_options': None,
     'try_task_config': None,
 }
 
+COMM_PARAMETERS = {
+    'comm_base_repository': 'https://hg.mozilla.org/comm-central',
+    'comm_head_ref': None,
+    'comm_head_repository': 'https://hg.mozilla.org/comm-central',
+    'comm_head_rev': None,
+}
+
 
 class Parameters(ReadOnlyDict):
     """An immutable dictionary with nicer KeyError messages on failure"""
 
     def __init__(self, strict=True, **kwargs):
         self.strict = strict
 
         if not self.strict:
             # apply defaults to missing parameters
             for name, default in PARAMETERS.items():
                 if name not in kwargs:
                     if callable(default):
                         default = default()
                     kwargs[name] = default
 
+            if set(kwargs) & set(COMM_PARAMETERS.keys()):
+                for name, default in COMM_PARAMETERS.items():
+                    if name not in kwargs:
+                        if callable(default):
+                            default = default()
+                        kwargs[name] = default
+
         ReadOnlyDict.__init__(self, **kwargs)
 
     def check(self):
         names = set(self)
         valid = set(PARAMETERS.keys())
+        valid_comm = set(COMM_PARAMETERS.keys())
         msg = []
 
         missing = valid - names
         if missing:
             msg.append("missing parameters: " + ", ".join(missing))
 
         extra = names - valid
+
+        if extra & set(valid_comm):
+            # If any comm_* parameters are specified, ensure all of them are specified.
+            missing = valid_comm - extra
+            if missing:
+                msg.append("missing parameters: " + ", ".join(missing))
+            extra = extra - valid_comm
+
         if extra and self.strict:
             msg.append("extra parameters: " + ", ".join(extra))
 
         if msg:
             raise ParameterMismatch("; ".join(msg))
 
     def __getitem__(self, k):
-        if k not in PARAMETERS.keys():
+        if not (k in PARAMETERS.keys() or k in COMM_PARAMETERS.keys()):
             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 load_parameters_file(filename, strict=True):
--- a/taskcluster/taskgraph/test/test_parameters.py
+++ b/taskcluster/taskgraph/test/test_parameters.py
@@ -6,16 +6,17 @@ from __future__ import absolute_import, 
 
 import unittest
 
 from taskgraph.parameters import (
     Parameters,
     ParameterMismatch,
     load_parameters_file,
     PARAMETERS,
+    COMM_PARAMETERS,
 )
 from mozunit import main, MockedOpen
 
 
 class TestParameters(unittest.TestCase):
 
     vals = {n: n for n in PARAMETERS.keys()}
 
@@ -65,10 +66,38 @@ class TestParameters(unittest.TestCase):
 
     def test_load_parameters_file_json(self):
         with MockedOpen({"params.json": '{"some": "data"}'}):
             self.assertEqual(
                     load_parameters_file('params.json'),
                     {'some': 'data'})
 
 
+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.
+        """
+        p = Parameters(**self.vals)
+        p.check()  # should not raise
+
+    def test_Parameters_check_missing(self):
+        """
+        If any of the comm parameters are specified, all of them must be specified.
+        """
+        vals = self.vals.copy()
+        del vals[next(iter(COMM_PARAMETERS.keys()))]
+        p = Parameters(**vals)
+        self.assertRaises(Exception, p.check)
+
+    def test_Parameters_check_extra(self):
+        """
+        If parameters other than the global and comm parameters are specified,
+        an error is reported.
+        """
+        p = Parameters(extra="data", **self.vals)
+        self.assertRaises(Exception, p.check)
+
+
 if __name__ == '__main__':
     main()