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

Side by Side Diff: git_cl.py

Issue 1063103002: git cl try uses buildbucket via OAuth2 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: fix Created 5 years, 8 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | third_party/google_api_python_client/apiclient/__init__.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 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 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 # Copyright (C) 2008 Evan Martin <martine@danga.com> 6 # Copyright (C) 2008 Evan Martin <martine@danga.com>
7 7
8 """A git-command for integrating reviews on Rietveld.""" 8 """A git-command for integrating reviews on Rietveld."""
9 9
10 from distutils.version import LooseVersion 10 from distutils.version import LooseVersion
11 from multiprocessing.pool import ThreadPool 11 from multiprocessing.pool import ThreadPool
12 import base64 12 import base64
13 import glob 13 import glob
14 import httplib
14 import json 15 import json
15 import logging 16 import logging
16 import optparse 17 import optparse
17 import os 18 import os
18 import Queue 19 import Queue
19 import re 20 import re
20 import stat 21 import stat
21 import sys 22 import sys
22 import tempfile 23 import tempfile
23 import textwrap 24 import textwrap
25 import time
26 import traceback
24 import urllib2 27 import urllib2
25 import urlparse 28 import urlparse
26 import webbrowser 29 import webbrowser
27 import zlib 30 import zlib
28 31
29 try: 32 try:
30 import readline # pylint: disable=F0401,W0611 33 import readline # pylint: disable=F0401,W0611
31 except ImportError: 34 except ImportError:
32 pass 35 pass
33 36
37 from third_party import colorama
38 from third_party import httplib2
39 from third_party import upload
34 40
35 from third_party import colorama 41 ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
36 from third_party import upload 42 sys.path.insert(
43 0, os.path.join(ROOT_DIR, 'third_party', 'google_api_python_client'))
44
45 import apiclient
37 import auth 46 import auth
38 import breakpad # pylint: disable=W0611 47 import breakpad # pylint: disable=W0611
39 import clang_format 48 import clang_format
40 import dart_format 49 import dart_format
41 import fix_encoding 50 import fix_encoding
42 import gclient_utils 51 import gclient_utils
43 import git_common 52 import git_common
44 import owners 53 import owners
45 import owners_finder 54 import owners_finder
46 import presubmit_support 55 import presubmit_support
47 import rietveld 56 import rietveld
48 import scm 57 import scm
49 import subcommand 58 import subcommand
50 import subprocess2 59 import subprocess2
51 import watchlists 60 import watchlists
52 61
53 __version__ = '1.0' 62 __version__ = '1.0'
54 63
55 DEFAULT_SERVER = 'https://codereview.appspot.com' 64 DEFAULT_SERVER = 'https://codereview.appspot.com'
56 POSTUPSTREAM_HOOK_PATTERN = '.git/hooks/post-cl-%s' 65 POSTUPSTREAM_HOOK_PATTERN = '.git/hooks/post-cl-%s'
57 DESCRIPTION_BACKUP_FILE = '~/.git_cl_description_backup' 66 DESCRIPTION_BACKUP_FILE = '~/.git_cl_description_backup'
58 GIT_INSTRUCTIONS_URL = 'http://code.google.com/p/chromium/wiki/UsingGit' 67 GIT_INSTRUCTIONS_URL = 'http://code.google.com/p/chromium/wiki/UsingGit'
59 CHANGE_ID = 'Change-Id:' 68 CHANGE_ID = 'Change-Id:'
60 REFS_THAT_ALIAS_TO_OTHER_REFS = { 69 REFS_THAT_ALIAS_TO_OTHER_REFS = {
61 'refs/remotes/origin/lkgr': 'refs/remotes/origin/master', 70 'refs/remotes/origin/lkgr': 'refs/remotes/origin/master',
62 'refs/remotes/origin/lkcr': 'refs/remotes/origin/master', 71 'refs/remotes/origin/lkcr': 'refs/remotes/origin/master',
63 } 72 }
64 73
74 # Buildbucket-related constants
75 DISCOVERY_URL = (
76 'https://cr-buildbucket.appspot.com/_ah/api/discovery/v1/apis/'
77 '{api}/{apiVersion}/rest')
nodir 2015/04/14 16:12:48 Rename to BUILDBUCKET_DISCOVERY_URL
sheyang 2015/04/14 17:29:57 Done.
78 BUILDSET_STR = 'patch/rietveld/{hostname}/{issue}/{patch}'
79
65 # Valid extensions for files we want to lint. 80 # Valid extensions for files we want to lint.
66 DEFAULT_LINT_REGEX = r"(.*\.cpp|.*\.cc|.*\.h)" 81 DEFAULT_LINT_REGEX = r"(.*\.cpp|.*\.cc|.*\.h)"
67 DEFAULT_LINT_IGNORE_REGEX = r"$^" 82 DEFAULT_LINT_IGNORE_REGEX = r"$^"
68 83
69 # Shortcut since it quickly becomes redundant. 84 # Shortcut since it quickly becomes redundant.
70 Fore = colorama.Fore 85 Fore = colorama.Fore
71 86
72 # Initialized in main() 87 # Initialized in main()
73 settings = None 88 settings = None
74 89
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 else: 210 else:
196 git_set_branch_value('git-find-copies', int(options.find_copies)) 211 git_set_branch_value('git-find-copies', int(options.find_copies))
197 212
198 print('Using %d%% similarity for rename/copy detection. ' 213 print('Using %d%% similarity for rename/copy detection. '
199 'Override with --similarity.' % options.similarity) 214 'Override with --similarity.' % options.similarity)
200 215
201 return options, args 216 return options, args
202 parser.parse_args = Parse 217 parser.parse_args = Parse
203 218
204 219
220 def _prefix_master(master):
221 prefix = 'master.'
222 if master.startswith(prefix):
223 return master
224 else:
225 return '%s%s' % (prefix, master)
226
227
228 def _get_buildbucket(rietveld_host, auth_config):
229 authenticator = auth.get_authenticator_for_host(rietveld_host, auth_config)
230 http = httplib2.Http()
231 return apiclient.discovery.build(
232 'buildbucket', 'v1',
233 http=authenticator.authorize(http),
234 discoveryServiceUrl=DISCOVERY_URL,
235 )
236
237
238 def trigger_distributed_try_jobs(
239 auth_config, changelist, options, masters, category):
240 rietveld_host = urlparse.urlparse(changelist.GetRietveldServer()).hostname
nodir 2015/04/14 16:12:48 We will need to make sure that all branches on all
sheyang 2015/04/14 17:29:57 As a fallback, rietveld_server will be fetched fro
241 buildbucket = _get_buildbucket(rietveld_host, auth_config)
242 issue_props = changelist.GetIssueProperties()
243 issue = changelist.GetIssue()
244 patchset = changelist.GetMostRecentPatchset()
245 buildset = BUILDSET_STR.format(
246 hostname=rietveld_host,
247 issue=str(issue),
248 patch=str(patchset))
nodir 2015/04/14 16:12:48 You don't need str calls here
sheyang 2015/04/14 17:29:57 Done.
249 print 'Tried jobs on:'
nodir 2015/04/14 16:12:48 "Trying", as they were not tried yet
sheyang 2015/04/14 17:29:57 This is from the old code... Updated.
250 for (master, builders_and_tests) in masters.iteritems():
nodir 2015/04/14 16:12:48 Parens are unnecessary
sheyang 2015/04/14 17:29:57 Done.
251 print 'Master: %s' % master
252 bucket = _prefix_master(master)
253 for builder, tests in builders_and_tests.iteritems():
254 req = buildbucket.put(body={
nodir 2015/04/14 16:12:48 In https://codereview.chromium.org/1058893004/ esp
sheyang 2015/04/14 17:29:57 Acknowledged.
255 'bucket': bucket,
256 'parameters_json': json.dumps({
257 'builder_name': builder,
258 'changes':[
259 {'author': {'email': issue_props['owner_email']}},
260 ],
261 'properties': {
262 'category': category,
263 'clobber': options.clobber,
264 'issue': issue,
265 'master': master,
266 'patch_project': issue_props['project'],
267 'patch_storage': 'rietveld',
268 'patchset': patchset,
269 'reason': options.name,
270 'revision': options.revision,
271 'rietveld': changelist.GetRietveldServer(),
nodir 2015/04/14 16:12:48 why not rietveld_host ?
sheyang 2015/04/14 17:29:57 I think it needs 'https' prefix... adding rietveld
272 'testfilter': tests,
273 },
274 }),
275 'tags': ['buildset:%s' % buildset,
276 'master:%s' % master,
277 'builder:%s' % builder,
278 'user_agent:git-cl-try']
279 })
280 wait = 1
281 try_count = 3
282 while try_count > 0:
283 try:
284 try_count -= 1
285 response = req.execute()
286 if response.get('error'):
287 msg = 'Error in response. Reason: %s. Message: %s.' % (
288 response['error'].get('reason', ''),
289 response['error'].get('message', ''))
290 raise BuildbucketResponseException(msg)
291 break
292 except apiclient.errors.HttpError as ex:
293 status = ex.resp.status if ex.resp else None
294 if status >= 500:
nodir 2015/04/14 16:12:48 Inverse this condition so you can unindent the ">=
sheyang 2015/04/14 17:29:57 Done.
sheyang 2015/04/14 17:29:57 Done.
295 logging.debug('Transient errors when triggering tryjobs. '
296 'Will retry in %d seconds.', wait)
297 time.sleep(wait)
298 wait *= 2
299 if try_count <= 0:
300 raise
nodir 2015/04/14 16:12:48 Move these two lines before logging about transien
sheyang 2015/04/14 17:29:57 Done.
sheyang 2015/04/14 17:29:57 Done.
301 else:
302 raise
303 print ' %s: %s' % (builder, tests)
304
305
205 def MatchSvnGlob(url, base_url, glob_spec, allow_wildcards): 306 def MatchSvnGlob(url, base_url, glob_spec, allow_wildcards):
206 """Return the corresponding git ref if |base_url| together with |glob_spec| 307 """Return the corresponding git ref if |base_url| together with |glob_spec|
207 matches the full |url|. 308 matches the full |url|.
208 309
209 If |allow_wildcards| is true, |glob_spec| can contain wildcards (see below). 310 If |allow_wildcards| is true, |glob_spec| can contain wildcards (see below).
210 """ 311 """
211 fetch_suburl, as_ref = glob_spec.split(':') 312 fetch_suburl, as_ref = glob_spec.split(':')
212 if allow_wildcards: 313 if allow_wildcards:
213 glob_match = re.match('(.+/)?(\*|{[^/]*})(/.+)?', fetch_suburl) 314 glob_match = re.match('(.+/)?(\*|{[^/]*})(/.+)?', fetch_suburl)
214 if glob_match: 315 if glob_match:
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 try: 363 try:
263 stdout = sys.stdout.fileno() 364 stdout = sys.stdout.fileno()
264 except AttributeError: 365 except AttributeError:
265 stdout = None 366 stdout = None
266 return subprocess2.call( 367 return subprocess2.call(
267 ['git', 368 ['git',
268 'diff', '--no-ext-diff', '--stat'] + similarity_options + args, 369 'diff', '--no-ext-diff', '--stat'] + similarity_options + args,
269 stdout=stdout, env=env) 370 stdout=stdout, env=env)
270 371
271 372
373 class BuildbucketResponseException(Exception):
374 pass
375
376
272 class Settings(object): 377 class Settings(object):
273 def __init__(self): 378 def __init__(self):
274 self.default_server = None 379 self.default_server = None
275 self.cc = None 380 self.cc = None
276 self.root = None 381 self.root = None
277 self.is_git_svn = None 382 self.is_git_svn = None
278 self.svn_branch = None 383 self.svn_branch = None
279 self.tree_status_url = None 384 self.tree_status_url = None
280 self.viewvc_url = None 385 self.viewvc_url = None
281 self.updated = False 386 self.updated = False
(...skipping 2571 matching lines...) Expand 10 before | Expand all | Expand 10 after
2853 'Bot list: %s' % builders) 2958 'Bot list: %s' % builders)
2854 return 1 2959 return 1
2855 2960
2856 patchset = cl.GetMostRecentPatchset() 2961 patchset = cl.GetMostRecentPatchset()
2857 if patchset and patchset != cl.GetPatchset(): 2962 if patchset and patchset != cl.GetPatchset():
2858 print( 2963 print(
2859 '\nWARNING Mismatch between local config and server. Did a previous ' 2964 '\nWARNING Mismatch between local config and server. Did a previous '
2860 'upload fail?\ngit-cl try always uses latest patchset from rietveld. ' 2965 'upload fail?\ngit-cl try always uses latest patchset from rietveld. '
2861 'Continuing using\npatchset %s.\n' % patchset) 2966 'Continuing using\npatchset %s.\n' % patchset)
2862 try: 2967 try:
2863 cl.RpcServer().trigger_distributed_try_jobs( 2968 trigger_distributed_try_jobs(
2864 cl.GetIssue(), patchset, options.name, options.clobber, 2969 auth_config, cl, options, masters, 'git cl try')
2865 options.revision, masters) 2970 except apiclient.errors.HttpError as ex:
2866 except urllib2.HTTPError, e: 2971 status = ex.resp.status if ex.resp else None
2867 if e.code == 404: 2972 if status == httplib.FORBIDDEN:
2868 print('404 from rietveld; ' 2973 print 'ERROR: Access denied. Please verify you have tryjob access.'
2869 'did you mean to use "git try" instead of "git cl try"?') 2974 else:
2870 return 1 2975 print 'ERROR: Tryjob request failed: %s.' % ex
2871 print('Tried jobs on:') 2976 return 1
2872 2977 except BuildbucketResponseException as ex:
2873 for (master, builders) in masters.iteritems(): 2978 print ex
2874 if master: 2979 return 1
2875 print 'Master: %s' % master 2980 except Exception as e:
2876 length = max(len(builder) for builder in builders) 2981 stacktrace = (''.join(traceback.format_stack()) + traceback.format_exc())
2877 for builder in sorted(builders): 2982 print 'ERROR: unexpected error when trying to trigger tryjobs: %s\n%s' % (
2878 print ' %*s: %s' % (length, builder, ','.join(builders[builder])) 2983 e, stacktrace)
nodir 2015/04/14 16:12:48 doesn't logging.exception do the same with current
sheyang 2015/04/14 17:29:57 logging.exception only has traceback.format_exc().
2984 return 1
2879 return 0 2985 return 0
2880 2986
2881 2987
2882 @subcommand.usage('[new upstream branch]') 2988 @subcommand.usage('[new upstream branch]')
2883 def CMDupstream(parser, args): 2989 def CMDupstream(parser, args):
2884 """Prints or sets the name of the upstream branch, if any.""" 2990 """Prints or sets the name of the upstream branch, if any."""
2885 _, args = parser.parse_args(args) 2991 _, args = parser.parse_args(args)
2886 if len(args) > 1: 2992 if len(args) > 1:
2887 parser.error('Unrecognized args: %s' % ' '.join(args)) 2993 parser.error('Unrecognized args: %s' % ' '.join(args))
2888 2994
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
3202 if __name__ == '__main__': 3308 if __name__ == '__main__':
3203 # These affect sys.stdout so do it outside of main() to simplify mocks in 3309 # These affect sys.stdout so do it outside of main() to simplify mocks in
3204 # unit testing. 3310 # unit testing.
3205 fix_encoding.fix_encoding() 3311 fix_encoding.fix_encoding()
3206 colorama.init() 3312 colorama.init()
3207 try: 3313 try:
3208 sys.exit(main(sys.argv[1:])) 3314 sys.exit(main(sys.argv[1:]))
3209 except KeyboardInterrupt: 3315 except KeyboardInterrupt:
3210 sys.stderr.write('interrupted\n') 3316 sys.stderr.write('interrupted\n')
3211 sys.exit(1) 3317 sys.exit(1)
OLDNEW
« no previous file with comments | « no previous file | third_party/google_api_python_client/apiclient/__init__.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698