Chromium Code Reviews| 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 |