Bug 1380454 - Port retrigger to actions.json draft
authorBrian Stack <bstack@mozilla.com>
Thu, 13 Jul 2017 10:41:58 -0700
changeset 612596 da223dfcf828250e674b7246e69ee856f1a8bf8e
parent 611331 c5ea72577f794635a334a30780d104a1d89267a0
child 638453 2cd09260baffe1868cd178c9679b10d9c4740349
push id69546
push userbstack@mozilla.com
push dateThu, 20 Jul 2017 21:21:01 +0000
bugs1380454
milestone56.0a1
Bug 1380454 - Port retrigger to actions.json MozReview-Commit-ID: 3942ptSNiss
taskcluster/actions/registry.py
taskcluster/actions/retrigger.py
taskcluster/docs/action-implementation.rst
--- a/taskcluster/actions/registry.py
+++ b/taskcluster/actions/registry.py
@@ -22,17 +22,17 @@ def is_json(data):
     """ Return ``True``, if ``data`` is a JSON serializable data structure. """
     try:
         json.dumps(data)
     except ValueError:
         return False
     return True
 
 
-def register_task_action(name, title, description, order, context, schema):
+def register_task_action(name, title, description, order, context, schema=None):
     """
     Register an action task that can be triggered from supporting
     user interfaces, such as Treeherder.
 
     Most actions will create intermediate action tasks that call back into
     in-tree python code. To write such an action please use
     :func:`register_callback_action`.
 
@@ -262,25 +262,28 @@ def render_actions_json(parameters):
     """
     global actions
     assert isinstance(parameters, Parameters), 'requires instance of Parameters'
     result = []
     for action in sorted(actions, key=lambda action: action.order):
         task = action.task_template_builder(parameters)
         if task:
             assert is_json(task), 'task must be a JSON compatible object'
-            result.append({
+            res = {
                 'kind': 'task',
                 'name': action.name,
                 'title': action.title,
                 'description': action.description,
                 'context': action.context,
                 'schema': action.schema,
                 'task': task,
-            })
+            }
+            if res['schema'] is None:
+                res.pop('schema')
+            result.append(res)
     return {
         'version': 1,
         'variables': {
             'parameters': dict(**parameters),
         },
         'actions': result,
     }
 
new file mode 100644
--- /dev/null
+++ b/taskcluster/actions/retrigger.py
@@ -0,0 +1,56 @@
+from registry import register_task_action
+
+
+@register_task_action(
+    title='Retrigger',
+    name='retrigger',
+    description='Create a clone of the task',
+    order=1,
+    context=[{}],
+)
+def retrigger_task_builder(parameters):
+
+    new_expires = '30 days'
+
+    return {
+        '$merge': [
+            {'$eval': 'task'},
+            {'created': {'$fromNow': ''}},
+            {'deadline': {'$fromNow': '1 day'}},
+            {'expires': {'$fromNow': new_expires}},
+            {'payload': {
+                '$merge': [
+                    {'$eval': 'task.payload'},
+                    {
+                        '$if': '"artifacts" in task.payload',
+                        'then': {
+                            'artifacts': {
+                                '$if': 'typeof(task.payload.artifacts) == "object"',
+                                'then': {
+                                    '$map': {'$eval': 'task.payload.artifacts'},
+                                    'each(artifact)': {
+                                        '${artifact.key}': {
+                                            '$merge': [
+                                                {'$eval': 'artifact.val'},
+                                                {'expires': {'$fromNow': new_expires}},
+                                            ],
+                                        },
+                                    },
+                                },
+                                'else': {
+                                    '$map': {'$eval': 'task.payload.artifacts'},
+                                    'each(artifact)': {
+                                        '$merge': [
+                                            {'$eval': 'artifact'},
+                                            {'expires': {'$fromNow': new_expires}},
+                                        ],
+                                    },
+                                },
+                            },
+                        },
+                        'else': {},
+                    }
+                ]
+            }}
+        ]
+    }
--- a/taskcluster/docs/action-implementation.rst
+++ b/taskcluster/docs/action-implementation.rst
@@ -205,16 +205,17 @@ the example below illustrates how to cre
       context=[{'platform': 'linux'}],
       input={
           'title': 'priority'
           'description': 'Priority that should be given to the tasks',
           'type': 'string',
           'enum': ['low', 'normal', 'high'],
           'default': 'low',
       },
+  )
   def task_template_builder(parameters):
       # The task template builder may return None to signal that the action
       # isn't available.
       if parameters.get('project', None) != 'try':
         return None
       return {
           'created': {'$fromNow': ''},
           'deadline': {'$fromNow': '1 hour'},
@@ -228,17 +229,16 @@ the example below illustrates how to cre
                   'TASK_DEFINITION': {'$json': {'eval': 'task'}}
               },
               ...
           },
           # It's now your responsibility to include treeherder routes, as well
           # additional metadata for treeherder in task.extra.treeherder.
           ...
       },
-  )
 
 This kind of action is useful for creating simple derivative tasks, but is
 limited by the expressiveness of the template language. On the other hand, it
 is more efficient than an action callback as it does not involve an
 intermediate action task before creating the task the user requested.
 
 For further details on the template language, see :doc:`the specification for
 actions.json <action-spec>`.