retrigger_custom.py (6259B)
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 6 import logging 7 8 from taskgraph.util import json 9 from taskgraph.util.parameterization import resolve_task_references 10 from taskgraph.util.taskcluster import get_task_definition 11 12 from .registry import register_callback_action 13 from .util import create_task_from_def, fetch_graph_and_labels 14 15 logger = logging.getLogger(__name__) 16 17 # Properties available for custom retrigger of any supported test suites 18 basic_properties = { 19 "path": { 20 "type": "string", 21 "maxLength": 255, 22 "default": "", 23 "title": "Path name", 24 "description": "Path of test(s) to retrigger", 25 }, 26 "logLevel": { 27 "type": "string", 28 "enum": ["debug", "info", "warning", "error", "critical"], 29 "default": "info", 30 "title": "Log level", 31 "description": "Log level for output (INFO is normal, DEBUG gives more detail)", 32 }, 33 "environment": { 34 "type": "object", 35 "default": {"MOZ_LOG": ""}, 36 "title": "Extra environment variables", 37 "description": "Extra environment variables to use for this run", 38 "additionalProperties": {"type": "string"}, 39 }, 40 } 41 42 # Additional properties available for custom retrigger of some additional test suites 43 extended_properties = basic_properties.copy() 44 extended_properties.update({ 45 "runUntilFail": { 46 "type": "boolean", 47 "default": False, 48 "title": "Run until failure", 49 "description": ( 50 "Runs the specified set of tests repeatedly " 51 "until failure (up to REPEAT times)" 52 ), 53 }, 54 "repeat": { 55 "type": "integer", 56 "default": 0, 57 "minimum": 0, 58 "title": "Repeat test(s) N times", 59 "description": ( 60 "Run test(s) repeatedly (usually used in conjunction with runUntilFail)" 61 ), 62 }, 63 "preferences": { 64 "type": "object", 65 "default": {"remote.log.level": "Info"}, 66 "title": "Extra gecko (about:config) preferences", 67 "description": "Extra gecko (about:config) preferences to use for this run", 68 "additionalProperties": {"type": "string"}, 69 }, 70 }) 71 72 73 @register_callback_action( 74 name="retrigger-custom", 75 title="Retrigger task with custom parameters", 76 symbol="rt", 77 description="Retriggers the specified task with custom environment and parameters", 78 context=[ 79 {"test-type": "mochitest", "worker-implementation": "docker-worker"}, 80 {"test-type": "reftest", "worker-implementation": "docker-worker"}, 81 {"test-type": "geckoview-junit", "worker-implementation": "docker-worker"}, 82 ], 83 order=10, 84 schema={ 85 "type": "object", 86 "properties": extended_properties, 87 "additionalProperties": False, 88 "required": ["path"], 89 }, 90 ) 91 def extended_custom_retrigger_action( 92 parameters, graph_config, input, task_group_id, task_id 93 ): 94 handle_custom_retrigger(parameters, graph_config, input, task_group_id, task_id) 95 96 97 @register_callback_action( 98 name="retrigger-custom (gtest)", 99 title="Retrigger gtest task with custom parameters", 100 symbol="rt", 101 description="Retriggers the specified task with custom environment and parameters", 102 context=[{"test-type": "gtest", "worker-implementation": "docker-worker"}], 103 order=10, 104 schema={ 105 "type": "object", 106 "properties": basic_properties, 107 "additionalProperties": False, 108 "required": ["path"], 109 }, 110 ) 111 def basic_custom_retrigger_action_basic( 112 parameters, graph_config, input, task_group_id, task_id 113 ): 114 handle_custom_retrigger(parameters, graph_config, input, task_group_id, task_id) 115 116 117 def handle_custom_retrigger(parameters, graph_config, input, task_group_id, task_id): 118 task = get_task_definition(task_id) 119 decision_task_id, full_task_graph, label_to_taskid, _ = fetch_graph_and_labels( 120 parameters, graph_config 121 ) 122 123 pre_task = full_task_graph.tasks[task["metadata"]["name"]] 124 125 # fix up the task's dependencies, similar to how optimization would 126 # have done in the decision 127 dependencies = { 128 name: label_to_taskid[label] for name, label in pre_task.dependencies.items() 129 } 130 new_task_definition = resolve_task_references( 131 pre_task.label, pre_task.task, task_id, decision_task_id, dependencies 132 ) 133 new_task_definition.setdefault("dependencies", []).extend(dependencies.values()) 134 135 # don't want to run mozharness tests, want a custom mach command instead 136 new_task_definition["payload"]["command"] += ["--no-run-tests"] 137 138 custom_mach_command = [task["tags"]["test-type"]] 139 140 # mochitests may specify a flavor 141 if new_task_definition["payload"]["env"].get("MOCHITEST_FLAVOR"): 142 custom_mach_command += [ 143 "--keep-open=false", 144 "-f", 145 new_task_definition["payload"]["env"]["MOCHITEST_FLAVOR"], 146 ] 147 148 enable_e10s = json.loads( 149 new_task_definition["payload"]["env"].get("ENABLE_E10S", "true") 150 ) 151 if not enable_e10s: 152 custom_mach_command += ["--disable-e10s"] 153 154 custom_mach_command += [ 155 "--log-tbpl=-", 156 "--log-tbpl-level={}".format(input.get("logLevel", "debug")), 157 ] 158 if input.get("runUntilFail"): 159 custom_mach_command += ["--run-until-failure"] 160 if input.get("repeat"): 161 custom_mach_command += ["--repeat", str(input.get("repeat", 30))] 162 163 # add any custom gecko preferences 164 for key, val in input.get("preferences", {}).items(): 165 custom_mach_command += ["--setpref", f"{key}={val}"] 166 167 custom_mach_command += [input["path"]] 168 new_task_definition["payload"]["env"]["CUSTOM_MACH_COMMAND"] = " ".join( 169 custom_mach_command 170 ) 171 172 # update environment 173 new_task_definition["payload"]["env"].update(input.get("environment", {})) 174 175 # tweak the treeherder symbol 176 new_task_definition["extra"]["treeherder"]["symbol"] += "-custom" 177 178 logging.info("New task definition: %s", new_task_definition) 179 180 create_task_from_def( 181 new_task_definition, parameters["level"], action_tag="retrigger-custom-task" 182 )