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

Unified Diff: scripts/master/try_job_gerrit.py

Issue 250983003: Added TryJobGerritScheduler (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: 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 | « scripts/master/gerrit_poller.py ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: scripts/master/try_job_gerrit.py
diff --git a/scripts/master/try_job_gerrit.py b/scripts/master/try_job_gerrit.py
new file mode 100644
index 0000000000000000000000000000000000000000..60e24755a81f2bcf56cac794650e2716a898cdc7
--- /dev/null
+++ b/scripts/master/try_job_gerrit.py
@@ -0,0 +1,141 @@
+# Copyright (c) 2014 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.
+
+import json
+import re
+
+from twisted.internet import defer
+from twisted.python import log
+
+from buildbot.changes import filter
+from buildbot.schedulers.basic import SingleBranchScheduler
+
+from master.gerrit_poller import GerritPoller
+from master.builders_pools import BuildersPools
+
+
+ALWAYS_TRUE_FILTER = filter.ChangeFilter(filter_fn=lambda x: True)
+
+
+class JobDefinition(object):
+ """Describes a try job posted on Gerrit."""
+ def __init__(self, builder_names=None):
+ # Force str type and remove empty builder names.
+ self.builder_names = [str(b) for b in builder_names or []
+ if b]
+
+ def __repr__(self):
+ return repr(self.__dict__)
+
+ @staticmethod
+ def parse(text):
+ """Parses a try job definition."""
+ text = text and text.strip()
+ if not text:
+ # Return an empty definition.
+ return JobDefinition()
+
+ # Parse as json.
+ job = json.loads(text)
+
+ # Convert to canonical form.
+ if isinstance(job, list):
+ # Treat a list as builder name list.
+ job = {'builderNames': job}
+
+ return JobDefinition(job.get('builderNames'))
+
+
+class _TryJobGerritPoller(GerritPoller):
+ """Polls issues, creates changes and calls scheduler.submitJob.
+
+ This class is a part of TryJobGerritScheduler implementation and not designed
+ to be used otherwise.
+ """
+
+ MESSAGE_REGEX_TRYJOB = re.compile('Patch set \d+:\s+\!tryjob', re.I)
+
+ def __init__(self, scheduler, gerrit_host, gerrit_projects=None,
+ pollInterval=None):
+ assert scheduler
+ GerritPoller.__init__(self, gerrit_host, gerrit_projects, pollInterval)
+ self.scheduler = scheduler
Dan Jacques 2014/04/26 00:38:51 I don't think the 'change source' / 'scheduler' se
nodir 2014/04/28 22:31:11 In general, yes, a poller and scheduler don't know
+
+ def _is_interesting_comment(self, comment):
+ return self.MESSAGE_REGEX_TRYJOB.match(comment['message'])
+
+ def getChangeQuery(self):
+ query = GerritPoller.getChangeQuery(self)
+ # Request only issues with TryJob=+1 label.
+ query += '+label:TryJob=%2B1'
Dan Jacques 2014/04/26 00:38:51 While you're constraining the query, you might as
nodir 2014/04/28 22:31:11 I think I will wait for your GerritAgent
+ return query
+
+ def parseJob(self, comment):
+ """Parses a JobDefinition from a Gerrit comment."""
+ msg = comment['message']
+ tryjob_match = self.MESSAGE_REGEX_TRYJOB.match(msg)
+ assert tryjob_match
+ job_def_str = msg[tryjob_match.end():]
+ return JobDefinition.parse(job_def_str)
+
+ @defer.inlineCallbacks
+ def addChange(self, (change, comment)):
+ """Parses a job, adds a change and calls self.scheduler.submitJob."""
+ try:
+ job = self.parseJob(comment)
+ buildbotChange = yield self.addBuildbotChange(change, comment)
+ self.scheduler.submitJob(buildbotChange, job)
Dan Jacques 2014/04/26 00:38:51 This needs to be yielded, doesn't it?
nodir 2014/04/28 22:31:11 Done.
+ except Exception as e:
+ log.err('TryJobGerritPoller failed: %s' % e)
+
+
+class TryJobGerritScheduler(SingleBranchScheduler):
Dan Jacques 2014/04/26 00:38:51 It would be nice if you could use a less heavy-han
nodir 2014/04/28 22:31:11 This scheduler takes the builder names from the jo
+ """Polls try jobs on Gerrit and creates buildsets."""
+ def __init__(self, name, default_builder_names, gerrit_host,
+ gerrit_projects=None, pollInterval=None):
+ """Creates a new TryJobGerritScheduler.
+
+ Args:
+ name: name of the scheduler.
+ default_builder_names: a list of builder names used in case a job didn't
+ specify any.
+ gerrit_host: URL to the Gerrit instance
+ gerrit_projects: Gerrit projects to filter issues.
+ pollInterval: frequency of polling.
+ """
+ SingleBranchScheduler.__init__(self, name,
+ builderNames=default_builder_names,
Kevin Graney 2014/04/26 02:45:11 Are you somehow running PRESUBMIT.py for the jobs
nodir 2014/04/28 22:31:11 This code lives on server. The git-try will run PR
+ change_filter=ALWAYS_TRUE_FILTER)
+ self.poller = _TryJobGerritPoller(self, gerrit_host, gerrit_projects,
+ pollInterval)
+
+ def setServiceParent(self, parent):
+ SingleBranchScheduler.setServiceParent(self, parent)
+ self.poller.master = self.master
+ self.poller.setServiceParent(self)
+
+ def gotChange(self, *args, **kwargs):
+ """Do nothing because changes are processed by submitJob."""
+
+ def addSourcestamp(self, change):
+ return self.master.db.sourcestamps.addSourceStamp(
+ project=change.project,
+ repository=change.repository,
+ branch=change.branch,
+ revision=change.revision)
+
+ def addBuildset(self, change, ssid, job):
+ return self.addBuildsetForSourceStamp(
+ ssid=ssid,
+ reason='tryjob',
+ properties=change.properties,
+ builderNames=job.builder_names)
+
+ @defer.inlineCallbacks
+ def submitJob(self, change, job):
+ ssid = yield self.addSourcestamp(change)
+ bsid = yield self.addBuildset(change, ssid, job)
+ log.msg('Successfully submitted a Gerrit try job for %s: %s.' % (change.who,
+ job))
+ defer.returnValue(bsid)
« no previous file with comments | « scripts/master/gerrit_poller.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698