taskcluster-run.py (4745B)
1 #!/usr/bin/env python3 2 # mypy: allow-untyped-defs 3 4 import argparse 5 import gzip 6 import logging 7 import os 8 import shutil 9 import subprocess 10 import sys 11 12 13 def get_browser_args(product, channel, artifact_path): 14 if product == "firefox": 15 local_binary = os.path.expanduser(os.path.join("~", "build", "firefox", "firefox")) 16 if os.path.exists(local_binary): 17 return ["--binary=%s" % local_binary] 18 print("WARNING: Local firefox binary not found") 19 return ["--install-browser", "--install-webdriver"] 20 if product == "firefox_android": 21 return ["--install-browser", "--install-webdriver", "--logcat-dir", artifact_path] 22 if product == "servo": 23 return ["--install-browser", "--processes=12"] 24 if product == "chrome" or product == "chromium": 25 # Taskcluster machines do not have GPUs, so use software rendering via --enable-swiftshader. 26 return ["--enable-swiftshader", "--install-browser", "--install-webdriver"] 27 if product in ["webkitgtk_minibrowser", "wpewebkit_minibrowser"]: 28 # Using 4 parallel jobs gives 4x speed-up even on a 1-core machine and doesn't cause extra timeouts. 29 # See: https://github.com/web-platform-tests/wpt/issues/38723#issuecomment-1470938179 30 return ["--install-browser", "--processes=4"] 31 return [] 32 33 34 def find_wptreport(args): 35 parser = argparse.ArgumentParser() 36 parser.add_argument('--log-wptreport') 37 return parser.parse_known_args(args)[0].log_wptreport 38 39 40 def find_wptscreenshot(args): 41 parser = argparse.ArgumentParser() 42 parser.add_argument('--log-wptscreenshot') 43 return parser.parse_known_args(args)[0].log_wptscreenshot 44 45 46 def gzip_file(filename, delete_original=True): 47 with open(filename, 'rb') as f_in: 48 with gzip.open('%s.gz' % filename, 'wb') as f_out: 49 shutil.copyfileobj(f_in, f_out) 50 if delete_original: 51 os.unlink(filename) 52 53 54 def main(product, channel, commit_range, artifact_path, wpt_args): 55 """Invoke the `wpt run` command according to the needs of the Taskcluster 56 continuous integration service.""" 57 58 logger = logging.getLogger("tc-run") 59 logger.setLevel(logging.INFO) 60 handler = logging.StreamHandler() 61 handler.setFormatter( 62 logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") 63 ) 64 logger.addHandler(handler) 65 66 subprocess.call(['python3', './wpt', 'manifest-download']) 67 68 if commit_range: 69 logger.info( 70 "Running tests affected in range '%s'..." % commit_range 71 ) 72 wpt_args += ['--affected', commit_range] 73 else: 74 logger.info("Running all tests") 75 76 wpt_args += [ 77 "--log-mach-level=info", 78 "--log-mach=-", 79 "-y", 80 "--no-pause", 81 "--no-restart-on-unexpected", 82 "--install-fonts", 83 "--verify-log-full" 84 ] 85 # Enable headless mode for WPE MiniBrowser and Servo because they do not work under Xvfb/X11 (needs Wayland) 86 wpt_args.append("--headless" if product in ("wpewebkit_minibrowser", "servo") else "--no-headless") 87 88 wpt_args += get_browser_args(product, channel, artifact_path) 89 90 # Hack to run servo with one process only for wdspec 91 if product == "servo" and "--test-type=wdspec" in wpt_args: 92 wpt_args = [item for item in wpt_args if not item.startswith("--processes")] 93 94 wpt_args.append(product) 95 96 command = ["python3", "./wpt", "run"] + wpt_args 97 98 logger.info("Executing command: %s" % " ".join(command)) 99 with open(os.path.join(artifact_path, "checkrun.md"), "a") as f: 100 f.write("\n**WPT Command:** `%s`\n\n" % " ".join(command)) 101 102 retcode = subprocess.call(command, env=dict(os.environ, TERM="dumb")) 103 if retcode != 0: 104 sys.exit(retcode) 105 106 wptreport = find_wptreport(wpt_args) 107 if wptreport: 108 gzip_file(wptreport) 109 wptscreenshot = find_wptscreenshot(wpt_args) 110 if wptscreenshot: 111 gzip_file(wptscreenshot) 112 113 114 if __name__ == "__main__": 115 parser = argparse.ArgumentParser(description=main.__doc__) 116 parser.add_argument("--commit-range", 117 help="""Git commit range. If specified, this will be 118 supplied to the `wpt tests-affected` command to 119 determine the list of test to execute""") 120 parser.add_argument("--artifact-path", default="/home/test/artifacts/", 121 help="Path to store output files") 122 parser.add_argument("product", help="Browser to run tests in") 123 parser.add_argument("channel", help="Channel of the browser") 124 parser.add_argument("wpt_args", nargs="*", 125 help="Arguments to forward to `wpt run` command") 126 main(**vars(parser.parse_args())) # type: ignore