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 import argparse | 6 import argparse |
7 import datetime | 7 import datetime |
8 import json | 8 import json |
9 import logging | 9 import logging |
10 import sys | 10 import sys |
(...skipping 15 matching lines...) Expand all Loading... | |
26 build_scripts_dir = os.path.join(top_dir, 'build', 'scripts') | 26 build_scripts_dir = os.path.join(top_dir, 'build', 'scripts') |
27 sys.path.insert(0, build_scripts_dir) | 27 sys.path.insert(0, build_scripts_dir) |
28 | 28 |
29 # Our sys.path hacks are too bursting with chest-hair for pylint's little brain. | 29 # Our sys.path hacks are too bursting with chest-hair for pylint's little brain. |
30 from slave import gatekeeper_ng_config # pylint: disable=F0401 | 30 from slave import gatekeeper_ng_config # pylint: disable=F0401 |
31 | 31 |
32 | 32 |
33 CACHE_PATH = 'build_cache' | 33 CACHE_PATH = 'build_cache' |
34 | 34 |
35 | 35 |
36 def apply_gatekeeper_rules(alerts, gatekeeper): | |
37 filtered_alerts = [] | |
38 for alert in alerts: | |
39 master_url = alert['master_url'] | |
40 master_name = buildbot.master_name_from_url(master_url) | |
41 config = gatekeeper.get(master_url) | |
42 if not config: | |
43 # Unclear if this should be set or not? | |
44 # alert['would_close_tree'] = False | |
45 filtered_alerts.append(alert) | |
46 continue | |
47 excluded_builders = gatekeeper_extras.excluded_builders(config) | |
48 if alert['builder_name'] in excluded_builders: | |
49 continue | |
50 alert['would_close_tree'] = \ | |
51 gatekeeper_extras.would_close_tree(config, | |
52 alert['builder_name'], alert['step_name']) | |
53 filtered_alerts.append(alert) | |
54 alert['tree_name'] = gatekeeper_extras.tree_for_master(master_name) | |
55 return filtered_alerts | |
56 | |
57 | |
58 def fetch_master_urls(gatekeeper, args): | |
59 # Currently using gatekeeper.json, but could use: | |
60 # https://chrome-infra-stats.appspot.com/_ah/api#p/stats/v1/stats.masters.list | |
61 master_urls = gatekeeper.keys() | |
62 if args.master_filter: | |
63 master_urls = [url for url in master_urls if args.master_filter not in url] | |
64 return master_urls | |
65 | |
66 | |
67 def main(args): | 36 def main(args): |
68 parser = argparse.ArgumentParser(prog='run.py %s' % __package__) | 37 parser = argparse.ArgumentParser(prog='run.py %s' % __package__) |
69 parser.add_argument('data_url', action='store', nargs='*') | 38 parser.add_argument('data_url', action='store', nargs='*') |
70 parser.add_argument('--use-cache', action='store_true') | 39 parser.add_argument('--use-cache', action='store_true') |
71 parser.add_argument('--master-filter', action='store') | 40 parser.add_argument('--master-filter', action='store') |
72 parser.add_argument('--builder-filter', action='store') | 41 parser.add_argument('--builder-filter', action='store') |
73 # FIXME: Ideally we'd have adjustable logging instead of just DEBUG vs. CRIT. | 42 # FIXME: Ideally we'd have adjustable logging instead of just DEBUG vs. CRIT. |
74 parser.add_argument("-v", "--verbose", action='store_true') | 43 parser.add_argument("-v", "--verbose", action='store_true') |
75 | 44 |
76 gatekeeper_json = os.path.join(build_scripts_dir, 'slave', 'gatekeeper.json') | 45 gatekeeper_json = os.path.join(build_scripts_dir, 'slave', 'gatekeeper.json') |
77 parser.add_argument('--gatekeeper', action='store', default=gatekeeper_json) | 46 parser.add_argument('--gatekeeper', action='store', default=gatekeeper_json) |
78 args = parser.parse_args(args) | 47 args = parser.parse_args(args) |
79 | 48 |
80 logging.basicConfig(level=logging.DEBUG if args.verbose else logging.CRITICAL) | 49 logging.basicConfig(level=logging.DEBUG if args.verbose else logging.CRITICAL) |
81 | 50 |
82 if not args.data_url: | 51 if not args.data_url: |
83 logging.warn("No /data url passed, will write to builder_alerts.json") | 52 logging.warn("No /data url passed, will write to builder_alerts.json") |
84 | 53 |
85 if args.use_cache: | 54 if args.use_cache: |
86 requests_cache.install_cache('failure_stats') | 55 requests_cache.install_cache('failure_stats') |
87 else: | 56 else: |
88 requests_cache.install_cache(backend='memory') | 57 requests_cache.install_cache(backend='memory') |
89 | 58 |
90 # FIXME: gatekeeper_config should find gatekeeper.json for us. | 59 # FIXME: gatekeeper_config should find gatekeeper.json for us. |
91 gatekeeper_path = os.path.abspath(args.gatekeeper) | 60 gatekeeper_path = os.path.abspath(args.gatekeeper) |
92 print "Processsing gatekeeper json: %s" % (gatekeeper_path) | 61 logging.debug("Processsing gatekeeper json: %s" % gatekeeper_path) |
93 gatekeeper = gatekeeper_ng_config.load_gatekeeper_config(gatekeeper_path) | 62 gatekeeper = gatekeeper_ng_config.load_gatekeeper_config(gatekeeper_path) |
94 master_urls = fetch_master_urls(gatekeeper, args) | 63 |
64 gatekeeper_trees_path = os.path.join(os.path.dirname(gatekeeper_path), | |
65 'gatekeeper_trees.json') | |
66 logging.debug('Processing gatekeeper trees json: %s' % gatekeeper_trees_path) | |
tandrii(chromium)
2014/09/04 14:21:06
logging accepts *args at the end, and does string
Sergiy Byelozyorov
2014/09/05 12:59:06
Done.
| |
67 gatekeeper_trees = gatekeeper_ng_config.load_gatekeeper_tree_config( | |
68 gatekeeper_trees_path) | |
69 | |
70 master_urls = gatekeeper_extras.fetch_master_urls(gatekeeper, args) | |
95 start_time = datetime.datetime.now() | 71 start_time = datetime.datetime.now() |
96 | 72 |
97 latest_builder_info = {} | 73 latest_builder_info = {} |
98 | 74 |
99 cache = buildbot.BuildCache(CACHE_PATH) | 75 cache = buildbot.BuildCache(CACHE_PATH) |
100 | 76 |
101 alerts = [] | 77 alerts = [] |
102 for master_url in master_urls: | 78 for master_url in master_urls: |
103 master_json = buildbot.fetch_master_json(master_url) | 79 master_json = buildbot.fetch_master_json(master_url) |
104 master_alerts = alert_builder.alerts_for_master(cache, | 80 master_alerts = alert_builder.alerts_for_master(cache, |
105 master_url, master_json, args.builder_filter) | 81 master_url, master_json, args.builder_filter) |
106 alerts.extend(master_alerts) | 82 alerts.extend(master_alerts) |
107 | 83 |
108 # FIXME: This doesn't really belong here. garden-o-matic wants | 84 # FIXME: This doesn't really belong here. garden-o-matic wants |
109 # this data and we happen to have the builder json cached at | 85 # this data and we happen to have the builder json cached at |
110 # this point so it's cheap to compute. | 86 # this point so it's cheap to compute. |
111 builder_info = buildbot.latest_builder_info_for_master(cache, | 87 builder_info = buildbot.latest_builder_info_for_master(cache, |
112 master_url, master_json) | 88 master_url, master_json) |
113 latest_builder_info.update(builder_info) | 89 latest_builder_info.update(builder_info) |
114 | 90 |
115 | 91 |
116 print "Fetch took: %s" % (datetime.datetime.now() - start_time) | 92 print "Fetch took: %s" % (datetime.datetime.now() - start_time) |
117 | 93 |
118 alerts = apply_gatekeeper_rules(alerts, gatekeeper) | 94 alerts = gatekeeper_extras.apply_gatekeeper_rules(alerts, gatekeeper, |
95 gatekeeper_trees) | |
119 | 96 |
120 alerts = analysis.assign_keys(alerts) | 97 alerts = analysis.assign_keys(alerts) |
121 reason_groups = analysis.group_by_reason(alerts) | 98 reason_groups = analysis.group_by_reason(alerts) |
122 range_groups = analysis.merge_by_range(reason_groups) | 99 range_groups = analysis.merge_by_range(reason_groups) |
123 data = { 'content': json.dumps({ | 100 data = { 'content': json.dumps({ |
124 'alerts': alerts, | 101 'alerts': alerts, |
125 'reason_groups': reason_groups, | 102 'reason_groups': reason_groups, |
126 'range_groups': range_groups, | 103 'range_groups': range_groups, |
127 'latest_builder_info': latest_builder_info, | 104 'latest_builder_info': latest_builder_info, |
128 })} | 105 })} |
129 | 106 |
130 if not args.data_url: | 107 if not args.data_url: |
131 with open('builder_alerts.json', 'w') as f: | 108 with open('builder_alerts.json', 'w') as f: |
132 f.write(json.dumps(data, indent=1)) | 109 f.write(json.dumps(data, indent=1)) |
133 | 110 |
134 for url in args.data_url: | 111 for url in args.data_url: |
135 logging.info('POST %s alerts to %s' % (len(alerts), url)) | 112 logging.info('POST %s alerts to %s' % (len(alerts), url)) |
136 requests.post(url, data=data) | 113 requests.post(url, data=data) |
137 | 114 |
138 | 115 |
139 if __name__ == '__main__': | 116 if __name__ == '__main__': |
140 sys.exit(main(sys.argv[1:])) | 117 sys.exit(main(sys.argv[1:])) |
OLD | NEW |