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

Side by Side Diff: tools/autoroller/roll_chromium_revision.py

Issue 1381963003: autoroller: Always roll and improve description (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Made CL description clearer when no deps or Clang changes. Created 5 years, 2 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 | « no previous file | 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 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 2 # Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 # 3 #
4 # Use of this source code is governed by a BSD-style license 4 # Use of this source code is governed by a BSD-style license
5 # that can be found in the LICENSE file in the root of the source 5 # that can be found in the LICENSE file in the root of the source
6 # tree. An additional intellectual property rights grant can be found 6 # tree. An additional intellectual property rights grant can be found
7 # in the file PATENTS. All contributing project authors may 7 # in the file PATENTS. All contributing project authors may
8 # be found in the AUTHORS file in the root of the source tree. 8 # be found in the AUTHORS file in the root of the source tree.
9 9
10 """Script to roll chromium_revision in the WebRTC DEPS file.""" 10 """Script to roll chromium_revision in the WebRTC DEPS file."""
11 11
12 import argparse 12 import argparse
13 import base64 13 import base64
14 import collections 14 import collections
15 import logging 15 import logging
16 import os 16 import os
17 import re 17 import re
18 import subprocess 18 import subprocess
19 import sys 19 import sys
20 import urllib 20 import urllib
21 21
22 22
23 CHROMIUM_LKGR_URL = 'https://chromium-status.appspot.com/lkgr' 23 CHROMIUM_LKGR_URL = 'https://chromium-status.appspot.com/lkgr'
24 CHROMIUM_SRC_URL = 'https://chromium.googlesource.com/chromium/src' 24 CHROMIUM_SRC_URL = 'https://chromium.googlesource.com/chromium/src'
25 CHROMIUM_COMMIT_TEMPLATE = CHROMIUM_SRC_URL + '/+/%s' 25 CHROMIUM_COMMIT_TEMPLATE = CHROMIUM_SRC_URL + '/+/%s'
26 CHROMIUM_LOG_TEMPLATE = CHROMIUM_SRC_URL + '/+log/%s'
26 CHROMIUM_FILE_TEMPLATE = CHROMIUM_SRC_URL + '/+/%s/%s' 27 CHROMIUM_FILE_TEMPLATE = CHROMIUM_SRC_URL + '/+/%s/%s'
27 28
28 COMMIT_POSITION_RE = re.compile('^Cr-Commit-Position: .*#([0-9]+).*$') 29 COMMIT_POSITION_RE = re.compile('^Cr-Commit-Position: .*#([0-9]+).*$')
29 CLANG_REVISION_RE = re.compile(r'^CLANG_REVISION=(\d+)$') 30 CLANG_REVISION_RE = re.compile(r'^CLANG_REVISION=(\d+)$')
30 ROLL_BRANCH_NAME = 'roll_chromium_revision' 31 ROLL_BRANCH_NAME = 'roll_chromium_revision'
31 32
32 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) 33 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
33 CHECKOUT_ROOT_DIR = os.path.realpath(os.path.join(SCRIPT_DIR, os.pardir, 34 CHECKOUT_ROOT_DIR = os.path.realpath(os.path.join(SCRIPT_DIR, os.pardir,
34 os.pardir)) 35 os.pardir))
35 sys.path.append(CHECKOUT_ROOT_DIR) 36 sys.path.append(CHECKOUT_ROOT_DIR)
36 import setup_links 37 import setup_links
37 38
38 sys.path.append(os.path.join(CHECKOUT_ROOT_DIR, 'tools')) 39 sys.path.append(os.path.join(CHECKOUT_ROOT_DIR, 'tools'))
39 import find_depot_tools 40 import find_depot_tools
40 find_depot_tools.add_depot_tools_to_path() 41 find_depot_tools.add_depot_tools_to_path()
41 from gclient import GClientKeywords 42 from gclient import GClientKeywords
42 43
43 CLANG_UPDATE_SCRIPT_URL_PATH = 'tools/clang/scripts/update.sh' 44 CLANG_UPDATE_SCRIPT_URL_PATH = 'tools/clang/scripts/update.sh'
44 CLANG_UPDATE_SCRIPT_LOCAL_PATH = os.path.join('tools', 'clang', 'scripts', 45 CLANG_UPDATE_SCRIPT_LOCAL_PATH = os.path.join('tools', 'clang', 'scripts',
45 'update.sh') 46 'update.sh')
46 47
47 DepsEntry = collections.namedtuple('DepsEntry', 'path url revision') 48 DepsEntry = collections.namedtuple('DepsEntry', 'path url revision')
48 ChangedDep = collections.namedtuple('ChangedDep', 'path current_rev new_rev') 49 ChangedDep = collections.namedtuple('ChangedDep',
50 'path url current_rev new_rev')
49 51
50 52
51 def ParseDepsDict(deps_content): 53 def ParseDepsDict(deps_content):
52 local_scope = {} 54 local_scope = {}
53 var = GClientKeywords.VarImpl({}, local_scope) 55 var = GClientKeywords.VarImpl({}, local_scope)
54 global_scope = { 56 global_scope = {
55 'File': GClientKeywords.FileImpl, 57 'File': GClientKeywords.FileImpl,
56 'From': GClientKeywords.FromImpl, 58 'From': GClientKeywords.FromImpl,
57 'Var': var.Lookup, 59 'Var': var.Lookup,
58 'deps_os': {}, 60 'deps_os': {},
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 for deps_dir in all_deps_dirs: 215 for deps_dir in all_deps_dirs:
214 # All deps have 'src' prepended to the path in the Chromium DEPS file. 216 # All deps have 'src' prepended to the path in the Chromium DEPS file.
215 dir_path = 'src/%s' % deps_dir 217 dir_path = 'src/%s' % deps_dir
216 218
217 for entry in GetMatchingDepsEntries(current_entries, dir_path): 219 for entry in GetMatchingDepsEntries(current_entries, dir_path):
218 new_matching_entries = GetMatchingDepsEntries(new_entries, entry.path) 220 new_matching_entries = GetMatchingDepsEntries(new_entries, entry.path)
219 assert len(new_matching_entries) <= 1, ( 221 assert len(new_matching_entries) <= 1, (
220 'Should never find more than one entry matching %s in %s, found %d' % 222 'Should never find more than one entry matching %s in %s, found %d' %
221 (entry.path, new_entries, len(new_matching_entries))) 223 (entry.path, new_entries, len(new_matching_entries)))
222 if not new_matching_entries: 224 if not new_matching_entries:
223 result.append(ChangedDep(entry.path, entry.revision, 'None')) 225 result.append(ChangedDep(entry.path, entry.url, entry.revision, 'None'))
224 elif entry != new_matching_entries[0]: 226 elif entry != new_matching_entries[0]:
225 result.append(ChangedDep(entry.path, entry.revision, 227 result.append(ChangedDep(entry.path, entry.url, entry.revision,
226 new_matching_entries[0].revision)) 228 new_matching_entries[0].revision))
227 return result 229 return result
228 230
229 231
230 def CalculateChangedClang(new_cr_rev): 232 def CalculateChangedClang(new_cr_rev):
231 def GetClangRev(lines): 233 def GetClangRev(lines):
232 for line in lines: 234 for line in lines:
233 match = CLANG_REVISION_RE.match(line) 235 match = CLANG_REVISION_RE.match(line)
234 if match: 236 if match:
235 return match.group(1) 237 return match.group(1)
236 return None 238 return None
237 239
238 chromium_src_path = os.path.join(CHECKOUT_ROOT_DIR, 'chromium', 'src', 240 chromium_src_path = os.path.join(CHECKOUT_ROOT_DIR, 'chromium', 'src',
239 CLANG_UPDATE_SCRIPT_LOCAL_PATH) 241 CLANG_UPDATE_SCRIPT_LOCAL_PATH)
240 with open(chromium_src_path, 'rb') as f: 242 with open(chromium_src_path, 'rb') as f:
241 current_lines = f.readlines() 243 current_lines = f.readlines()
242 current_rev = GetClangRev(current_lines) 244 current_rev = GetClangRev(current_lines)
243 245
244 new_clang_update_sh = ReadRemoteCrFile(CLANG_UPDATE_SCRIPT_URL_PATH, 246 new_clang_update_sh = ReadRemoteCrFile(CLANG_UPDATE_SCRIPT_URL_PATH,
245 new_cr_rev).splitlines() 247 new_cr_rev).splitlines()
246 new_rev = GetClangRev(new_clang_update_sh) 248 new_rev = GetClangRev(new_clang_update_sh)
247 return ChangedDep(CLANG_UPDATE_SCRIPT_LOCAL_PATH, current_rev, new_rev) 249 return ChangedDep(CLANG_UPDATE_SCRIPT_LOCAL_PATH, None, current_rev, new_rev)
248 250
249 251
250 def GenerateCommitMessage(current_cr_rev, new_cr_rev, changed_deps_list, 252 def GenerateCommitMessage(current_cr_rev, new_cr_rev, current_git_number,
251 clang_change): 253 new_git_number, changed_deps_list, clang_change):
252 current_cr_rev = current_cr_rev[0:7] 254 current_cr_rev = current_cr_rev[0:7]
253 new_cr_rev = new_cr_rev[0:7] 255 new_cr_rev = new_cr_rev[0:7]
254 rev_interval = '%s..%s' % (current_cr_rev, new_cr_rev) 256 rev_interval = '%s..%s' % (current_cr_rev, new_cr_rev)
255
256 current_git_number = ParseCommitPosition(ReadRemoteCrCommit(current_cr_rev))
257 new_git_number = ParseCommitPosition(ReadRemoteCrCommit(new_cr_rev))
258 git_number_interval = '%s:%s' % (current_git_number, new_git_number) 257 git_number_interval = '%s:%s' % (current_git_number, new_git_number)
259 258
260 commit_msg = ['Roll chromium_revision %s (%s)' % (rev_interval, 259 commit_msg = ['Roll chromium_revision %s (%s)\n' % (rev_interval,
261 git_number_interval)] 260 git_number_interval)]
262 261 commit_msg.append('Change log: %s' % (CHROMIUM_LOG_TEMPLATE % rev_interval))
262 commit_msg.append('Full diff: %s\n' % (CHROMIUM_COMMIT_TEMPLATE %
263 rev_interval))
263 if changed_deps_list: 264 if changed_deps_list:
264 commit_msg.append('\nRelevant changes:') 265 commit_msg.append('Changed dependencies:')
265 266
266 for c in changed_deps_list: 267 for c in changed_deps_list:
267 commit_msg.append('* %s: %s..%s' % (c.path, c.current_rev[0:7], 268 commit_msg.append('* %s: %s/+log/%s..%s' % (c.path, c.url,
268 c.new_rev[0:7])) 269 c.current_rev[0:7],
269 270 c.new_rev[0:7]))
270 change_url = CHROMIUM_FILE_TEMPLATE % (rev_interval, 'DEPS') 271 change_url = CHROMIUM_FILE_TEMPLATE % (rev_interval, 'DEPS')
271 commit_msg.append('Details: %s' % change_url) 272 commit_msg.append('DEPS diff: %s\n' % change_url)
273 else:
274 commit_msg.append('No dependencies changed.')
272 275
273 if clang_change.current_rev != clang_change.new_rev: 276 if clang_change.current_rev != clang_change.new_rev:
274 commit_msg.append('\nClang version changed %s:%s' % 277 commit_msg.append('Clang version changed %s:%s' %
275 (clang_change.current_rev, clang_change.new_rev)) 278 (clang_change.current_rev, clang_change.new_rev))
276 change_url = CHROMIUM_FILE_TEMPLATE % (rev_interval, 279 change_url = CHROMIUM_FILE_TEMPLATE % (rev_interval,
277 CLANG_UPDATE_SCRIPT_URL_PATH) 280 CLANG_UPDATE_SCRIPT_URL_PATH)
278 commit_msg.append('Details: %s' % change_url) 281 commit_msg.append('Details: %s' % change_url)
279 else: 282 else:
280 commit_msg.append('\nClang version was not updated in this roll.') 283 commit_msg.append('No update to Clang.')
281 return '\n'.join(commit_msg) 284 return '\n'.join(commit_msg)
282 285
283 286
284 def UpdateDeps(deps_filename, old_cr_revision, new_cr_revision): 287 def UpdateDeps(deps_filename, old_cr_revision, new_cr_revision):
285 """Update the DEPS file with the new revision.""" 288 """Update the DEPS file with the new revision."""
286 with open(deps_filename, 'rb') as deps_file: 289 with open(deps_filename, 'rb') as deps_file:
287 deps_content = deps_file.read() 290 deps_content = deps_file.read()
288 deps_content = deps_content.replace(old_cr_revision, new_cr_revision) 291 deps_content = deps_content.replace(old_cr_revision, new_cr_revision)
289 with open(deps_filename, 'wb') as deps_file: 292 with open(deps_filename, 'wb') as deps_file:
290 deps_file.write(deps_content) 293 deps_file.write(deps_content)
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 p = argparse.ArgumentParser() 354 p = argparse.ArgumentParser()
352 p.add_argument('--clean', action='store_true', default=False, 355 p.add_argument('--clean', action='store_true', default=False,
353 help='Removes any previous local roll branch.') 356 help='Removes any previous local roll branch.')
354 p.add_argument('-r', '--revision', 357 p.add_argument('-r', '--revision',
355 help=('Chromium Git revision to roll to. Defaults to the ' 358 help=('Chromium Git revision to roll to. Defaults to the '
356 'Chromium LKGR revision if omitted.')) 359 'Chromium LKGR revision if omitted.'))
357 p.add_argument('--dry-run', action='store_true', default=False, 360 p.add_argument('--dry-run', action='store_true', default=False,
358 help=('Calculate changes and modify DEPS, but don\'t create ' 361 help=('Calculate changes and modify DEPS, but don\'t create '
359 'any local branch, commit, upload CL or send any ' 362 'any local branch, commit, upload CL or send any '
360 'tryjobs.')) 363 'tryjobs.'))
364 p.add_argument('--allow-reverse', action='store_true', default=False,
365 help=('Allow rolling back in time (disabled by default but '
366 'may be useful to be able do to manually).'))
361 p.add_argument('-s', '--skip-try', action='store_true', default=False, 367 p.add_argument('-s', '--skip-try', action='store_true', default=False,
362 help='Do everything except sending tryjobs.') 368 help='Do everything except sending tryjobs.')
363 p.add_argument('-v', '--verbose', action='store_true', default=False, 369 p.add_argument('-v', '--verbose', action='store_true', default=False,
364 help='Be extra verbose in printing of log messages.') 370 help='Be extra verbose in printing of log messages.')
365 opts = p.parse_args() 371 opts = p.parse_args()
366 372
367 if opts.verbose: 373 if opts.verbose:
368 logging.basicConfig(level=logging.DEBUG) 374 logging.basicConfig(level=logging.DEBUG)
369 else: 375 else:
370 logging.basicConfig(level=logging.INFO) 376 logging.basicConfig(level=logging.INFO)
371 377
372 if not _IsTreeClean(): 378 if not _IsTreeClean():
373 logging.error('Please clean your local checkout first.') 379 logging.error('Please clean your local checkout first.')
374 return 1 380 return 1
375 381
376 if opts.clean: 382 if opts.clean:
377 _RemovePreviousRollBranch(opts.dry_run) 383 _RemovePreviousRollBranch(opts.dry_run)
378 384
379 _EnsureUpdatedMasterBranch(opts.dry_run) 385 _EnsureUpdatedMasterBranch(opts.dry_run)
380 386
381 if not opts.revision: 387 new_cr_rev = opts.revision
388 if not new_cr_rev:
382 lkgr_contents = ReadUrlContent(CHROMIUM_LKGR_URL) 389 lkgr_contents = ReadUrlContent(CHROMIUM_LKGR_URL)
383 logging.info('No revision specified. Using LKGR: %s', lkgr_contents[0]) 390 logging.info('No revision specified. Using LKGR: %s', lkgr_contents[0])
384 opts.revision = lkgr_contents[0] 391 new_cr_rev = lkgr_contents[0]
385 392
386 deps_filename = os.path.join(CHECKOUT_ROOT_DIR, 'DEPS') 393 deps_filename = os.path.join(CHECKOUT_ROOT_DIR, 'DEPS')
387 local_deps = ParseLocalDepsFile(deps_filename) 394 local_deps = ParseLocalDepsFile(deps_filename)
388 current_cr_rev = local_deps['vars']['chromium_revision'] 395 current_cr_rev = local_deps['vars']['chromium_revision']
389 396
397 current_git_number = ParseCommitPosition(ReadRemoteCrCommit(current_cr_rev))
phoglund 2015/10/02 06:53:42 Nit: current_git_pos or current_commit_pos? That i
kjellander_webrtc 2015/10/02 07:10:36 Good idea, I incorporated it in PS#3.
398 new_git_number = ParseCommitPosition(ReadRemoteCrCommit(new_cr_rev))
phoglund 2015/10/02 06:53:42 Ditto
kjellander_webrtc 2015/10/02 07:10:36 Done.
399
390 current_cr_deps = ParseRemoteCrDepsFile(current_cr_rev) 400 current_cr_deps = ParseRemoteCrDepsFile(current_cr_rev)
391 new_cr_deps = ParseRemoteCrDepsFile(opts.revision) 401 new_cr_deps = ParseRemoteCrDepsFile(new_cr_rev)
392 402
393 changed_deps = sorted(CalculateChangedDeps(current_cr_deps, new_cr_deps)) 403 if new_git_number > current_git_number or opts.allow_reverse:
394 clang_change = CalculateChangedClang(opts.revision) 404 changed_deps = sorted(CalculateChangedDeps(current_cr_deps, new_cr_deps))
395 if changed_deps or clang_change: 405 clang_change = CalculateChangedClang(new_cr_rev)
396 commit_msg = GenerateCommitMessage(current_cr_rev, opts.revision, 406 commit_msg = GenerateCommitMessage(current_cr_rev, new_cr_rev,
407 current_git_number, new_git_number,
397 changed_deps, clang_change) 408 changed_deps, clang_change)
398 logging.debug('Commit message:\n%s', commit_msg) 409 logging.debug('Commit message:\n%s', commit_msg)
399 else: 410 else:
400 logging.info('No deps changes detected when rolling from %s to %s. ' 411 logging.info('Currently pinned chromium_revision: %s (#%s) is newer than '
401 'Aborting without action.', current_cr_rev, opts.revision) 412 '%s (#%s). To roll to older revisions, you must pass the '
413 '--allow-reverse flag.\n'
414 'Aborting without action.', current_cr_rev, current_git_number,
415 new_cr_rev, new_git_number)
402 return 0 416 return 0
403 417
404 _CreateRollBranch(opts.dry_run) 418 _CreateRollBranch(opts.dry_run)
405 UpdateDeps(deps_filename, current_cr_rev, opts.revision) 419 UpdateDeps(deps_filename, current_cr_rev, new_cr_rev)
406 _LocalCommit(commit_msg, opts.dry_run) 420 _LocalCommit(commit_msg, opts.dry_run)
407 _UploadCL(opts.dry_run) 421 _UploadCL(opts.dry_run)
408 _LaunchTrybots(opts.dry_run, opts.skip_try) 422 _LaunchTrybots(opts.dry_run, opts.skip_try)
409 return 0 423 return 0
410 424
411 425
412 if __name__ == '__main__': 426 if __name__ == '__main__':
413 sys.exit(main()) 427 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698