|
# This file is part of Buildbot. Buildbot is free software: you can # redistribute it and/or modify it under the terms of the GNU General Public # License as published by the Free Software Foundation, version 2. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program; if not, write to the Free Software Foundation, Inc., 51 # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # Copyright Buildbot Team Members
# No default limit to the log size
# service management
# subscribe to the things we need to know about self.master.subscribeToBuildsetCompletions( self._buildsetCompletionCallback) self.master.subscribeToBuildsets( self._buildsetCallback) self.master.subscribeToBuildRequests( self._buildRequestCallback) self.master.subscribeToChanges( self.changeAdded)
def reconfigService(self, new_config): # remove the old listeners, then add the new sr.disownServiceParent())
# reconfig any newly-added change sources, as well as existing new_config)
self._buildset_completion_sub.unsubscribe() self._buildset_sub.unsubscribe() self._build_request_sub.unsubscribe() self._change_sub.unsubscribe()
return service.MultiService.stopService(self)
# clean shutdown
def shuttingDown(self): return self.botmaster.shuttingDown
return self.botmaster.cleanShutdown()
return self.botmaster.cancelCleanShutdown()
# methods called by our clients
return self.master.config.title return self.master.config.titleURL
# some listeners expect their .parent to be a BuildMaster object, and # use this method to get the Status object. This is documented, so for # now keep it working. return self
return self.master.metrics
urllib.quote(builder_name, safe=''), build_number)
return None return prefix pass bldr = thing return prefix + "builders/%s" % ( urllib.quote(bldr.getName(), safe=''), ) build = thing bldr = build.getBuilder() return self.getURLForBuild(bldr.getName(), build.getNumber())
step = thing build = step.getBuild() bldr = build.getBuilder() return prefix + "builders/%s/builds/%d/steps/%s" % ( urllib.quote(bldr.getName(), safe=''), build.getNumber(), urllib.quote(step.getName(), safe='')) # IBuildSetStatus # IBuildRequestStatus # ISlaveStatus
# IStatusEvent # TODO: this is goofy, create IChange or something if isinstance(thing, changes.Change): change = thing return "%schanges/%d" % (prefix, change.number)
else: return None urllib.quote(bldr.getName(), safe=''), build.getNumber(), urllib.quote(step.getName(), safe=''), urllib.quote(loog.getName(), safe=''))
return list(self.master.change_svc)
"""Get a Change object; returns a deferred""" d = self.master.db.changes.getChange(number) def chdict2change(chdict): if not chdict: return None return changes.Change.fromChdict(self.master, chdict) d.addCallback(chdict2change) return d
return self.master.allSchedulers()
if categories == None: return util.naturalSort(self.botmaster.builderNames) # don't let them break it
l = [] # respect addition order for name in self.botmaster.builderNames: bldr = self.botmaster.builders[name] if bldr.config.category in categories: l.append(name) return util.naturalSort(l)
""" @rtype: L{BuilderStatus} """ return self.botmaster.builders[name].builder_status
return self.botmaster.slaves.keys()
return self.botmaster.slaves[slavename].slave_status
for bsdict in bsdicts ]
num_builds=None, finished_before=None, max_search=200):
def want_builder(bn): if builders: return bn in builders return True builder_names = [bn for bn in self.getBuilderNames() if want_builder(bn)]
# 'sources' is a list of generators, one for each Builder we're # using. When the generator is exhausted, it is replaced in this list # with None. sources = [] for bn in builder_names: b = self.getBuilder(bn) g = b.generateFinishedBuilds(branches, finished_before=finished_before, max_search=max_search) sources.append(g)
# next_build the next build from each source next_build = [None] * len(sources)
def refill(): for i,g in enumerate(sources): if next_build[i]: # already filled continue if not g: # already exhausted continue try: next_build[i] = g.next() except StopIteration: next_build[i] = None sources[i] = None
got = 0 while True: refill() # find the latest build among all the candidates candidates = [(i, b, b.getTimes()[1]) for i,b in enumerate(next_build) if b is not None] candidates.sort(lambda x,y: cmp(x[2], y[2])) if not candidates: return
# and remove it from the list i, build, finshed_time = candidates[-1] next_build[i] = None got += 1 yield build if num_builds is not None: if got >= num_builds: return
self.watchers.append(target) for name in self.botmaster.builderNames: self.announceNewBuilder(target, name, self.getBuilder(name)) self.watchers.remove(target)
# methods called by upstream objects
t = target.builderAdded(name, builder_status) if t: builder_status.subscribe(t)
""" @rtype: L{BuilderStatus} """ filename = os.path.join(self.basedir, basedir, "builder") log.msg("trying to load status pickle from %s" % filename) builder_status = None try: with open(filename, "rb") as f: builder_status = load(f) builder_status.master = self.master
# (bug #1068) if we need to upgrade, we probably need to rewrite # this pickle, too. We determine this by looking at the list of # Versioned objects that have been unpickled, and (after doUpgrade) # checking to see if any of them set wasUpgraded. The Versioneds' # upgradeToVersionNN methods all set this. versioneds = styles.versionedsToUpgrade styles.doUpgrade() if True in [ hasattr(o, 'wasUpgraded') for o in versioneds.values() ]: log.msg("re-writing upgraded builder pickle") builder_status.saveYourself()
except IOError: log.msg("no saved status pickle, creating a new one") except: log.msg("error while loading status pickle, creating a new one") log.msg("error follows:") log.err() if not builder_status: builder_status = builder.BuilderStatus(name, category, self.master) builder_status.addPointEvent(["builder", "created"]) log.msg("added builder %s in category %s" % (name, category)) # an unpickled object might not have category set from before, # so set it here to make sure builder_status.category = category builder_status.master = self.master builder_status.basedir = os.path.join(self.basedir, basedir) builder_status.name = name # it might have been updated builder_status.status = self
if not os.path.isdir(builder_status.basedir): os.makedirs(builder_status.basedir) builder_status.determineNextBuildNumber()
builder_status.setBigState("offline")
for t in self.watchers: self.announceNewBuilder(t, name, builder_status)
return builder_status
for t in self.watchers: if hasattr(t, 'builderRemoved'): t.builderRemoved(name)
for t in self.watchers: if hasattr(t, 'slaveConnected'): t.slaveConnected(name)
for t in self.watchers: if hasattr(t, 'slaveDisconnected'): t.slaveDisconnected(name)
for t in self.watchers: if hasattr(t, 'changeAdded'): t.changeAdded(change)
result = {} # Constant result['title'] = self.getTitle() result['titleURL'] = self.getTitleURL() result['buildbotURL'] = self.getBuildbotURL() # TODO: self.getSchedulers() # self.getChangeSources() return result
if brid in self._buildreq_observers: for o in self._buildreq_observers[brid]: eventually(o, build_status)
self._buildreq_observers.add(brid, observer)
self._buildreq_observers.discard(brid, observer)
d = defer.Deferred() self._buildset_finished_waiters.add(bsid, d) self._maybeBuildsetFinished(bsid) return d
# check bsid to see if it's successful or finished, and notify anyone # who cares if bsid not in self._buildset_finished_waiters: return d = self.master.db.buildsets.getBuildset(bsid) def do_notifies(bsdict): bss = buildset.BuildSetStatus(bsdict, self) if bss.isFinished(): for d in self._buildset_finished_waiters.pop(bsid): eventually(d.callback, bss) d.addCallback(do_notifies) d.addErrback(log.err, 'while notifying for buildset finishes')
# should get requestSubmitted and requestCancelled self._builder_observers.add(buildername, watcher)
self._builder_observers.discard(buildername, watcher)
bsid = kwargs['bsid'] d = self.master.db.buildsets.getBuildset(bsid) def do_notifies(bsdict): bss = buildset.BuildSetStatus(bsdict, self) for t in self.watchers: if hasattr(t, 'buildsetSubmitted'): t.buildsetSubmitted(bss) d.addCallback(do_notifies) d.addErrback(log.err, 'while notifying buildsetSubmitted')
self._maybeBuildsetFinished(bsid)
buildername = notif['buildername'] if buildername in self._builder_observers: brs = buildrequest.BuildRequestStatus(buildername, notif['brid'], self) for observer in self._builder_observers[buildername]: if hasattr(observer, 'requestSubmitted'): eventually(observer.requestSubmitted, brs) |