OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2013 The Chromium Authors. All rights reserved. | 2 # Copyright 2013 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 """Closes tree if configured masters have failed tree-closing steps. | 6 """Closes tree if configured masters have failed tree-closing steps. |
7 | 7 |
8 Given a list of masters, gatekeeper_ng will get a list of the latest builds from | 8 Given a list of masters, gatekeeper_ng will get a list of the latest builds from |
9 the specified masters. It then checks if any tree-closing steps have failed, and | 9 the specified masters. It then checks if any tree-closing steps have failed, and |
10 if so closes the tree and emails appropriate parties. Configuration for which | 10 if so closes the tree and emails appropriate parties. Configuration for which |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 'password': password | 80 'password': password |
81 }) | 81 }) |
82 | 82 |
83 # Standard urllib doesn't raise an exception on 403, urllib2 does. | 83 # Standard urllib doesn't raise an exception on 403, urllib2 does. |
84 status_url = status_url_root + "/status" | 84 status_url = status_url_root + "/status" |
85 f = logging_urlopen(status_url, params) | 85 f = logging_urlopen(status_url, params) |
86 f.close() | 86 f.close() |
87 logging.info('success') | 87 logging.info('success') |
88 | 88 |
89 | 89 |
90 def get_tree_status(status_url_root): | 90 def get_tree_status(status_url_root, username, password): |
91 status_url = status_url_root + "/current?format=json" | 91 status_url = status_url_root + "/current?format=json" |
92 return json.load(logging_urlopen(status_url)) | 92 data = logging_urlopen(status_url).read() |
| 93 try: |
| 94 return json.loads(data) |
| 95 except ValueError: |
| 96 if 'Login Required' not in data: |
| 97 raise |
| 98 # try using bot password to authenticate |
| 99 params = urllib.urlencode({ |
| 100 'username': username, |
| 101 'password': password |
| 102 }) |
| 103 try: |
| 104 data = logging_urlopen(status_url, params).read() |
| 105 except urllib2.HTTPError, e: |
| 106 if e.code == 405: |
| 107 logging.warn("update your chromium_status app.") |
| 108 raise |
| 109 return json.loads(data) |
93 | 110 |
94 | 111 |
95 def get_builder_section(gatekeeper_section, builder): | 112 def get_builder_section(gatekeeper_section, builder): |
96 """Returns the applicable gatekeeper config for the builder. | 113 """Returns the applicable gatekeeper config for the builder. |
97 | 114 |
98 If the builder isn't present or is excluded, return None. | 115 If the builder isn't present or is excluded, return None. |
99 """ | 116 """ |
100 if builder in gatekeeper_section: | 117 if builder in gatekeeper_section: |
101 builder_section = gatekeeper_section[builder] | 118 builder_section = gatekeeper_section[builder] |
102 elif '*' in gatekeeper_section: | 119 elif '*' in gatekeeper_section: |
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
502 ','.join(still_failing_steps), builder, master_url, | 519 ','.join(still_failing_steps), builder, master_url, |
503 urllib.quote(builder), buildnum)) | 520 urllib.quote(builder), buildnum)) |
504 | 521 |
505 if previously_failed_builds: | 522 if previously_failed_builds: |
506 logging.debug( | 523 logging.debug( |
507 'Not opening tree because previous builds weren\'t successful:') | 524 'Not opening tree because previous builds weren\'t successful:') |
508 for build in previously_failed_builds: | 525 for build in previously_failed_builds: |
509 logging.debug(' %s' % build) | 526 logging.debug(' %s' % build) |
510 return | 527 return |
511 | 528 |
512 status = get_tree_status(status_url_root) | 529 status = get_tree_status(status_url_root, username, password) |
513 # Don't change the status unless the tree is currently closed. | 530 # Don't change the status unless the tree is currently closed. |
514 if status['general_state'] != 'closed': | 531 if status['general_state'] != 'closed': |
515 return | 532 return |
516 | 533 |
517 # Don't override human closures. | 534 # Don't override human closures. |
518 # FIXME: We could check that we closed the tree instead? | 535 # FIXME: We could check that we closed the tree instead? |
519 if not re.search(r"automatic", status['message'], re.IGNORECASE): | 536 if not re.search(r"automatic", status['message'], re.IGNORECASE): |
520 return | 537 return |
521 | 538 |
522 logging.info('All builders are green, opening the tree...') | 539 logging.info('All builders are green, opening the tree...') |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
557 | 574 |
558 def close_tree_if_necessary(failed_builds, username, password, status_url_root, | 575 def close_tree_if_necessary(failed_builds, username, password, status_url_root, |
559 set_status, revision_properties): | 576 set_status, revision_properties): |
560 """Given a list of failed builds, close the tree if necessary.""" | 577 """Given a list of failed builds, close the tree if necessary.""" |
561 | 578 |
562 closing_builds = [b for b in failed_builds if b['close_tree']] | 579 closing_builds = [b for b in failed_builds if b['close_tree']] |
563 if not closing_builds: | 580 if not closing_builds: |
564 logging.info('no tree-closing failures!') | 581 logging.info('no tree-closing failures!') |
565 return | 582 return |
566 | 583 |
567 status = get_tree_status(status_url_root) | 584 status = get_tree_status(status_url_root, username, password) |
568 # Don't change the status unless the tree is currently open. | 585 # Don't change the status unless the tree is currently open. |
569 if status['general_state'] != 'open': | 586 if status['general_state'] != 'open': |
570 return | 587 return |
571 | 588 |
572 logging.info('%d failed builds found, closing the tree...' % | 589 logging.info('%d failed builds found, closing the tree...' % |
573 len(closing_builds)) | 590 len(closing_builds)) |
574 | 591 |
575 template_build = closing_builds[0] | 592 template_build = closing_builds[0] |
576 template_vars = { | 593 template_vars = { |
577 'blamelist': ','.join(template_build['build']['blame']), | 594 'blamelist': ','.join(template_build['build']['blame']), |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
881 | 898 |
882 if not options.skip_build_db_update: | 899 if not options.skip_build_db_update: |
883 build_scan_db.save_build_db(build_db, gatekeeper_config, | 900 build_scan_db.save_build_db(build_db, gatekeeper_config, |
884 options.build_db) | 901 options.build_db) |
885 | 902 |
886 return 0 | 903 return 0 |
887 | 904 |
888 | 905 |
889 if __name__ == '__main__': | 906 if __name__ == '__main__': |
890 sys.exit(main()) | 907 sys.exit(main()) |
OLD | NEW |