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

Side by Side Diff: scripts/master/try_job_gerrit.py

Issue 250983003: Added TryJobGerritScheduler (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: 'except' simplification in JobDefinition.parse Created 6 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « scripts/master/gerrit_poller.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Copyright (c) 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 import json
6 import re
7
8 from twisted.internet import defer
9 from twisted.python import log
10
11 from buildbot.schedulers.base import BaseScheduler
12
13 from master.gerrit_poller import GerritPoller
14
15
16 class JobDefinition(object):
17 """Describes a try job posted on Gerrit."""
18 def __init__(self, builder_names=None):
19 # Force str type and remove empty builder names.
20 self.builder_names = [str(b) for b in builder_names or []
21 if b]
22
23 def __repr__(self):
24 return repr(self.__dict__)
25
26 @staticmethod
27 def parse(text):
28 """Parses a try job definition."""
29 text = text and text.strip()
30 if not text:
31 # Return an empty definition.
32 return JobDefinition()
33
34 # Parse as json.
35 try:
36 job = json.loads(text)
37 except:
38 raise ValueError('Couldn\'t parse job definition: %s' % text)
39
40 # Convert to canonical form.
41 if isinstance(job, list):
42 # Treat a list as builder name list.
43 job = {'builderNames': job}
44 elif not isinstance(job, dict):
45 raise ValueError('Job definition must be a JSON object or array.')
46
47 return JobDefinition(job.get('builderNames'))
48
49
50 class _TryJobGerritPoller(GerritPoller):
51 """Polls issues, creates changes and calls scheduler.submitJob.
52
53 This class is a part of TryJobGerritScheduler implementation and not designed
54 to be used otherwise.
55 """
56
57 change_category = 'tryjob'
58
59 MESSAGE_REGEX_TRYJOB = re.compile('Patch set \d+:\s+\!tryjob(.*)', re.I)
60
61 def __init__(self, scheduler, gerrit_host, gerrit_projects=None,
62 pollInterval=None):
63 assert scheduler
64 GerritPoller.__init__(self, gerrit_host, gerrit_projects, pollInterval)
65 self.scheduler = scheduler
66
67 def _is_interesting_message(self, message):
68 return self.MESSAGE_REGEX_TRYJOB.match(message['message'])
69
70 def getChangeQuery(self):
71 query = GerritPoller.getChangeQuery(self)
72 # Request only issues with TryJob=+1 label.
73 query += '+label:TryJob=%2B1'
74 return query
75
76 def parseJob(self, message):
77 """Parses a JobDefinition from a Gerrit message."""
78 tryjob_match = self.MESSAGE_REGEX_TRYJOB.match(message['message'])
79 assert tryjob_match
80 job_def_str = tryjob_match.group(1)
81 return JobDefinition.parse(job_def_str)
Vadim Sh. 2014/04/29 18:17:39 nit: no need for job_def_str variable, just return
82
83 @defer.inlineCallbacks
84 def addChange(self, change, message):
85 """Parses a job, adds a change and calls self.scheduler.submitJob."""
86 try:
87 job = self.parseJob(message)
88 buildbotChange = yield self.addBuildbotChange(change, message)
89 yield self.scheduler.submitJob(buildbotChange, job)
90 defer.returnValue(buildbotChange)
91 except Exception as e:
92 log.err('TryJobGerritPoller failed: %s' % e)
93 raise
94
95
96 class TryJobGerritScheduler(BaseScheduler):
97 """Polls try jobs on Gerrit and creates buildsets."""
98 def __init__(self, name, default_builder_names, gerrit_host,
99 gerrit_projects=None, pollInterval=None):
100 """Creates a new TryJobGerritScheduler.
101
102 Args:
103 name: name of the scheduler.
104 default_builder_names: a list of builder names used in case a job didn't
105 specify any.
106 gerrit_host: URL to the Gerrit instance
107 gerrit_projects: Gerrit projects to filter issues.
108 pollInterval: frequency of polling.
109 """
110 BaseScheduler.__init__(self, name,
111 builderNames=default_builder_names,
112 properties={})
113 self.poller = _TryJobGerritPoller(self, gerrit_host, gerrit_projects,
114 pollInterval)
115
116 def setServiceParent(self, parent):
117 BaseScheduler.setServiceParent(self, parent)
118 self.poller.master = self.master
119 self.poller.setServiceParent(self)
120
121 def gotChange(self, *args, **kwargs):
122 """Do nothing because changes are processed by submitJob."""
123
124 @defer.inlineCallbacks
125 def submitJob(self, change, job):
126 bsid = yield self.addBuildsetForChanges(
127 reason='tryjob',
128 changeids=[change.number],
129 builderNames=job.builder_names,
130 properties=change.properties)
131 log.msg('Successfully submitted a Gerrit try job for %s: %s.' %
132 (change.who, job))
133 defer.returnValue(bsid)
OLDNEW
« 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