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

Unified 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: rebase Created 5 years, 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: git_cl.py
diff --git a/git_cl.py b/git_cl.py
index 1f7854551cb112dfc9647896ad28089f874036c2..065847957f9983e8d2d6dea945010203e25c03ae 100755
--- a/git_cl.py
+++ b/git_cl.py
@@ -11,6 +11,7 @@ from distutils.version import LooseVersion
from multiprocessing.pool import ThreadPool
import base64
import glob
+import httplib
import json
import logging
import optparse
@@ -21,6 +22,8 @@ import stat
import sys
import tempfile
import textwrap
+import time
+import traceback
import urllib2
import urlparse
import webbrowser
@@ -31,8 +34,8 @@ try:
except ImportError:
pass
-
from third_party import colorama
+from third_party import httplib2
from third_party import upload
import auth
import breakpad # pylint: disable=W0611
@@ -62,6 +65,11 @@ REFS_THAT_ALIAS_TO_OTHER_REFS = {
'refs/remotes/origin/lkcr': 'refs/remotes/origin/master',
}
+# Buildbucket-related constants
+BUILDBUCKET_PUT_URL = (
M-A Ruel 2015/05/12 00:46:21 Please only code the host here. Host != API, so th
sheyang 2015/05/12 01:37:56 Done.
+ 'https://cr-buildbucket.appspot.com/_ah/api/buildbucket/v1/builds/batch')
M-A Ruel 2015/05/11 22:21:28 That URL shouldn't be hardcoded there.
nodir 2015/05/11 22:48:29 I think hardcoding the default hostname is fine, b
M-A Ruel 2015/05/11 23:01:27 Not lgtm. It's not optional nor nice to have.
sheyang 2015/05/12 01:37:56 Done.
+BUILDSET_STR = 'patch/rietveld/{hostname}/{issue}/{patch}'
+
# Valid extensions for files we want to lint.
DEFAULT_LINT_REGEX = r"(.*\.cpp|.*\.cc|.*\.h)"
DEFAULT_LINT_IGNORE_REGEX = r"$^"
@@ -202,6 +210,107 @@ def add_git_similarity(parser):
parser.parse_args = Parse
+def _prefix_master(master):
M-A Ruel 2015/05/12 00:46:21 Why?
sheyang 2015/05/12 01:37:56 See the comments about 'black magic' below.
+ prefix = 'master.'
+ if master.startswith(prefix):
+ return master
+ else:
+ return '%s%s' % (prefix, master)
+
+
+def trigger_try_jobs(
+ auth_config, changelist, options, masters, category):
+ rietveld_url = settings.GetDefaultServerUrl()
+ rietveld_host = urlparse.urlparse(rietveld_url).hostname
+ authenticator = auth.get_authenticator_for_host(rietveld_host, auth_config)
+ http = authenticator.authorize(httplib2.Http())
+ http.force_exception_to_status_code = True
+ issue_props = changelist.GetIssueProperties()
+ issue = changelist.GetIssue()
+ patchset = changelist.GetMostRecentPatchset()
+ buildset = BUILDSET_STR.format(
+ hostname=rietveld_host,
+ issue=issue,
+ patch=patchset)
+
+ batch_req_body = {'builds': []}
+ print_text = []
+ print_text.append('Tried jobs on:')
M-A Ruel 2015/05/11 23:13:59 Why not printing as it's happening? Why hang outpu
sheyang 2015/05/12 01:37:56 Here we're only preparing parameters for the PUT c
+ for master, builders_and_tests in masters.iteritems():
M-A Ruel 2015/05/11 23:13:59 Please sort.
sheyang 2015/05/12 01:37:56 Done.
+ print_text.append('Master: %s' % master)
+ bucket = _prefix_master(master)
M-A Ruel 2015/05/12 00:46:21 This looks like black magic, explain the context.
sheyang 2015/05/12 01:37:56 Buildbucket uses full master name as bucket name '
M-A Ruel 2015/05/12 13:05:27 Please add this to _prefix_master docstring then.
sheyang 2015/05/12 17:40:38 Done.
+ for builder, tests in builders_and_tests.iteritems():
M-A Ruel 2015/05/12 00:46:21 sort this too.
sheyang 2015/05/12 01:37:56 Done.
+ print_text.append(' %s: %s' % (builder, tests))
+ parameters = {
+ 'builder_name': builder,
+ 'changes':[
+ {'author': {'email': issue_props['owner_email']}},
+ ],
+ 'properties': {
+ 'category': category,
+ 'issue': issue,
+ 'master': master,
+ 'patch_project': issue_props['project'],
+ 'patch_storage': 'rietveld',
+ 'patchset': patchset,
+ 'reason': options.name,
+ 'revision': options.revision,
+ 'rietveld': rietveld_url,
+ 'testfilter': tests,
+ },
+ }
+ if options.clobber:
+ parameters['properties']['clobber'] = True
+ batch_req_body['builds'].append(
+ {
+ 'bucket': bucket,
+ 'parameters_json': json.dumps(parameters),
M-A Ruel 2015/05/12 00:46:21 What. You are encoding json inside json? Why? Beca
sheyang 2015/05/12 01:37:56 Yes this parameter property is for buildbot about
+ 'tags': ['builder:%s' % builder,
+ 'buildset:%s' % buildset,
+ 'master:%s' % master,
+ 'user_agent:git_cl_try']
+ }
+ )
+
+ wait = 1
+ try_count = 3
+ while try_count > 0:
+ try_count -= 1
M-A Ruel 2015/05/11 23:13:59 try_count--
nodir 2015/05/11 23:19:36 this is invalid Python syntax
M-A Ruel 2015/05/11 23:20:22 Eh, damn python.
sheyang 2015/05/12 01:37:56 Acknowledged.
+ response, content = http.request(
+ BUILDBUCKET_PUT_URL,
+ 'PUT',
M-A Ruel 2015/05/11 23:01:27 If I understand correctly, the sole reason http is
nodir 2015/05/11 23:19:36 to authenticate the request.
sheyang 2015/05/12 01:37:56 Discussed with maruel@ offline and the recommended
+ body=json.dumps(batch_req_body),
+ headers={'Content-Type': 'application/json'},
+ )
+ content_json = None
+ try:
+ content_json = json.loads(content)
+ except ValueError:
+ pass
+
+ # Buildbucket could return an error even if status==200.
+ if content_json and content_json.get('error'):
+ msg = 'Error in response. Code: %d. Reason: %s. Message: %s.' % (
+ content_json['error'].get('code', ''),
+ content_json['error'].get('reason', ''),
+ content_json['error'].get('message', ''))
+ raise BuildbucketResponseException(msg)
+
+ if response.status == 200:
+ break
+
+ if response.status < 500 or try_count <= 0:
+ raise httplib2.HttpLib2Error(content)
+
+ # status >= 500 means transient failures.
+ logging.debug('Transient errors when triggering tryjobs. '
+ 'Will retry in %d seconds.', wait)
+ time.sleep(wait)
Vadim Sh. 2015/05/11 22:14:01 nit: no need to wait if it was the last attempt (i
M-A Ruel 2015/05/11 23:13:59 Please address this.
sheyang 2015/05/12 01:37:56 if try_count <=0, we'll raise an exception above s
+ wait *= 2
+
+ print '\n'.join(print_text)
+
+
def MatchSvnGlob(url, base_url, glob_spec, allow_wildcards):
"""Return the corresponding git ref if |base_url| together with |glob_spec|
matches the full |url|.
@@ -269,6 +378,10 @@ def print_stats(similarity, find_copies, args):
stdout=stdout, env=env)
+class BuildbucketResponseException(Exception):
+ pass
+
+
class Settings(object):
def __init__(self):
self.default_server = None
@@ -2764,6 +2877,9 @@ def CMDtry(parser, args):
"server-side to define what default bot set to use")
group.add_option(
"-n", "--name", help="Try job name; default to current branch name")
+ group.add_option(
+ "--use-buildbucket", action="store_true", default=False,
+ help="Use buildbucket to trigger try jobs.")
parser.add_option_group(group)
auth.add_auth_options(parser)
options, args = parser.parse_args(args)
@@ -2861,23 +2977,36 @@ def CMDtry(parser, args):
'\nWARNING Mismatch between local config and server. Did a previous '
'upload fail?\ngit-cl try always uses latest patchset from rietveld. '
'Continuing using\npatchset %s.\n' % patchset)
- try:
- cl.RpcServer().trigger_distributed_try_jobs(
- cl.GetIssue(), patchset, options.name, options.clobber,
- options.revision, masters)
- except urllib2.HTTPError, e:
- if e.code == 404:
- print('404 from rietveld; '
- 'did you mean to use "git try" instead of "git cl try"?')
+ if options.use_buildbucket:
+ try:
+ trigger_try_jobs(
+ auth_config, cl, options, masters, 'git_cl_try')
+ except BuildbucketResponseException as ex:
+ print 'ERROR: %s' % ex
+ return 1
+ except Exception as e:
+ stacktrace = (''.join(traceback.format_stack()) + traceback.format_exc())
+ print 'ERROR: Exception when trying to trigger tryjobs: %s\n%s' % (
+ e, stacktrace)
return 1
- print('Tried jobs on:')
-
- for (master, builders) in masters.iteritems():
- if master:
- print 'Master: %s' % master
- length = max(len(builder) for builder in builders)
- for builder in sorted(builders):
- print ' %*s: %s' % (length, builder, ','.join(builders[builder]))
+ else:
+ try:
+ cl.RpcServer().trigger_distributed_try_jobs(
+ cl.GetIssue(), patchset, options.name, options.clobber,
+ options.revision, masters)
+ except urllib2.HTTPError, e:
+ if e.code == 404:
+ print('404 from rietveld; '
+ 'did you mean to use "git try" instead of "git cl try"?')
+ return 1
+ print('Tried jobs on:')
+
+ for (master, builders) in masters.iteritems():
+ if master:
+ print 'Master: %s' % master
+ length = max(len(builder) for builder in builders)
+ for builder in sorted(builders):
+ print ' %*s: %s' % (length, builder, ','.join(builders[builder]))
return 0
« 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