|
# 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
""" Base class for all schedulers; this provides the equipment to manage reconfigurations and to handle basic scheduler state. It also provides utility methods to begin various sorts of builds.
Subclasses should add any configuration-derived attributes to C{base.Scheduler.compare_attrs}. """
codebases = DefaultCodebases): """ Initialize a Scheduler.
@param name: name of this scheduler (used as a key for state) @type name: unicode
@param builderNames: list of builders this scheduler may start @type builderNames: list of unicode
@param properties: properties to add to builds triggered by this scheduler @type properties: dictionary
@param codebases: codebases that are necessary to process the changes @type codebases: dict with following struct: key: '<codebase>' value: {'repository':'<repo>', 'branch':'<br>', 'revision:'<rev>'}
@param consumeChanges: true if this scheduler wishes to be informed about the addition of new changes. Defaults to False. This should be passed explicitly from subclasses to indicate their interest in consuming changes. @type consumeChanges: boolean """ "name of this scheduler; used to identify replacements on reconfig"
else: ok = False "The builderNames argument to a scheduler must be a list " "of Builder names.")
"list of builder names to start in each buildset"
"properties that are contributed to each buildset"
# Set the codebases that are necessary to process the changes # These codebases will always result in a sourcestamp with or without changes config.error("Codebases must be a dict of dicts") config.error("Codebases must be a dict of dicts") 'repository' not in codebase_attrs): else: config.error("Codebases cannot be None")
# internal variables
## service handling
## state management
def getState(self, *args, **kwargs): """ For use by subclasses; get a named state value from the scheduler's state, defaulting to DEFAULT.
@param name: name of the value to retrieve @param default: (optional) value to return if C{name} is not present @returns: state value via a Deferred @raises KeyError: if C{name} is not present and no default is given @raises TypeError: if JSON parsing fails """ # get the objectid, if not known self.__class__.__name__)
**kwargs)
def setState(self, key, value): """ For use by subclasses; set a named state value in the scheduler's persistent state. Note that value must be json-able.
@param name: the name of the value to change @param value: the value to set - must be a JSONable object @param returns: Deferred @raises TypeError: if JSONification fails """ # get the objectid, if not known self.__class__.__name__)
## status queries
# TODO: these aren't compatible with distributed schedulers
"Returns the list of builder names"
"Returns a list of the next times that builds are scheduled, if known."
## change handling
onlyImportant=False): """ Subclasses should call this method from startService to register to receive changes. The BaseScheduler class will take care of filtering the changes (using change_filter) and (if fileIsImportant is not None) classifying them. See L{gotChange}. Returns a Deferred.
@param fileIsImportant: a callable provided by the user to distinguish important and unimportant changes @type fileIsImportant: callable
@param change_filter: a filter to determine which changes are even considered by this scheduler, or C{None} to consider all changes @type change_filter: L{buildbot.changes.filter.ChangeFilter} instance
@param onlyImportant: If True, only important changes, as specified by fileIsImportant, will be added to the buildset. @type onlyImportant: boolean
"""
# register for changes with master # ignore changes delivered while we're not running return
log.msg('change contains codebase %s that is not processed by this scheduler' % change.codebase) return 'in fileIsImportant check for %s' % change) else:
# use change_consumption_lock to ensure the service does not stop # while this change is being processed
# (note: called automatically in stopService)
# acquire the lock change consumption lock to ensure that any change # consumption is complete before we are done stopping consumption
""" Called when a change is received; returns a Deferred. If the C{fileIsImportant} parameter to C{startConsumingChanges} was C{None}, then all changes are considered important. The C{codebase} of the change has always an entry in the C{codebases} dictionary of the scheduler.
@param change: the new change object @type change: L{buildbot.changes.changes.Change} instance @param important: true if this is an important change, according to C{fileIsImportant}. @type important: boolean @returns: Deferred """ raise NotImplementedError
## starting bulids
branch=None, repository='', project='', builderNames=None, properties=None): """ Add a buildset for the 'latest' source in the given branch, repository, and project. This will create a relative sourcestamp for the buildset.
This method will add any properties provided to the scheduler constructor to the buildset, and will call the master's addBuildset method with the appropriate parameters.
@param reason: reason for this buildset @type reason: unicode string @param external_idstring: external identifier for this buildset, or None @param branch: branch to build (note that None often has a special meaning) @param repository: repository name for sourcestamp @param project: project name for sourcestamp @param builderNames: builders to name in the buildset (defaults to C{self.builderNames}) @param properties: a properties object containing initial properties for the buildset @type properties: L{buildbot.process.properties.Properties} @returns: (buildset ID, buildrequest IDs) via Deferred """ # Define setid for this set of changed repositories
# add a sourcestamp for each codebase codebase=codebase, repository=ss_repository, branch=ss_branch, revision=ss_revision, project=project, changeids=set(), sourcestampsetid=setid)
setid=setid, reason=reason, external_idstring=external_idstring, builderNames=builderNames, properties=properties)
branch=None, repository='', project='', revision=None, builderNames=None, properties=None): """ Given details about the source code to build, create a source stamp and then add a buildset for it.
@param reason: reason for this buildset @type reason: unicode string @param external_idstring: external identifier for this buildset, or None @param branch: branch to build (note that None often has a special meaning) @param repository: repository name for sourcestamp @param project: project name for sourcestamp @param revision: revision to build - default is latest @param builderNames: builders to name in the buildset (defaults to C{self.builderNames}) @param properties: a properties object containing initial properties for the buildset @type properties: L{buildbot.process.properties.Properties} @returns: (buildset ID, buildrequest IDs) via Deferred """ # Define setid for this set of changed repositories
branch=branch, revision=revision, repository=repository, project=project, sourcestampsetid=setid)
setid=setid, reason=reason, external_idstring=external_idstring, builderNames=builderNames, properties=properties)
changeids=[], builderNames=None, properties=None):
# Define setid for this set of changed repositories
# Changes are retrieved from database and grouped by their codebase # group change by codebase
# codebase has no changes # create a sourcestamp that has no changes else: #codebase has changes
# add one buildset, this buildset is connected to the sourcestamps by the setid reason=reason, external_idstring=external_idstring, builderNames=builderNames, properties=properties)
properties=None, builderNames=None): """ Add a buildset for the given, already-existing sourcestamp.
This method will add any properties provided to the scheduler constructor to the buildset, and will call the master's L{BuildMaster.addBuildset} method with the appropriate parameters, and return the same result.
@param reason: reason for this buildset @type reason: unicode string @param external_idstring: external identifier for this buildset, or None @param properties: a properties object containing initial properties for the buildset @type properties: L{buildbot.process.properties.Properties} @param builderNames: builders to name in the buildset (defaults to C{self.builderNames}) @param setid: idenitification of a set of sourcestamps @returns: (buildset ID, buildrequest IDs) via Deferred """ or (ssid is not None and setid is None), "pass a single sourcestamp OR set not both"
# combine properties else:
# apply the default builderNames
# translate properties object into a dict as required by the # addBuildset method
if ssid is not None: ssdict = yield self.master.db.sourcestamps.getSourceStamp(ssid) setid = ssdict['sourcestampsetid'] else: # no sourcestamp and no sets yield None
reason=reason, properties=properties_dict, builderNames=builderNames, external_idstring=external_idstring)
|