blob: d62c9fb5c6033dfdebbf4598f73f35c6c65eee39 [file] [log] [blame]
borenet@google.com6b5388e2013-01-23 20:54:29 +00001#!/usr/bin/python
2
3# Copyright (c) 2013 The Chromium Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7
8"""
9submit_try: Submit a try request.
10
11This is a thin wrapper around the try request utilities in depot_tools which
12adds some validation and supports both git and svn.
13"""
14
15
16import argparse
17import httplib
18import json
19import os
20import subprocess
21import sys
22
23
24# Alias which can be used to run a try on every builder.
25ALL_BUILDERS = 'all'
26
27# Contact information for the build master.
28# TODO(borenet): Share this information from a single location. Filed bug:
29# http://code.google.com/p/skia/issues/detail?id=1081
30SKIA_BUILD_MASTER_HOST = '70.32.156.51'
31SKIA_BUILD_MASTER_PORT = '10117'
32
33# All try builders have this suffix.
34TRYBOT_SUFFIX = '_Trybot'
35
36# Location of the codereview.settings file in the Skia repo.
37SKIA_URL = 'skia.googlecode.com'
38CODEREVIEW_SETTINGS = '/svn/codereview.settings'
39
40# String for matching the svn url of the try server inside codereview.settings.
41TRYSERVER_SVN_URL = 'TRYSERVER_SVN_URL: '
42
43# Strings used for matching svn config properties.
44URL_STR = 'URL: '
45REPO_ROOT_STR = 'Repository Root: '
46
47
48def FindDepotTools():
49 """ Find depot_tools on the local machine and return its location. """
50 which_cmd = 'where' if os.name == 'nt' else 'which'
51 cmd = [which_cmd, 'gcl']
52 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
53 if proc.wait() != 0:
54 raise Exception('Couldn\'t find depot_tools in PATH!')
55 gcl = proc.communicate()[0]
56 depot_tools_dir = os.path.dirname(gcl)
57 return depot_tools_dir
58
59
60def GetCheckoutRoot(is_svn=True):
61 """ Determine where the local checkout is rooted.
62
63 is_svn: boolean; whether we're in an SVN checkout. If False, assume we're in
64 a git checkout.
65 """
66 if is_svn:
67 cmd = ['svn', 'info']
68 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
69 stderr=subprocess.STDOUT)
70 if proc.wait() != 0:
71 raise Exception('Couldn\'t find checkout root!')
72 output = proc.communicate()[0].split('\n')
73 url = None
74 repo_root = None
75 for line in output:
76 if line.startswith(REPO_ROOT_STR):
77 repo_root = line[len(REPO_ROOT_STR):].rstrip()
78 elif line.startswith(URL_STR):
79 url = line[len(URL_STR):].rstrip()
80 if not url or not repo_root:
81 raise Exception('Couldn\'t find checkout root!')
82 if url == repo_root:
83 return 'svn'
84 return url[len(repo_root)+1:]
85 else:
86 cmd = ['git', 'rev-parse', '--show-toplevel']
87 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
88 stderr=subprocess.STDOUT)
89 if proc.wait() != 0:
90 raise Exception('Couldn\'t find checkout root!')
91 return os.path.basename(proc.communicate()[0])
92
93
94def GetTryRepo():
95 """ Determine the TRYSERVER_SVN_URL from the codereview.settings file in the
96 Skia repo. """
97 connection = httplib.HTTPConnection(SKIA_URL)
98 connection.request('GET', CODEREVIEW_SETTINGS)
99 content = connection.getresponse().read()
100 for line in content.split('\n'):
101 if line.startswith(TRYSERVER_SVN_URL):
102 return line[len(TRYSERVER_SVN_URL):].rstrip()
103 raise Exception('Couldn\'t determine the TRYSERVER_SVN_URL. Make sure it is '
104 'defined in the %s file.' % CODEREVIEW_SETTINGS)
105
106
107def RetrieveTrybotList():
108 """ Retrieve the list of known trybots from the build master, stripping
109 TRYBOT_SUFFIX from the name. """
110 trybots = []
111 connection = httplib.HTTPConnection(SKIA_BUILD_MASTER_HOST,
112 SKIA_BUILD_MASTER_PORT)
113 connection.request('GET', '/json/builders')
114 response = connection.getresponse()
115 builders = json.load(response)
116
117 for builder in builders:
118 if builder.endswith(TRYBOT_SUFFIX):
119 trybots.append(builder[:-len(TRYBOT_SUFFIX)])
120 return trybots
121
122
123def ValidateArgs(trybots, is_svn=True):
124 """ Parse and validate command-line arguments. If the arguments are valid,
125 returns a tuple of (<changelist name>, <list of trybots>).
126
127 trybots: A list of the known try builders.
128 """
129 if is_svn:
130 parser = argparse.ArgumentParser(
131 prog=os.path.basename(__file__),
132 description='%(prog)s: Submit a try request.',
133 usage=('%(prog)s [-h] <changelist> --bot <buildername> '
134 '[<buildername ...]'))
135 parser.add_argument('changelist', metavar='<changelist>',
136 help='Changelist to try.')
137 else:
138 parser = argparse.ArgumentParser(
139 prog=os.path.basename(__file__),
140 description='%(prog)s: Submit a try request.')
141
142 parser.add_argument('-r', '--revision', metavar='<revision#>', nargs=1,
143 type=int, help='Revision from which to try the change.')
144 parser.add_argument('--bot', metavar='<buildername>', nargs='+',
145 help='Builder(s) on which to try the change. One of: %s'
146 % ', '.join(trybots),
147 choices=trybots + [ALL_BUILDERS], required=True)
148 args = parser.parse_args()
149 if args.bot == [ALL_BUILDERS]:
150 args.bot = trybots
151 return args
152
153
154def SubmitTryRequest(args, is_svn=True):
155 """ Submits a try request for the given changelist on the given list of
156 trybots.
157
158 args: Object whose properties are derived from command-line arguments. If
159 is_svn is True, it should contain:
160 - changelist: string; the name of the changelist to try.
161 - bot: list of strings; the names of the try builders to run.
162 - revision: optional, int; the revision number from which to run the try.
163 If is_svn is False, it should contain:
164 - bot: list of strings; the names of the try builders to run.
165 - revision: optional, int; the revision number from which to run the try.
166 is_svn: boolean; are we in an SVN repo?
167 """
168 # First, find depot_tools. This is needed for the imports below.
169 sys.path.append(FindDepotTools())
170
171 botlist = ','.join(['%s%s' % (bot, TRYBOT_SUFFIX) for bot in args.bot])
172 if is_svn:
173 import gcl
174 try_args = [args.changelist, '--root', GetCheckoutRoot(is_svn),
175 '--bot', botlist]
176 if args.revision:
177 try_args.extend(['-r', args.revision])
178 gcl.CMDtry(try_args)
179 else:
180 import trychange
181 try_args = ['--use_svn',
182 '--svn_repo', GetTryRepo(),
183 '--root', GetCheckoutRoot(is_svn),
184 '--bot', botlist]
185 if args.revision:
186 try_args.extend(['-r', args.revision])
187 trychange.TryChange(try_args, None, False)
188
189
190def main():
191 # Retrieve the list of active try builders from the build master.
192 trybots = RetrieveTrybotList()
193
194 # Determine if we're in an SVN checkout.
195 is_svn = os.path.isdir('.svn')
196
197 # Parse and validate the command-line arguments.
198 args = ValidateArgs(trybots=trybots, is_svn=is_svn)
199
200 # Submit the try request.
201 SubmitTryRequest(args, is_svn=is_svn)
202
203
204if __name__ == '__main__':
205 sys.exit(main())