1
# This file is part of Buildbot. Buildbot is free software: you can
2
# redistribute it and/or modify it under the terms of the GNU General Public
3
# License as published by the Free Software Foundation, version 2.
5
# This program is distributed in the hope that it will be useful, but WITHOUT
6
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
7
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
10
# You should have received a copy of the GNU General Public License along with
11
# this program; if not, write to the Free Software Foundation, Inc., 51
12
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
14
# Copyright Buildbot Team Members
16
from twisted.internet import defer
17
from twisted.python import log
18
from buildbot import util
19
from buildbot.status.results import SUCCESS, WARNINGS
20
from buildbot.schedulers import base
22
class Dependent(base.BaseScheduler):
24
compare_attrs = base.BaseScheduler.compare_attrs + ('upstream_name',)
26
def __init__(self, name, upstream, builderNames, properties={}):
27
base.BaseScheduler.__init__(self, name, builderNames, properties)
28
assert base.isScheduler(upstream), \
29
"upstream must be another Scheduler instance"
30
self.upstream_name = upstream.name
31
self._buildset_addition_subscr = None
32
self._buildset_completion_subscr = None
34
# the subscription lock makes sure that we're done inserting a
35
# subcription into the DB before registering that the buildset is
37
self._subscription_lock = defer.DeferredLock()
39
def startService(self):
40
self._buildset_addition_subscr = \
41
self.master.subscribeToBuildsets(self._buildsetAdded)
42
self._buildset_completion_subscr = \
43
self.master.subscribeToBuildsetCompletions(self._buildsetCompleted)
44
# check for any buildsets completed before we started
45
d = self._checkCompletedBuildsets(None, None)
46
d.addErrback(log.err, 'while checking for completed buildsets in start')
48
def stopService(self):
49
if self._buildset_addition_subscr:
50
self._buildset_addition_subscr.unsubscribe()
51
if self._buildset_completion_subscr:
52
self._buildset_completion_subscr.unsubscribe()
53
return defer.succeed(None)
55
@util.deferredLocked('_subscription_lock')
56
def _buildsetAdded(self, bsid=None, properties=None, **kwargs):
57
# check if this was submitetted by our upstream by checking the
59
submitter = properties.get('scheduler', (None, None))[0]
60
if submitter != self.upstream_name:
63
# record our interest in this buildset, both locally and in the
65
d = self.master.db.buildsets.subscribeToBuildset(
66
self.schedulerid, bsid)
67
d.addErrback(log.err, 'while subscribing to buildset %d' % bsid)
69
def _buildsetCompleted(self, bsid, result):
70
d = self._checkCompletedBuildsets(bsid, result)
71
d.addErrback(log.err, 'while checking for completed buildsets')
73
@util.deferredLocked('_subscription_lock')
74
@defer.deferredGenerator
75
def _checkCompletedBuildsets(self, bsid, result):
76
wfd = defer.waitForDeferred(
77
self.master.db.buildsets.getSubscribedBuildsets(self.schedulerid))
79
subs = wfd.getResult()
81
for (sub_bsid, sub_ssid, sub_complete, sub_results) in subs:
82
# skip incomplete builds, handling the case where the 'complete'
83
# column has not been updated yet
84
if not sub_complete and sub_bsid != bsid:
87
# build a dependent build if the status is appropriate
88
if sub_results in (SUCCESS, WARNINGS):
89
wfd = defer.waitForDeferred(
90
self.addBuildsetForSourceStamp(ssid=sub_ssid,
95
# and regardless of status, remove the subscription
96
wfd = defer.waitForDeferred(
97
self.master.db.buildsets.unsubscribeFromBuildset(
98
self.schedulerid, sub_bsid))