Joshua Hesketh | da8ac65 | 2014-07-09 20:13:46 +1000 | [diff] [blame] | 1 | #!/usr/bin/python |
| 2 | # This tool is useful to query gerrit for negative or missing votes left by |
| 3 | # a user. It may require tweaking for different failure messages etc. |
| 4 | |
| 5 | import json |
| 6 | import requests |
| 7 | import traceback |
| 8 | |
| 9 | # Set the user to watch |
| 10 | user = 'turbo-hipster' |
Joshua Hesketh | 0d2c8b8 | 2014-08-14 12:51:46 +1000 | [diff] [blame] | 11 | author_name = 'DB Datasets CI' |
Joshua Hesketh | 426742f | 2015-12-17 17:11:38 +1100 | [diff] [blame] | 12 | author_account_id = 9578 |
Joshua Hesketh | 6730ed4 | 2015-06-12 21:33:57 +1000 | [diff] [blame] | 13 | upstream_user = 'jenkins' |
| 14 | upstream_author_name = "Jenkins" |
Joshua Hesketh | 426742f | 2015-12-17 17:11:38 +1100 | [diff] [blame] | 15 | upstream_author_account_id = 3 |
Joshua Hesketh | da8ac65 | 2014-07-09 20:13:46 +1000 | [diff] [blame] | 16 | |
| 17 | # Grab a list of missing or negative reviews for a user: |
| 18 | url = ("https://review.openstack.org/changes/?q=status:open " |
| 19 | "project:openstack/nova NOT label:Verified>=0,%s " |
| 20 | "branch:master&o=CURRENT_REVISION&o=MESSAGES" % user) |
| 21 | |
| 22 | print "Grabbing reviews from %s" % url |
| 23 | r = requests.get(url) |
| 24 | |
| 25 | no_votes = [] |
| 26 | negative_votes = [] |
| 27 | merge_failures = [] |
Joshua Hesketh | 6730ed4 | 2015-06-12 21:33:57 +1000 | [diff] [blame] | 28 | upstream_merge_failures = [] |
Joshua Hesketh | da8ac65 | 2014-07-09 20:13:46 +1000 | [diff] [blame] | 29 | unknown = [] |
| 30 | |
| 31 | for change in json.loads(r.text[5:]): |
| 32 | try: |
| 33 | patchset = change['revisions'][change['current_revision']]['_number'] |
| 34 | change_id = str(change['_number']) + ',' + str(patchset) |
| 35 | last_message = None |
Joshua Hesketh | 6730ed4 | 2015-06-12 21:33:57 +1000 | [diff] [blame] | 36 | last_upstream_message = None |
Joshua Hesketh | da8ac65 | 2014-07-09 20:13:46 +1000 | [diff] [blame] | 37 | for message in sorted(change['messages'], |
| 38 | key=lambda k: (k['_revision_number'], |
| 39 | k['date']), reverse=True): |
| 40 | if message['_revision_number'] < patchset: |
| 41 | # Finished looking at all the messages on this patchset |
| 42 | break |
Joshua Hesketh | 426742f | 2015-12-17 17:11:38 +1100 | [diff] [blame] | 43 | if (not last_message and |
| 44 | message['author']['_account_id'] == author_account_id): |
Joshua Hesketh | da8ac65 | 2014-07-09 20:13:46 +1000 | [diff] [blame] | 45 | last_message = message['message'] |
Joshua Hesketh | 6730ed4 | 2015-06-12 21:33:57 +1000 | [diff] [blame] | 46 | if (not last_upstream_message and |
Joshua Hesketh | 426742f | 2015-12-17 17:11:38 +1100 | [diff] [blame] | 47 | message['author']['_account_id'] == |
| 48 | upstream_author_account_id): |
Joshua Hesketh | 6730ed4 | 2015-06-12 21:33:57 +1000 | [diff] [blame] | 49 | last_upstream_message = message['message'] |
Joshua Hesketh | da8ac65 | 2014-07-09 20:13:46 +1000 | [diff] [blame] | 50 | |
Joshua Hesketh | 6730ed4 | 2015-06-12 21:33:57 +1000 | [diff] [blame] | 51 | if (last_upstream_message and |
| 52 | 'Merge Failed.' in last_upstream_message.split('\n')[2]): |
| 53 | upstream_merge_failures.append({ |
| 54 | 'change_id': change_id, |
| 55 | 'updated': change['updated'], |
| 56 | 'change': change, |
| 57 | 'last_upstream_message': last_upstream_message, |
| 58 | }) |
| 59 | elif not last_message: |
Joshua Hesketh | da8ac65 | 2014-07-09 20:13:46 +1000 | [diff] [blame] | 60 | # turbo-hister hasn't commented on this patchset |
| 61 | no_votes.append({ |
| 62 | 'change_id': change_id, |
| 63 | 'updated': change['updated'], |
Joshua Hesketh | 6730ed4 | 2015-06-12 21:33:57 +1000 | [diff] [blame] | 64 | 'change': change, |
| 65 | 'last_upstream_message': last_upstream_message, |
Joshua Hesketh | da8ac65 | 2014-07-09 20:13:46 +1000 | [diff] [blame] | 66 | }) |
| 67 | elif ('This change was unable to be automatically merged with the ' |
| 68 | 'current state of the repository.' in last_message): |
| 69 | merge_failures.append({ |
| 70 | 'change_id': change_id, |
| 71 | 'updated': change['updated'], |
Joshua Hesketh | 6730ed4 | 2015-06-12 21:33:57 +1000 | [diff] [blame] | 72 | 'change': change, |
| 73 | 'last_upstream_message': last_upstream_message, |
Joshua Hesketh | da8ac65 | 2014-07-09 20:13:46 +1000 | [diff] [blame] | 74 | }) |
| 75 | elif 'Database migration testing failed' in last_message: |
| 76 | negative_votes.append({ |
| 77 | 'change_id': change_id, |
| 78 | 'updated': change['updated'], |
Joshua Hesketh | 6730ed4 | 2015-06-12 21:33:57 +1000 | [diff] [blame] | 79 | 'change': change, |
| 80 | 'last_upstream_message': last_upstream_message, |
Joshua Hesketh | da8ac65 | 2014-07-09 20:13:46 +1000 | [diff] [blame] | 81 | }) |
| 82 | else: |
| 83 | unknown.append({ |
| 84 | 'change_id': change_id, |
| 85 | 'updated': change['updated'], |
Joshua Hesketh | 6730ed4 | 2015-06-12 21:33:57 +1000 | [diff] [blame] | 86 | 'change': change, |
| 87 | 'last_upstream_message': last_upstream_message, |
Joshua Hesketh | da8ac65 | 2014-07-09 20:13:46 +1000 | [diff] [blame] | 88 | }) |
| 89 | |
| 90 | except Exception: |
| 91 | print "Something failed.. Here is the change..." |
| 92 | print change |
| 93 | traceback.print_exc() |
| 94 | |
| 95 | |
| 96 | def print_enqueues(changes): |
| 97 | for change in sorted(changes, key=lambda k: k['updated'], reverse=True): |
| 98 | print ("zuul enqueue --trigger gerrit --pipeline check " |
| 99 | "--project openstack/nova --change %s" % (change['change_id'])) |
| 100 | |
| 101 | print "=" * 20 + (" Changes with no votes (%d) " % len(no_votes)) + "=" * 20 |
| 102 | print_enqueues(no_votes) |
| 103 | print ("=" * 20 + (" Changes with negative votes (%d) " % len(negative_votes)) |
| 104 | + "=" * 20) |
| 105 | print_enqueues(negative_votes) |
| 106 | print ("=" * 20 + (" Changes with merge failure (%d) " % len(merge_failures)) + |
| 107 | "=" * 20) |
| 108 | print_enqueues(merge_failures) |
| 109 | print "=" * 20 + (" Others in this query (%d) " % len(unknown)) + "=" * 20 |
| 110 | print_enqueues(unknown) |
Joshua Hesketh | 6730ed4 | 2015-06-12 21:33:57 +1000 | [diff] [blame] | 111 | print "=" * 20 + (" Changes with merge failures upstream (%d) " |
| 112 | % len(upstream_merge_failures)) + "=" * 20 |
| 113 | print_enqueues(upstream_merge_failures) |