Bug 1463522 - include .taskcluster.yml hash in hookId; r?tomprince
MozReview-Commit-ID: 7KJGRKuFlna
--- a/taskcluster/taskgraph/actions/registry.py
+++ b/taskcluster/taskgraph/actions/registry.py
@@ -9,17 +9,17 @@ from __future__ import absolute_import,
import json
import os
import re
from slugid import nice as slugid
from types import FunctionType
from collections import namedtuple
from taskgraph import create
from taskgraph.config import load_graph_config
-from taskgraph.util import taskcluster, yaml
+from taskgraph.util import taskcluster, yaml, hash
from taskgraph.parameters import Parameters
from mozbuild.util import memoize
actions = []
callbacks = {}
Action = namedtuple('Action', ['order', 'action_builder'])
@@ -35,16 +35,26 @@ def is_json(data):
@memoize
def read_taskcluster_yml(filename):
'''Load and parse .taskcluster.yml, memoized to save some time'''
return yaml.load_yaml(*os.path.split(filename))
+@memoize
+def hash_taskcluster_yml(filename):
+ '''
+ Generate a hash of the given .taskcluster.yml. This is the first 10 digits
+ of the sha256 of the file's content, and is used by administrative scripts
+ to create a hook based on this content.
+ '''
+ return hash.hash_path(filename)[:10]
+
+
def register_callback_action(name, title, symbol, description, order=10000,
context=[], available=lambda parameters: True,
schema=None, kind='task', generic=True):
"""
Register an action callback that can be triggered from supporting
user interfaces, such as Treeherder.
This function is to be used as a decorator for a callback that takes
@@ -199,20 +209,30 @@ def register_callback_action(name, title
'in': taskcluster_yml['tasks'][0],
},
})
# for kind=hook
elif kind == 'hook':
trustDomain = graph_config['trust-domain']
level = parameters['level']
+ tcyml_hash = hash_taskcluster_yml(graph_config.taskcluster_yml)
+
+ # the tcyml_hash is prefixed with `/` in the hookId, so users will be granted
+ # hooks:trigger-hook:project-gecko/in-tree-action-3-myaction/*; if another
+ # action was named `myaction/release`, then the `*` in the scope would also
+ # match that action. To prevent such an accident, we prohibit `/` in hook
+ # names.
+ if '/' in actionPerm:
+ raise Exception('`/` is not allowed in action names; use `-`')
+
rv.update({
'kind': 'hook',
'hookGroupId': 'project-{}'.format(trustDomain),
- 'hookId': 'in-tree-action-{}-{}'.format(level, actionPerm),
+ 'hookId': 'in-tree-action-{}-{}/{}'.format(level, actionPerm, tcyml_hash),
'hookPayload': {
# provide the decision-task parameters as context for triggerHook
"decision": {
'action': action,
'repository': repository,
'push': push,
# parameters is long, so fetch it from the actions.json variables
'parameters': {'$eval': 'parameters'},