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

Unified Diff: trychange_git.py

Issue 23205010: Create trychange_git.py, for starting tryjobs in a pure-git world. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Better build properties. Created 7 years, 4 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: trychange_git.py
diff --git a/trychange_git.py b/trychange_git.py
new file mode 100755
index 0000000000000000000000000000000000000000..6a324dc36ddc73ff0fbd32459bfa3b5fdef54e15
--- /dev/null
+++ b/trychange_git.py
@@ -0,0 +1,139 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Client-side script to send local git changes to a tryserver.
+
+It pushes the local feature branch to a private ref on googlesource
+and posts a description of the job to an appengine instance, where it will get
+picked up by the buildbot tryserver itself.
+"""
+
+from __future__ import print_function
+
+import json
+import os
+import subprocess
+import sys
+import urllib
+
+
+def DieWithError(msg):
+ """Prints the message to stderr and exits."""
+ print(msg, file=sys.stderr)
+ sys.exit(1)
+
+
+def RunGit(*args, **kwargs):
+ """Runs the given git command with arguments, or dies.
+
+ Passes the given kwargs (e.g. cwd or env) through to subprocess."""
+ cmd = ('git',) + args
+ try:
+ return subprocess.check_output(cmd, **kwargs).strip()
+ except subprocess.CalledProcessError as e:
+ DieWithError('Command "%s" failed.\n%s' % (' '.join(cmd), e))
+
+
+def EnsureInGitRepo():
+ """Quick sanity check to make sure we're in a git repo."""
+ if not RunGit('rev-parse', '--is-inside-work-tree') == 'true':
+ DieWithError('You don\'t appear to be inside a git repository.')
+
+
+def GetCodeReviewSettings():
+ """Reads codereview.settings and returns a dict of settings."""
+ top_dir = RunGit('rev-parse', '--show-toplevel')
+ this_dir = os.getcwd()
+ assert this_dir.startswith(top_dir), (top_dir, this_dir)
+
+ settings_file = os.path.join(this_dir, 'codereview.settings')
+ while not os.path.isfile(settings_file):
+ this_dir = os.path.split(this_dir)[0]
+ if not this_dir.startswith(top_dir):
+ DieWithError('Unable to find codereview.settings in this repo.')
+ settings_file = os.path.join(this_dir, 'codereview.settings')
+
+ settings = {}
+ with open(settings_file, 'r') as f:
+ for line in f.readlines():
+ if line.startswith('#'):
+ continue
+ k, v = line.split(':', 1)
+ settings[k.strip()] = v.strip()
+ return settings
+
+
+def PushBranch():
+ """Pushes the current local branch to a ref in the try repo.
+
+ The try repo is either the remote called 'try', or 'origin' otherwise.
+ The ref is '/refs/try/<username>/<local branch>-<short hash>.
+
+ Returns the ref to which the local branch was pushed."""
+ username = RunGit('config', '--get', 'user.email').split('@', 1)[0]
+ branch = RunGit('symbolic-ref', '--short', '-q', 'HEAD')
+ commit = RunGit('rev-parse', branch)[:8]
+ remotes = RunGit('remote').splitlines()
+ if not all((username, branch, commit, remotes)):
+ DieWithError('Unable to get necessary git configuration.')
+
+ remote = 'try' if 'try' in remotes else 'origin'
+ ref = 'refs/try/%s/%s-%s' % (username, branch, commit)
+
+ RunGit('push', remote, '%s:%s' % (branch, ref))
+ return ref
+
+
+def MakeJob(project, jobname, ref):
+ """Creates a job description blob."""
+ email = RunGit('config', '--get', 'user.email')
+ repository = RunGit('config', '--get', 'remote.origin.url')
+ job = {
+ # Fields for buildbot sourcestamp.
+ 'project': project,
+ 'repository': repository,
+ 'branch': ref,
+ 'revision': 'HEAD',
+ # Fields for buildbot builder factory.
+ 'buildername': jobname,
+ 'recipe': project,
+ # Other useful fields.
+ 'blamelist': [email],
+ }
+ return json.dumps(job)
+
+
+def PostJob(server, project, job):
+ """POSTs the job description blob to the tryserver instance."""
+ url = '%s/%s/push' % (server, project)
+ data = urllib.urlencode({'job': job})
+ try:
+ conn = urllib.urlopen(url, data)
+ except IOError as e:
+ DieWithError(e)
+ response = conn.getcode()
+ if response != 200:
+ DieWithError('Failed to POST. Got: %d' % response)
+
+
+def Main(argv):
+ """Main entry point."""
+ EnsureInGitRepo()
+
+ settings = GetCodeReviewSettings()
+ server = settings.get('TRYSERVER_HTTP_HOST')
cmp 2013/08/20 05:52:29 It would be for the best to enforce that TRYSERVER
agable 2013/08/20 07:48:08 Done.
+ project = settings.get('TRYSERVER_PROJECT')
+ jobnames = settings.get('TRYSERVER_JOB_NAME')
+ if not all((server, project, jobnames)):
+ DieWithError('Missing configuration in codereview.settings.')
+
+ ref = PushBranch()
+ for jobname in jobnames.split(','):
+ job = MakeJob(project, jobname, ref)
+ PostJob(server, project, job)
+
+
+if __name__ == "__main__":
cmp 2013/08/20 05:52:29 single quotes here instead of double quotes
agable 2013/08/20 07:48:08 Done.
+ sys.exit(Main(sys.argv))
« 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