| Dan Albert | 7c78d24 | 2015-01-09 14:12:52 -0800 | [diff] [blame] | 1 | #!/usr/bin/env python2 | 
| Dan Albert | c02df47 | 2015-01-09 17:22:00 -0800 | [diff] [blame] | 2 | # | 
|  | 3 | # Copyright (C) 2015 The Android Open Source Project | 
|  | 4 | # | 
|  | 5 | # Licensed under the Apache License, Version 2.0 (the 'License'); | 
|  | 6 | # you may not use this file except in compliance with the License. | 
|  | 7 | # You may obtain a copy of the License at | 
|  | 8 | # | 
|  | 9 | #      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 10 | # | 
|  | 11 | # Unless required by applicable law or agreed to in writing, software | 
|  | 12 | # distributed under the License is distributed on an 'AS IS' BASIS, | 
|  | 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 14 | # See the License for the specific language governing permissions and | 
|  | 15 | # limitations under the License. | 
|  | 16 | # | 
| Dan Albert | 7c78d24 | 2015-01-09 14:12:52 -0800 | [diff] [blame] | 17 | import json | 
| Dan Albert | a4061cd | 2015-04-16 14:20:13 -0700 | [diff] [blame] | 18 | import logging | 
| Dan Albert | d3fe4f1 | 2015-04-17 13:01:29 -0700 | [diff] [blame] | 19 | import os | 
|  | 20 |  | 
|  | 21 | from apscheduler.schedulers.background import BackgroundScheduler | 
|  | 22 | from flask import Flask, request | 
| Dan Albert | 7c78d24 | 2015-01-09 14:12:52 -0800 | [diff] [blame] | 23 | import requests | 
| Dan Albert | 7c78d24 | 2015-01-09 14:12:52 -0800 | [diff] [blame] | 24 |  | 
| Dan Albert | 8a15a4e | 2015-01-09 16:52:07 -0800 | [diff] [blame] | 25 | import gerrit | 
| Dan Albert | d3fe4f1 | 2015-04-17 13:01:29 -0700 | [diff] [blame] | 26 | import tasks | 
| Dan Albert | 7c78d24 | 2015-01-09 14:12:52 -0800 | [diff] [blame] | 27 |  | 
| Dan Albert | 7c78d24 | 2015-01-09 14:12:52 -0800 | [diff] [blame] | 28 | app = Flask(__name__) | 
|  | 29 |  | 
|  | 30 |  | 
|  | 31 | def gerrit_url(endpoint): | 
| Dan Albert | c02df47 | 2015-01-09 17:22:00 -0800 | [diff] [blame] | 32 | gerrit_base_url = 'https://android-review.googlesource.com' | 
|  | 33 | return gerrit_base_url + endpoint | 
| Dan Albert | 7c78d24 | 2015-01-09 14:12:52 -0800 | [diff] [blame] | 34 |  | 
|  | 35 |  | 
|  | 36 | @app.route('/', methods=['POST']) | 
|  | 37 | def handle_build_message(): | 
| Dan Albert | c02df47 | 2015-01-09 17:22:00 -0800 | [diff] [blame] | 38 | result = json.loads(request.data) | 
| Dan Albert | 7c78d24 | 2015-01-09 14:12:52 -0800 | [diff] [blame] | 39 |  | 
| Dan Albert | c02df47 | 2015-01-09 17:22:00 -0800 | [diff] [blame] | 40 | name = result['name'] | 
|  | 41 | number = result['build']['number'] | 
|  | 42 | status = result['build']['status'] | 
|  | 43 | go_url = 'http://go/bionicbb/' + result['build']['url'] | 
|  | 44 | full_url = result['build']['full_url'] | 
|  | 45 | params = result['build']['parameters'] | 
|  | 46 | change_id = params['CHANGE_ID'] | 
|  | 47 | ref = params['REF'] | 
|  | 48 | patch_set = ref.split('/')[-1] | 
| Dan Albert | 7c78d24 | 2015-01-09 14:12:52 -0800 | [diff] [blame] | 49 |  | 
| Dan Albert | a4061cd | 2015-04-16 14:20:13 -0700 | [diff] [blame] | 50 | logging.debug('%s #%s %s: %s', name, number, status, full_url) | 
| Dan Albert | 7c78d24 | 2015-01-09 14:12:52 -0800 | [diff] [blame] | 51 |  | 
| Dan Albert | c02df47 | 2015-01-09 17:22:00 -0800 | [diff] [blame] | 52 | # bionic-lint is always broken, so we don't want to reject changes for | 
|  | 53 | # those failures until we clean things up. | 
|  | 54 | if name == 'bionic-presubmit': | 
|  | 55 | message_lines = ['{} #{} checkbuild {}: {}'.format( | 
|  | 56 | name, number, status, go_url)] | 
|  | 57 | if status == 'FAILURE': | 
|  | 58 | message_lines += ['If you believe this Verified-1 was in error, ' | 
|  | 59 | '+1 the change and bionicbb will remove the -1 ' | 
|  | 60 | 'shortly.'] | 
| Dan Albert | 7c78d24 | 2015-01-09 14:12:52 -0800 | [diff] [blame] | 61 |  | 
| Dan Albert | c02df47 | 2015-01-09 17:22:00 -0800 | [diff] [blame] | 62 | request_data = { | 
|  | 63 | 'message': '\n'.join(message_lines) | 
|  | 64 | } | 
| Dan Albert | 7c78d24 | 2015-01-09 14:12:52 -0800 | [diff] [blame] | 65 |  | 
| Dan Albert | c02df47 | 2015-01-09 17:22:00 -0800 | [diff] [blame] | 66 | label = 'Verified' | 
|  | 67 | if status == 'FAILURE': | 
|  | 68 | request_data['labels'] = {label: -1} | 
|  | 69 | elif status == 'SUCCESS': | 
|  | 70 | request_data['labels'] = {label: +1} | 
| Dan Albert | 7c78d24 | 2015-01-09 14:12:52 -0800 | [diff] [blame] | 71 |  | 
| Dan Albert | c02df47 | 2015-01-09 17:22:00 -0800 | [diff] [blame] | 72 | url = gerrit_url('/a/changes/{}/revisions/{}/review'.format(change_id, | 
|  | 73 | patch_set)) | 
| Dan Albert | 7c78d24 | 2015-01-09 14:12:52 -0800 | [diff] [blame] | 74 |  | 
| Dan Albert | c02df47 | 2015-01-09 17:22:00 -0800 | [diff] [blame] | 75 | headers = {'Content-Type': 'application/json;charset=UTF-8'} | 
| Dan Albert | a4061cd | 2015-04-16 14:20:13 -0700 | [diff] [blame] | 76 | logging.debug('POST %s: %s', url, request_data) | 
|  | 77 | requests.post(url, headers=headers, json=request_data) | 
| Dan Albert | c02df47 | 2015-01-09 17:22:00 -0800 | [diff] [blame] | 78 | elif name == 'clean-bionic-presubmit': | 
|  | 79 | request_data = {'message': 'out/ directory removed'} | 
|  | 80 | url = gerrit_url('/a/changes/{}/revisions/{}/review'.format(change_id, | 
|  | 81 | patch_set)) | 
|  | 82 | headers = {'Content-Type': 'application/json;charset=UTF-8'} | 
| Dan Albert | a4061cd | 2015-04-16 14:20:13 -0700 | [diff] [blame] | 83 | logging.debug('POST %s: %s', url, request_data) | 
|  | 84 | requests.post(url, headers=headers, json=request_data) | 
| Dan Albert | c02df47 | 2015-01-09 17:22:00 -0800 | [diff] [blame] | 85 | elif name == 'bionic-lint': | 
| Dan Albert | a4061cd | 2015-04-16 14:20:13 -0700 | [diff] [blame] | 86 | logging.warning('Result for bionic-lint ignored') | 
| Dan Albert | c02df47 | 2015-01-09 17:22:00 -0800 | [diff] [blame] | 87 | else: | 
| Dan Albert | a4061cd | 2015-04-16 14:20:13 -0700 | [diff] [blame] | 88 | logging.error('Unknown project: %s', name) | 
| Dan Albert | c02df47 | 2015-01-09 17:22:00 -0800 | [diff] [blame] | 89 | return '' | 
| Dan Albert | 7c78d24 | 2015-01-09 14:12:52 -0800 | [diff] [blame] | 90 |  | 
|  | 91 |  | 
|  | 92 | @app.route('/drop-rejection', methods=['POST']) | 
|  | 93 | def drop_rejection(): | 
| Dan Albert | c02df47 | 2015-01-09 17:22:00 -0800 | [diff] [blame] | 94 | revision_info = json.loads(request.data) | 
| Dan Albert | 7c78d24 | 2015-01-09 14:12:52 -0800 | [diff] [blame] | 95 |  | 
| Dan Albert | c02df47 | 2015-01-09 17:22:00 -0800 | [diff] [blame] | 96 | change_id = revision_info['changeid'] | 
|  | 97 | patch_set = revision_info['patchset'] | 
| Dan Albert | 7c78d24 | 2015-01-09 14:12:52 -0800 | [diff] [blame] | 98 |  | 
| Dan Albert | c02df47 | 2015-01-09 17:22:00 -0800 | [diff] [blame] | 99 | bb_email = 'bionicbb@android.com' | 
|  | 100 | labels = gerrit.get_labels(change_id, patch_set) | 
|  | 101 | if bb_email in labels['Verified']: | 
|  | 102 | bb_review = labels['Verified'][bb_email] | 
|  | 103 | else: | 
|  | 104 | bb_review = 0 | 
| Dan Albert | 7c78d24 | 2015-01-09 14:12:52 -0800 | [diff] [blame] | 105 |  | 
| Dan Albert | c02df47 | 2015-01-09 17:22:00 -0800 | [diff] [blame] | 106 | if bb_review >= 0: | 
| Dan Albert | a4061cd | 2015-04-16 14:20:13 -0700 | [diff] [blame] | 107 | logging.info('No rejection to drop: %s %s', change_id, patch_set) | 
| Dan Albert | c02df47 | 2015-01-09 17:22:00 -0800 | [diff] [blame] | 108 | return '' | 
|  | 109 |  | 
| Dan Albert | a4061cd | 2015-04-16 14:20:13 -0700 | [diff] [blame] | 110 | logging.info('Dropping rejection: %s %s', change_id, patch_set) | 
| Dan Albert | c02df47 | 2015-01-09 17:22:00 -0800 | [diff] [blame] | 111 |  | 
|  | 112 | request_data = {'labels': {'Verified': 0}} | 
|  | 113 | url = gerrit_url('/a/changes/{}/revisions/{}/review'.format(change_id, | 
|  | 114 | patch_set)) | 
|  | 115 | headers = {'Content-Type': 'application/json;charset=UTF-8'} | 
| Dan Albert | a4061cd | 2015-04-16 14:20:13 -0700 | [diff] [blame] | 116 | logging.debug('POST %s: %s', url, request_data) | 
|  | 117 | requests.post(url, headers=headers, json=request_data) | 
| Dan Albert | 7c78d24 | 2015-01-09 14:12:52 -0800 | [diff] [blame] | 118 | return '' | 
|  | 119 |  | 
| Dan Albert | 7c78d24 | 2015-01-09 14:12:52 -0800 | [diff] [blame] | 120 |  | 
|  | 121 | if __name__ == "__main__": | 
| Dan Albert | d3fe4f1 | 2015-04-17 13:01:29 -0700 | [diff] [blame] | 122 | logging.basicConfig(level=logging.INFO) | 
| Dan Albert | 21988a3 | 2015-04-17 17:51:39 -0700 | [diff] [blame] | 123 | logger = logging.getLogger() | 
|  | 124 | fh = logging.FileHandler('bionicbb.log') | 
|  | 125 | fh.setLevel(logging.INFO) | 
|  | 126 | logger.addHandler(fh) | 
| Dan Albert | d3fe4f1 | 2015-04-17 13:01:29 -0700 | [diff] [blame] | 127 |  | 
|  | 128 | # Prevent the job from being rescheduled by the reloader. | 
|  | 129 | if os.environ.get('WERKZEUG_RUN_MAIN') == 'true': | 
|  | 130 | scheduler = BackgroundScheduler() | 
|  | 131 | scheduler.start() | 
|  | 132 | scheduler.add_job(tasks.get_and_process_jobs, 'interval', minutes=5) | 
|  | 133 |  | 
| Dan Albert | c02df47 | 2015-01-09 17:22:00 -0800 | [diff] [blame] | 134 | app.run(host='0.0.0.0', debug=True) |