1# This Source Code Form is subject to the terms of the Mozilla Public 2# License, v. 2.0. If a copy of the MPL was not distributed with this 3# file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 5""" 6Utilities for generating a decision task from :file:`.taskcluster.yml`. 7""" 8 9 10import jsone 11import yaml 12import os 13import slugid 14 15from .vcs import find_hg_revision_push_info 16from .templates import merge 17from .time import current_json_time 18 19 20def make_decision_task(params, root, context, head_rev=None): 21 """Generate a basic decision task, based on the root .taskcluster.yml""" 22 with open(os.path.join(root, ".taskcluster.yml"), "rb") as f: 23 taskcluster_yml = yaml.safe_load(f) 24 25 if not head_rev: 26 head_rev = params["head_rev"] 27 28 if params["repository_type"] == "hg": 29 pushlog = find_hg_revision_push_info(params["repository_url"], head_rev) 30 31 hg_push_context = { 32 "pushlog_id": pushlog["pushid"], 33 "pushdate": pushlog["pushdate"], 34 "owner": pushlog["user"], 35 } 36 else: 37 hg_push_context = {} 38 39 slugids = {} 40 41 def as_slugid(name): 42 # https://github.com/taskcluster/json-e/issues/164 43 name = name[0] 44 if name not in slugids: 45 slugids[name] = slugid.nice() 46 return slugids[name] 47 48 # provide a similar JSON-e context to what mozilla-taskcluster provides: 49 # https://docs.taskcluster.net/reference/integrations/mozilla-taskcluster/docs/taskcluster-yml 50 # but with a different tasks_for and an extra `cron` section 51 context = merge( 52 { 53 "repository": { 54 "url": params["repository_url"], 55 "project": params["project"], 56 "level": params["level"], 57 }, 58 "push": merge( 59 { 60 "revision": params["head_rev"], 61 # remainder are fake values, but the decision task expects them anyway 62 "comment": " ", 63 }, 64 hg_push_context, 65 ), 66 "now": current_json_time(), 67 "as_slugid": as_slugid, 68 }, 69 context, 70 ) 71 72 rendered = jsone.render(taskcluster_yml, context) 73 if len(rendered["tasks"]) != 1: 74 raise Exception("Expected .taskcluster.yml to only produce one cron task") 75 task = rendered["tasks"][0] 76 77 task_id = task.pop("taskId") 78 return (task_id, task) 79