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

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: Rebase and git number -> commit position 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_SRC_URL = 'https://chromium.googlesource.com/chromium/src' 23 CHROMIUM_SRC_URL = 'https://chromium.googlesource.com/chromium/src'
24 CHROMIUM_COMMIT_TEMPLATE = CHROMIUM_SRC_URL + '/+/%s' 24 CHROMIUM_COMMIT_TEMPLATE = CHROMIUM_SRC_URL + '/+/%s'
25 CHROMIUM_LOG_TEMPLATE = CHROMIUM_SRC_URL + '/+log/%s'
25 CHROMIUM_FILE_TEMPLATE = CHROMIUM_SRC_URL + '/+/%s/%s' 26 CHROMIUM_FILE_TEMPLATE = CHROMIUM_SRC_URL + '/+/%s/%s'
26 27
27 COMMIT_POSITION_RE = re.compile('^Cr-Commit-Position: .*#([0-9]+).*$') 28 COMMIT_POSITION_RE = re.compile('^Cr-Commit-Position: .*#([0-9]+).*$')
28 CLANG_REVISION_RE = re.compile(r'^CLANG_REVISION=(\d+)$') 29 CLANG_REVISION_RE = re.compile(r'^CLANG_REVISION=(\d+)$')
29 ROLL_BRANCH_NAME = 'roll_chromium_revision' 30 ROLL_BRANCH_NAME = 'roll_chromium_revision'
30 31
31 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) 32 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
32 CHECKOUT_ROOT_DIR = os.path.realpath(os.path.join(SCRIPT_DIR, os.pardir, 33 CHECKOUT_ROOT_DIR = os.path.realpath(os.path.join(SCRIPT_DIR, os.pardir,
33 os.pardir)) 34 os.pardir))
34 sys.path.append(CHECKOUT_ROOT_DIR) 35 sys.path.append(CHECKOUT_ROOT_DIR)
35 import setup_links 36 import setup_links
36 37
37 sys.path.append(os.path.join(CHECKOUT_ROOT_DIR, 'tools')) 38 sys.path.append(os.path.join(CHECKOUT_ROOT_DIR, 'tools'))
38 import find_depot_tools 39 import find_depot_tools
39 find_depot_tools.add_depot_tools_to_path() 40 find_depot_tools.add_depot_tools_to_path()
40 from gclient import GClientKeywords 41 from gclient import GClientKeywords
41 42
42 CLANG_UPDATE_SCRIPT_URL_PATH = 'tools/clang/scripts/update.sh' 43 CLANG_UPDATE_SCRIPT_URL_PATH = 'tools/clang/scripts/update.sh'
43 CLANG_UPDATE_SCRIPT_LOCAL_PATH = os.path.join('tools', 'clang', 'scripts', 44 CLANG_UPDATE_SCRIPT_LOCAL_PATH = os.path.join('tools', 'clang', 'scripts',
44 'update.sh') 45 'update.sh')
45 46
46 DepsEntry = collections.namedtuple('DepsEntry', 'path url revision') 47 DepsEntry = collections.namedtuple('DepsEntry', 'path url revision')
47 ChangedDep = collections.namedtuple('ChangedDep', 'path current_rev new_rev') 48 ChangedDep = collections.namedtuple('ChangedDep',
49 'path url current_rev new_rev')
48 50
49 51
50 def ParseDepsDict(deps_content): 52 def ParseDepsDict(deps_content):
51 local_scope = {} 53 local_scope = {}
52 var = GClientKeywords.VarImpl({}, local_scope) 54 var = GClientKeywords.VarImpl({}, local_scope)
53 global_scope = { 55 global_scope = {
54 'File': GClientKeywords.FileImpl, 56 'File': GClientKeywords.FileImpl,
55 'From': GClientKeywords.FromImpl, 57 'From': GClientKeywords.FromImpl,
56 'Var': var.Lookup, 58 'Var': var.Lookup,
57 'deps_os': {}, 59 'deps_os': {},
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 for deps_dir in all_deps_dirs: 214 for deps_dir in all_deps_dirs:
213 # All deps have 'src' prepended to the path in the Chromium DEPS file. 215 # All deps have 'src' prepended to the path in the Chromium DEPS file.
214 dir_path = 'src/%s' % deps_dir 216 dir_path = 'src/%s' % deps_dir
215 217
216 for entry in GetMatchingDepsEntries(current_entries, dir_path): 218 for entry in GetMatchingDepsEntries(current_entries, dir_path):
217 new_matching_entries = GetMatchingDepsEntries(new_entries, entry.path) 219 new_matching_entries = GetMatchingDepsEntries(new_entries, entry.path)
218 assert len(new_matching_entries) <= 1, ( 220 assert len(new_matching_entries) <= 1, (
219 'Should never find more than one entry matching %s in %s, found %d' % 221 'Should never find more than one entry matching %s in %s, found %d' %
220 (entry.path, new_entries, len(new_matching_entries))) 222 (entry.path, new_entries, len(new_matching_entries)))
221 if not new_matching_entries: 223 if not new_matching_entries:
222 result.append(ChangedDep(entry.path, entry.revision, 'None')) 224 result.append(ChangedDep(entry.path, entry.url, entry.revision, 'None'))
223 elif entry != new_matching_entries[0]: 225 elif entry != new_matching_entries[0]:
224 result.append(ChangedDep(entry.path, entry.revision, 226 result.append(ChangedDep(entry.path, entry.url, entry.revision,
225 new_matching_entries[0].revision)) 227 new_matching_entries[0].revision))
226 return result 228 return result
227 229
228 230
229 def CalculateChangedClang(new_cr_rev): 231 def CalculateChangedClang(new_cr_rev):
230 def GetClangRev(lines): 232 def GetClangRev(lines):
231 for line in lines: 233 for line in lines:
232 match = CLANG_REVISION_RE.match(line) 234 match = CLANG_REVISION_RE.match(line)
233 if match: 235 if match:
234 return match.group(1) 236 return match.group(1)
235 return None 237 return None
236 238
237 chromium_src_path = os.path.join(CHECKOUT_ROOT_DIR, 'chromium', 'src', 239 chromium_src_path = os.path.join(CHECKOUT_ROOT_DIR, 'chromium', 'src',
238 CLANG_UPDATE_SCRIPT_LOCAL_PATH) 240 CLANG_UPDATE_SCRIPT_LOCAL_PATH)
239 with open(chromium_src_path, 'rb') as f: 241 with open(chromium_src_path, 'rb') as f:
240 current_lines = f.readlines() 242 current_lines = f.readlines()
241 current_rev = GetClangRev(current_lines) 243 current_rev = GetClangRev(current_lines)
242 244
243 new_clang_update_sh = ReadRemoteCrFile(CLANG_UPDATE_SCRIPT_URL_PATH, 245 new_clang_update_sh = ReadRemoteCrFile(CLANG_UPDATE_SCRIPT_URL_PATH,
244 new_cr_rev).splitlines() 246 new_cr_rev).splitlines()
245 new_rev = GetClangRev(new_clang_update_sh) 247 new_rev = GetClangRev(new_clang_update_sh)
246 return ChangedDep(CLANG_UPDATE_SCRIPT_LOCAL_PATH, current_rev, new_rev) 248 return ChangedDep(CLANG_UPDATE_SCRIPT_LOCAL_PATH, None, current_rev, new_rev)
247 249
248 250
249 def GenerateCommitMessage(current_cr_rev, new_cr_rev, changed_deps_list, 251 def GenerateCommitMessage(current_cr_rev, new_cr_rev, current_commit_pos,
250 clang_change): 252 new_commit_pos, changed_deps_list, clang_change):
251 current_cr_rev = current_cr_rev[0:7] 253 current_cr_rev = current_cr_rev[0:7]
252 new_cr_rev = new_cr_rev[0:7] 254 new_cr_rev = new_cr_rev[0:7]
253 rev_interval = '%s..%s' % (current_cr_rev, new_cr_rev) 255 rev_interval = '%s..%s' % (current_cr_rev, new_cr_rev)
256 git_number_interval = '%s:%s' % (current_commit_pos, new_commit_pos)
254 257
255 current_git_number = ParseCommitPosition(ReadRemoteCrCommit(current_cr_rev)) 258 commit_msg = ['Roll chromium_revision %s (%s)\n' % (rev_interval,
256 new_git_number = ParseCommitPosition(ReadRemoteCrCommit(new_cr_rev)) 259 git_number_interval)]
257 git_number_interval = '%s:%s' % (current_git_number, new_git_number) 260 commit_msg.append('Change log: %s' % (CHROMIUM_LOG_TEMPLATE % rev_interval))
261 commit_msg.append('Full diff: %s\n' % (CHROMIUM_COMMIT_TEMPLATE %
262 rev_interval))
258 263
259 commit_msg = ['Roll chromium_revision %s (%s)' % (rev_interval,
260 git_number_interval)]
261 # TBR field will be empty unless in some custom cases, where some engineers 264 # TBR field will be empty unless in some custom cases, where some engineers
262 # are added. 265 # are added.
263 tbr_authors = '' 266 tbr_authors = ''
267
264 if changed_deps_list: 268 if changed_deps_list:
265 commit_msg.append('\nRelevant changes:') 269 commit_msg.append('Changed dependencies:')
266 270
267 for c in changed_deps_list: 271 for c in changed_deps_list:
268 commit_msg.append('* %s: %s..%s' % (c.path, c.current_rev[0:7], 272 commit_msg.append('* %s: %s/+log/%s..%s' % (c.path, c.url,
269 c.new_rev[0:7])) 273 c.current_rev[0:7],
274 c.new_rev[0:7]))
270 if 'libvpx' in c.path: 275 if 'libvpx' in c.path:
271 tbr_authors += 'marpan@webrtc.org, stefan@webrtc.org, ' 276 tbr_authors += 'marpan@webrtc.org, stefan@webrtc.org, '
272 277
273 change_url = CHROMIUM_FILE_TEMPLATE % (rev_interval, 'DEPS') 278 change_url = CHROMIUM_FILE_TEMPLATE % (rev_interval, 'DEPS')
274 commit_msg.append('Details: %s' % change_url) 279 commit_msg.append('DEPS diff: %s\n' % change_url)
280 else:
281 commit_msg.append('No dependencies changed.')
275 282
276 if clang_change.current_rev != clang_change.new_rev: 283 if clang_change.current_rev != clang_change.new_rev:
277 commit_msg.append('\nClang version changed %s:%s' % 284 commit_msg.append('Clang version changed %s:%s' %
278 (clang_change.current_rev, clang_change.new_rev)) 285 (clang_change.current_rev, clang_change.new_rev))
279 change_url = CHROMIUM_FILE_TEMPLATE % (rev_interval, 286 change_url = CHROMIUM_FILE_TEMPLATE % (rev_interval,
280 CLANG_UPDATE_SCRIPT_URL_PATH) 287 CLANG_UPDATE_SCRIPT_URL_PATH)
281 commit_msg.append('Details: %s' % change_url) 288 commit_msg.append('Details: %s' % change_url)
282 tbr_authors += 'pbos@webrtc.org' 289 tbr_authors += 'pbos@webrtc.org'
283 else: 290 else:
284 commit_msg.append('\nClang version was not updated in this roll.') 291 commit_msg.append('No update to Clang.')
292
285 commit_msg.append('\nTBR=%s\n' % tbr_authors) 293 commit_msg.append('\nTBR=%s\n' % tbr_authors)
286 return '\n'.join(commit_msg) 294 return '\n'.join(commit_msg)
287 295
288 296
289 def UpdateDeps(deps_filename, old_cr_revision, new_cr_revision): 297 def UpdateDeps(deps_filename, old_cr_revision, new_cr_revision):
290 """Update the DEPS file with the new revision.""" 298 """Update the DEPS file with the new revision."""
291 with open(deps_filename, 'rb') as deps_file: 299 with open(deps_filename, 'rb') as deps_file:
292 deps_content = deps_file.read() 300 deps_content = deps_file.read()
293 deps_content = deps_content.replace(old_cr_revision, new_cr_revision) 301 deps_content = deps_content.replace(old_cr_revision, new_cr_revision)
294 with open(deps_filename, 'wb') as deps_file: 302 with open(deps_filename, 'wb') as deps_file:
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 p = argparse.ArgumentParser() 363 p = argparse.ArgumentParser()
356 p.add_argument('--clean', action='store_true', default=False, 364 p.add_argument('--clean', action='store_true', default=False,
357 help='Removes any previous local roll branch.') 365 help='Removes any previous local roll branch.')
358 p.add_argument('-r', '--revision', 366 p.add_argument('-r', '--revision',
359 help=('Chromium Git revision to roll to. Defaults to the ' 367 help=('Chromium Git revision to roll to. Defaults to the '
360 'Chromium HEAD revision if omitted.')) 368 'Chromium HEAD revision if omitted.'))
361 p.add_argument('--dry-run', action='store_true', default=False, 369 p.add_argument('--dry-run', action='store_true', default=False,
362 help=('Calculate changes and modify DEPS, but don\'t create ' 370 help=('Calculate changes and modify DEPS, but don\'t create '
363 'any local branch, commit, upload CL or send any ' 371 'any local branch, commit, upload CL or send any '
364 'tryjobs.')) 372 'tryjobs.'))
373 p.add_argument('--allow-reverse', action='store_true', default=False,
374 help=('Allow rolling back in time (disabled by default but '
375 'may be useful to be able do to manually).'))
365 p.add_argument('-s', '--skip-try', action='store_true', default=False, 376 p.add_argument('-s', '--skip-try', action='store_true', default=False,
366 help='Do everything except sending tryjobs.') 377 help='Do everything except sending tryjobs.')
367 p.add_argument('-v', '--verbose', action='store_true', default=False, 378 p.add_argument('-v', '--verbose', action='store_true', default=False,
368 help='Be extra verbose in printing of log messages.') 379 help='Be extra verbose in printing of log messages.')
369 opts = p.parse_args() 380 opts = p.parse_args()
370 381
371 if opts.verbose: 382 if opts.verbose:
372 logging.basicConfig(level=logging.DEBUG) 383 logging.basicConfig(level=logging.DEBUG)
373 else: 384 else:
374 logging.basicConfig(level=logging.INFO) 385 logging.basicConfig(level=logging.INFO)
375 386
376 if not _IsTreeClean(): 387 if not _IsTreeClean():
377 logging.error('Please clean your local checkout first.') 388 logging.error('Please clean your local checkout first.')
378 return 1 389 return 1
379 390
380 if opts.clean: 391 if opts.clean:
381 _RemovePreviousRollBranch(opts.dry_run) 392 _RemovePreviousRollBranch(opts.dry_run)
382 393
383 _EnsureUpdatedMasterBranch(opts.dry_run) 394 _EnsureUpdatedMasterBranch(opts.dry_run)
384 395
385 if not opts.revision: 396 new_cr_rev = opts.revision
397 if not new_cr_rev:
386 stdout, _ = _RunCommand(['git', 'ls-remote', CHROMIUM_SRC_URL, 'HEAD']) 398 stdout, _ = _RunCommand(['git', 'ls-remote', CHROMIUM_SRC_URL, 'HEAD'])
387 head_rev = stdout.strip().split('\t')[0] 399 head_rev = stdout.strip().split('\t')[0]
388 logging.info('No revision specified. Using HEAD: %s', head_rev) 400 logging.info('No revision specified. Using HEAD: %s', head_rev)
389 opts.revision = head_rev 401 new_cr_rev = head_rev
390 402
391 deps_filename = os.path.join(CHECKOUT_ROOT_DIR, 'DEPS') 403 deps_filename = os.path.join(CHECKOUT_ROOT_DIR, 'DEPS')
392 local_deps = ParseLocalDepsFile(deps_filename) 404 local_deps = ParseLocalDepsFile(deps_filename)
393 current_cr_rev = local_deps['vars']['chromium_revision'] 405 current_cr_rev = local_deps['vars']['chromium_revision']
394 406
407 current_commit_pos = ParseCommitPosition(ReadRemoteCrCommit(current_cr_rev))
408 new_commit_pos = ParseCommitPosition(ReadRemoteCrCommit(new_cr_rev))
409
395 current_cr_deps = ParseRemoteCrDepsFile(current_cr_rev) 410 current_cr_deps = ParseRemoteCrDepsFile(current_cr_rev)
396 new_cr_deps = ParseRemoteCrDepsFile(opts.revision) 411 new_cr_deps = ParseRemoteCrDepsFile(new_cr_rev)
397 412
398 changed_deps = sorted(CalculateChangedDeps(current_cr_deps, new_cr_deps)) 413 if new_commit_pos > current_commit_pos or opts.allow_reverse:
399 clang_change = CalculateChangedClang(opts.revision) 414 changed_deps = sorted(CalculateChangedDeps(current_cr_deps, new_cr_deps))
400 if changed_deps or clang_change: 415 clang_change = CalculateChangedClang(new_cr_rev)
401 commit_msg = GenerateCommitMessage(current_cr_rev, opts.revision, 416 commit_msg = GenerateCommitMessage(current_cr_rev, new_cr_rev,
417 current_commit_pos, new_commit_pos,
402 changed_deps, clang_change) 418 changed_deps, clang_change)
403 logging.debug('Commit message:\n%s', commit_msg) 419 logging.debug('Commit message:\n%s', commit_msg)
404 else: 420 else:
405 logging.info('No deps changes detected when rolling from %s to %s. ' 421 logging.info('Currently pinned chromium_revision: %s (#%s) is newer than '
406 'Aborting without action.', current_cr_rev, opts.revision) 422 '%s (#%s). To roll to older revisions, you must pass the '
423 '--allow-reverse flag.\n'
424 'Aborting without action.', current_cr_rev, current_commit_pos,
425 new_cr_rev, new_commit_pos)
407 return 0 426 return 0
408 427
409 _CreateRollBranch(opts.dry_run) 428 _CreateRollBranch(opts.dry_run)
410 UpdateDeps(deps_filename, current_cr_rev, opts.revision) 429 UpdateDeps(deps_filename, current_cr_rev, new_cr_rev)
411 _LocalCommit(commit_msg, opts.dry_run) 430 _LocalCommit(commit_msg, opts.dry_run)
412 _UploadCL(opts.dry_run) 431 _UploadCL(opts.dry_run)
413 _LaunchTrybots(opts.dry_run, opts.skip_try) 432 _LaunchTrybots(opts.dry_run, opts.skip_try)
414 return 0 433 return 0
415 434
416 435
417 if __name__ == '__main__': 436 if __name__ == '__main__':
418 sys.exit(main()) 437 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