1*8975f5c5SAndroid Build Coastguard Worker#!/usr/bin/python3 2*8975f5c5SAndroid Build Coastguard Worker# 3*8975f5c5SAndroid Build Coastguard Worker# Copyright 2019 The ANGLE Project Authors. All rights reserved. 4*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 5*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file. 6*8975f5c5SAndroid Build Coastguard Worker# 7*8975f5c5SAndroid Build Coastguard Worker# trigger.py: 8*8975f5c5SAndroid Build Coastguard Worker# Helper script for triggering GPU tests on LUCI swarming. 9*8975f5c5SAndroid Build Coastguard Worker# 10*8975f5c5SAndroid Build Coastguard Worker# HOW TO USE THIS SCRIPT 11*8975f5c5SAndroid Build Coastguard Worker# 12*8975f5c5SAndroid Build Coastguard Worker# Prerequisites: 13*8975f5c5SAndroid Build Coastguard Worker# - Your host OS must be able to build the targets. Linux can cross-compile Android and Windows. 14*8975f5c5SAndroid Build Coastguard Worker# - You might need to be logged in to some services. Look in the error output to verify. 15*8975f5c5SAndroid Build Coastguard Worker# 16*8975f5c5SAndroid Build Coastguard Worker# Steps: 17*8975f5c5SAndroid Build Coastguard Worker# 1. Visit https://ci.chromium.org/p/angle/g/ci/console and find a builder with a similar OS and configuration. 18*8975f5c5SAndroid Build Coastguard Worker# Replicating GN args exactly is not necessary. For example, linux-test: 19*8975f5c5SAndroid Build Coastguard Worker# https://ci.chromium.org/p/angle/builders/ci/linux-test 20*8975f5c5SAndroid Build Coastguard Worker# 2. Find a recent green build from the builder, for example: 21*8975f5c5SAndroid Build Coastguard Worker# https://ci.chromium.org/ui/p/angle/builders/ci/linux-test/2443/overview 22*8975f5c5SAndroid Build Coastguard Worker# 3. Find a test step shard that matches your test and intended target. For example, angle_unittests on Intel: 23*8975f5c5SAndroid Build Coastguard Worker# https://chromium-swarm.appspot.com/task?id=5d6eecdda8e82210 24*8975f5c5SAndroid Build Coastguard Worker# 4. Now run this script without arguments to print the help message. For example: 25*8975f5c5SAndroid Build Coastguard Worker# usage: trigger.py [-h] [-s SHARDS] [-p POOL] [-g GPU] [-t DEVICE_TYPE] [-o DEVICE_OS] [-l LOG] [--gold] 26*8975f5c5SAndroid Build Coastguard Worker# [--priority PRIORITY] [-e ENV] gn_path test os_dim 27*8975f5c5SAndroid Build Coastguard Worker# 5. Next, find values for "GPU" on a desktop platform, and "DEVICE_TYPE" and "DEVICE_OS" on Android. You'll 28*8975f5c5SAndroid Build Coastguard Worker# also need to find a value for "os_dim". For the above example: 29*8975f5c5SAndroid Build Coastguard Worker# "os_dim" -> Ubuntu-18.04.6, "GPU" -> 8086:9bc5-20.0.8. 30*8975f5c5SAndroid Build Coastguard Worker# 6. For "gn_path" and "test", use your local GN out directory path and triggered test name. The test name must 31*8975f5c5SAndroid Build Coastguard Worker# match an entry in infra/specs/gn_isolate_map.pyl. For example: 32*8975f5c5SAndroid Build Coastguard Worker# trigger.py -g 8086:9bc5-20.0.8 out/Debug angle_unittests Ubuntu-18.04.6 33*8975f5c5SAndroid Build Coastguard Worker# 7. Finally, append the same arguments you'd run with locally when invoking this trigger script, e.g: 34*8975f5c5SAndroid Build Coastguard Worker# --gtest_filter=*YourTest* 35*8975f5c5SAndroid Build Coastguard Worker# --use-angle=backend 36*8975f5c5SAndroid Build Coastguard Worker# 8. Note that you can look up test artifacts in the test CAS outputs. For example: 37*8975f5c5SAndroid Build Coastguard Worker# https://cas-viewer.appspot.com/projects/chromium-swarm/instances/default_instance/blobs/6165a0ede67ef2530f595ed9a1202671a571da952b6c887f516641993c9a96d4/87/tree 38*8975f5c5SAndroid Build Coastguard Worker# 39*8975f5c5SAndroid Build Coastguard Worker# Additional Notes: 40*8975f5c5SAndroid Build Coastguard Worker# - Use --priority 1 to ensure your task is scheduled immediately, just be mindful of resources. 41*8975f5c5SAndroid Build Coastguard Worker# - For Skia Gold tests specifically, append --gold. Otherwise ignore this argument. 42*8975f5c5SAndroid Build Coastguard Worker# - You can also specify environment variables with --env. 43*8975f5c5SAndroid Build Coastguard Worker# - For SwiftShader, use a GPU dimension of "none". 44*8975f5c5SAndroid Build Coastguard Worker 45*8975f5c5SAndroid Build Coastguard Workerimport argparse 46*8975f5c5SAndroid Build Coastguard Workerimport json 47*8975f5c5SAndroid Build Coastguard Workerimport hashlib 48*8975f5c5SAndroid Build Coastguard Workerimport logging 49*8975f5c5SAndroid Build Coastguard Workerimport os 50*8975f5c5SAndroid Build Coastguard Workerimport re 51*8975f5c5SAndroid Build Coastguard Workerimport subprocess 52*8975f5c5SAndroid Build Coastguard Workerimport sys 53*8975f5c5SAndroid Build Coastguard Worker 54*8975f5c5SAndroid Build Coastguard Worker# This is the same as the trybots. 55*8975f5c5SAndroid Build Coastguard WorkerDEFAULT_TASK_PRIORITY = 30 56*8975f5c5SAndroid Build Coastguard WorkerDEFAULT_POOL = 'chromium.tests.gpu' 57*8975f5c5SAndroid Build Coastguard WorkerDEFAULT_LOG_LEVEL = 'info' 58*8975f5c5SAndroid Build Coastguard WorkerDEFAULT_REALM = 'chromium:try' 59*8975f5c5SAndroid Build Coastguard WorkerGOLD_SERVICE_ACCOUNT = '[email protected]' 60*8975f5c5SAndroid Build Coastguard WorkerEXIT_SUCCESS = 0 61*8975f5c5SAndroid Build Coastguard WorkerEXIT_FAILURE = 1 62*8975f5c5SAndroid Build Coastguard Worker 63*8975f5c5SAndroid Build Coastguard Worker 64*8975f5c5SAndroid Build Coastguard Workerdef parse_args(): 65*8975f5c5SAndroid Build Coastguard Worker parser = argparse.ArgumentParser(os.path.basename(sys.argv[0])) 66*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('gn_path', help='path to GN. (e.g. out/Release)') 67*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('test', help='test name. (e.g. angle_end2end_tests)') 68*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('os_dim', help='OS dimension. (e.g. Windows-10)') 69*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('-s', '--shards', default=1, help='number of shards', type=int) 70*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 71*8975f5c5SAndroid Build Coastguard Worker '-p', '--pool', default=DEFAULT_POOL, help='swarming pool, default is %s.' % DEFAULT_POOL) 72*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('-g', '--gpu', help='GPU dimension. (e.g. intel-hd-630-win10-stable)') 73*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('-t', '--device-type', help='Android device type (e.g. bullhead)') 74*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('-o', '--device-os', help='Android OS.') 75*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 76*8975f5c5SAndroid Build Coastguard Worker '-l', 77*8975f5c5SAndroid Build Coastguard Worker '--log', 78*8975f5c5SAndroid Build Coastguard Worker default=DEFAULT_LOG_LEVEL, 79*8975f5c5SAndroid Build Coastguard Worker help='Log level. Default is %s.' % DEFAULT_LOG_LEVEL) 80*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 81*8975f5c5SAndroid Build Coastguard Worker '--gold', action='store_true', help='Use swarming arguments for Gold tests.') 82*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 83*8975f5c5SAndroid Build Coastguard Worker '--priority', 84*8975f5c5SAndroid Build Coastguard Worker help='Task priority. Default is %s. Use judiciously.' % DEFAULT_TASK_PRIORITY, 85*8975f5c5SAndroid Build Coastguard Worker default=DEFAULT_TASK_PRIORITY) 86*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 87*8975f5c5SAndroid Build Coastguard Worker '-e', 88*8975f5c5SAndroid Build Coastguard Worker '--env', 89*8975f5c5SAndroid Build Coastguard Worker action='append', 90*8975f5c5SAndroid Build Coastguard Worker default=[], 91*8975f5c5SAndroid Build Coastguard Worker help='Environment variables. Can be specified multiple times.') 92*8975f5c5SAndroid Build Coastguard Worker 93*8975f5c5SAndroid Build Coastguard Worker return parser.parse_known_args() 94*8975f5c5SAndroid Build Coastguard Worker 95*8975f5c5SAndroid Build Coastguard Worker 96*8975f5c5SAndroid Build Coastguard Workerdef invoke_mb(args, stdout=None): 97*8975f5c5SAndroid Build Coastguard Worker mb_script_path = os.path.join('tools', 'mb', 'mb.py') 98*8975f5c5SAndroid Build Coastguard Worker mb_args = [sys.executable, mb_script_path] + args 99*8975f5c5SAndroid Build Coastguard Worker 100*8975f5c5SAndroid Build Coastguard Worker # Attempt to detect standalone vs chromium component build. 101*8975f5c5SAndroid Build Coastguard Worker is_standalone = not os.path.isdir(os.path.join('third_party', 'angle')) 102*8975f5c5SAndroid Build Coastguard Worker 103*8975f5c5SAndroid Build Coastguard Worker if is_standalone: 104*8975f5c5SAndroid Build Coastguard Worker logging.info('Standalone mode detected.') 105*8975f5c5SAndroid Build Coastguard Worker mb_args += ['-i', os.path.join('infra', 'specs', 'gn_isolate_map.pyl')] 106*8975f5c5SAndroid Build Coastguard Worker 107*8975f5c5SAndroid Build Coastguard Worker logging.info('Invoking mb: %s' % ' '.join(mb_args)) 108*8975f5c5SAndroid Build Coastguard Worker proc = subprocess.run(mb_args, stdout=stdout) 109*8975f5c5SAndroid Build Coastguard Worker if proc.returncode != EXIT_SUCCESS: 110*8975f5c5SAndroid Build Coastguard Worker print('Aborting run because mb retured a failure.') 111*8975f5c5SAndroid Build Coastguard Worker sys.exit(EXIT_FAILURE) 112*8975f5c5SAndroid Build Coastguard Worker if stdout != None: 113*8975f5c5SAndroid Build Coastguard Worker return proc.stdout.decode() 114*8975f5c5SAndroid Build Coastguard Worker 115*8975f5c5SAndroid Build Coastguard Worker 116*8975f5c5SAndroid Build Coastguard Workerdef main(): 117*8975f5c5SAndroid Build Coastguard Worker args, unknown = parse_args() 118*8975f5c5SAndroid Build Coastguard Worker 119*8975f5c5SAndroid Build Coastguard Worker logging.basicConfig(level=args.log.upper()) 120*8975f5c5SAndroid Build Coastguard Worker 121*8975f5c5SAndroid Build Coastguard Worker path = args.gn_path.replace('\\', '/') 122*8975f5c5SAndroid Build Coastguard Worker out_gn_path = '//' + path 123*8975f5c5SAndroid Build Coastguard Worker out_file_path = os.path.join(*path.split('/')) 124*8975f5c5SAndroid Build Coastguard Worker 125*8975f5c5SAndroid Build Coastguard Worker get_command_output = invoke_mb(['get-swarming-command', out_gn_path, args.test, '--as-list'], 126*8975f5c5SAndroid Build Coastguard Worker stdout=subprocess.PIPE) 127*8975f5c5SAndroid Build Coastguard Worker swarming_cmd = json.loads(get_command_output) 128*8975f5c5SAndroid Build Coastguard Worker logging.info('Swarming command: %s' % ' '.join(swarming_cmd)) 129*8975f5c5SAndroid Build Coastguard Worker 130*8975f5c5SAndroid Build Coastguard Worker invoke_mb(['isolate', out_gn_path, args.test]) 131*8975f5c5SAndroid Build Coastguard Worker 132*8975f5c5SAndroid Build Coastguard Worker isolate_cmd_path = os.path.join('tools', 'luci-go', 'isolate') 133*8975f5c5SAndroid Build Coastguard Worker isolate_file = os.path.join(out_file_path, '%s.isolate' % args.test) 134*8975f5c5SAndroid Build Coastguard Worker archive_file = os.path.join(out_file_path, '%s.archive.json' % args.test) 135*8975f5c5SAndroid Build Coastguard Worker 136*8975f5c5SAndroid Build Coastguard Worker isolate_args = [ 137*8975f5c5SAndroid Build Coastguard Worker isolate_cmd_path, 'archive', '-i', isolate_file, '-cas-instance', 'chromium-swarm', 138*8975f5c5SAndroid Build Coastguard Worker '-dump-json', archive_file 139*8975f5c5SAndroid Build Coastguard Worker ] 140*8975f5c5SAndroid Build Coastguard Worker logging.info('Invoking isolate: %s' % ' '.join(isolate_args)) 141*8975f5c5SAndroid Build Coastguard Worker subprocess.check_call(isolate_args) 142*8975f5c5SAndroid Build Coastguard Worker with open(archive_file) as f: 143*8975f5c5SAndroid Build Coastguard Worker digest = json.load(f).get(args.test) 144*8975f5c5SAndroid Build Coastguard Worker 145*8975f5c5SAndroid Build Coastguard Worker logging.info('Got an CAS digest %s' % digest) 146*8975f5c5SAndroid Build Coastguard Worker swarming_script_path = os.path.join('tools', 'luci-go', 'swarming') 147*8975f5c5SAndroid Build Coastguard Worker 148*8975f5c5SAndroid Build Coastguard Worker swarming_args = [ 149*8975f5c5SAndroid Build Coastguard Worker swarming_script_path, 'trigger', '-S', 'chromium-swarm.appspot.com', '-d', 150*8975f5c5SAndroid Build Coastguard Worker 'os=' + args.os_dim, '-d', 'pool=' + args.pool, '-digest', digest 151*8975f5c5SAndroid Build Coastguard Worker ] 152*8975f5c5SAndroid Build Coastguard Worker 153*8975f5c5SAndroid Build Coastguard Worker # Set priority. Don't abuse this! 154*8975f5c5SAndroid Build Coastguard Worker swarming_args += ['-priority', str(args.priority), '-realm', DEFAULT_REALM] 155*8975f5c5SAndroid Build Coastguard Worker 156*8975f5c5SAndroid Build Coastguard Worker # Define a user tag. 157*8975f5c5SAndroid Build Coastguard Worker try: 158*8975f5c5SAndroid Build Coastguard Worker whoami = subprocess.check_output(['whoami']) 159*8975f5c5SAndroid Build Coastguard Worker # Strip extra stuff (e.g. on Windows we are 'hostname\username') 160*8975f5c5SAndroid Build Coastguard Worker whoami = re.sub(r'\w+[^\w]', '', whoami.strip()) 161*8975f5c5SAndroid Build Coastguard Worker swarming_args += ['-user', whoami] 162*8975f5c5SAndroid Build Coastguard Worker except: 163*8975f5c5SAndroid Build Coastguard Worker pass 164*8975f5c5SAndroid Build Coastguard Worker 165*8975f5c5SAndroid Build Coastguard Worker if args.gpu: 166*8975f5c5SAndroid Build Coastguard Worker swarming_args += ['-d', 'gpu=' + args.gpu] 167*8975f5c5SAndroid Build Coastguard Worker 168*8975f5c5SAndroid Build Coastguard Worker if args.device_type: 169*8975f5c5SAndroid Build Coastguard Worker swarming_args += ['-d', 'device_type=' + args.device_type] 170*8975f5c5SAndroid Build Coastguard Worker 171*8975f5c5SAndroid Build Coastguard Worker if args.device_os: 172*8975f5c5SAndroid Build Coastguard Worker swarming_args += ['-d', 'device_os=' + args.device_os] 173*8975f5c5SAndroid Build Coastguard Worker 174*8975f5c5SAndroid Build Coastguard Worker cmd_args = ['-relative-cwd', args.gn_path, '--'] 175*8975f5c5SAndroid Build Coastguard Worker 176*8975f5c5SAndroid Build Coastguard Worker if args.gold: 177*8975f5c5SAndroid Build Coastguard Worker swarming_args += ['-service-account', GOLD_SERVICE_ACCOUNT] 178*8975f5c5SAndroid Build Coastguard Worker cmd_args += ['luci-auth', 'context', '--'] 179*8975f5c5SAndroid Build Coastguard Worker 180*8975f5c5SAndroid Build Coastguard Worker for env in args.env: 181*8975f5c5SAndroid Build Coastguard Worker swarming_args += ['-env', env] 182*8975f5c5SAndroid Build Coastguard Worker 183*8975f5c5SAndroid Build Coastguard Worker cmd_args += swarming_cmd 184*8975f5c5SAndroid Build Coastguard Worker 185*8975f5c5SAndroid Build Coastguard Worker if unknown: 186*8975f5c5SAndroid Build Coastguard Worker cmd_args += unknown 187*8975f5c5SAndroid Build Coastguard Worker 188*8975f5c5SAndroid Build Coastguard Worker if args.shards > 1: 189*8975f5c5SAndroid Build Coastguard Worker for i in range(args.shards): 190*8975f5c5SAndroid Build Coastguard Worker shard_args = swarming_args[:] 191*8975f5c5SAndroid Build Coastguard Worker shard_args.extend([ 192*8975f5c5SAndroid Build Coastguard Worker '--env', 193*8975f5c5SAndroid Build Coastguard Worker 'GTEST_TOTAL_SHARDS=%d' % args.shards, 194*8975f5c5SAndroid Build Coastguard Worker '--env', 195*8975f5c5SAndroid Build Coastguard Worker 'GTEST_SHARD_INDEX=%d' % i, 196*8975f5c5SAndroid Build Coastguard Worker ]) 197*8975f5c5SAndroid Build Coastguard Worker 198*8975f5c5SAndroid Build Coastguard Worker shard_args += cmd_args 199*8975f5c5SAndroid Build Coastguard Worker 200*8975f5c5SAndroid Build Coastguard Worker logging.info('Invoking swarming: %s' % ' '.join(shard_args)) 201*8975f5c5SAndroid Build Coastguard Worker subprocess.call(shard_args) 202*8975f5c5SAndroid Build Coastguard Worker else: 203*8975f5c5SAndroid Build Coastguard Worker swarming_args += cmd_args 204*8975f5c5SAndroid Build Coastguard Worker logging.info('Invoking swarming: %s' % ' '.join(swarming_args)) 205*8975f5c5SAndroid Build Coastguard Worker subprocess.call(swarming_args) 206*8975f5c5SAndroid Build Coastguard Worker return EXIT_SUCCESS 207*8975f5c5SAndroid Build Coastguard Worker 208*8975f5c5SAndroid Build Coastguard Worker 209*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__': 210*8975f5c5SAndroid Build Coastguard Worker sys.exit(main()) 211