1#!/usr/bin/env python 2 3# Copyright 2017 Google Inc. 4# 5# Use of this source code is governed by a BSD-style license that can be 6# found in the LICENSE file. 7 8 9"""Submit one or more try jobs.""" 10 11 12import argparse 13import json 14import os 15import re 16import subprocess 17import sys 18import tempfile 19 20 21BUCKET_SKIA_PRIMARY = 'skia.primary' 22BUCKET_SKIA_INTERNAL = 'skia.internal' 23CHECKOUT_ROOT = os.path.realpath(os.path.join( 24 os.path.dirname(os.path.abspath(__file__)), os.pardir)) 25INFRA_BOTS = os.path.join(CHECKOUT_ROOT, 'infra', 'bots') 26JOBS_JSON = os.path.join(INFRA_BOTS, 'jobs.json') 27REPO_INTERNAL = 'https://skia.googlesource.com/internal_test.git' 28TMP_DIR = os.path.join(tempfile.gettempdir(), 'sktry') 29 30sys.path.insert(0, INFRA_BOTS) 31 32import update_meta_config 33import utils 34 35 36def get_jobs(repo): 37 """Obtain the list of jobs from the given repo.""" 38 # Maintain a copy of the repo in the temp dir. 39 if not os.path.isdir(TMP_DIR): 40 os.mkdir(TMP_DIR) 41 with utils.chdir(TMP_DIR): 42 dirname = repo.split('/')[-1] 43 if not os.path.isdir(dirname): 44 subprocess.check_call([ 45 utils.GIT, 'clone', '--mirror', repo, dirname]) 46 with utils.chdir(dirname): 47 subprocess.check_call([utils.GIT, 'remote', 'update']) 48 jobs = json.loads(subprocess.check_output([ 49 utils.GIT, 'show', 'master:infra/bots/jobs.json'])) 50 return (BUCKET_SKIA_INTERNAL, jobs) 51 52 53def main(): 54 # Parse arguments. 55 d = 'Helper script for triggering try jobs defined in %s.' % JOBS_JSON 56 parser = argparse.ArgumentParser(description=d) 57 parser.add_argument('--list', action='store_true', default=False, 58 help='Just list the jobs; do not trigger anything.') 59 parser.add_argument('--internal', action='store_true', default=False, 60 help=('If set, include internal jobs. You must have ' 61 'permission to view internal repos.')) 62 parser.add_argument('job', nargs='?', default=None, 63 help='Job name or regular expression to match job names.') 64 args = parser.parse_args() 65 66 # Load and filter the list of jobs. 67 jobs = [] 68 with open(JOBS_JSON) as f: 69 jobs.append((BUCKET_SKIA_PRIMARY, json.load(f))) 70 if args.internal: 71 jobs.append(get_jobs(REPO_INTERNAL)) 72 jobs.extend(update_meta_config.CQ_INCLUDE_CHROMIUM_TRYBOTS) 73 if args.job: 74 filtered_jobs = [] 75 for bucket, job_list in jobs: 76 filtered = [j for j in job_list if re.search(args.job, j)] 77 if len(filtered) > 0: 78 filtered_jobs.append((bucket, filtered)) 79 jobs = filtered_jobs 80 81 # Display the list of jobs. 82 if len(jobs) == 0: 83 print 'Found no jobs matching "%s"' % repr(args.job) 84 sys.exit(1) 85 count = 0 86 for bucket, job_list in jobs: 87 count += len(job_list) 88 print 'Found %d jobs:' % count 89 for bucket, job_list in jobs: 90 print ' %s:' % bucket 91 for j in job_list: 92 print ' %s' % j 93 if args.list: 94 return 95 96 if count > 1: 97 # Prompt before triggering jobs. 98 resp = raw_input('\nDo you want to trigger these jobs? (y/n or i for ' 99 'interactive): ') 100 print '' 101 if resp != 'y' and resp != 'i': 102 sys.exit(1) 103 if resp == 'i': 104 filtered_jobs = [] 105 for bucket, job_list in jobs: 106 new_job_list = [] 107 for j in job_list: 108 incl = raw_input(('Trigger %s? (y/n): ' % j)) 109 if incl == 'y': 110 new_job_list.append(j) 111 if len(new_job_list) > 0: 112 filtered_jobs.append((bucket, new_job_list)) 113 jobs = filtered_jobs 114 115 # Trigger the try jobs. 116 for bucket, job_list in jobs: 117 cmd = ['git', 'cl', 'try', '-B', bucket] 118 for j in job_list: 119 cmd.extend(['-b', j]) 120 try: 121 subprocess.check_call(cmd) 122 except subprocess.CalledProcessError: 123 # Output from the command will fall through, so just exit here rather than 124 # printing a stack trace. 125 sys.exit(1) 126 127 128if __name__ == '__main__': 129 main() 130