mach_commands.py (5626B)
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 # Integrates Talos mozharness with mach 6 7 import json 8 import logging 9 import os 10 import socket 11 import sys 12 13 from mach.decorators import Command 14 from mach.util import get_state_dir 15 from mozbuild.base import BinaryNotFoundException, MozbuildObject 16 17 HERE = os.path.dirname(os.path.realpath(__file__)) 18 19 20 class TalosRunner(MozbuildObject): 21 def run_test(self, talos_args): 22 """ 23 We want to do couple of things before running Talos 24 1. Clone mozharness 25 2. Make config for Talos Mozharness 26 3. Run mozharness 27 """ 28 # Validate that the user is using a supported python version before doing anything else 29 max_py_major, max_py_minor = 3, 13 30 sys_maj, sys_min = sys.version_info.major, sys.version_info.minor 31 if sys_min > max_py_minor: 32 raise PythonVersionException( 33 print( 34 f"\tPlease downgrade your Python version as talos does not yet support Python " 35 f"versions greater than {max_py_major}.{max_py_minor}." 36 f"\n\tYou seem to currently be using Python {sys_maj}.{sys_min}." 37 f"\n\tSee here for a possible solution in debugging your python environment: " 38 f"https://firefox-source-docs.mozilla.org/testing/perfdocs/" 39 f"debugging.html#debugging-local-python-environment" 40 ) 41 ) 42 try: 43 self.init_variables(talos_args) 44 except BinaryNotFoundException as e: 45 self.log(logging.ERROR, "talos", {"error": str(e)}, "ERROR: {error}") 46 self.log(logging.INFO, "raptor", {"help": e.help()}, "{help}") 47 return 1 48 49 self.make_config() 50 self.write_config() 51 self.make_args() 52 return self.run_mozharness() 53 54 def init_variables(self, talos_args): 55 self.talos_dir = os.path.join(self.topsrcdir, "testing", "talos") 56 self.mozharness_dir = os.path.join(self.topsrcdir, "testing", "mozharness") 57 self.talos_json = os.path.join(self.talos_dir, "talos.json") 58 self.config_file_path = os.path.join( 59 self._topobjdir, "testing", "talos-in_tree_conf.json" 60 ) 61 self.binary_path = self.get_binary_path() 62 self.virtualenv_script = os.path.join( 63 self.topsrcdir, "third_party", "python", "virtualenv", "virtualenv.py" 64 ) 65 self.virtualenv_path = os.path.join(self._topobjdir, "testing", "talos-venv") 66 self.python_interp = sys.executable 67 self.talos_args = talos_args 68 69 def make_config(self): 70 default_actions = ["populate-webroot"] 71 default_actions.extend([ 72 "create-virtualenv", 73 "run-tests", 74 ]) 75 self.config = { 76 "run_local": True, 77 "talos_json": self.talos_json, 78 "binary_path": self.binary_path, 79 "repo_path": self.topsrcdir, 80 "obj_path": self.topobjdir, 81 "log_name": "talos", 82 "virtualenv_path": self.virtualenv_path, 83 "pypi_url": "http://pypi.python.org/simple", 84 "base_work_dir": self.mozharness_dir, 85 "exes": { 86 "python": self.python_interp, 87 "virtualenv": [self.python_interp, self.virtualenv_script], 88 }, 89 "title": socket.gethostname(), 90 "default_actions": default_actions, 91 "talos_extra_options": ["--develop"] + self.talos_args, 92 "python3_manifest": { 93 "win32": "python3.manifest", 94 "win64": "python3_x64.manifest", 95 }, 96 "mozbuild_path": get_state_dir(), 97 } 98 99 def make_args(self): 100 self.args = { 101 "config": {}, 102 "initial_config_file": self.config_file_path, 103 } 104 105 def write_config(self): 106 try: 107 with open(self.config_file_path, "wb") as config_file: 108 config_file.write(json.dumps(self.config).encode("utf-8")) 109 except OSError as e: 110 err_str = "Error writing to Talos Mozharness config file {0}:{1}" 111 print(err_str.format(self.config_file_path, str(e))) 112 raise e 113 114 def run_mozharness(self): 115 sys.path.insert(0, self.mozharness_dir) 116 from mozharness.mozilla.testing.talos import Talos 117 118 talos_mh = Talos( 119 config=self.args["config"], 120 initial_config_file=self.args["initial_config_file"], 121 ) 122 return talos_mh.run() 123 124 125 def create_parser(): 126 sys.path.insert(0, HERE) # allow to import the talos package 127 from talos.cmdline import create_parser 128 129 return create_parser(mach_interface=True) 130 131 132 def setup_toolchain_artifacts(args, command_context): 133 if not any(arg.lower() == "pdfpaint" for arg in args): 134 return 135 136 from mozbuild.bootstrap import bootstrap_toolchain 137 138 print("Setting up pdfpaint PDFs...") 139 bootstrap_toolchain("talos-pdfs") 140 141 142 @Command( 143 "talos-test", 144 category="testing", 145 description="Run talos tests (performance testing).", 146 parser=create_parser, 147 ) 148 def run_talos_test(command_context, **kwargs): 149 talos = command_context._spawn(TalosRunner) 150 151 try: 152 args = sys.argv[2:] 153 setup_toolchain_artifacts(args, command_context) 154 return talos.run_test(args) 155 except Exception as e: 156 print(str(e)) 157 return 1 158 159 160 class PythonVersionException(Exception): 161 pass