Caution
This page documents the latest, unreleased version of Buildbot. For documentation for released versions, see https://docs.buildbot.net/current/.
2.6.3. Priorities
This section describes various priority functions that can be used to control the order in which builds are processed.
2.6.3.1. Builder Priority Functions
The prioritizeBuilders
configuration key specifies a function which is called with two
arguments: a BuildMaster
and a list of Builder
objects. It should return a list
of the same Builder
objects, in the desired order. It may also remove items from the list
if builds should not be started on those builders. If necessary, this function can return its
results via a Deferred (it is called with maybeDeferred
).
A simple prioritizeBuilders
implementation might look like this:
def prioritizeBuilders(buildmaster, builders):
"""Prioritize builders. 'finalRelease' builds have the highest
priority, so they should be built before running tests, or
creating builds."""
builderPriorities = {
"finalRelease": 0,
"test": 1,
"build": 2,
}
builders.sort(key=lambda b: builderPriorities.get(b.name, 0))
return builders
c['prioritizeBuilders'] = prioritizeBuilders
If the change frequency is higher than the turn-around of the builders, the following approach might be helpful:
from buildbot.util.async_sort import async_sort
from twisted.internet import defer
@defer.inlineCallbacks
def prioritizeBuilders(buildmaster, builders):
"""Prioritize builders. First, prioritize inactive builders.
Second, consider the last time a job was completed (no job is infinite past).
Third, consider the time the oldest request has been queued.
This provides a simple round-robin scheme that works with collapsed builds."""
def isBuilding(b):
return bool(b.building) or bool(b.old_building)
@defer.inlineCallbacks
def key(b):
newest_complete_time = yield b.getNewestCompleteTime()
if newest_complete_time is None:
newest_complete_time = datetime.datetime.min
oldest_request_time = yield b.getOldestRequestTime()
if oldest_request_time is None:
oldest_request_time = datetime.datetime.min
return (isBuilding(b), newest_complete_time, oldest_request_time)
yield async_sort(builders, key)
return builders
c['prioritizeBuilders'] = prioritizeBuilders
2.6.3.2. Build Priority Functions
When a builder has multiple pending build requests, it uses a nextBuild
function to decide
which build it should start first. This function is given two parameters: the Builder
, and
a list of BuildRequest
objects representing pending build requests.
A simple function to prioritize release builds over other builds might look like this:
def nextBuild(bldr, requests):
for r in requests:
if r.source.branch == 'release':
return r
return requests[0]
If some non-immediate result must be calculated, the nextBuild
function can also return a Deferred:
def nextBuild(bldr, requests):
d = get_request_priorities(requests)
def pick(priorities):
if requests:
return sorted(zip(priorities, requests))[0][1]
d.addCallback(pick)
return d
The nextBuild
function is passed as parameter to BuilderConfig
:
... BuilderConfig(..., nextBuild=nextBuild, ...) ...
2.6.3.3. Scheduler Priority Functions
When a Scheduler
is creating a a new BuildRequest
from a (list of)
Change
(s),it is possible to set the BuildRequest
priority. This can either be an
integer or a function, which receives a list of builder names and a dictionary of Change
,
grouped by their codebase.
A simple implementation might look like this:
def scheduler_priority(builderNames, changesByCodebase):
priority = 0
for codebase, changes in changesByCodebase.items():
for chg in changes:
if chg["branch"].startswith("dev/"):
priority = max(priority, 0)
elif chg["branch"].startswith("bugfix/"):
priority = max(priority, 5)
elif chg["branch"] == "main":
priority = max(priority, 10)
return priority
The priority function/integer can be passed as a parameter to Scheduler
:
... schedulers.SingleBranchScheduler(..., priority=scheduler_priority, ...) ...