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

Unified Diff: trychange.py

Issue 254133007: trychange.py: Gerrit protocol (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: nit Created 6 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tests/trychange_unittest.py ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: trychange.py
diff --git a/trychange.py b/trychange.py
index d181e141baff4c312c8fd1c8343fc98c8918991c..b9d43e1802d1f79aca75b3f7b423293132937f96 100755
--- a/trychange.py
+++ b/trychange.py
@@ -24,12 +24,14 @@ import sys
import tempfile
import urllib
import urllib2
+import urlparse
import breakpad # pylint: disable=W0611
-import gcl
import fix_encoding
+import gcl
import gclient_utils
+import gerrit_util
import scm
import subprocess2
@@ -95,17 +97,21 @@ def RunGit(args, **kwargs):
"""Returns stdout."""
return RunCommand(['git'] + args, **kwargs)
+class Error(Exception):
+ """An error during a try job submission.
+
+ For this error, trychange.py does not display stack trace, only message
+ """
-class InvalidScript(Exception):
+class InvalidScript(Error):
def __str__(self):
return self.args[0] + '\n' + HELP_STRING
-class NoTryServerAccess(Exception):
+class NoTryServerAccess(Error):
def __str__(self):
return self.args[0] + '\n' + HELP_STRING
-
def Escape(name):
"""Escapes characters that could interfere with the file system or try job
parsing.
@@ -168,6 +174,7 @@ class SCM(object):
'port': self.GetCodeReviewSetting('TRYSERVER_HTTP_PORT'),
'host': self.GetCodeReviewSetting('TRYSERVER_HTTP_HOST'),
'svn_repo': self.GetCodeReviewSetting('TRYSERVER_SVN_URL'),
+ 'gerrit_url': self.GetCodeReviewSetting('TRYSERVER_GERRIT_URL'),
'git_repo': self.GetCodeReviewSetting('TRYSERVER_GIT_URL'),
'project': self.GetCodeReviewSetting('TRYSERVER_PROJECT'),
# Primarily for revision=auto
@@ -706,6 +713,73 @@ def _SendChangeGit(bot_spec, options):
patch_git('reset', '--hard', 'origin/master')
raise
+def _SendChangeGerrit(bot_spec, options):
+ """Posts a try job to a Gerrit change.
+
+ Reads Change-Id from the HEAD commit, resolves the current revision, checks
+ that local revision matches the uploaded one, posts a try job in form of a
+ message, sets Tryjob label to 1.
+
+ Gerrit message format: starts with !tryjob, optionally followed by a tryjob
+ definition in JSON format:
+ buildNames: list of strings specifying build names.
+ """
+
+ logging.info('Sending by Gerrit')
+ if not options.gerrit_url:
+ raise NoTryServerAccess('Please use --gerrit_url option to specify the '
+ 'Gerrit instance url to connect to')
+ gerrit_host = urlparse.urlparse(options.gerrit_url).hostname
+ logging.debug('Gerrit host: %s' % gerrit_host)
+
+ def get_change_id():
Vadim Sh. 2014/04/30 00:40:48 looks like this file is using GetChangeId naming s
+ """Finds Change-ID of the HEAD commit."""
+ CHANGE_ID_RGX = '^Change-Id: (I[a-f0-9]{10,})'
+ comment = scm.GIT.Capture(['log', '-1', '--format=%b'], cwd=os.getcwd())
+ change_id_match = re.search(CHANGE_ID_RGX, comment, re.I | re.M)
+ if not change_id_match:
+ raise Error('Change-Id was not found in the HEAD commit.')
Vadim Sh. 2014/04/30 00:40:48 It would be helpful to explain what to do in that
+ change_id = change_id_match.group(1)
+ assert change_id and change_id.startswith('I')
Vadim Sh. 2014/04/30 00:40:48 I think this assert is redundant since your regexp
+ return change_id
+
+ def format_message():
+ # Build job definition.
+ job_def = {}
+ builderNames = [builder for builder, _ in bot_spec]
+ if builderNames:
+ job_def['builderNames'] = builderNames
+
+ # Format message.
+ msg = '!tryjob'
+ if job_def:
+ msg = '%s %s' % (msg, json.dumps(job_def))
Vadim Sh. 2014/04/30 00:40:48 json.dumps(job_def, sort_keys=True)
+ return msg
Vadim Sh. 2014/04/30 00:40:48 Does Gerrit append '\n' for you here? I think it's
nodir 2014/04/30 18:57:27 The regexp expects EOL or EOF after job definitio
+
+ head_sha = scm.GIT.Capture(['log', '-1', '--format=%H'], cwd=os.getcwd())
+
+ change_id = get_change_id()
Vadim Sh. 2014/04/30 00:40:48 I think it would be cleaner to pass |head_sha| to
nodir 2014/04/30 18:57:27 Done.
+ assert change_id
Vadim Sh. 2014/04/30 00:40:48 I think this is redundant too..
+
+ # Check that the uploaded revision matches the local one.
+ changes = gerrit_util.GetChangeCurrentRevision(gerrit_host, change_id)
+ assert len(changes) in (0, 1), 'Multiple changes with id %s' % change_id
Vadim Sh. 2014/04/30 00:40:48 hm.. len(changes) <= 1?
nodir 2014/04/30 18:57:27 Wanted to be more explicit, it's probably looks we
+ if not changes:
+ raise Error('A change %s was not found on the server. Was it uploaded?' %
+ change_id)
+ logging.debug('Found Gerrit change: %s' % changes[0])
+ if changes[0]['current_revision'] != head_sha:
+ raise Error('Some changes were made since last upload to Gerrit, '
Vadim Sh. 2014/04/30 00:40:48 I'd rephrase it somehow. Maybe "Please reupload yo
nodir 2014/04/30 18:57:27 Modified the string a bit.
+ 'so stopping.')
+
+ # Post a try job.
+ message = format_message()
+ logging.info('Posting gerrit message: %s' % message)
+ if not options.dry_run:
+ # Post a message and set TryJob=1 label
Vadim Sh. 2014/04/30 00:40:48 nit: append '.' at the end of a sentence :)
+ gerrit_util.SetReview(gerrit_host, change_id, msg=message,
+ labels={'Tryjob': 1})
Vadim Sh. 2014/04/30 00:40:48 What happens here if project doesn't have Tryjob l
nodir 2014/04/30 18:57:27 It will report: Bad Request: label "Tryjb" is not
+
def PrintSuccess(bot_spec, options):
if not options.dry_run:
@@ -920,6 +994,19 @@ def gen_parser(prog):
help="GIT url to use to write the changes in; --use_git is "
"implied when using --git_repo")
parser.add_option_group(group)
+
+ group = optparse.OptionGroup(parser, "Access the try server with Gerrit")
+ group.add_option("--use_gerrit",
+ action="store_const",
+ const=_SendChangeGerrit,
+ dest="send_patch",
+ help="Use Gerrit to talk to the try server")
+ group.add_option("--gerrit_url",
+ metavar="GERRIT_URL",
+ help="Gerrit url to post a tryjob to; --use_gerrit is "
+ "implied when using --gerrit_url")
+ parser.add_option_group(group)
+
return parser
@@ -1033,9 +1120,11 @@ def TryChange(argv,
can_http = options.port and options.host
can_svn = options.svn_repo
can_git = options.git_repo
+ can_gerrit = options.gerrit_url
+ can_anything = can_http or can_svn or can_git or can_gerrit
Vadim Sh. 2014/04/30 00:40:48 I'm far from english expert, but shouldn't it be "
nodir 2014/04/30 18:57:27 Done
# If there was no transport selected yet, now we must have enough data to
# select one.
- if not options.send_patch and not (can_http or can_svn or can_git):
+ if not options.send_patch and not can_anything:
parser.error('Please specify an access method.')
# Convert options.diff into the content of the diff.
@@ -1122,7 +1211,8 @@ def TryChange(argv,
all_senders = [
(_SendChangeHTTP, can_http),
(_SendChangeSVN, can_svn),
- (_SendChangeGit, can_git)
+ (_SendChangeGerrit, can_gerrit),
+ (_SendChangeGit, can_git),
]
senders = [sender for sender, can in all_senders if can]
@@ -1137,7 +1227,7 @@ def TryChange(argv,
if is_last:
raise
assert False, "Unreachable code"
- except (InvalidScript, NoTryServerAccess), e:
+ except Error, e:
if swallow_exception:
return 1
print >> sys.stderr, e
« no previous file with comments | « tests/trychange_unittest.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698