Bug 1381597 - create a taskcluster task that tests the decision graph for invalid buildbot-bridge builder names. r=dustin
authorJustin Wood <Callek@gmail.com>
Tue, 19 Sep 2017 16:21:19 -0400
changeset 382224 1eabbea52ac1fdeaec97a2285b997487c777d797
parent 382223 db6679f42d980c1267971a6102459ae9501c32eb
child 382225 3c6d8d0c66f504ae8097c4bda1afe1159a320d0e
push id32551
push userkwierso@gmail.com
push dateThu, 21 Sep 2017 23:29:53 +0000
treeherdermozilla-central@d6d6fd889f7b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdustin
bugs1381597
milestone58.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 1381597 - create a taskcluster task that tests the decision graph for invalid buildbot-bridge builder names. r=dustin This adds a download of allthethings.json to the Decision Task (in optimize phase). If there is a network error, in order to avoid a broken decision task, we treat all buildbot-bridge jobs as valid. MozReview-Commit-ID: GpKVV5pUwGL
taskcluster/taskgraph/util/bbb_validation.py
taskcluster/taskgraph/util/verify.py
new file mode 100644
--- /dev/null
+++ b/taskcluster/taskgraph/util/bbb_validation.py
@@ -0,0 +1,53 @@
+# -*- coding: utf-8 -*-
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+import json
+import logging
+import requests
+
+from mozbuild.util import memoize
+from redo import retry
+from requests import exceptions
+
+ALLTHETHINGS_URL = "https://secure.pub.build.mozilla.org/builddata/reports/allthethings.json.gz"
+
+logger = logging.getLogger(__name__)
+
+
+def fetch_all_the_things():
+    response = retry(requests.get, attempts=2, sleeptime=10,
+                     args=(ALLTHETHINGS_URL,),
+                     kwargs={'timeout': 60})
+    return response.content
+
+
+@memoize
+def valid_bbb_builders():
+    try:
+        allthethings = fetch_all_the_things()
+        builders = set(json.loads(allthethings).get('builders', {}).keys())
+        return builders
+
+    # In the event of request times out, requests will raise a TimeoutError.
+    except exceptions.Timeout:
+        logger.warning("Timeout fetching list of buildbot builders.")
+
+    # In the event of a network problem (e.g. DNS failure, refused connection, etc),
+    # requests will raise a ConnectionError.
+    except exceptions.ConnectionError:
+        logger.warning("Connection Error while fetching list of buildbot builders")
+
+    # We just print the error out as a debug message if we failed to catch the exception above
+    except exceptions.RequestException as error:
+        logger.warning(error)
+
+    # When we get invalid JSON (i.e. 500 error), it results in a ValueError
+    except ValueError as error:
+        logger.warning("Invalid JSON, possible server error: {}".format(error))
+
+    # None returned to treat as "All Builders Valid"
+    return None
--- a/taskcluster/taskgraph/util/verify.py
+++ b/taskcluster/taskgraph/util/verify.py
@@ -5,16 +5,17 @@
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 import re
 import os
 import sys
 
 from .. import GECKO
+from taskgraph.util.bbb_validation import valid_bbb_builders
 
 base_path = os.path.join(GECKO, 'taskcluster', 'docs')
 
 
 class VerificationSequence(object):
     """
     Container for a sequence of verifications over a TaskGraph. Each
     verification is represented as a callable taking (task, taskgraph,
@@ -142,8 +143,31 @@ def verify_dependency_tiers(task, taskgr
         for task in taskgraph.tasks.itervalues():
             tier = tiers[task.label]
             for d in task.dependencies.itervalues():
                 if tier < tiers[d]:
                     raise Exception(
                         '{} (tier {}) cannot depend on {} (tier {})'
                         .format(task.label, printable_tier(tier),
                                 d, printable_tier(tiers[d])))
+
+
+@verifications.add('optimized_task_graph')
+def verify_bbb_builders_valid(task, taskgraph, scratch_pad):
+    """
+        This function ensures that any task which is run
+        in buildbot (via buildbot-bridge) is using a recognized buildername.
+
+        If you see an unexpected failure with a task due to this check, please
+        see the IRC Channel, #releng.
+    """
+    if task is None:
+        return
+    valid_builders = valid_bbb_builders()
+    if valid_builders is None:
+        return
+    if task.task.get('workerType') == 'buildbot-bridge':
+        buildername = task.task['payload']['buildername']
+        if buildername not in valid_builders:
+            raise Exception(
+                '{} uses an invalid buildbot buildername ("{}") '
+                ' - contact #releng for help'
+                .format(task.label, buildername))