Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(866)

Side by Side Diff: presubmit_support.py

Issue 178223016: Support multiple try masters when sending tries to rietveld. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Fix JSON serialization. Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Enables directory-specific presubmit checks to run at upload and/or commit. 6 """Enables directory-specific presubmit checks to run at upload and/or commit.
7 """ 7 """
8 8
9 __version__ = '1.8.0' 9 __version__ = '1.8.0'
10 10
(...skipping 989 matching lines...) Expand 10 before | Expand all | Expand 10 after
1000 results.append(p) 1000 results.append(p)
1001 1001
1002 logging.debug('Presubmit files: %s' % ','.join(results)) 1002 logging.debug('Presubmit files: %s' % ','.join(results))
1003 return results 1003 return results
1004 1004
1005 1005
1006 class GetTrySlavesExecuter(object): 1006 class GetTrySlavesExecuter(object):
1007 @staticmethod 1007 @staticmethod
1008 def ExecPresubmitScript(script_text, presubmit_path, project, change): 1008 def ExecPresubmitScript(script_text, presubmit_path, project, change):
1009 """Executes GetPreferredTrySlaves() from a single presubmit script. 1009 """Executes GetPreferredTrySlaves() from a single presubmit script.
1010
1011 This will soon be deprecated and replaced by GetPreferredTryMasters().
1010 1012
1011 Args: 1013 Args:
1012 script_text: The text of the presubmit script. 1014 script_text: The text of the presubmit script.
1013 presubmit_path: Project script to run. 1015 presubmit_path: Project script to run.
1014 project: Project name to pass to presubmit script for bot selection. 1016 project: Project name to pass to presubmit script for bot selection.
1015 1017
1016 Return: 1018 Return:
1017 A list of try slaves. 1019 A list of try slaves.
1018 """ 1020 """
1019 context = {} 1021 context = {}
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1067 ) 1069 )
1068 1070
1069 # Ensure it's either all old-style or all new-style. 1071 # Ensure it's either all old-style or all new-style.
1070 if not valid_oldstyle(result) and not valid_newstyle(result): 1072 if not valid_oldstyle(result) and not valid_newstyle(result):
1071 raise PresubmitFailure( 1073 raise PresubmitFailure(
1072 'PRESUBMIT.py returned invalid trybot specification!') 1074 'PRESUBMIT.py returned invalid trybot specification!')
1073 1075
1074 return result 1076 return result
1075 1077
1076 1078
1079 class GetTryMastersExecuter(object):
1080 @staticmethod
1081 def ExecPresubmitScript(script_text, presubmit_path, project, change):
1082 """Executes GetPreferredTryMasters() from a single presubmit script.
1083
1084 Args:
1085 script_text: The text of the presubmit script.
1086 presubmit_path: Project script to run.
1087 project: Project name to pass to presubmit script for bot selection.
1088
1089 Return:
1090 A map of try masters to (list of builders or map of builders to set of
1091 tests).
1092 """
1093 context = {}
1094 try:
1095 exec script_text in context
1096 except Exception, e:
1097 raise PresubmitFailure('"%s" had an exception.\n%s'
1098 % (presubmit_path, e))
1099
1100 function_name = 'GetPreferredTryMasters'
1101 if function_name not in context:
1102 return {}
1103 get_preferred_try_masters = context[function_name]
1104 function_info = inspect.getargspec(get_preferred_try_masters)
Paweł Hajdan Jr. 2014/02/27 02:20:24 Since this is new, can we standardize on one signa
Michael Achenbach 2014/02/27 18:35:23 Done.
1105 if len(function_info[0]) == 1:
1106 result = get_preferred_try_masters(project)
1107 elif len(function_info[0]) == 2:
1108 result = get_preferred_try_masters(project, change)
1109 else:
1110 result = get_preferred_try_masters()
1111
1112 def CheckType(item, t):
Paweł Hajdan Jr. 2014/02/27 02:20:24 It's not obvious to me how much these type checks
Michael Achenbach 2014/02/27 18:35:23 If presubmit hooks return the wrong formats, it'd
1113 if not isinstance(item, t):
1114 raise PresubmitFailure(
1115 'Expected a %s, got a %s instead: %s' %
1116 (str(t), type(item), str(item)))
1117
1118 def CheckString(item):
1119 if not item:
1120 raise PresubmitFailure(
1121 'PRESUBMIT.py returned empty trymaster/builder string.')
1122 CheckType(item, basestring)
1123 if item != item.strip():
1124 raise PresubmitFailure(
1125 'Try master/builder names cannot start/end with whitespace')
1126 if ',' in item:
1127 raise PresubmitFailure(
1128 'Do not use \',\' separated master, builder or test names: %s'
1129 % item)
1130
1131 CheckType(result, dict)
1132 for (master, builders) in result.iteritems():
1133 CheckString(master)
1134 if isinstance(builders, dict):
Paweł Hajdan Jr. 2014/02/27 02:20:24 Similarly, since this is new, can we standardize o
Michael Achenbach 2014/02/27 18:35:23 Done.
1135 for (builder, tests) in builders.iteritems():
1136 CheckString(builder)
1137 CheckType(tests, set)
1138 elif isinstance(builders, list):
1139 for builder in builders:
1140 CheckString(builder)
1141 else:
1142 raise PresubmitFailure(
1143 'Expected a list, got a %s instead: %s' %
1144 (type(builders), str(builders)))
1145 return result
1146
1147
1077 def DoGetTrySlaves(change, 1148 def DoGetTrySlaves(change,
1078 changed_files, 1149 changed_files,
1079 repository_root, 1150 repository_root,
1080 default_presubmit, 1151 default_presubmit,
1081 project, 1152 project,
1082 verbose, 1153 verbose,
1083 output_stream): 1154 output_stream):
1084 """Get the list of try servers from the presubmit scripts. 1155 """Get the list of try servers from the presubmit scripts (deprecated).
1085 1156
1086 Args: 1157 Args:
1087 changed_files: List of modified files. 1158 changed_files: List of modified files.
1088 repository_root: The repository root. 1159 repository_root: The repository root.
1089 default_presubmit: A default presubmit script to execute in any case. 1160 default_presubmit: A default presubmit script to execute in any case.
1090 project: Optional name of a project used in selecting trybots. 1161 project: Optional name of a project used in selecting trybots.
1091 verbose: Prints debug info. 1162 verbose: Prints debug info.
1092 output_stream: A stream to write debug output to. 1163 output_stream: A stream to write debug output to.
1093 1164
1094 Return: 1165 Return:
(...skipping 30 matching lines...) Expand all
1125 slaves = list(slave_dict.items()) 1196 slaves = list(slave_dict.items())
1126 1197
1127 slaves.extend(set(old_style)) 1198 slaves.extend(set(old_style))
1128 1199
1129 if slaves and verbose: 1200 if slaves and verbose:
1130 output_stream.write(', '.join((str(x) for x in slaves))) 1201 output_stream.write(', '.join((str(x) for x in slaves)))
1131 output_stream.write('\n') 1202 output_stream.write('\n')
1132 return slaves 1203 return slaves
1133 1204
1134 1205
1206 def _ExpandBuilders(builders):
1207 """Expands builders in list format to dict format."""
1208 if isinstance(builders, list):
Paweł Hajdan Jr. 2014/02/27 02:20:24 Why do we need to make a decision based on type he
Michael Achenbach 2014/02/27 18:35:23 This is removed now, since now only dicts are allo
1209 return dict((builder, set()) for builder in builders)
1210 else:
1211 return builders
1212
1213
1214 def _MergeMasters(results, masters):
1215 """Merges masters into results.
Paweł Hajdan Jr. 2014/02/27 02:20:24 It's not obvious to me what this does, could you c
Michael Achenbach 2014/02/27 18:35:23 I tried to simplify it and made it a function. The
1216
1217 Merges with side effects on the original results dict.
1218 """
1219 for (master, builders) in masters.iteritems():
1220 if master in results:
1221 result_builders = results[master]
1222 for (builder, tests) in _ExpandBuilders(builders).iteritems():
1223 if builder in result_builders:
1224 for test in tests:
1225 result_builders.add(test)
1226 else:
1227 result_builders[builder] = tests
1228 else:
1229 results[master] = _ExpandBuilders(builders)
1230 return results
1231
1232
1233 def DoGetTryMasters(change,
1234 changed_files,
1235 repository_root,
1236 default_presubmit,
1237 project,
1238 verbose,
1239 output_stream):
1240 """Get the list of try masters from the presubmit scripts.
1241
1242 Args:
1243 changed_files: List of modified files.
1244 repository_root: The repository root.
1245 default_presubmit: A default presubmit script to execute in any case.
1246 project: Optional name of a project used in selecting trybots.
1247 verbose: Prints debug info.
1248 output_stream: A stream to write debug output to.
1249
1250 Return:
1251 Map of try masters to map of builders to set of tests.
1252 """
1253 presubmit_files = ListRelevantPresubmitFiles(changed_files, repository_root)
1254 if not presubmit_files and verbose:
1255 output_stream.write("Warning, no presubmit.py found.\n")
1256 results = {}
1257 executer = GetTryMastersExecuter()
1258
1259 if default_presubmit:
1260 if verbose:
1261 output_stream.write("Running default presubmit script.\n")
1262 fake_path = os.path.join(repository_root, 'PRESUBMIT.py')
1263 results = _MergeMasters(results, executer.ExecPresubmitScript(
1264 default_presubmit, fake_path, project, change))
1265 for filename in presubmit_files:
1266 filename = os.path.abspath(filename)
1267 if verbose:
1268 output_stream.write("Running %s\n" % filename)
1269 # Accept CRLF presubmit script.
1270 presubmit_script = gclient_utils.FileRead(filename, 'rU')
1271 results = _MergeMasters(results, executer.ExecPresubmitScript(
1272 presubmit_script, filename, project, change))
1273
1274 # Make sets to lists again for later JSON serialization. Add
1275 # defaulttests where tests are missing.
1276 for (_, builders) in results.iteritems():
1277 for builder in builders:
1278 builders[builder] = list(builders[builder])
1279 if not builders[builder]:
1280 builders[builder].append('defaulttests')
1281
1282 if results and verbose:
1283 output_stream.write('%s\n' % str(results))
1284 return results
1285
1286
1135 class PresubmitExecuter(object): 1287 class PresubmitExecuter(object):
1136 def __init__(self, change, committing, rietveld_obj, verbose): 1288 def __init__(self, change, committing, rietveld_obj, verbose):
1137 """ 1289 """
1138 Args: 1290 Args:
1139 change: The Change object. 1291 change: The Change object.
1140 committing: True if 'gcl commit' is running, False if 'gcl upload' is. 1292 committing: True if 'gcl commit' is running, False if 'gcl upload' is.
1141 rietveld_obj: rietveld.Rietveld client object. 1293 rietveld_obj: rietveld.Rietveld client object.
1142 """ 1294 """
1143 self.change = change 1295 self.change = change
1144 self.committing = committing 1296 self.committing = committing
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after
1508 except PresubmitFailure, e: 1660 except PresubmitFailure, e:
1509 print >> sys.stderr, e 1661 print >> sys.stderr, e
1510 print >> sys.stderr, 'Maybe your depot_tools is out of date?' 1662 print >> sys.stderr, 'Maybe your depot_tools is out of date?'
1511 print >> sys.stderr, 'If all fails, contact maruel@' 1663 print >> sys.stderr, 'If all fails, contact maruel@'
1512 return 2 1664 return 2
1513 1665
1514 1666
1515 if __name__ == '__main__': 1667 if __name__ == '__main__':
1516 fix_encoding.fix_encoding() 1668 fix_encoding.fix_encoding()
1517 sys.exit(Main(None)) 1669 sys.exit(Main(None))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698