michael@0: # This Source Code Form is subject to the terms of the Mozilla Public michael@0: # License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: # file, You can obtain one at http://mozilla.org/MPL/2.0/. michael@0: michael@0: # Integrates Talos mozharness with mach michael@0: michael@0: from __future__ import print_function, unicode_literals michael@0: michael@0: import os michael@0: import sys michael@0: import json michael@0: import which michael@0: import socket michael@0: michael@0: from mozbuild.base import ( michael@0: MozbuildObject, michael@0: MachCommandBase michael@0: ) michael@0: michael@0: from mach.decorators import ( michael@0: CommandArgument, michael@0: CommandProvider, michael@0: Command, michael@0: ) michael@0: michael@0: class TalosRunner(MozbuildObject): michael@0: def run_test(self, suite, repo, rev): michael@0: """ michael@0: We want to do couple of things before running Talos michael@0: 1. Clone mozharness michael@0: 2. Make config for Talos Mozharness michael@0: 3. Run mozharness michael@0: """ michael@0: michael@0: print("Running Talos test suite %s" % suite) michael@0: self.init_variables(suite, repo, rev) michael@0: self.clone_mozharness() michael@0: self.make_config() michael@0: self.write_config() michael@0: self.make_args() michael@0: return self.run_mozharness() michael@0: michael@0: def init_variables(self, suite, repo, rev): michael@0: self.suite = suite michael@0: self.mozharness_repo = repo michael@0: self.mozharness_rev = rev michael@0: michael@0: self.talos_dir = os.path.join(self.topsrcdir, 'testing', 'talos') michael@0: self.mozharness_dir = os.path.join(self.topobjdir, 'mozharness') michael@0: self.config_dir = os.path.join(self.mozharness_dir, 'configs', 'talos') michael@0: self.talos_json = os.path.join(self.talos_dir, 'talos.json') michael@0: self.config_filename = 'in_tree_conf.json' michael@0: self.config_file_path = os.path.join(self.config_dir, michael@0: self.config_filename) michael@0: self.binary_path = self.get_binary_path() michael@0: self.virtualenv_script = os.path.join(self.topsrcdir, 'python', michael@0: 'virtualenv', 'virtualenv.py') michael@0: self.virtualenv_path = os.path.join(self.mozharness_dir, 'venv') michael@0: self.python_interp = sys.executable michael@0: michael@0: def clone_mozharness(self): michael@0: """Clones mozharness into topobjdir/mozharness michael@0: using mercurial. If mozharness is already cloned, michael@0: it updates it to the latest version""" michael@0: try: michael@0: mercurial = which.which('hg') michael@0: except which.WhichError as e: michael@0: print("You don't have hg in your PATH: {0}".format(e)) michael@0: raise e michael@0: clone_cmd = [mercurial, 'clone', '-r', self.mozharness_rev, michael@0: self.mozharness_repo, self.mozharness_dir] michael@0: pull_cmd = [mercurial, 'pull', '-r', self.mozharness_rev, '-u'] michael@0: michael@0: dot_hg = os.path.join(self.mozharness_dir, '.hg') michael@0: if os.path.exists(dot_hg): michael@0: self.run_process(args=pull_cmd, cwd=self.mozharness_dir) michael@0: else: michael@0: self.run_process(args=clone_cmd) michael@0: michael@0: def make_config(self): michael@0: self.config = { michael@0: 'talos_json': self.talos_json, michael@0: 'binary_path': self.binary_path, michael@0: 'log_name': 'talos', michael@0: 'virtualenv_path': self.virtualenv_path, michael@0: 'pypi_url': 'http://pypi.python.org/simple', michael@0: 'use_talos_json': True, michael@0: 'base_work_dir': self.mozharness_dir, michael@0: 'exes': { michael@0: 'python': self.python_interp, michael@0: 'virtualenv': [self.python_interp, self.virtualenv_script] michael@0: }, michael@0: 'title': socket.gethostname(), michael@0: 'default_actions': [ michael@0: 'clone-talos', michael@0: 'create-virtualenv', michael@0: 'run-tests', michael@0: ], michael@0: 'python_webserver': True michael@0: } michael@0: michael@0: def make_args(self): michael@0: self.args = { michael@0: 'config': { michael@0: 'suite': self.suite, michael@0: 'use_talos_json': True michael@0: }, michael@0: 'initial_config_file': self.config_file_path, michael@0: } michael@0: michael@0: def write_config(self): michael@0: try: michael@0: config_file = open(self.config_file_path, 'wb') michael@0: config_file.write(json.dumps(self.config)) michael@0: except IOError as e: michael@0: err_str = "Error writing to Talos Mozharness config file {0}:{1}" michael@0: print(err_str.format(self.config_file_path, str(e))) michael@0: raise e michael@0: michael@0: def run_mozharness(self): michael@0: sys.path.insert(0, self.mozharness_dir) michael@0: from mozharness.mozilla.testing.talos import Talos michael@0: talos_mh = Talos(config=self.args['config'], michael@0: initial_config_file=self.args['initial_config_file']) michael@0: return talos_mh.run() michael@0: michael@0: @CommandProvider michael@0: class MachCommands(MachCommandBase): michael@0: mozharness_repo = 'https://hg.mozilla.org/build/mozharness' michael@0: mozharness_rev = 'production' michael@0: michael@0: @Command('talos-test', category='testing', michael@0: description='Run talos tests.') michael@0: @CommandArgument('suite', help='Talos test suite to run. Valid suites are ' michael@0: 'chromez, dirtypaint, dromaeojs, other,' michael@0: 'svgr, rafx, tpn, tp5o, xperf.') michael@0: @CommandArgument('--repo', default=mozharness_repo, michael@0: help='The mozharness repository to clone from. ' michael@0: 'Defaults to http://hg.mozilla.org/build/mozharness') michael@0: @CommandArgument('--rev', default=mozharness_rev, michael@0: help='The mozharness revision to clone. Defaults to ' michael@0: 'production') michael@0: def run_talos_test(self, suite, repo=None, rev=None): michael@0: talos = self._spawn(TalosRunner) michael@0: michael@0: try: michael@0: return talos.run_test(suite, repo, rev) michael@0: except Exception as e: michael@0: print(str(e)) michael@0: return 1