OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2015 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. |
| 5 |
| 6 |
| 7 """Tool to send a recipe job to run on Swarming.""" |
| 8 |
| 9 |
| 10 import argparse |
| 11 import base64 |
| 12 import json |
| 13 import os |
| 14 import re |
| 15 import subprocess |
| 16 import sys |
| 17 import zlib |
| 18 |
| 19 |
| 20 SWARMING_URL = 'https://chromium.googlesource.com/external/swarming.client.git' |
| 21 CLIENT_LOCATION = os.path.expanduser('~/.swarming_client') |
| 22 THIS_DIR = os.path.dirname(os.path.abspath(__file__)) |
| 23 ISOLATE = os.path.join(THIS_DIR, 'luci_recipe_run.isolate') |
| 24 |
| 25 # This is put in place in order to not need to parse this information from |
| 26 # master.cfg. In the LUCI future this would all be stored in a luci.cfg |
| 27 # file alongside the repo. |
| 28 RECIPE_MAPPING = { |
| 29 'Infra Linux Trusty 64 Tester': |
| 30 ('tryserver.infra', 'infra/infra_repo_trybot', 'Ubuntu-14.04'), |
| 31 'Infra Linux Precise 32 Tester': |
| 32 ('tryserver.infra', 'infra/infra_repo_trybot', 'Ubuntu-12.04'), |
| 33 'Infra Mac Tester': |
| 34 ('tryserver.infra', 'infra/infra_repo_trybot', 'Mac'), |
| 35 'Infra Win Tester': |
| 36 ('tryserver.infra', 'infra/infra_repo_trybot', 'Win'), |
| 37 'Infra Windows Tester': |
| 38 ('tryserver.infra', 'infra/infra_repo_trybot', 'Win'), |
| 39 'Infra Presubmit': |
| 40 ('tryserver.infra', 'run_presubmit', 'Linux') |
| 41 } |
| 42 |
| 43 |
| 44 def parse_args(args): |
| 45 # Once Clank switches to bot_update, bot_update would no longer require |
| 46 # master/builder detection, and we can remove the master/builder from the args |
| 47 parser = argparse.ArgumentParser() |
| 48 parser.add_argument('--builder', required=True) |
| 49 parser.add_argument('--issue',required=True) |
| 50 parser.add_argument('--patchset', required=True) |
| 51 parser.add_argument('--revision', default='HEAD') |
| 52 parser.add_argument('--patch_project') |
| 53 |
| 54 return parser.parse_args(args) |
| 55 |
| 56 |
| 57 def ensure_swarming_client(): |
| 58 if not os.path.exists(CLIENT_LOCATION): |
| 59 parent, target = os.path.split(CLIENT_LOCATION) |
| 60 subprocess.check_call(['git', 'clone', SWARMING_URL, target], cwd=parent) |
| 61 else: |
| 62 subprocess.check_call(['git', 'pull'], cwd=CLIENT_LOCATION) |
| 63 |
| 64 |
| 65 def archive_isolate(isolate): |
| 66 isolate_py = os.path.join(CLIENT_LOCATION, 'isolate.py') |
| 67 cmd = [ |
| 68 sys.executable, isolate_py, 'archive', |
| 69 '--isolated=%sd' % isolate, |
| 70 '--isolate-server', 'https://isolateserver.appspot.com', |
| 71 '--isolate=%s' % isolate] |
| 72 out = subprocess.check_output(cmd) |
| 73 return out.split()[0].strip() |
| 74 |
| 75 |
| 76 def trigger_swarm(isolated, platform, build_props, factory_props): |
| 77 # TODO: Make this trigger DM instead. |
| 78 swarm_py = os.path.join(CLIENT_LOCATION, 'swarming.py') |
| 79 build_props_gz = base64.b64encode(zlib.compress(json.dumps(build_props))) |
| 80 fac_props_gz = base64.b64encode(zlib.compress(json.dumps(factory_props))) |
| 81 cmd = [ |
| 82 sys.executable, swarm_py, 'trigger', isolated, |
| 83 '--isolate-server', 'isolateserver.appspot.com', |
| 84 '--swarming', 'chromium-swarm-dev.appspot.com', |
| 85 '-d', 'os', platform, |
| 86 '--', |
| 87 '--factory-properties-gz=%s' % fac_props_gz, |
| 88 '--build-properties-gz=%s' % build_props_gz |
| 89 ] |
| 90 out = subprocess.check_output(cmd) |
| 91 m = re.search( |
| 92 r'https://chromium-swarm-dev.appspot.com/user/task/(.*)', out) |
| 93 return m.group(1) |
| 94 |
| 95 |
| 96 def trigger(builder, revision, issue, patchset, project): |
| 97 """Constructs/uploads an isolated file and send the job to swarming.""" |
| 98 master, recipe, platform = RECIPE_MAPPING[builder] |
| 99 build_props = { |
| 100 'buildnumber': 1, |
| 101 'buildername': builder, |
| 102 'recipe': recipe, |
| 103 'mastername': master, |
| 104 'slavename': 'fakeslave', |
| 105 'revision': revision, |
| 106 'patch_project': project, |
| 107 } |
| 108 if issue: |
| 109 build_props['issue'] = issue |
| 110 if patchset: |
| 111 build_props['patchset'] = patchset |
| 112 factory_props = { |
| 113 'recipe': recipe |
| 114 } |
| 115 ensure_swarming_client() |
| 116 arun_isolated = archive_isolate(ISOLATE) |
| 117 task = trigger_swarm(arun_isolated, platform, build_props, factory_props) |
| 118 print 'https://luci-milo.appspot.com/swarming/%s' % task |
| 119 |
| 120 |
| 121 def main(args): |
| 122 args = parse_args(args) |
| 123 trigger(args.builder, args.revision, args.issue, |
| 124 args.patchset, args.patch_project) |
| 125 |
| 126 |
| 127 if __name__ == '__main__': |
| 128 sys.exit(main(sys.argv[1:])) |
OLD | NEW |