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, ...) ...