Source code

Revision control

Other Tools

1
# -*- coding: utf-8 -*-
2
3
# This Source Code Form is subject to the terms of the Mozilla Public
4
# License, v. 2.0. If a copy of the MPL was not distributed with this
5
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7
from __future__ import absolute_import, print_function, unicode_literals
8
9
import logging
10
11
import requests
12
from requests.exceptions import HTTPError
13
14
from .registry import register_callback_action
15
from .util import create_tasks, combine_task_graph_files
16
from taskgraph.util.taskcluster import get_artifact_from_index
17
from taskgraph.util.taskgraph import find_decision_task
18
from taskgraph.taskgraph import TaskGraph
19
from taskgraph.util import taskcluster
20
21
PUSHLOG_TMPL = '{}/json-pushes?version=2&startID={}&endID={}'
22
INDEX_TMPL = 'gecko.v2.{}.pushlog-id.{}.decision'
23
24
logger = logging.getLogger(__name__)
25
26
27
@register_callback_action(
28
title='GeckoProfile',
29
name='geckoprofile',
30
generic=True,
31
symbol='Gp',
32
description=('Take the label of the current task, '
33
'and trigger the task with that label '
34
'on previous pushes in the same project '
35
'while adding the --geckoProfile cmd arg.'),
36
order=200,
37
context=[{'test-type': 'talos'}, {'test-type': 'raptor'}],
38
schema={},
39
available=lambda parameters: True
40
)
41
def geckoprofile_action(parameters, graph_config, input, task_group_id, task_id):
42
task = taskcluster.get_task_definition(task_id)
43
label = task['metadata']['name']
44
pushes = []
45
depth = 2
46
end_id = int(parameters['pushlog_id'])
47
48
while True:
49
start_id = max(end_id - depth, 0)
50
pushlog_url = PUSHLOG_TMPL.format(parameters['head_repository'], start_id, end_id)
51
r = requests.get(pushlog_url)
52
r.raise_for_status()
53
pushes = pushes + r.json()['pushes'].keys()
54
if len(pushes) >= depth:
55
break
56
57
end_id = start_id - 1
58
start_id -= depth
59
if start_id < 0:
60
break
61
62
pushes = sorted(pushes)[-depth:]
63
backfill_pushes = []
64
65
for push in pushes:
66
try:
67
full_task_graph = get_artifact_from_index(
68
INDEX_TMPL.format(parameters['project'], push),
69
'public/full-task-graph.json')
70
_, full_task_graph = TaskGraph.from_json(full_task_graph)
71
label_to_taskid = get_artifact_from_index(
72
INDEX_TMPL.format(parameters['project'], push),
73
'public/label-to-taskid.json')
74
push_params = get_artifact_from_index(
75
INDEX_TMPL.format(parameters['project'], push),
76
'public/parameters.yml')
77
push_decision_task_id = find_decision_task(push_params, graph_config)
78
except HTTPError as e:
79
logger.info('Skipping {} due to missing index artifacts! Error: {}'.format(push, e))
80
continue
81
82
if label in full_task_graph.tasks.keys():
83
def modifier(task):
84
if task.label != label:
85
return task
86
87
cmd = task.task['payload']['command']
88
task.task['payload']['command'] = add_args_to_command(cmd, ['--geckoProfile'])
89
task.task['extra']['treeherder']['symbol'] += '-p'
90
return task
91
92
create_tasks(graph_config, [label], full_task_graph, label_to_taskid,
93
push_params, push_decision_task_id, push, modifier=modifier)
94
backfill_pushes.append(push)
95
else:
96
logging.info('Could not find {} on {}. Skipping.'.format(label, push))
97
combine_task_graph_files(backfill_pushes)
98
99
100
def add_args_to_command(cmd_parts, extra_args=[]):
101
"""
102
Add custom command line args to a given command.
103
args:
104
cmd_parts: the raw command as seen by taskcluster
105
extra_args: array of args we want to add
106
"""
107
cmd_type = 'default'
108
if len(cmd_parts) == 1 and isinstance(cmd_parts[0], dict):
109
# windows has single cmd part as dict: 'task-reference', with long string
110
cmd_parts = cmd_parts[0]['task-reference'].split(' ')
111
cmd_type = 'dict'
112
elif len(cmd_parts) == 1 and isinstance(cmd_parts[0], list):
113
# osx has an single value array with an array inside
114
cmd_parts = cmd_parts[0]
115
cmd_type = 'subarray'
116
117
cmd_parts.extend(extra_args)
118
119
if cmd_type == 'dict':
120
cmd_parts = [{'task-reference': ' '.join(cmd_parts)}]
121
elif cmd_type == 'subarray':
122
cmd_parts = [cmd_parts]
123
return cmd_parts