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

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: More review. 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
11 # TODO(joi) Add caching where appropriate/needed. The API is designed to allow 11 # TODO(joi) Add caching where appropriate/needed. The API is designed to allow
12 # caching (between all different invocations of presubmit scripts for a given 12 # caching (between all different invocations of presubmit scripts for a given
13 # change). We should add it as our presubmit scripts start feeling slow. 13 # change). We should add it as our presubmit scripts start feeling slow.
14 14
15 import cpplint 15 import cpplint
16 import cPickle # Exposed through the API. 16 import cPickle # Exposed through the API.
17 import cStringIO # Exposed through the API. 17 import cStringIO # Exposed through the API.
18 import contextlib 18 import contextlib
19 import fnmatch 19 import fnmatch
20 import glob 20 import glob
21 import inspect 21 import inspect
22 import itertools
22 import json # Exposed through the API. 23 import json # Exposed through the API.
23 import logging 24 import logging
24 import marshal # Exposed through the API. 25 import marshal # Exposed through the API.
25 import multiprocessing 26 import multiprocessing
26 import optparse 27 import optparse
27 import os # Somewhat exposed through the API. 28 import os # Somewhat exposed through the API.
28 import pickle # Exposed through the API. 29 import pickle # Exposed through the API.
29 import random 30 import random
30 import re # Exposed through the API. 31 import re # Exposed through the API.
31 import sys # Parts exposed through API. 32 import sys # Parts exposed through API.
(...skipping 968 matching lines...) Expand 10 before | Expand all | Expand 10 after
1000 results.append(p) 1001 results.append(p)
1001 1002
1002 logging.debug('Presubmit files: %s' % ','.join(results)) 1003 logging.debug('Presubmit files: %s' % ','.join(results))
1003 return results 1004 return results
1004 1005
1005 1006
1006 class GetTrySlavesExecuter(object): 1007 class GetTrySlavesExecuter(object):
1007 @staticmethod 1008 @staticmethod
1008 def ExecPresubmitScript(script_text, presubmit_path, project, change): 1009 def ExecPresubmitScript(script_text, presubmit_path, project, change):
1009 """Executes GetPreferredTrySlaves() from a single presubmit script. 1010 """Executes GetPreferredTrySlaves() from a single presubmit script.
1011
1012 This will soon be deprecated and replaced by GetPreferredTryMasters().
1010 1013
1011 Args: 1014 Args:
1012 script_text: The text of the presubmit script. 1015 script_text: The text of the presubmit script.
1013 presubmit_path: Project script to run. 1016 presubmit_path: Project script to run.
1014 project: Project name to pass to presubmit script for bot selection. 1017 project: Project name to pass to presubmit script for bot selection.
1015 1018
1016 Return: 1019 Return:
1017 A list of try slaves. 1020 A list of try slaves.
1018 """ 1021 """
1019 context = {} 1022 context = {}
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1067 ) 1070 )
1068 1071
1069 # Ensure it's either all old-style or all new-style. 1072 # Ensure it's either all old-style or all new-style.
1070 if not valid_oldstyle(result) and not valid_newstyle(result): 1073 if not valid_oldstyle(result) and not valid_newstyle(result):
1071 raise PresubmitFailure( 1074 raise PresubmitFailure(
1072 'PRESUBMIT.py returned invalid trybot specification!') 1075 'PRESUBMIT.py returned invalid trybot specification!')
1073 1076
1074 return result 1077 return result
1075 1078
1076 1079
1080 class GetTryMastersExecuter(object):
1081 @staticmethod
1082 def ExecPresubmitScript(script_text, presubmit_path, project, change):
1083 """Executes GetPreferredTryMasters() from a single presubmit script.
1084
1085 Args:
1086 script_text: The text of the presubmit script.
1087 presubmit_path: Project script to run.
1088 project: Project name to pass to presubmit script for bot selection.
1089
1090 Return:
1091 A map of try masters to map of builders to set of 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 if not len(inspect.getargspec(get_preferred_try_masters)[0]) == 2:
1105 raise PresubmitFailure(
1106 'Expected function "GetPreferredTryMasters" to take two arguments.')
1107 return get_preferred_try_masters(project, change)
1108
1109
1077 def DoGetTrySlaves(change, 1110 def DoGetTrySlaves(change,
1078 changed_files, 1111 changed_files,
1079 repository_root, 1112 repository_root,
1080 default_presubmit, 1113 default_presubmit,
1081 project, 1114 project,
1082 verbose, 1115 verbose,
1083 output_stream): 1116 output_stream):
1084 """Get the list of try servers from the presubmit scripts. 1117 """Get the list of try servers from the presubmit scripts (deprecated).
1085 1118
1086 Args: 1119 Args:
1087 changed_files: List of modified files. 1120 changed_files: List of modified files.
1088 repository_root: The repository root. 1121 repository_root: The repository root.
1089 default_presubmit: A default presubmit script to execute in any case. 1122 default_presubmit: A default presubmit script to execute in any case.
1090 project: Optional name of a project used in selecting trybots. 1123 project: Optional name of a project used in selecting trybots.
1091 verbose: Prints debug info. 1124 verbose: Prints debug info.
1092 output_stream: A stream to write debug output to. 1125 output_stream: A stream to write debug output to.
1093 1126
1094 Return: 1127 Return:
(...skipping 30 matching lines...) Expand all
1125 slaves = list(slave_dict.items()) 1158 slaves = list(slave_dict.items())
1126 1159
1127 slaves.extend(set(old_style)) 1160 slaves.extend(set(old_style))
1128 1161
1129 if slaves and verbose: 1162 if slaves and verbose:
1130 output_stream.write(', '.join((str(x) for x in slaves))) 1163 output_stream.write(', '.join((str(x) for x in slaves)))
1131 output_stream.write('\n') 1164 output_stream.write('\n')
1132 return slaves 1165 return slaves
1133 1166
1134 1167
1168 def _MergeMasters(masters1, masters2):
1169 """Merges two master maps. Merges also the tests of each builder."""
1170 result = {}
1171 for (master, builders) in itertools.chain(masters1.iteritems(),
1172 masters2.iteritems()):
1173 new_builders = result.setdefault(master, {})
1174 for (builder, tests) in builders.iteritems():
1175 new_builders.setdefault(builder, set([])).update(tests)
1176 return result
1177
1178
1179 def DoGetTryMasters(change,
1180 changed_files,
1181 repository_root,
1182 default_presubmit,
1183 project,
1184 verbose,
1185 output_stream):
1186 """Get the list of try masters from the presubmit scripts.
1187
1188 Args:
1189 changed_files: List of modified files.
1190 repository_root: The repository root.
1191 default_presubmit: A default presubmit script to execute in any case.
1192 project: Optional name of a project used in selecting trybots.
1193 verbose: Prints debug info.
1194 output_stream: A stream to write debug output to.
1195
1196 Return:
1197 Map of try masters to map of builders to set of tests.
1198 """
1199 presubmit_files = ListRelevantPresubmitFiles(changed_files, repository_root)
1200 if not presubmit_files and verbose:
1201 output_stream.write("Warning, no PRESUBMIT.py found.\n")
1202 results = {}
1203 executer = GetTryMastersExecuter()
1204
1205 if default_presubmit:
1206 if verbose:
1207 output_stream.write("Running default presubmit script.\n")
1208 fake_path = os.path.join(repository_root, 'PRESUBMIT.py')
1209 results = _MergeMasters(results, executer.ExecPresubmitScript(
1210 default_presubmit, fake_path, project, change))
1211 for filename in presubmit_files:
1212 filename = os.path.abspath(filename)
1213 if verbose:
1214 output_stream.write("Running %s\n" % filename)
1215 # Accept CRLF presubmit script.
1216 presubmit_script = gclient_utils.FileRead(filename, 'rU')
1217 results = _MergeMasters(results, executer.ExecPresubmitScript(
1218 presubmit_script, filename, project, change))
1219
1220 # Make sets to lists again for later JSON serialization.
1221 for builders in results.itervalues():
1222 for builder in builders:
1223 builders[builder] = list(builders[builder])
1224
1225 if results and verbose:
1226 output_stream.write('%s\n' % str(results))
1227 return results
1228
1229
1135 class PresubmitExecuter(object): 1230 class PresubmitExecuter(object):
1136 def __init__(self, change, committing, rietveld_obj, verbose): 1231 def __init__(self, change, committing, rietveld_obj, verbose):
1137 """ 1232 """
1138 Args: 1233 Args:
1139 change: The Change object. 1234 change: The Change object.
1140 committing: True if 'gcl commit' is running, False if 'gcl upload' is. 1235 committing: True if 'gcl commit' is running, False if 'gcl upload' is.
1141 rietveld_obj: rietveld.Rietveld client object. 1236 rietveld_obj: rietveld.Rietveld client object.
1142 """ 1237 """
1143 self.change = change 1238 self.change = change
1144 self.committing = committing 1239 self.committing = committing
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after
1508 except PresubmitFailure, e: 1603 except PresubmitFailure, e:
1509 print >> sys.stderr, e 1604 print >> sys.stderr, e
1510 print >> sys.stderr, 'Maybe your depot_tools is out of date?' 1605 print >> sys.stderr, 'Maybe your depot_tools is out of date?'
1511 print >> sys.stderr, 'If all fails, contact maruel@' 1606 print >> sys.stderr, 'If all fails, contact maruel@'
1512 return 2 1607 return 2
1513 1608
1514 1609
1515 if __name__ == '__main__': 1610 if __name__ == '__main__':
1516 fix_encoding.fix_encoding() 1611 fix_encoding.fix_encoding()
1517 sys.exit(Main(None)) 1612 sys.exit(Main(None))
OLDNEW
« no previous file with comments | « git_cl.py ('k') | rietveld.py » ('j') | tests/presubmit_unittest.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698