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

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

Issue 2207813002: Prompt for a reason when restarting a master, include that reason in the CL description. (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Created 4 years, 4 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/restart/__main__.py ('k') | no next file » | 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 import collections 5 import collections
6 import contextlib 6 import contextlib
7 import datetime 7 import datetime
8 import dateutil.tz 8 import dateutil.tz
9 import distutils.util 9 import distutils.util
10 import json 10 import json
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 parser.add_argument( 84 parser.add_argument(
85 'masters', type=str, nargs='+', 85 'masters', type=str, nargs='+',
86 help='Master(s) to restart. "master." prefix can be omitted.') 86 help='Master(s) to restart. "master." prefix can be omitted.')
87 parser.add_argument( 87 parser.add_argument(
88 '-m', '--minutes-in-future', default=15, type=int, 88 '-m', '--minutes-in-future', default=15, type=int,
89 help='how many minutes in the future to schedule the restart. ' 89 help='how many minutes in the future to schedule the restart. '
90 'use 0 for "now." default %(default)d') 90 'use 0 for "now." default %(default)d')
91 parser.add_argument( 91 parser.add_argument(
92 '--eod', action='store_true', 92 '--eod', action='store_true',
93 help='schedules restart for 6:30PM Google Standard Time.') 93 help='schedules restart for 6:30PM Google Standard Time.')
94 parser.add_argument('-b', '--bug', default=None, type=str, 94 parser.add_argument(
95 help='Bug containing master restart request.') 95 '-b', '--bug', default=None, type=str,
96 help='Bug containing master restart request.')
96 parser.add_argument( 97 parser.add_argument(
97 '-r', '--reviewer', action='append', type=str, 98 '-r', '--reviewer', action='append', type=str,
98 help=('Reviewer (ldap or ldap@google.com) to TBR the CL to. ' 99 help=('Reviewer (ldap or ldap@google.com) to TBR the CL to. '
99 'If not specified, chooses a random reviewer from OWNERS file')) 100 'If not specified, chooses a random reviewer from OWNERS file'))
100 parser.add_argument( 101 parser.add_argument(
101 '-f', '--force', action='store_true', 102 '-f', '--force', action='store_true',
102 help='don\'t ask for confirmation, just commit') 103 help='don\'t ask for confirmation, just commit')
103 parser.add_argument( 104 parser.add_argument(
104 '-n', '--no-commit', action='store_true', 105 '-n', '--no-commit', action='store_true',
105 help='update the file, but refrain from performing the actual commit') 106 help='update the file, but refrain from performing the actual commit')
106 parser.add_argument( 107 parser.add_argument(
107 '-s', '--desired-state', default='running', 108 '-s', '--desired-state', default='running',
108 choices=buildbot_state.STATES['desired_buildbot_state'], 109 choices=buildbot_state.STATES['desired_buildbot_state'],
109 help='which desired state to put the buildbot master in ' 110 help='which desired state to put the buildbot master in '
110 '(default %(default)s)') 111 '(default %(default)s)')
112 parser.add_argument(
113 '-e', '--reason', type=str, default='',
114 help='reason for restarting the master')
111 115
112 116
113 def get_restart_spec(name, restart_time): 117 def get_restart_spec(name, restart_time):
114 def _trim_prefix(v, prefix): 118 def _trim_prefix(v, prefix):
115 if v.startswith(prefix): 119 if v.startswith(prefix):
116 return v[len(prefix):] 120 return v[len(prefix):]
117 return v 121 return v
118 name = _trim_prefix(name, 'master.') 122 name = _trim_prefix(name, 'master.')
119 123
120 def _get_restart_config(name, seen): 124 def _get_restart_config(name, seen):
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 _, domain = r.split('@', 1) 185 _, domain = r.split('@', 1)
182 if domain != 'google.com': 186 if domain != 'google.com':
183 other.append(r) 187 other.append(r)
184 else: 188 else:
185 google.append(r) 189 google.append(r)
186 else: 190 else:
187 google.append('%s@google.com' % r) 191 google.append('%s@google.com' % r)
188 return google, other 192 return google, other
189 193
190 def commit( 194 def commit(
191 target, specs, reviewers, bug, force, no_commit, desired_state): 195 target, specs, reviewers, bug, force, no_commit, desired_state, reason):
192 """Commits the local CL via the CQ.""" 196 """Commits the local CL via the CQ."""
193 if desired_state == 'running': 197 if desired_state == 'running':
194 action = 'Restarting' 198 action = 'Restarting'
195 else: 199 else:
196 action = desired_state.title() + 'ing' 200 action = desired_state.title() + 'ing'
197 201
198 desc = '%s master(s) %s\n' % ( 202 desc = '%(action)s master%(plural)s %(names)s\n\n%(reason)s\n' % {
199 action, ', '.join([s.name for s in specs])) 203 'action': action,
204 'plural': 's' if len(specs) > 1 else '',
205 'names': ', '.join([s.name for s in specs]),
206 'reason': reason,
207 }
200 if bug: 208 if bug:
201 desc += '\nBUG=%s' % bug 209 desc += '\nBUG=%s' % bug
202 tbr_whom = 'an owner' 210 tbr_whom = 'an owner'
203 if reviewers: 211 if reviewers:
204 google, other = autocomplete_and_partition(reviewers) 212 google, other = autocomplete_and_partition(reviewers)
205 if other: 213 if other:
206 print 214 print
207 print 'Error: not @google.com email(s) for reviewers found:' 215 print 'Error: not @google.com email(s) for reviewers found:'
208 print ' %s' % ('\n '.join(other)) 216 print ' %s' % ('\n '.join(other))
209 print 'Hint: save your fingertips - use just ldap: -r <ldap>' 217 print 'Hint: save your fingertips - use just ldap: -r <ldap>'
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 if not reviewers: 273 if not reviewers:
266 upload_cmd.append('--tbr-owners') 274 upload_cmd.append('--tbr-owners')
267 if not no_commit: 275 if not no_commit:
268 upload_cmd.append('-c') 276 upload_cmd.append('-c')
269 else: 277 else:
270 LOGGER.info('CQ bit not set, please commit manually. (--no-commit)') 278 LOGGER.info('CQ bit not set, please commit manually. (--no-commit)')
271 subprocess.check_call(upload_cmd, cwd=target) 279 subprocess.check_call(upload_cmd, cwd=target)
272 280
273 281
274 def run(masters, restart_time, reviewers, bug, force, no_commit, 282 def run(masters, restart_time, reviewers, bug, force, no_commit,
275 desired_state): 283 desired_state, reason):
276 """Restart all the masters in the list of masters. 284 """Restart all the masters in the list of masters.
277 285
278 Schedules the restart for restart_time. 286 Schedules the restart for restart_time.
279 287
280 Args: 288 Args:
281 masters - a list(str) of masters to restart 289 masters - a list(str) of masters to restart
282 restart_time - a datetime in UTC of when to restart them. If None, restart 290 restart_time - a datetime in UTC of when to restart them. If None, restart
283 at a predefined "end of day". 291 at a predefined "end of day".
284 reviewers - a list(str) of reviewers for the CL (may be empty) 292 reviewers - a list(str) of reviewers for the CL (may be empty)
285 bug - an integer bug number to include in the review or None 293 bug - an integer bug number to include in the review or None
286 force - a bool which causes commit not to prompt if true 294 force - a bool which causes commit not to prompt if true
287 no_commit - doesn't set the CQ bit on upload 295 no_commit - doesn't set the CQ bit on upload
288 desired_state - nominally 'running', picks which desired_state 296 desired_state - nominally 'running', picks which desired_state
289 to put the buildbot in 297 to put the buildbot in
298 reason - a short message saying why the master is being restarted
290 """ 299 """
291 masters = [get_restart_spec(m, restart_time) for m in sorted(set(masters))] 300 masters = [get_restart_spec(m, restart_time) for m in sorted(set(masters))]
292 301
302 reason = reason.strip()
303 if not reason:
304 reason = raw_input('Please provide a reason for this restart: ').strip()
305 if not reason:
306 print 'No reason provided, exiting'
307 return 0
308
293 # Step 1: Acquire a clean master state checkout. 309 # Step 1: Acquire a clean master state checkout.
294 # This repo is too small to consider caching. 310 # This repo is too small to consider caching.
295 with get_master_state_checkout() as master_state_dir: 311 with get_master_state_checkout() as master_state_dir:
296 master_state_json = os.path.join( 312 master_state_json = os.path.join(
297 master_state_dir, 'desired_master_state.json') 313 master_state_dir, 'desired_master_state.json')
298 314
299 # Step 2: make modifications to the master state json. 315 # Step 2: make modifications to the master state json.
300 LOGGER.info('Reading %s' % master_state_json) 316 LOGGER.info('Reading %s' % master_state_json)
301 with open(master_state_json, 'r') as f: 317 with open(master_state_json, 'r') as f:
302 desired_master_state = json.load(f) 318 desired_master_state = json.load(f)
(...skipping 21 matching lines...) Expand all
324 entries += 1 340 entries += 1
325 341
326 LOGGER.info('Writing back to JSON file, %d new entries' % (entries,)) 342 LOGGER.info('Writing back to JSON file, %d new entries' % (entries,))
327 desired_state_parser.write_master_state( 343 desired_state_parser.write_master_state(
328 desired_master_state, master_state_json, 344 desired_master_state, master_state_json,
329 prune_only_masters=set(m.desired_state_name for m in masters)) 345 prune_only_masters=set(m.desired_state_name for m in masters))
330 346
331 # Step 3: Send the patch to Rietveld and commit it via the CQ. 347 # Step 3: Send the patch to Rietveld and commit it via the CQ.
332 LOGGER.info('Committing back into repository') 348 LOGGER.info('Committing back into repository')
333 commit(master_state_dir, masters, reviewers, bug, force, no_commit, 349 commit(master_state_dir, masters, reviewers, bug, force, no_commit,
334 desired_state) 350 desired_state, reason)
OLDNEW
« no previous file with comments | « infra/tools/restart/__main__.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698