Bug 1486970 - Create revision and pushlog-id index routes for cron decision tasks. r=dustin
☠☠ backed out by e547a1a4ac86 ☠ ☠
authorJustin Wood <Callek@gmail.com>
Wed, 29 Aug 2018 15:40:37 +0000
changeset 433906 3db3193ec938e49a0ea38705cd32310e055859a3
parent 433905 b38bcb2c577c0e5052ae595ef572b301aa88046e
child 433907 332b73bd0c423e922efb2a2eb3c84fe67a7ac0ce
push id34525
push useraiakab@mozilla.com
push dateWed, 29 Aug 2018 21:52:41 +0000
treeherdermozilla-central@b946a1ac70e5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdustin
bugs1486970
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 1486970 - Create revision and pushlog-id index routes for cron decision tasks. r=dustin Differential Revision: https://phabricator.services.mozilla.com/D4501
.taskcluster.yml
taskcluster/taskgraph/cron/decision.py
taskcluster/taskgraph/cron/util.py
--- a/.taskcluster.yml
+++ b/.taskcluster.yml
@@ -78,16 +78,19 @@ tasks:
               else:
                 $if: 'tasks_for == "action"'
                 then:
                 - "notify.email.taskcluster-notifications+action-task@mozilla.com.on-failed"
                 - "notify.email.taskcluster-notifications+action-task@mozilla.com.on-exception"
                 - "index.gecko.v2.${repository.project}.pushlog-id.${push.pushlog_id}.actions.${ownTaskId}"
                 else:  # cron
                 - "index.gecko.v2.${repository.project}.latest.taskgraph.decision-${cron.job_name}"
+                - "index.gecko.v2.${repository.project}.revision.${push.revision}.taskgraph.decision-${cron.job_name}"
+                - "index.gecko.v2.${repository.project}.pushlog-id.${push.pushlog_id}.decision-${cron.job_name}"
+                # These are the old index routes for the decision task.
                 - "index.gecko.v2.${repository.project}.latest.firefox.decision-${cron.job_name}"
 
         scopes:
           $if: 'tasks_for == "hg-push"'
           then:
             - 'assume:repo:${repoUrl[8:]}:branch:default'
             - 'queue:route:notify.email.${ownerEmail}.*'
             - 'in-tree:hook-action:project-gecko/in-tree-action-${repository.level}-*'
--- a/taskcluster/taskgraph/cron/decision.py
+++ b/taskcluster/taskgraph/cron/decision.py
@@ -9,16 +9,17 @@ from __future__ import absolute_import, 
 
 import jsone
 import pipes
 import yaml
 import os
 import slugid
 
 from taskgraph.util.time import current_json_time
+from .util import find_pushlog_info
 
 
 def run_decision_task(job, params, root):
     arguments = []
     if 'target-tasks-method' in job:
         arguments.append('--target-tasks-method={}'.format(job['target-tasks-method']))
     return [
         make_decision_task(
@@ -31,16 +32,22 @@ def run_decision_task(job, params, root)
 
 def make_decision_task(params, root, symbol, arguments=[], head_rev=None):
     """Generate a basic decision task, based on the root .taskcluster.yml"""
     with open(os.path.join(root, '.taskcluster.yml'), 'rb') as f:
         taskcluster_yml = yaml.safe_load(f)
 
     if not head_rev:
         head_rev = params['head_rev']
+    try:
+        pushlog = find_pushlog_info(
+            params['repository_url'],
+            params['head_rev'])
+    except (IOError, RuntimeError):
+        pushlog = {'pushid': -1, 'pushdate': 0}
 
     slugids = {}
 
     def as_slugid(name):
         # https://github.com/taskcluster/json-e/issues/164
         name = name[0]
         if name not in slugids:
             slugids[name] = slugid.nice()
@@ -54,18 +61,18 @@ def make_decision_task(params, root, sym
         'repository': {
             'url': params['repository_url'],
             'project': params['project'],
             'level': params['level'],
         },
         'push': {
             'revision': params['head_rev'],
             # remainder are fake values, but the decision task expects them anyway
-            'pushlog_id': -1,
-            'pushdate': 0,
+            'pushlog_id': pushlog['pushid'],
+            'pushdate': pushlog['pushdate'],
             'owner': 'cron',
             'comment': '',
         },
         'cron': {
             'task_id': os.environ.get('TASK_ID', '<cron task id>'),
             'job_name': params['job_name'],
             'job_symbol': symbol,
             # args are shell-quoted since they are given to `bash -c`
--- a/taskcluster/taskgraph/cron/util.py
+++ b/taskcluster/taskgraph/cron/util.py
@@ -2,18 +2,21 @@
 
 # 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 requests
 import subprocess
 
+PUSHLOG_TMPL = '{}/json-pushes?version=2&changeset={}&tipsonly=1&full=1'
+
 
 def match_utc(params, sched):
     """Return True if params['time'] matches the given schedule.
 
     If minute is not specified, then every multiple of fifteen minutes will match.
     Times not an even multiple of fifteen minutes will result in an exception
     (since they would never run).
     If hour is not specified, any hour will match. Similar for day and weekday.
@@ -40,8 +43,25 @@ def match_utc(params, sched):
     return True
 
 
 def calculate_head_rev(root):
     # we assume that run-task has correctly checked out the revision indicated by
     # GECKO_HEAD_REF, so all that remains is to see what the current revision is.
     # Mercurial refers to that as `.`.
     return subprocess.check_output(['hg', 'log', '-r', '.', '-T', '{node}'], cwd=root)
+
+
+def find_pushlog_info(repo, revision):
+    """Given a repo url and a revision, find the pushlog_id of the revision."""
+
+    pushlog_url = PUSHLOG_TMPL.format(repo, revision)
+    r = requests.get(pushlog_url)
+    r.raise_for_status()
+    pushes = r.json()['pushes']
+    if len(pushes) != 1:
+        raise RuntimeError(
+            "Unable to find a single pushlog_id for {} revision {}: {}".format(
+                repo, revision, pushes
+            )
+        )
+    pushid = pushes.keys()[0]
+    return {'pushdate': pushes[pushid]['date'], 'pushid': pushid}