Bug 591688 - Notify when decision task fails r=dustin,gps
authorBrian Stack <bstack@mozilla.com>
Wed, 12 Apr 2017 21:01:46 -0700
changeset 353693 5748607f3014e8cec573fccebce5dcbf83b6ffd6
parent 353692 71005756f3fb9d37516ae1dcb5cacbccf4eca636
child 353694 ce2f726a2b86e7c16fb64815e962a4268d8618d9
push id31675
push usercbook@mozilla.com
push dateWed, 19 Apr 2017 08:28:05 +0000
treeherdermozilla-central@245811243903 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdustin, gps
bugs591688
milestone55.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 591688 - Notify when decision task fails r=dustin,gps This uses the email provided by mozilla-taskcluster to find who to email about failed decision tasks. It also adds some validation of the try syntax that we've previously ignored. Any platforms or build types specified in try sytax that don't exist in the full task graph will throw an error. MozReview-Commit-ID: JOKkLle7hEe
.taskcluster.yml
taskcluster/taskgraph/try_option_syntax.py
--- a/.taskcluster.yml
+++ b/.taskcluster.yml
@@ -60,16 +60,18 @@ tasks:
 
       tags:
         createdForUser: {{owner}}
 
       routes:
         - "index.gecko.v2.{{project}}.latest.firefox.decision"
         - "tc-treeherder.v2.{{project}}.{{revision}}.{{pushlog_id}}"
         - "tc-treeherder-stage.v2.{{project}}.{{revision}}.{{pushlog_id}}"
+        - "notify.email.{{owner}}.on-failed"
+        - "notify.email.{{owner}}.on-exception"
 
       payload:
         env:
           # checkout-gecko uses these to check out the source; the inputs
           # to `mach taskgraph decision` are all on the command line.
           GECKO_BASE_REPOSITORY: 'https://hg.mozilla.org/mozilla-unified'
           GECKO_HEAD_REPOSITORY: '{{{url}}}'
           GECKO_HEAD_REF: '{{revision}}'
--- a/taskcluster/taskgraph/try_option_syntax.py
+++ b/taskcluster/taskgraph/try_option_syntax.py
@@ -244,17 +244,17 @@ def parse_message(message):
                         dest='taskcluster_worker', action='store_true', default=False)
     # Similarly, an extra flag for enabling os x jobs in generic-worker
     parser.add_argument('-g', '--generic-worker',
                         dest='generic_worker', action='store_true', default=False)
 
     # In order to run test jobs multiple times
     parser.add_argument('--rebuild', dest='trigger_tests', type=int, default=1)
     parts = parts[try_idx:] if try_idx is not None else []
-    args, _ = parser.parse_known_args(parts[try_idx:])
+    args, _ = parser.parse_known_args(parts)
     return args
 
 
 class TryOptionSyntax(object):
 
     def __init__(self, message, full_task_graph):
         """
         Parse a "try syntax" formatted commit message.  This is the old "-b do -p
@@ -301,18 +301,18 @@ class TryOptionSyntax(object):
         try_idx, _ = find_try_idx(message)
         if try_idx is None:
             return None
 
         args = parse_message(message)
         assert args is not None
 
         self.jobs = self.parse_jobs(args.jobs)
-        self.build_types = self.parse_build_types(args.build_types)
-        self.platforms = self.parse_platforms(args.platforms)
+        self.build_types = self.parse_build_types(args.build_types, full_task_graph)
+        self.platforms = self.parse_platforms(args.platforms, full_task_graph)
         self.unittests = self.parse_test_option(
             "unittest_try_name", args.unittests, full_task_graph)
         self.talos = self.parse_test_option("talos_try_name", args.talos, full_task_graph)
         self.trigger_tests = args.trigger_tests
         self.interactive = args.interactive
         self.notifications = args.notifications
         self.talos_trigger_tests = args.talos_trigger_tests
         self.env = args.env
@@ -324,35 +324,55 @@ class TryOptionSyntax(object):
     def parse_jobs(self, jobs_arg):
         if not jobs_arg or jobs_arg == ['all']:
             return None
         expanded = []
         for job in jobs_arg:
             expanded.extend(j.strip() for j in job.split(','))
         return expanded
 
-    def parse_build_types(self, build_types_arg):
+    def parse_build_types(self, build_types_arg, full_task_graph):
         if build_types_arg is None:
             build_types_arg = []
+
         build_types = filter(None, [BUILD_TYPE_ALIASES.get(build_type) for
                              build_type in build_types_arg])
+
+        all_types = set(t.attributes['build_type']
+                        for t in full_task_graph.tasks.itervalues()
+                        if 'build_type' in t.attributes)
+        bad_types = set(build_types) - all_types
+        if bad_types:
+            raise Exception("Unknown build type(s) [%s] specified for try" % ','.join(bad_types))
+
         return build_types
 
-    def parse_platforms(self, platform_arg):
+    def parse_platforms(self, platform_arg, full_task_graph):
         if platform_arg == 'all':
             return None
 
         results = []
         for build in platform_arg.split(','):
             results.append(build)
             if build in RIDEALONG_BUILDS:
                 results.extend(RIDEALONG_BUILDS[build])
                 logger.info("platform %s triggers ridealong builds %s" %
                             (build, ', '.join(RIDEALONG_BUILDS[build])))
 
+        test_platforms = set(t.attributes['test_platform']
+                             for t in full_task_graph.tasks.itervalues()
+                             if 'test_platform' in t.attributes)
+        build_platforms = set(t.attributes['build_platform']
+                              for t in full_task_graph.tasks.itervalues()
+                              if 'build_platform' in t.attributes)
+        all_platforms = test_platforms | build_platforms
+        bad_platforms = set(results) - all_platforms
+        if bad_platforms:
+            raise Exception("Unknown platform(s) [%s] specified for try" % ','.join(bad_platforms))
+
         return results
 
     def parse_test_option(self, attr_name, test_arg, full_task_graph):
         '''
 
         Parse a unittest (-u) or talos (-t) option, in the context of a full
         task graph containing available `unittest_try_name` or `talos_try_name`
         attributes.  There are three cases: