Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: infra/tools/antibody/antibody.py

Issue 1235373004: Added script to generate stats on a git checkout (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@new_antibody_db_schema
Patch Set: Rebase Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « infra/tools/antibody/__main__.py ('k') | infra/tools/antibody/cloudsql_connect.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2015 The Chromium Authors. All rights reserved. 1 # Copyright 2015 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """Testable functions for Antibody.""" 5 """Testable functions for Antibody."""
6 6
7 import jinja2 7 import jinja2
8 import json 8 import json
9 import logging 9 import logging
10 import os 10 import os
11 import shutil 11 import shutil
12 import time 12 import time
13 13
14 import infra.tools.antibody.cloudsql_connect as csql 14 import infra.tools.antibody.cloudsql_connect as csql
15 from infra.tools.antibody import compute_stats
15 16
16 THIS_DIR = os.path.dirname(os.path.realpath(__file__)) 17 THIS_DIR = os.path.dirname(os.path.realpath(__file__))
17 ANTIBODY_UI_MAIN_NAME = 'index.html' 18 ANTIBODY_UI_MAIN_NAME = 'index.html'
18 TBR_BY_USER_NAME = 'tbr_by_user.html' 19 TBR_BY_USER_NAME = 'tbr_by_user.html'
20 STATS_NAME = 'stats.html'
21 LEADERBOARD_NAME = 'leaderboard.html'
19 22
20 # https://storage.googleapis.com/chromium-infra-docs/infra/html/logging.html 23 # https://storage.googleapis.com/chromium-infra-docs/infra/html/logging.html
21 LOGGER = logging.getLogger(__name__) 24 LOGGER = logging.getLogger(__name__)
22 25
23 26
24 def add_argparse_options(parser): 27 def add_argparse_options(parser):
25 """Define command-line arguments.""" 28 """Define command-line arguments."""
26 parser.add_argument('--cache-path', '-c', help="path to the rietveld cache") 29 parser.add_argument('--cache-path', '-c', help="path to the rietveld cache")
27 parser.add_argument('--git-checkout-path', '-g', required=True, 30 parser.add_argument('--git-checkout-path', '-g', required=True,
28 help="path to the git checkout") 31 help="path to the git checkout")
(...skipping 15 matching lines...) Expand all
44 "format as YYYY-MM-DD") 47 "format as YYYY-MM-DD")
45 48
46 49
47 def setup_antibody_db(cc, filename): # pragma: no cover 50 def setup_antibody_db(cc, filename): # pragma: no cover
48 csql.execute_sql_script_from_file(cc, filename) 51 csql.execute_sql_script_from_file(cc, filename)
49 52
50 53
51 def generate_antibody_ui(suspicious_commits_data, gitiles_prefix, ui_dirpath): 54 def generate_antibody_ui(suspicious_commits_data, gitiles_prefix, ui_dirpath):
52 template_loader = jinja2.FileSystemLoader(os.path.join(THIS_DIR, 'templates')) 55 template_loader = jinja2.FileSystemLoader(os.path.join(THIS_DIR, 'templates'))
53 template_env = jinja2.Environment(loader=template_loader) 56 template_env = jinja2.Environment(loader=template_loader)
54 index_template = template_env.get_template('antibody_ui_all.jinja') 57 template_vars_all = {
55 tbr_by_user_template = template_env.get_template('tbr_by_user.jinja')
56
57 template_vars = {
58 'title' : 'Potentially Suspicious Commits', 58 'title' : 'Potentially Suspicious Commits',
59 'description' : 'List of commits with a TBR but no lgtm', 59 'description' : 'List of commits with a TBR but no lgtm',
60 'antibody_main_link' : ANTIBODY_UI_MAIN_NAME, 60 'antibody_main_link' : ANTIBODY_UI_MAIN_NAME,
61 'tbr_by_user_link' : TBR_BY_USER_NAME, 61 'tbr_by_user_link' : TBR_BY_USER_NAME,
62 'stats_link' : STATS_NAME,
63 'leaderboard_link' : LEADERBOARD_NAME,
62 'generation_time' : time.strftime("%a, %d %b %Y %H:%M:%S", 64 'generation_time' : time.strftime("%a, %d %b %Y %H:%M:%S",
63 time.gmtime()), 65 time.gmtime()),
64 'page_header_text' : "All Potentially Suspicious Commits", 66 'page_header_text' : "Antibody",
65 'to_be_reviewed' : "To be reviewed by user", 67 'to_be_reviewed' : "TBR by user",
66 'num_tbr_no_lgtm': len(suspicious_commits_data), 68 'stats' : 'Stats',
67 'num_no_review_url': 42, 69 'leaderboard' : 'Leaderboard',
68 'blank_TBR': 3,
69 'table_headers' : ['git_hash', 'rietveld_url',
70 'request_timestamp'],
71 'suspicious_commits' : suspicious_commits_data, 70 'suspicious_commits' : suspicious_commits_data,
72 'gitiles_prefix' : gitiles_prefix, 71 'gitiles_prefix' : gitiles_prefix,
73 } 72 }
74 with open(os.path.join(ui_dirpath, ANTIBODY_UI_MAIN_NAME), 'wb') as f:
75 f.write(index_template.render(template_vars))
76
77 with open(os.path.join(ui_dirpath, TBR_BY_USER_NAME), 'wb') as f:
78 f.write(tbr_by_user_template.render(template_vars))
79
80 try: # pragma: no cover 73 try: # pragma: no cover
81 if (ui_dirpath != THIS_DIR): # pragma: no cover 74 if (ui_dirpath != THIS_DIR): # pragma: no cover
82 shutil.rmtree(os.path.join(ui_dirpath, 'static')) 75 shutil.rmtree(os.path.join(ui_dirpath, 'static'))
83 except OSError, e: # pragma: no cover 76 except OSError, e: # pragma: no cover
84 if e.errno == 2: # [Errno 2] No such file or directory 77 if e.errno == 2: # [Errno 2] No such file or directory
85 pass 78 pass
86 else: 79 else:
87 raise 80 raise
88 if (ui_dirpath != THIS_DIR): # pragma: no cover 81 if (ui_dirpath != THIS_DIR): # pragma: no cover
89 shutil.copytree(os.path.join(THIS_DIR, 'static'), 82 shutil.copytree(os.path.join(THIS_DIR, 'static'),
90 os.path.join(ui_dirpath, 'static')) 83 os.path.join(ui_dirpath, 'static'))
91 84
85 file_generators = [generate_homepage, generate_tbr_page, generate_stats_page,
86 generate_leaderboard_page]
87 for item in file_generators:
88 item(template_env, template_vars_all, ui_dirpath)
89
90
91 def generate_homepage(template_env, template_vars_all, ui_dirpath):
92 index_template = template_env.get_template('antibody_ui_all.jinja')
93 with open(os.path.join(ui_dirpath, 'all_monthly_stats.json')) as f:
94 data = json.load(f)
95 stats_7_day = data['7_days']
96 template_vars = {
97 'num_tbr_no_lgtm': stats_7_day['tbr_no_lgtm'],
98 'num_no_review_url': stats_7_day['no_review_url'],
99 'blank_TBR': stats_7_day['blank_tbr'],
100 'table_headers' : ['Git Commit Subject', 'Review URL',
101 'Request Timestamp']}
102 template_vars.update(template_vars_all)
103 with open(os.path.join(ui_dirpath, ANTIBODY_UI_MAIN_NAME), 'wb') as f:
104 f.write(index_template.render(template_vars))
105
106
107 def generate_tbr_page(template_env, template_vars_all, ui_dirpath):
108 tbr_by_user_template = template_env.get_template('tbr_by_user.jinja')
109 template_vars = {
110 }
111 template_vars.update(template_vars_all)
112 with open(os.path.join(ui_dirpath, TBR_BY_USER_NAME), 'wb') as f:
113 f.write(tbr_by_user_template.render(template_vars))
114
115
116 def generate_stats_page(template_env, template_vars_all, ui_dirpath):
117 stats_template = template_env.get_template('stats.jinja')
118 with open(os.path.join(ui_dirpath, 'all_monthly_stats.json')) as f:
119 data = json.load(f)
120 template_vars = {}
121 stats_all = [
122 [data['7_days'], 'stats_7_day'],
123 [data['30_days'], 'stats_30_day'],
124 [data['all_time'], 'stats_all_time'],
125 ]
126 categories_keys = [
127 ['"Suspicious":Total Commits', 'suspicious_to_total_ratio'],
128 ['Total Commits', 'total_commits'],
129 ['TBR without LGTM', 'tbr_no_lgtm'],
130 ['Without review url', 'no_review_url'],
131 ['Blank TBR', 'blank_tbr'],
132 ]
133 for stats, key in stats_all:
134 template_vars[key] = [[x[0], stats[x[1]]] for x in categories_keys]
135 template_vars.update(template_vars_all)
136 with open(os.path.join(ui_dirpath, STATS_NAME), 'wb') as f:
137 f.write(stats_template.render(template_vars))
138
139
140 def generate_leaderboard_page(template_env, template_vars_all, ui_dirpath):
141 leaderboard_template = template_env.get_template('leaderboard.jinja')
142 template_vars = {
143 }
144 template_vars.update(template_vars_all)
145 with open(os.path.join(ui_dirpath, LEADERBOARD_NAME), 'wb') as f:
146 f.write(leaderboard_template.render(template_vars))
147
92 148
93 def get_tbr_by_user(tbr_no_lgtm, gitiles_prefix, output_dirpath): 149 def get_tbr_by_user(tbr_no_lgtm, gitiles_prefix, output_dirpath):
94 # tbr_no_lgtm: review_url, request_timestamp, hash, people_email_address 150 # tbr_no_lgtm: review_url, request_timestamp, subject, people_email_address,
151 # hash
95 tbr_blame_dict = {} 152 tbr_blame_dict = {}
96 for url, timestamp, git_hash, reviewer in tbr_no_lgtm: 153 for url, timestamp, subject, reviewer, git_hash in tbr_no_lgtm:
97 reviewer = reviewer.strip().split('@') 154 # timestamp = timestamp.strftime("%Y-%m-%d %H:%M:%S")
98 timestamp = timestamp.strftime("%Y-%m-%d %H:%M:%S") 155 tbr_blame_dict.setdefault(reviewer, []).append(
99 tbr_blame_dict.setdefault(reviewer[0], []).append( 156 [subject, url, timestamp, git_hash])
100 [git_hash, url, timestamp])
101 tbr_data = { 157 tbr_data = {
102 "by_user" : tbr_blame_dict, 158 "by_user" : tbr_blame_dict,
103 "gitiles_prefix" : gitiles_prefix, 159 "gitiles_prefix" : gitiles_prefix,
104 } 160 }
105 with open(os.path.join(output_dirpath, 'tbr_by_user.json'), 'wb') as f: 161 with open(os.path.join(output_dirpath, 'tbr_by_user.json'), 'wb') as f:
106 f.write(json.dumps(tbr_data)) 162 f.write(json.dumps(tbr_data))
107 163
108 164
165 def generate_stats_files(cc, output_dirpath): # pragma: no cover
166 compute_stats.all_time_leaderboard(cc,
167 os.path.join(output_dirpath, 'all_time_leaderboard.json'))
168 compute_stats.past_month_leaderboard(cc,
169 os.path.join(output_dirpath, 'past_month_leaderboard.json'))
170 compute_stats.all_monthly_stats(cc,
171 os.path.join(output_dirpath, 'all_monthly_stats.json'))
172
173
109 def get_gitiles_prefix(git_checkout_path): 174 def get_gitiles_prefix(git_checkout_path):
110 with open(os.path.join(git_checkout_path, 'codereview.settings'), 'r') as f: 175 with open(os.path.join(git_checkout_path, 'codereview.settings'), 'r') as f:
111 lines = f.readlines() 176 lines = f.readlines()
112 for line in lines: 177 for line in lines:
113 if line.startswith('VIEW_VC:'): 178 if line.startswith('VIEW_VC:'):
114 return line[len('VIEW_VC:'):].strip() 179 return line[len('VIEW_VC:'):].strip()
115 # TODO (ksho): implement more sophisticated solution if codereview.settings 180 # TODO (ksho): implement more sophisticated solution if codereview.settings
116 # does not contain VIEW_VC 181 # does not contain VIEW_VC
117 return None 182 return None
OLDNEW
« no previous file with comments | « infra/tools/antibody/__main__.py ('k') | infra/tools/antibody/cloudsql_connect.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698