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

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

Issue 250983003: Added TryJobGerritScheduler (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: nit 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 | « no previous file | scripts/master/try_job_gerrit.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2013 The Chromium Authors. All rights reserved. 1 # Copyright 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import datetime 5 import datetime
6 6
7 from buildbot.changes import base 7 from buildbot.changes import base
8 from buildbot.util import deferredLocked 8 from buildbot.util import deferredLocked
9 from twisted.python import log 9 from twisted.python import log
10 from twisted.internet import defer 10 from twisted.internet import defer
11 11
12 from common.gerrit_agent import GerritAgent 12 from common.gerrit_agent import GerritAgent
13 13
14 14
15 class GerritPoller(base.PollingChangeSource): 15 class GerritPoller(base.PollingChangeSource):
16 """A poller which queries a gerrit server for new changes and patchsets.""" 16 """A poller which queries a gerrit server for new changes and patchsets."""
17 17
18 change_category = 'patchset-created'
19
18 def __init__(self, gerrit_host, gerrit_projects=None, pollInterval=None): 20 def __init__(self, gerrit_host, gerrit_projects=None, pollInterval=None):
19 if isinstance(gerrit_projects, basestring): 21 if isinstance(gerrit_projects, basestring):
20 gerrit_projects = [gerrit_projects] 22 gerrit_projects = [gerrit_projects]
21 self.gerrit_projects = gerrit_projects 23 self.gerrit_projects = gerrit_projects
22 if pollInterval: 24 if pollInterval:
23 self.pollInterval = pollInterval 25 self.pollInterval = pollInterval
24 self.initLock = defer.DeferredLock() 26 self.initLock = defer.DeferredLock()
25 self.last_timestamp = None 27 self.last_timestamp = None
26 self.agent = GerritAgent(gerrit_host) 28 self.agent = GerritAgent(gerrit_host)
27 29
28 @staticmethod 30 @staticmethod
29 def _parse_timestamp(tm): 31 def _parse_timestamp(tm):
30 tm = tm[:tm.index('.')+7] 32 tm = tm[:tm.index('.')+7]
31 return datetime.datetime.strptime(tm, '%Y-%m-%d %H:%M:%S.%f') 33 return datetime.datetime.strptime(tm, '%Y-%m-%d %H:%M:%S.%f')
32 34
33 def startService(self): 35 def startService(self):
34 self.initLastTimeStamp() 36 self.initLastTimeStamp()
35 base.PollingChangeSource.startService(self) 37 base.PollingChangeSource.startService(self)
36 38
39 def getChangeQuery(self): # pylint: disable=R0201
40 return 'status:open'
41
37 @deferredLocked('initLock') 42 @deferredLocked('initLock')
38 def initLastTimeStamp(self): 43 def initLastTimeStamp(self):
39 log.msg('GerritPoller: Getting latest timestamp from gerrit server.') 44 log.msg('GerritPoller: Getting latest timestamp from gerrit server.')
40 path = '/changes/?q=status:open&n=1' 45 path = '/changes/?q=%s&n=1' % self.getChangeQuery()
41 d = self.agent.request('GET', path) 46 d = self.agent.request('GET', path)
42 def _get_timestamp(j): 47 def _get_timestamp(j):
43 if len(j) == 0: 48 if len(j) == 0:
44 self.last_timestamp = datetime.datetime.now() 49 self.last_timestamp = datetime.datetime.now()
45 else: 50 else:
46 self.last_timestamp = self._parse_timestamp(j[0]['updated']) 51 self.last_timestamp = self._parse_timestamp(j[0]['updated'])
47 d.addCallback(_get_timestamp) 52 d.addCallback(_get_timestamp)
48 return d 53 return d
49 54
50 def getChanges(self, sortkey=None): 55 def getChanges(self, sortkey=None):
51 path = '/changes/?q=status:open&n=10' 56 path = '/changes/?q=%s&n=10' % self.getChangeQuery()
52 if sortkey: 57 if sortkey:
53 path += '&N=%s' % sortkey 58 path += '&N=%s' % sortkey
54 return self.agent.request('GET', path) 59 return self.agent.request('GET', path)
55 60
61 def _is_interesting_message(self, message): # pylint: disable=R0201
62 return message['message'].startswith('Uploaded patch set ')
63
56 def checkForNewPatchset(self, change, since): 64 def checkForNewPatchset(self, change, since):
57 o_params = '&'.join('o=%s' % x for x in ( 65 o_params = '&'.join('o=%s' % x for x in (
58 'MESSAGES', 'CURRENT_REVISION', 'CURRENT_COMMIT', 'ALL_FILES')) 66 'MESSAGES', 'CURRENT_REVISION', 'CURRENT_COMMIT', 'ALL_FILES'))
59 path = '/changes/%s?%s' % (change['_number'], o_params) 67 path = '/changes/%s?%s' % (change['_number'], o_params)
60 d = self.agent.request('GET', path) 68 d = self.agent.request('GET', path)
61 def _parse_messages(j): 69 def _parse_messages(j):
62 if not j or 'messages' not in j: 70 if not j or 'messages' not in j:
63 return 71 return
64 for m in reversed(j['messages']): 72 for m in reversed(j['messages']):
65 if self._parse_timestamp(m['date']) <= since: 73 if self._parse_timestamp(m['date']) <= since:
66 break 74 break
67 if m['message'].startswith('Uploaded patch set '): 75 if self._is_interesting_message(m):
68 return j 76 return j, m
69 d.addCallback(_parse_messages) 77 d.addCallback(_parse_messages)
70 return d 78 return d
71 79
72 def createBuildbotChange(self, change): 80 def addBuildbotChange(self, change, message):
73 revision = change['revisions'].values()[0] 81 revision = change['revisions'].values()[0]
74 commit = revision['commit'] 82 commit = revision['commit']
75 properties = {'event.change.number': change['_number']} 83 properties = {'event.change.number': change['_number']}
76 if change['status'] == 'NEW': 84 if change['status'] == 'NEW':
77 ref = revision.get('fetch', {}).get('http', {}).get('ref') 85 ref = revision.get('fetch', {}).get('http', {}).get('ref')
78 if ref: 86 if ref:
79 properties['event.patchSet.ref'] = ref 87 properties['event.patchSet.ref'] = ref
80 elif change['status'] in ('SUBMITTED', 'MERGED'): 88 elif change['status'] in ('SUBMITTED', 'MERGED'):
81 properties['event.refUpdate.newRev'] = change['current_revision'] 89 properties['event.refUpdate.newRev'] = change['current_revision']
82 chdict = { 90 chdict = {
83 'author': '%s <%s>' % ( 91 'author': '%s <%s>' % (
84 commit['author']['name'], commit['author']['email']), 92 commit['author']['name'], commit['author']['email']),
85 'project': change['project'], 93 'project': change['project'],
86 'branch': change['branch'], 94 'branch': change['branch'],
87 'revision': change['current_revision'], 95 'revision': change['current_revision'],
88 'comments': commit['subject'], 96 'comments': commit['subject'],
89 'files': commit['files'].keys() if 'files' in commit else ['UNKNOWN'], 97 'files': commit['files'].keys() if 'files' in commit else ['UNKNOWN'],
90 'category': 'patchset-created', 98 'category': self.change_category,
91 'when_timestamp': self._parse_timestamp(commit['committer']['date']), 99 'when_timestamp': self._parse_timestamp(commit['committer']['date']),
92 'revlink': '%s://%s/#/c/%s' % ( 100 'revlink': '%s://%s/#/c/%s' % (
93 self.agent.gerrit_protocol, self.agent.gerrit_host, 101 self.agent.gerrit_protocol, self.agent.gerrit_host,
94 change['_number']), 102 change['_number']),
95 'repository': '%s://%s/%s' % ( 103 'repository': '%s://%s/%s' % (
96 self.agent.gerrit_protocol, self.agent.gerrit_host, 104 self.agent.gerrit_protocol, self.agent.gerrit_host,
97 change['project']), 105 change['project']),
98 'properties': properties} 106 'properties': properties,
107 }
99 d = self.master.addChange(**chdict) 108 d = self.master.addChange(**chdict)
100 d.addErrback(log.err, 'GerritPoller: Could not add buildbot change for ' 109 d.addErrback(log.err, 'GerritPoller: Could not add buildbot change for '
101 'gerrit change %s.' % revision['_number']) 110 'gerrit change %s.' % revision['_number'])
102 return d 111 return d
103 112
113 def addChange(self, change, message):
114 return self.addBuildbotChange(change, message)
115
104 def processChanges(self, j, since): 116 def processChanges(self, j, since):
105 need_more = bool(j) 117 need_more = bool(j)
106 for change in j: 118 for change in j:
107 tm = self._parse_timestamp(change['updated']) 119 tm = self._parse_timestamp(change['updated'])
108 if tm <= since: 120 if tm <= since:
109 need_more = False 121 need_more = False
110 break 122 break
111 if self.gerrit_projects and change['project'] not in self.gerrit_projects: 123 if self.gerrit_projects and change['project'] not in self.gerrit_projects:
112 continue 124 continue
113 d = self.checkForNewPatchset(change, since) 125 d = self.checkForNewPatchset(change, since)
114 d.addCallback(lambda x: self.createBuildbotChange(x) if x else None) 126 d.addCallback(lambda x: self.addChange(*x) if x else None)
115 if need_more and j[-1].get('_more_changes'): 127 if need_more and j[-1].get('_more_changes'):
116 d = self.getChanges(sortkey=j[-1]['_sortkey']) 128 d = self.getChanges(sortkey=j[-1]['_sortkey'])
117 d.addCallback(self.processChanges, since=since) 129 d.addCallback(self.processChanges, since=since)
118 else: 130 else:
119 d = defer.succeed(None) 131 d = defer.succeed(None)
120 return d 132 return d
121 133
122 @deferredLocked('initLock') 134 @deferredLocked('initLock')
123 def poll(self): 135 def poll(self):
124 log.msg('GerritPoller: getting latest changes...') 136 log.msg('GerritPoller: getting latest changes...')
125 since = self.last_timestamp 137 since = self.last_timestamp
126 d = self.getChanges() 138 d = self.getChanges()
127 def _update_last_timestamp(j): 139 def _update_last_timestamp(j):
128 if j: 140 if j:
129 self.last_timestamp = self._parse_timestamp(j[0]['updated']) 141 self.last_timestamp = self._parse_timestamp(j[0]['updated'])
130 return j 142 return j
131 d.addCallback(_update_last_timestamp) 143 d.addCallback(_update_last_timestamp)
132 d.addCallback(self.processChanges, since=since) 144 d.addCallback(self.processChanges, since=since)
133 return d 145 return d
OLDNEW
« no previous file with comments | « no previous file | scripts/master/try_job_gerrit.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698