OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2014 The Chromium Authors. All rights reserved. | 2 # Copyright 2014 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 # TODO(hinoka): Use logging. | 6 # TODO(hinoka): Use logging. |
7 | 7 |
8 import cStringIO | 8 import cStringIO |
9 import codecs | 9 import codecs |
10 import collections | 10 import collections |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
160 'src/native_client/': 'got_nacl_revision', | 160 'src/native_client/': 'got_nacl_revision', |
161 'src/tools/swarm_client/': 'got_swarm_client_revision', | 161 'src/tools/swarm_client/': 'got_swarm_client_revision', |
162 'src/tools/swarming_client/': 'got_swarming_client_revision', | 162 'src/tools/swarming_client/': 'got_swarming_client_revision', |
163 'src/third_party/WebKit/': 'got_webkit_revision', | 163 'src/third_party/WebKit/': 'got_webkit_revision', |
164 'src/third_party/webrtc/': 'got_webrtc_revision', | 164 'src/third_party/webrtc/': 'got_webrtc_revision', |
165 'src/v8/': 'got_v8_revision', | 165 'src/v8/': 'got_v8_revision', |
166 } | 166 } |
167 } | 167 } |
168 | 168 |
169 | 169 |
170 BOT_UPDATE_MESSAGE = """ | |
171 What is the "Bot Update" step? | |
172 ============================== | |
173 | |
174 This step ensures that the source checkout on the bot (e.g. Chromium's src/ and | |
175 its dependencies) is checked out in a consistent state. This means that all of | |
176 the necessary repositories are checked out, no extra repositories are checked | |
177 out, and no locally modified files are present. | |
178 | |
179 These actions used to be taken care of by the "gclient revert" and "update" | |
180 steps. However, those steps are known to be buggy and occasionally flaky. This | |
181 step has two main advantages over them: | |
182 * it only operates in Git, so the logic can be clearer and cleaner; and | |
183 * it is a slave-side script, so its behavior can be modified without | |
184 restarting the master. | |
185 | |
186 Why Git, you ask? Because that is the direction that the Chromium project is | |
187 heading. This step is an integral part of the transition from using the SVN repo | |
188 at chrome/trunk/src to using the Git repo src.git. Please pardon the dust while | |
189 we fully convert everything to Git. This message will get out of your way | |
190 eventually, and the waterfall will be a happier place because of it. | |
191 | |
192 This step can be activated or deactivated independently on every builder on | |
193 every master. When it is active, the "gclient revert" and "update" steps become | |
194 no-ops. When it is inactive, it prints this message, cleans up after itself, and | |
195 lets everything else continue as though nothing has changed. Eventually, when | |
196 everything is stable enough, this step will replace them entirely. | |
197 | |
198 Debugging information: | |
199 (master/builder/slave may be unspecified on recipes) | |
200 master: %(master)s | |
201 builder: %(builder)s | |
202 slave: %(slave)s | |
203 forced by recipes: %(recipe)s | |
204 CURRENT_DIR: %(CURRENT_DIR)s | |
205 BUILDER_DIR: %(BUILDER_DIR)s | |
206 SLAVE_DIR: %(SLAVE_DIR)s | |
207 THIS_DIR: %(THIS_DIR)s | |
208 SCRIPTS_DIR: %(SCRIPTS_DIR)s | |
209 BUILD_DIR: %(BUILD_DIR)s | |
210 ROOT_DIR: %(ROOT_DIR)s | |
211 DEPOT_TOOLS_DIR: %(DEPOT_TOOLS_DIR)s | |
212 bot_update.py is:""" | |
213 | 170 |
214 ACTIVATED_MESSAGE = """ACTIVE. | 171 ACTIVATED_MESSAGE = """ACTIVE. |
215 The bot will perform a Git checkout in this step. | 172 The bot will perform a Git checkout in this step. |
216 The "gclient revert" and "update" steps are no-ops. | 173 The "gclient revert" and "update" steps are no-ops. |
217 | 174 |
218 """ | 175 """ |
219 | 176 |
220 NOT_ACTIVATED_MESSAGE = """INACTIVE. | 177 NOT_ACTIVATED_MESSAGE = """INACTIVE. |
221 This step does nothing. You actually want to look at the "update" step. | 178 This step does nothing. You actually want to look at the "update" step. |
222 | 179 |
(...skipping 25 matching lines...) Expand all Loading... | |
248 # If SVN path matches key, the entire URL is rewritten to the Git url. | 205 # If SVN path matches key, the entire URL is rewritten to the Git url. |
249 '/chrome/trunk/src': | 206 '/chrome/trunk/src': |
250 CHROMIUM_SRC_URL, | 207 CHROMIUM_SRC_URL, |
251 '/chrome/trunk/src/tools/cros.DEPS': | 208 '/chrome/trunk/src/tools/cros.DEPS': |
252 CHROMIUM_GIT_HOST + '/chromium/src/tools/cros.DEPS.git', | 209 CHROMIUM_GIT_HOST + '/chromium/src/tools/cros.DEPS.git', |
253 '/chrome-internal/trunk/src-internal': | 210 '/chrome-internal/trunk/src-internal': |
254 'https://chrome-internal.googlesource.com/chrome/src-internal.git', | 211 'https://chrome-internal.googlesource.com/chrome/src-internal.git', |
255 } | 212 } |
256 RECOGNIZED_PATHS.update(internal_data.get('RECOGNIZED_PATHS', {})) | 213 RECOGNIZED_PATHS.update(internal_data.get('RECOGNIZED_PATHS', {})) |
257 | 214 |
258 ENABLED_MASTERS = [ | |
259 'bot_update.always_on', | |
260 'chromium.android', | |
261 'chromium.angle', | |
262 'chromium.chrome', | |
263 'chromium.chromedriver', | |
264 'chromium.chromiumos', | |
265 'chromium', | |
266 'chromium.fyi', | |
267 'chromium.goma', | |
268 'chromium.gpu', | |
269 'chromium.gpu.fyi', | |
270 'chromium.infra', | |
271 'chromium.infra.cron', | |
272 'chromium.linux', | |
273 'chromium.lkgr', | |
274 'chromium.mac', | |
275 'chromium.memory', | |
276 'chromium.memory.fyi', | |
277 'chromium.perf', | |
278 'chromium.perf.fyi', | |
279 'chromium.swarm', | |
280 'chromium.webkit', | |
281 'chromium.webrtc', | |
282 'chromium.webrtc.fyi', | |
283 'chromium.win', | |
284 'client.catapult', | |
285 'client.drmemory', | |
286 'client.mojo', | |
287 'client.nacl', | |
288 'client.nacl.ports', | |
289 'client.nacl.sdk', | |
290 'client.nacl.toolchain', | |
291 'client.pdfium', | |
292 'client.skia', | |
293 'client.skia.fyi', | |
294 'client.v8', | |
295 'client.v8.branches', | |
296 'client.v8.fyi', | |
297 'client.v8.ports', | |
298 'client.webrtc', | |
299 'client.webrtc.fyi', | |
300 'tryserver.blink', | |
301 'tryserver.client.catapult', | |
302 'tryserver.client.mojo', | |
303 'tryserver.chromium.android', | |
304 'tryserver.chromium.angle', | |
305 'tryserver.chromium.linux', | |
306 'tryserver.chromium.mac', | |
307 'tryserver.chromium.perf', | |
308 'tryserver.chromium.win', | |
309 'tryserver.infra', | |
310 'tryserver.nacl', | |
311 'tryserver.v8', | |
312 'tryserver.webrtc', | |
313 ] | |
314 ENABLED_MASTERS += internal_data.get('ENABLED_MASTERS', []) | |
315 | |
316 ENABLED_BUILDERS = { | |
317 'client.dart.fyi': [ | |
318 'v8-linux-release', | |
319 'v8-mac-release', | |
320 'v8-win-release', | |
321 ], | |
322 'client.dynamorio': [ | |
323 'linux-v8-dr', | |
324 ], | |
325 } | |
326 ENABLED_BUILDERS.update(internal_data.get('ENABLED_BUILDERS', {})) | |
327 | |
328 ENABLED_SLAVES = {} | |
329 ENABLED_SLAVES.update(internal_data.get('ENABLED_SLAVES', {})) | |
330 | |
331 # Disabled filters get run AFTER enabled filters, so for example if a builder | |
332 # config is enabled, but a bot on that builder is disabled, that bot will | |
333 # be disabled. | |
334 DISABLED_BUILDERS = {} | |
335 DISABLED_BUILDERS.update(internal_data.get('DISABLED_BUILDERS', {})) | |
336 | |
337 DISABLED_SLAVES = {} | |
338 DISABLED_SLAVES.update(internal_data.get('DISABLED_SLAVES', {})) | |
339 | |
340 # These masters work only in Git, meaning for got_revision, always output | 215 # These masters work only in Git, meaning for got_revision, always output |
341 # a git hash rather than a SVN rev. | 216 # a git hash rather than a SVN rev. |
342 GIT_MASTERS = [ | 217 GIT_MASTERS = [ |
343 'client.v8', | 218 'client.v8', |
344 'client.v8.branches', | 219 'client.v8.branches', |
345 'client.v8.ports', | 220 'client.v8.ports', |
346 'tryserver.v8', | 221 'tryserver.v8', |
347 ] | 222 ] |
348 GIT_MASTERS += internal_data.get('GIT_MASTERS', []) | 223 GIT_MASTERS += internal_data.get('GIT_MASTERS', []) |
349 | 224 |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
518 | 393 |
519 def get_gclient_spec(solutions, target_os, target_os_only, git_cache_dir): | 394 def get_gclient_spec(solutions, target_os, target_os_only, git_cache_dir): |
520 return GCLIENT_TEMPLATE % { | 395 return GCLIENT_TEMPLATE % { |
521 'solutions': pprint.pformat(solutions, indent=4), | 396 'solutions': pprint.pformat(solutions, indent=4), |
522 'cache_dir': '"%s"' % git_cache_dir, | 397 'cache_dir': '"%s"' % git_cache_dir, |
523 'target_os': ('\ntarget_os=%s' % target_os) if target_os else '', | 398 'target_os': ('\ntarget_os=%s' % target_os) if target_os else '', |
524 'target_os_only': '\ntarget_os_only=%s' % target_os_only | 399 'target_os_only': '\ntarget_os_only=%s' % target_os_only |
525 } | 400 } |
526 | 401 |
527 | 402 |
528 def check_enabled(master, builder, slave): | |
529 if master in ENABLED_MASTERS: | |
530 return True | |
531 builder_list = ENABLED_BUILDERS.get(master) | |
532 if builder_list and builder in builder_list: | |
533 return True | |
534 slave_list = ENABLED_SLAVES.get(master) | |
535 if slave_list and slave in slave_list: | |
536 return True | |
537 return False | |
538 | |
539 | |
540 def check_disabled(master, builder, slave): | |
541 """Returns True if disabled, False if not disabled.""" | |
542 builder_list = DISABLED_BUILDERS.get(master) | |
543 if builder_list and builder in builder_list: | |
544 return True | |
545 slave_list = DISABLED_SLAVES.get(master) | |
546 if slave_list and slave in slave_list: | |
547 return True | |
548 return False | |
549 | |
550 | |
551 def check_valid_host(master, builder, slave): | |
552 return (check_enabled(master, builder, slave) | |
553 and not check_disabled(master, builder, slave)) | |
554 | |
555 | |
556 def maybe_ignore_revision(revision, buildspec): | 403 def maybe_ignore_revision(revision, buildspec): |
557 """Handle builders that don't care what buildbot tells them to build. | 404 """Handle builders that don't care what buildbot tells them to build. |
558 | 405 |
559 This is especially the case with branch builders that build from buildspecs | 406 This is especially the case with branch builders that build from buildspecs |
560 and/or trigger off multiple repositories, where the --revision passed in has | 407 and/or trigger off multiple repositories, where the --revision passed in has |
561 nothing to do with the solution being built. Clearing the revision in this | 408 nothing to do with the solution being built. Clearing the revision in this |
562 case causes bot_update to use HEAD rather that trying to checkout an | 409 case causes bot_update to use HEAD rather that trying to checkout an |
563 inappropriate version of the solution. | 410 inappropriate version of the solution. |
564 """ | 411 """ |
565 if buildspec and buildspec.container == 'branches': | 412 if buildspec and buildspec.container == 'branches': |
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1190 # Compose a commit position from 'git-svn' metadata | 1037 # Compose a commit position from 'git-svn' metadata |
1191 value = footer_map.get(GIT_SVN_ID_FOOTER_KEY) | 1038 value = footer_map.get(GIT_SVN_ID_FOOTER_KEY) |
1192 if value: | 1039 if value: |
1193 m = GIT_SVN_ID_RE.match(value) | 1040 m = GIT_SVN_ID_RE.match(value) |
1194 if not m: | 1041 if not m: |
1195 raise ValueError("Invalid 'git-svn' value: [%s]" % (value,)) | 1042 raise ValueError("Invalid 'git-svn' value: [%s]" % (value,)) |
1196 return get_commit_position_for_git_svn(m.group(1), m.group(2)) | 1043 return get_commit_position_for_git_svn(m.group(1), m.group(2)) |
1197 return None | 1044 return None |
1198 | 1045 |
1199 | 1046 |
1200 def parse_got_revision(gclient_output, got_revision_mapping, use_svn_revs): | 1047 def parse_got_revision(gclient_output, got_revision_mapping): |
1201 """Translate git gclient revision mapping to build properties. | 1048 """Translate git gclient revision mapping to build properties. |
1202 | |
1203 If use_svn_revs is True, then translate git hashes in the revision mapping | |
1204 to svn revision numbers. | |
1205 """ | 1049 """ |
1206 properties = {} | 1050 properties = {} |
1207 solutions_output = { | 1051 solutions_output = { |
1208 # Make sure path always ends with a single slash. | 1052 # Make sure path always ends with a single slash. |
1209 '%s/' % path.rstrip('/') : solution_output for path, solution_output | 1053 '%s/' % path.rstrip('/') : solution_output for path, solution_output |
1210 in gclient_output['solutions'].iteritems() | 1054 in gclient_output['solutions'].iteritems() |
1211 } | 1055 } |
1212 for dir_name, property_name in got_revision_mapping.iteritems(): | 1056 for dir_name, property_name in got_revision_mapping.iteritems(): |
1213 # Make sure dir_name always ends with a single slash. | 1057 # Make sure dir_name always ends with a single slash. |
1214 dir_name = '%s/' % dir_name.rstrip('/') | 1058 dir_name = '%s/' % dir_name.rstrip('/') |
1215 if dir_name not in solutions_output: | 1059 if dir_name not in solutions_output: |
1216 continue | 1060 continue |
1217 solution_output = solutions_output[dir_name] | 1061 solution_output = solutions_output[dir_name] |
1218 if solution_output.get('scm') is None: | 1062 if solution_output.get('scm') is None: |
1219 # This is an ignored DEPS, so the output got_revision should be 'None'. | 1063 # This is an ignored DEPS, so the output got_revision should be 'None'. |
1220 git_revision = revision = commit_position = None | 1064 git_revision = revision = commit_position = None |
1221 else: | 1065 else: |
1222 # Since we are using .DEPS.git, everything had better be git. | 1066 # Since we are using .DEPS.git, everything had better be git. |
1223 assert solution_output.get('scm') == 'git' | 1067 assert solution_output.get('scm') == 'git' |
1224 git_revision = git('rev-parse', 'HEAD', cwd=dir_name).strip() | 1068 git_revision = git('rev-parse', 'HEAD', cwd=dir_name).strip() |
1225 if use_svn_revs: | 1069 revision = git_revision |
1226 revision = get_svn_rev(git_revision, dir_name) | |
1227 if not revision: | |
1228 revision = git_revision | |
1229 else: | |
1230 revision = git_revision | |
1231 commit_position = get_commit_position(dir_name) | 1070 commit_position = get_commit_position(dir_name) |
1232 | 1071 |
1233 properties[property_name] = revision | 1072 properties[property_name] = revision |
1234 if revision != git_revision: | 1073 if revision != git_revision: |
1235 properties['%s_git' % property_name] = git_revision | 1074 properties['%s_git' % property_name] = git_revision |
1236 if commit_position: | 1075 if commit_position: |
1237 properties['%s_cp' % property_name] = commit_position | 1076 properties['%s_cp' % property_name] = commit_position |
1238 | 1077 |
1239 return properties | 1078 return properties |
1240 | 1079 |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1420 default='codereview.chromium.org', | 1259 default='codereview.chromium.org', |
1421 help='Rietveld server.') | 1260 help='Rietveld server.') |
1422 parse.add_option('--gerrit_repo', | 1261 parse.add_option('--gerrit_repo', |
1423 help='Gerrit repository to pull the ref from.') | 1262 help='Gerrit repository to pull the ref from.') |
1424 parse.add_option('--gerrit_ref', help='Gerrit ref to apply.') | 1263 parse.add_option('--gerrit_ref', help='Gerrit ref to apply.') |
1425 parse.add_option('--gerrit_no_rebase_patch_ref', action='store_true', | 1264 parse.add_option('--gerrit_no_rebase_patch_ref', action='store_true', |
1426 help='Bypass rebase of Gerrit patch ref after checkout.') | 1265 help='Bypass rebase of Gerrit patch ref after checkout.') |
1427 parse.add_option('--gerrit_no_reset', action='store_true', | 1266 parse.add_option('--gerrit_no_reset', action='store_true', |
1428 help='Bypass calling reset after applying a gerrit ref.') | 1267 help='Bypass calling reset after applying a gerrit ref.') |
1429 parse.add_option('--specs', help='Gcilent spec.') | 1268 parse.add_option('--specs', help='Gcilent spec.') |
1430 parse.add_option('--master', | |
1431 help='Master name. If specified and it is not in ' | |
1432 'bot_update\'s whitelist, bot_update will be noop.') | |
1433 parse.add_option('-f', '--force', action='store_true', | |
1434 help='Bypass check to see if we want to be run. ' | |
1435 'Should ONLY be used locally or by smart recipes.') | |
1436 parse.add_option('--revision_mapping', | 1269 parse.add_option('--revision_mapping', |
1437 help='{"path/to/repo/": "property_name"}') | 1270 help='{"path/to/repo/": "property_name"}') |
1438 parse.add_option('--revision_mapping_file', | 1271 parse.add_option('--revision_mapping_file', |
1439 help=('Same as revision_mapping, except its a path to a json' | 1272 help=('Same as revision_mapping, except its a path to a json' |
1440 ' file containing that format.')) | 1273 ' file containing that format.')) |
1441 parse.add_option('--revision', action='append', default=[], | 1274 parse.add_option('--revision', action='append', default=[], |
1442 help='Revision to check out. Can be an SVN revision number, ' | 1275 help='Revision to check out. Can be an SVN revision number, ' |
1443 'git hash, or any form of git ref. Can prepend ' | 1276 'git hash, or any form of git ref. Can prepend ' |
1444 'root@<rev> to specify which repository, where root ' | 1277 'root@<rev> to specify which repository, where root ' |
1445 'is either a filesystem path, git https url, or ' | 1278 'is either a filesystem path, git https url, or ' |
1446 'svn url. To specify Tip of Tree, set rev to HEAD.' | 1279 'svn url. To specify Tip of Tree, set rev to HEAD.' |
1447 'To specify a git branch and an SVN rev, <rev> can be ' | 1280 'To specify a git branch and an SVN rev, <rev> can be ' |
1448 'set to <branch>:<revision>.') | 1281 'set to <branch>:<revision>.') |
1449 parse.add_option('--output_manifest', action='store_true', | 1282 parse.add_option('--output_manifest', action='store_true', |
1450 help=('Add manifest json to the json output.')) | 1283 help=('Add manifest json to the json output.')) |
1451 parse.add_option('--slave_name', default=socket.getfqdn().split('.')[0], | |
1452 help='Hostname of the current machine, ' | |
1453 'used for determining whether or not to activate.') | |
1454 parse.add_option('--builder_name', help='Name of the builder, ' | |
1455 'used for determining whether or not to activate.') | |
1456 parse.add_option('--build_dir', default=os.getcwd()) | 1284 parse.add_option('--build_dir', default=os.getcwd()) |
1457 parse.add_option('--flag_file', default=path.join(os.getcwd(), | 1285 parse.add_option('--flag_file', default=path.join(os.getcwd(), |
1458 'update.flag')) | 1286 'update.flag')) |
1459 parse.add_option('--shallow', action='store_true', | 1287 parse.add_option('--shallow', action='store_true', |
1460 help='Use shallow clones for cache repositories.') | 1288 help='Use shallow clones for cache repositories.') |
1461 parse.add_option('--gyp_env', action='append', default=[], | 1289 parse.add_option('--gyp_env', action='append', default=[], |
1462 help='Environment variables to pass into gclient runhooks.') | 1290 help='Environment variables to pass into gclient runhooks.') |
1463 parse.add_option('--clobber', action='store_true', | 1291 parse.add_option('--clobber', action='store_true', |
1464 help='Delete checkout first, always') | 1292 help='Delete checkout first, always') |
1465 parse.add_option('--bot_update_clobber', action='store_true', dest='clobber', | 1293 parse.add_option('--bot_update_clobber', action='store_true', dest='clobber', |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1552 # The first solution is where the primary DEPS file resides. | 1380 # The first solution is where the primary DEPS file resides. |
1553 first_sln = dir_names[0] | 1381 first_sln = dir_names[0] |
1554 | 1382 |
1555 # Split all the revision specifications into a nice dict. | 1383 # Split all the revision specifications into a nice dict. |
1556 print 'Revisions: %s' % options.revision | 1384 print 'Revisions: %s' % options.revision |
1557 revisions = parse_revisions(options.revision, first_sln) | 1385 revisions = parse_revisions(options.revision, first_sln) |
1558 print 'Fetching Git checkout at %s@%s' % (first_sln, revisions[first_sln]) | 1386 print 'Fetching Git checkout at %s@%s' % (first_sln, revisions[first_sln]) |
1559 return revisions, step_text | 1387 return revisions, step_text |
1560 | 1388 |
1561 | 1389 |
1562 def checkout(options, git_slns, specs, buildspec, master, | 1390 def checkout(options, git_slns, specs, buildspec, |
1563 svn_root, revisions, step_text): | 1391 svn_root, revisions, step_text): |
1564 first_sln = git_slns[0]['name'] | 1392 first_sln = git_slns[0]['name'] |
1565 dir_names = [sln.get('name') for sln in git_slns if 'name' in sln] | 1393 dir_names = [sln.get('name') for sln in git_slns if 'name' in sln] |
1566 try: | 1394 try: |
1567 # Outer try is for catching patch failures and exiting gracefully. | 1395 # Outer try is for catching patch failures and exiting gracefully. |
1568 # Inner try is for catching gclient failures and retrying gracefully. | 1396 # Inner try is for catching gclient failures and retrying gracefully. |
1569 try: | 1397 try: |
1570 checkout_parameters = dict( | 1398 checkout_parameters = dict( |
1571 # First, pass in the base of what we want to check out. | 1399 # First, pass in the base of what we want to check out. |
1572 solutions=git_slns, | 1400 solutions=git_slns, |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1616 patch_root=options.patch_root, | 1444 patch_root=options.patch_root, |
1617 patch_failure=True, | 1445 patch_failure=True, |
1618 step_text='%s PATCH FAILED' % step_text, | 1446 step_text='%s PATCH FAILED' % step_text, |
1619 fixed_revisions=revisions) | 1447 fixed_revisions=revisions) |
1620 else: | 1448 else: |
1621 # If we're not on recipes, tell annotator about our got_revisions. | 1449 # If we're not on recipes, tell annotator about our got_revisions. |
1622 emit_log_lines('patch error', e.output) | 1450 emit_log_lines('patch error', e.output) |
1623 print '@@@STEP_TEXT@%s PATCH FAILED@@@' % step_text | 1451 print '@@@STEP_TEXT@%s PATCH FAILED@@@' % step_text |
1624 raise | 1452 raise |
1625 | 1453 |
1626 # Revision is an svn revision, unless it's a git master. | |
1627 use_svn_rev = master not in GIT_MASTERS | |
1628 | |
1629 # Take care of got_revisions outputs. | 1454 # Take care of got_revisions outputs. |
1630 revision_mapping = dict(GOT_REVISION_MAPPINGS.get(svn_root, {})) | 1455 revision_mapping = dict(GOT_REVISION_MAPPINGS.get(svn_root, {})) |
1631 if options.revision_mapping: | 1456 if options.revision_mapping: |
1632 revision_mapping.update(options.revision_mapping) | 1457 revision_mapping.update(options.revision_mapping) |
1633 | 1458 |
1634 # If the repo is not in the default GOT_REVISION_MAPPINGS and no | 1459 # If the repo is not in the default GOT_REVISION_MAPPINGS and no |
1635 # revision_mapping were specified on the command line then | 1460 # revision_mapping were specified on the command line then |
1636 # default to setting 'got_revision' based on the first solution. | 1461 # default to setting 'got_revision' based on the first solution. |
1637 if not revision_mapping: | 1462 if not revision_mapping: |
1638 revision_mapping[first_sln] = 'got_revision' | 1463 revision_mapping[first_sln] = 'got_revision' |
1639 | 1464 |
1640 got_revisions = parse_got_revision(gclient_output, revision_mapping, | 1465 got_revisions = parse_got_revision(gclient_output, revision_mapping) |
1641 use_svn_rev) | |
1642 | 1466 |
1643 if not got_revisions: | 1467 if not got_revisions: |
1644 # TODO(hinoka): We should probably bail out here, but in the interest | 1468 # TODO(hinoka): We should probably bail out here, but in the interest |
1645 # of giving mis-configured bots some time to get fixed use a dummy | 1469 # of giving mis-configured bots some time to get fixed use a dummy |
1646 # revision here. | 1470 # revision here. |
1647 got_revisions = { 'got_revision': 'BOT_UPDATE_NO_REV_FOUND' } | 1471 got_revisions = { 'got_revision': 'BOT_UPDATE_NO_REV_FOUND' } |
1648 #raise Exception('No got_revision(s) found in gclient output') | 1472 #raise Exception('No got_revision(s) found in gclient output') |
1649 | 1473 |
1650 if options.output_json: | 1474 if options.output_json: |
1651 manifest = create_manifest() if options.output_manifest else None | 1475 manifest = create_manifest() if options.output_manifest else None |
1652 # Tell recipes information such as root, got_revision, etc. | 1476 # Tell recipes information such as root, got_revision, etc. |
1653 emit_json(options.output_json, | 1477 emit_json(options.output_json, |
1654 did_run=True, | 1478 did_run=True, |
1655 root=first_sln, | 1479 root=first_sln, |
1656 patch_root=options.patch_root, | 1480 patch_root=options.patch_root, |
1657 step_text=step_text, | 1481 step_text=step_text, |
1658 fixed_revisions=revisions, | 1482 fixed_revisions=revisions, |
1659 properties=got_revisions, | 1483 properties=got_revisions, |
1660 manifest=manifest) | 1484 manifest=manifest) |
1661 else: | 1485 else: |
1662 # If we're not on recipes, tell annotator about our got_revisions. | 1486 # If we're not on recipes, tell annotator about our got_revisions. |
1663 emit_properties(got_revisions) | 1487 emit_properties(got_revisions) |
1664 | 1488 |
1665 | 1489 |
1666 def print_help_text(force, output_json, active, master, builder, slave): | 1490 def print_debug_info(): |
1667 """Print helpful messages to tell devs whats going on.""" | 1491 print "Debugging information:" |
1668 if force and output_json: | |
1669 recipe_force = 'Forced on by recipes' | |
1670 elif active and output_json: | |
1671 recipe_force = 'Off by recipes, but forced on by bot update' | |
1672 elif not active and output_json: | |
1673 recipe_force = 'Forced off by recipes' | |
1674 else: | |
1675 recipe_force = 'N/A. Was not called by recipes' | |
1676 | 1492 |
1677 print BOT_UPDATE_MESSAGE % { | 1493 items = { |
1678 'master': master or 'Not specified', | |
1679 'builder': builder or 'Not specified', | |
1680 'slave': slave or 'Not specified', | |
1681 'recipe': recipe_force, | |
1682 'CURRENT_DIR': CURRENT_DIR, | 1494 'CURRENT_DIR': CURRENT_DIR, |
1683 'BUILDER_DIR': BUILDER_DIR, | 1495 'BUILDER_DIR': BUILDER_DIR, |
1684 'SLAVE_DIR': SLAVE_DIR, | 1496 'SLAVE_DIR': SLAVE_DIR, |
1685 'THIS_DIR': THIS_DIR, | 1497 'THIS_DIR': THIS_DIR, |
1686 'SCRIPTS_DIR': SCRIPTS_DIR, | 1498 'SCRIPTS_DIR': SCRIPTS_DIR, |
1687 'BUILD_DIR': BUILD_DIR, | 1499 'BUILD_DIR': BUILD_DIR, |
1688 'ROOT_DIR': ROOT_DIR, | 1500 'ROOT_DIR': ROOT_DIR, |
1689 'DEPOT_TOOLS_DIR': DEPOT_TOOLS_DIR, | 1501 'DEPOT_TOOLS_DIR': DEPOT_TOOLS_DIR, |
1690 }, | 1502 } |
1691 print ACTIVATED_MESSAGE if active else NOT_ACTIVATED_MESSAGE | 1503 for k, v in sorted(items.iteritems()): |
estaab
2016/09/03 01:52:25
Maybe add a message giving a little context, less
iannucci
2016/09/07 19:21:42
Yeah I do this with the print statement up above :
| |
1504 print k, v | |
1692 | 1505 |
1693 | 1506 |
1694 def main(): | 1507 def main(): |
1695 # Get inputs. | 1508 # Get inputs. |
1696 options, _ = parse_args() | 1509 options, _ = parse_args() |
1697 builder = options.builder_name | 1510 options.force = True |
1698 slave = options.slave_name | |
1699 master = options.master | |
1700 | 1511 |
1701 if not master: | 1512 print_debug_info() |
1702 # bot_update activation whitelist is checked only on buildbot masters. | |
1703 # If there is no master, bot_update is always active. | |
1704 options.force = True | |
1705 | |
1706 # Check if this script should activate or not. | |
1707 active = options.force or check_valid_host(master, builder, slave) | |
1708 | |
1709 # Print a helpful message to tell developers whats going on with this step. | |
1710 print_help_text( | |
1711 options.force, options.output_json, active, master, builder, slave) | |
1712 | 1513 |
1713 # Parse, munipulate, and print the gclient solutions. | 1514 # Parse, munipulate, and print the gclient solutions. |
1714 specs = {} | 1515 specs = {} |
1715 exec(options.specs, specs) | 1516 exec(options.specs, specs) |
1716 svn_solutions = specs.get('solutions', []) | 1517 svn_solutions = specs.get('solutions', []) |
1717 git_slns, svn_root, buildspec = solutions_to_git(svn_solutions) | 1518 git_slns, svn_root, buildspec = solutions_to_git(svn_solutions) |
1718 options.revision = maybe_ignore_revision(options.revision, buildspec) | 1519 options.revision = maybe_ignore_revision(options.revision, buildspec) |
1719 | 1520 |
1720 solutions_printer(git_slns) | 1521 solutions_printer(git_slns) |
1721 | 1522 |
1722 try: | 1523 try: |
1723 # Dun dun dun, the main part of bot_update. | 1524 # Dun dun dun, the main part of bot_update. |
1724 revisions, step_text = prepare(options, git_slns, active) | 1525 revisions, step_text = prepare(options, git_slns, True) |
1725 checkout(options, git_slns, specs, buildspec, master, svn_root, revisions, | 1526 checkout(options, git_slns, specs, buildspec, svn_root, revisions, |
1726 step_text) | 1527 step_text) |
1727 | 1528 |
1728 except Inactive: | 1529 except Inactive: |
1729 # Not active, should count as passing. | 1530 # Not active, should count as passing. |
1730 pass | 1531 pass |
1731 except PatchFailed as e: | 1532 except PatchFailed as e: |
1732 emit_flag(options.flag_file) | 1533 emit_flag(options.flag_file) |
1733 # Return a specific non-zero exit code for patch failure (because it is | 1534 # Return a specific non-zero exit code for patch failure (because it is |
1734 # a failure), but make it different than other failures to distinguish | 1535 # a failure), but make it different than other failures to distinguish |
1735 # between infra failures (independent from patch author), and patch | 1536 # between infra failures (independent from patch author), and patch |
1736 # failures (that patch author can fix). However, PatchFailure due to | 1537 # failures (that patch author can fix). However, PatchFailure due to |
1737 # download patch failure is still an infra problem. | 1538 # download patch failure is still an infra problem. |
1738 if e.code == 3: | 1539 if e.code == 3: |
1739 # Patch download problem. | 1540 # Patch download problem. |
1740 return 87 | 1541 return 87 |
1741 # Genuine patch problem. | 1542 # Genuine patch problem. |
1742 return 88 | 1543 return 88 |
1743 except Exception: | 1544 except Exception: |
1744 # Unexpected failure. | 1545 # Unexpected failure. |
1745 emit_flag(options.flag_file) | 1546 emit_flag(options.flag_file) |
1746 raise | 1547 raise |
1747 else: | 1548 else: |
1748 emit_flag(options.flag_file) | 1549 emit_flag(options.flag_file) |
1749 | 1550 |
1750 | 1551 |
1751 if __name__ == '__main__': | 1552 if __name__ == '__main__': |
1752 sys.exit(main()) | 1553 sys.exit(main()) |
OLD | NEW |