aboutsummaryrefslogtreecommitdiffstats
#
# SPDX-License-Identifier: GPL-2.0-only
#

from buildbot.plugins import schedulers as sched
from buildbot.plugins import util
from yoctoabb import config

from twisted.internet import defer
from twisted.python import log

from yoctoabb.yocto_console_view.yocto_console_view import ReleaseSelector

schedulers = []

branchdefaults = {
    'master': {
        'branch': 'master',
        'branch_poky': 'master',
        'branch_bitbake': 'master',
        'branch_meta-arm': 'master',
        'branch_meta-agl': 'next',
        'branch_meta-aws': 'master',
        'branch_meta-gplv2': 'master',
        'branch_meta-intel': 'master',
        'branch_meta-mingw': 'master',
        'branch_meta-exein': 'main',
        'branch_meta-openembedded': 'master',
        'branch_oecore': 'master',
    },
    'master-next': {
        'branch': 'master',
        'branch_poky': 'master-next',
        'branch_bitbake': 'master-next',
        'branch_meta-arm': 'master',
        'branch_meta-agl': 'next',
        'branch_meta-aws': 'master',
        'branch_meta-gplv2': 'master',
        'branch_meta-intel': 'master',
        'branch_meta-mingw': 'master',
        'branch_meta-openembedded': 'master',
        'branch_oecore': 'master-next',
    },
    'abelloni-next': {
        'repo_poky': 'ssh://git@push.yoctoproject.org/poky-contrib',
        'branch_poky': 'abelloni/master-next',
        'repo_oecore': 'ssh://git@push.openembedded.org/openembedded-core-contrib',
        'branch_oecore': 'abelloni/master-next',
        'repo_bitbake': 'ssh://git@push.openembedded.org/bitbake-contrib',
        'branch_bitbake': 'abelloni/master-next',
    },
    'mut': {
        'branch': 'master',
        'branch_poky': 'ross/mut',
        'repo_poky': 'ssh://git@push.yoctoproject.org/poky-contrib',
        'branch_bitbake': 'master',
        'branch_meta-arm': 'master',
        'branch_meta-agl': 'next',
        'branch_meta-aws': 'master',
        'branch_meta-gplv2': 'master',
        'branch_meta-intel': 'master',
        'branch_meta-mingw': 'master',
        'branch_meta-openembedded': 'master',
        'branch_oecore': 'master',
    },
    'scarthgap': {
        'branch': 'scarthgap',
        'branch_poky': 'scarthgap',
        'branch_bitbake': '2.8',
        'branch_meta-arm': 'master',
        'branch_meta-agl': 'next',
        'branch_meta-aws': 'master',
        'branch_meta-gplv2': 'master',
        'branch_meta-intel': 'master',
        'branch_meta-mingw': 'scarthgap',
        'branch_meta-openembedded': 'master',
        'branch_meta-ti': 'master',
        'branch_meta-virtualization': 'master',
        'branch_oecore': 'scarthgap',
    },
    'nanbield': {
        'branch': 'nanbield',
        'branch_poky': 'nanbield',
        'branch_bitbake': '2.6',
        'branch_meta-arm': 'nanbield',
        'branch_meta-agl': 'next',
        'branch_meta-aws': 'nanbield',
        'branch_meta-gplv2': 'master',
        'branch_meta-intel': 'nanbield',
        'branch_meta-mingw': 'nanbield',
        'branch_meta-openembedded': 'nanbield',
        'branch_meta-ti': 'master',
        'branch_meta-virtualization': 'nanbield',
        'branch_meta-exein': 'nanbield',
        'branch_oecore': 'nanbield',
    },
    'mickledore': {
        'branch': 'mickledore',
        'branch_poky': 'mickledore',
        'branch_bitbake': '2.4',
        'branch_meta-arm': 'mickledore',
        'branch_meta-agl': 'next',
        'branch_meta-aws': 'mickledore',
        'branch_meta-gplv2': 'master',
        'branch_meta-intel': 'mickledore',
        'branch_meta-mingw': 'mickledore',
        'branch_meta-openembedded': 'mickledore',
        'branch_meta-ti': 'master',
        'branch_meta-virtualization': 'mickledore',
        'branch_oecore': 'mickledore',
    },
    'langdale': {
        'branch': 'langdale',
        'branch_poky': 'langdale',
        'branch_bitbake': '2.2',
        'branch_meta-arm': 'langdale',
        'branch_meta-agl': 'next',
        'branch_meta-aws': 'langdale',
        'branch_meta-gplv2': 'master',
        'branch_meta-intel': 'langdale',
        'branch_meta-mingw': 'langdale',
        'branch_meta-openembedded': 'langdale',
        'branch_meta-ti': 'master',
        'branch_meta-virtualization': 'langdale',
        'branch_oecore': 'langdale',
    },
    'kirkstone': {
        'branch': 'kirkstone',
        'branch_poky': 'kirkstone',
        'branch_bitbake': '2.0',
        'branch_meta-arm': 'kirkstone',
        'branch_meta-agl': 'master',
        'branch_meta-aws': 'kirkstone',
        'branch_meta-gplv2': 'kirkstone',
        'branch_meta-intel': 'kirkstone',
        'branch_meta-mingw': 'kirkstone',
        'branch_meta-openembedded': 'kirkstone',
        'branch_meta-ti': 'kirkstone',
        'branch_meta-virtualization': 'kirkstone',
        'branch_oecore': 'kirkstone',
    },
    'honister': {
        'branch': 'honister',
        'branch_poky': 'honister',
        'branch_bitbake': '1.52',
        'branch_meta-arm': 'honister',
        'branch_meta-aws': 'honister',
        'branch_meta-gplv2': 'honister',
        'branch_meta-intel': 'honister',
        'branch_meta-mingw': 'honister',
        'branch_meta-openembedded': 'honister',
        'branch_meta-ti': 'master',
        'branch_meta-virtualization': 'honister',
        'branch_oecore': 'honister',
    },
    'hardknott': {
        'branch': 'hardknott',
        'branch_poky': 'hardknott',
        'branch_bitbake': '1.50',
        'branch_meta-arm': 'hardknott',
        'branch_meta-aws': 'hardknott',
        'branch_meta-gplv2': 'hardknott',
        'branch_meta-intel': 'hardknott',
        'branch_meta-mingw': 'hardknott',
        'branch_meta-openembedded': 'hardknott',
        'branch_meta-ti': 'master',
        'branch_meta-virtualization': 'hardknott',
        'branch_oecore': 'hardknott',
    },
    'gatesgarth': {
        'branch': 'gatesgarth',
        'branch_poky': 'gatesgarth',
        'branch_bitbake': '1.48',
        'branch_meta-arm': 'gatesgarth',
        'branch_meta-aws': 'gatesgarth',
        'branch_meta-gplv2': 'gatesgarth',
        'branch_meta-intel': 'gatesgarth',
        'branch_meta-mingw': 'gatesgarth',
        'branch_meta-openembedded': 'gatesgarth',
        'branch_meta-ti': 'master',
        'branch_meta-virtualization': 'gatesgarth',
        'branch_oecore': 'gatesgarth',
    },
    'dunfell': {
        'branch': 'dunfell',
        'branch_poky': 'dunfell',
        'branch_bitbake': '1.46',
        'branch_meta-arm': 'dunfell',
        'branch_meta-agl': 'lamprey',
        'branch_meta-aws': 'dunfell',
        'branch_meta-gplv2': 'dunfell',
        'branch_meta-intel': 'dunfell',
        'branch_meta-mingw': 'dunfell',
        'branch_meta-openembedded': 'dunfell',
        'branch_meta-ti': 'dunfell',
        'branch_meta-virtualization': 'dunfell',
        'branch_oecore': 'dunfell',
    },
    'zeus': {
        'branch': 'zeus',
        'branch_poky': 'zeus',
        'branch_bitbake': '1.44',
        'branch_meta-gplv2': 'zeus',
        'branch_meta-intel': 'zeus',
        'branch_meta-mingw': 'zeus',
        'branch_oecore': 'zeus',
    },
    'warrior': {
        'branch': 'warrior',
        'branch_poky': 'warrior',
        'branch_bitbake': '1.42',
        'branch_meta-gplv2': 'warrior',
        'branch_meta-intel': 'warrior',
        'branch_meta-mingw': 'warrior',
        'branch_oecore': 'warrior',
    },
    'thud': {
        'branch': 'thud',
        'branch_poky': 'thud',
        'branch_bitbake': '1.40',
        'branch_meta-gplv2': 'thud',
        'branch_meta-intel': 'thud',
        'branch_meta-mingw': 'thud',
        'branch_oecore': 'thud',
    },
    'sumo': {
        'branch': 'sumo',
        'branch_poky': 'sumo',
        'branch_bitbake': '1.38',
        'branch_meta-gplv2': 'sumo',
        'branch_meta-intel': 'sumo',
        'branch_meta-mingw': 'sumo',
        'branch_oecore': 'sumo',
    },
    'rocko': {
        'branch': 'rocko',
        'branch_poky': 'rocko',
        'branch_bitbake': '1.36',
        'branch_meta-gplv2': 'rocko',
        'branch_meta-intel': 'rocko',
        'branch_meta-mingw': 'rocko',
        'branch_oecore': 'rocko',
    },
    'pyro': {
        'branch': 'pyro',
        'branch_poky': 'pyro',
        'branch_bitbake': '1.34',
        'branch_meta-gplv2': 'pyro',
        'branch_meta-intel': 'pyro',
        'branch_meta-mingw': 'pyro',
        'branch_oecore': 'pyro',
    },
    'morty': {
        'branch': 'morty',
        'branch_poky': 'morty',
        'branch_bitbake': '1.32',
        'branch_meta-gplv2': 'master',
        'branch_meta-intel': 'morty',
        'branch_meta-mingw': 'morty',
        'branch_oecore': 'morty',
    }
}

def create_repo_inputs(reponame):
    """
    Given the name of a repository in yoctoab.config's repo dict creates
    StringParameter inputs to allow specification of alternative uri, branch
    and commit/hash values
    """

    repo = util.StringParameter("repo_{}".format(reponame),
                                label="Repository:",
                                default=config.repos[reponame][0])
    branch = util.StringParameter("branch_{}".format(reponame),
                                  label="Branch:",
                                  default=config.repos[reponame][1])
    commit = util.StringParameter("commit_{}".format(reponame),
                                  label="Revision:",
                                  default="HEAD")
    return [repo, branch, commit]


def repos_for_builder(buildername):
    """
    Returns a list of additional properties for a scheduler, a list of
    StringParameter allowing all of the repositories used by the
    builder/scheduler to be customised
    """

    parameters = []
    repos = config.buildertorepos.get(buildername)
    if not repos:
        repos = config.buildertorepos["default"]
    for repo in repos:
        inputs = create_repo_inputs(repo)
        parameters = parameters + [util.NestedParameter(name='', label=repo, fields=inputs, columns=2)]
    return parameters

def parent_default_props(buildername, branchname=None):
    props = {}
    props["swat_monitor"] = True
    if buildername in ['reproducible-meta-oe', 'meta-oe-mirror']:
        props["swat_monitor"] = False
    repos = config.buildertorepos.get(buildername)
    if not repos:
        repos = config.buildertorepos["default"]
    if branchname:
        props['branch'] = branchname
    for repo in repos:
        props["repo_{}".format(repo)] = config.repos[repo][0]
        branchkey = "branch_{}".format(repo)
        if branchname and branchname in branchdefaults and branchkey in branchdefaults[branchname]:
            props[branchkey] = branchdefaults[branchname][branchkey]
        else:
            props[branchkey] = config.repos[repo][1]
        config.repos[repo][1]
        props["commit_{}".format(repo)] = "HEAD"
    return props

def buildappsrcrev_param():
    return util.StringParameter(
            name="buildappsrcrev",
            label="""Build appliance source revision to use. "None" means default to the srcrev currently in the recipe, use "AUTOREV" to use latest revision or specify a revision to use:""",
            default="AUTOREV")

def props_for_builder(builder):
    """
    Generate an appropriate list of properties to use on a builder-specific
    scheduler
    """

    swat_default = True
    if builder in ['auh', 'meta-oe']:
        swat_default = False

    props = []
    props.append(util.BooleanParameter(
        name="swat_monitor",
        label="Should SWAT monitor this build?",
        default=swat_default))
    if builder == 'build-appliance':
        props.append(buildappsrcrev_param())
    props.append(util.BooleanParameter(
        name="deploy_artefacts",
        label="Do we want to deploy artefacts?",
        default=False
    ))
    props = props + repos_for_builder(builder)
    worker_list = config.builder_to_workers.get(builder, config.builder_to_workers['default'])
    props.append(util.ChoiceStringParameter(name="worker",
                              label="Worker to run the build on",
                              default="*",
                              multiple=False,
                              strict=True,
                              choices=worker_list + ["*"]))
    return props


for builder in config.subbuilders:
    schedulers.append(sched.ForceScheduler(
        name=builder,
        builderNames=[builder],
        reason=util.StringParameter(
                name="reason",
                label="""Reason (please note the reason for triggering the
 build and any expectations for the build's outcome:""",
                required=False),
        properties=props_for_builder(builder),
        buttonName="Force Build"))

@util.renderer
def builderNamesFromConfigQuick(props):
    #log.msg("builderNames: Sourcestamp %s, props %s" % (str(props.sourcestamps), str(props)))
    yp_branch = props.sourcestamps[0]['branch']

    builders = config.trigger_builders_wait_quick
    for b in config.trigger_builders_wait_quick_releases:
        if yp_branch and yp_branch.startswith(b):
            log.msg("builderNames: Filtering branch %s due to entry %s" % (str(yp_branch), str(b)))
            builders = config.trigger_builders_wait_quick_releases[b]

    return builders

@util.renderer
def builderNamesFromConfigFull(props):
    #log.msg("builderNames: Sourcestamp %s, props %s" % (str(props.sourcestamps), str(props)))
    yp_branch = props.sourcestamps[0]['branch']

    builders = config.trigger_builders_wait_full
    for b in config.trigger_builders_wait_full_releases:
        if yp_branch and yp_branch.startswith(b):
            log.msg("builderNames: Filtering branch %s due to entry %s" % (str(yp_branch), str(b)))
            builders = config.trigger_builders_wait_full_releases[b]

    # Only run performance runs on release builds
    if props.getProperty("is_release", False):
        builders = builders + config.trigger_builders_wait_perf

    return builders

# Upstream Triggerable class will rasise NotImplementedError() which will mean triggers abort upon reconfig
# Hack to intercept and ignore this, we'd rather they just survive in our case.
class ourTriggerable(sched.Triggerable):
    def reconfigService(self, name=None, *args, **kwargs):
        return

# nightly builder triggers various other builders
wait_quick = ourTriggerable(name="wait-quick",
                         builderNames=builderNamesFromConfigQuick)
schedulers.append(wait_quick)
wait_full = ourTriggerable(name="wait-full",
                         builderNames=builderNamesFromConfigFull)
schedulers.append(wait_full)

def parent_scheduler(target):
    return sched.ForceScheduler(
    name=target,
    builderNames=[target],
    buttonName="Start " + target + " Build",
    codebases = [util.CodebaseParameter(codebase='', label="yocto-autobuilder-helper:", project=None)],
    reason=util.StringParameter(
        name="reason",
        label="""Reason (please note the reason for triggering the build and
 any expectations for the build's outcome:""",
        required=False),
    properties=[
        ReleaseSelector(
            name="branchselector",
            default="master",
            label="Release Shortcut Selector",
            choices=["master", "master-next", "abelloni-next", "mut", "scarthgap", "nanbield", "mickledore", "langdale", "kirkstone", "honister", "hardknott", "gatesgarth", "dunfell", "zeus", "warrior", "thud", "sumo", "rocko", "pyro", "morty"],
            selectors=branchdefaults),
        util.BooleanParameter(
            name="swat_monitor",
            label="Should SWAT monitor this build?",
            default=True),
        buildappsrcrev_param(),
        util.BooleanParameter(
            name="is_release",
            label="Generate a release?",
            default=False),
        util.StringParameter(
            name="yocto_number",  # used to form publish path
            label="Yocto Project Release Number (1.5, 1.6 etc.)"),
        util.ChoiceStringParameter(
            name="milestone_number",
            label="Milestone number",
            choices=["", "M1", "M2", "M3", "M4"],
            default=""
        ),
        util.ChoiceStringParameter(
            name="rc_number",
            label="Release candidate number",
            choices=["", "rc1", "rc2", "rc3", "rc4", "rc5", "rc6", "rc7",
                     "rc8", "rc9"],
            default=""),
        util.BooleanParameter(
            name="send_email",
            label="Send QA alert emails?",
            default=False),
        util.BooleanParameter(
            name="deploy_artefacts",
            label="Do we want to save build output? ",
            default=False)
    ]+repos_for_builder(target))

schedulers.append(parent_scheduler("a-quick"))
schedulers.append(parent_scheduler("a-full"))


schedulers.append(sched.ForceScheduler(
        name="docs",
        builderNames=["docs"],
        reason=util.StringParameter(
                name="reason",
                label="""Reason (please note the reason for triggering the docs build:""",
                required=False),
        properties=props_for_builder("docs"),
        buttonName="Force Build"))


# Run a-quick at 1am each day Mon-Sat so we keep master tested and up to date in sstate and buildhistory
schedulers.append(sched.Nightly(name='nightly-quick', branch='master', properties=parent_default_props('a-quick'),
                  builderNames=['a-quick'], hour=1, minute=0, dayOfWeek=[0,1,2,3,4,5]))
# Run a-full at 1am Sun each Week
schedulers.append(sched.Nightly(name='nightly-full', branch='master', properties=parent_default_props('a-full'),
                  builderNames=['a-full'], hour=1, minute=0, dayOfWeek=6))

# Run check-layer-nightly each day for master
schedulers.append(sched.Nightly(name='nightly-check-layer', branch='master', properties=parent_default_props('check-layer-nightly'),
                  builderNames=['check-layer-nightly'], hour=0, minute=0))

# Run meta-oe-mirror each day for master
schedulers.append(sched.Nightly(name='nightly-meta-oe-mirror', branch='master', properties=parent_default_props('meta-oe-mirror'),
                  builderNames=['meta-oe-mirror'], hour=0, minute=0))

# Run reproducible-meta-oe for master once a week on weekends (2am on Saturday)
schedulers.append(sched.Nightly(name='nightly-reproducible-meta-oe', branch='master', properties=parent_default_props('reproducible-meta-oe'),
                  builderNames=['reproducible-meta-oe'], hour=2, minute=0, dayOfWeek=5))

# Run metrics at 3-7am each day
schedulers.append(sched.Nightly(name='nightly-metrics-dunfell', branch='dunfell', properties=parent_default_props('metrics', 'dunfell'), builderNames=['metrics'], hour=6, minute=0, codebases = {'' : {'branch' : 'dunfell'}}))
schedulers.append(sched.Nightly(name='nightly-metrics-kirkstone', branch='kirkstone', properties=parent_default_props('metrics', 'kirkstone'), builderNames=['metrics'], hour=6, minute=15, codebases = {'' : {'branch' : 'kirkstone'}}))
schedulers.append(sched.Nightly(name='nightly-metrics-mickledore', branch='mickledore', properties=parent_default_props('metrics', 'mickledore'), builderNames=['metrics'], hour=6, minute=30, codebases = {'' : {'branch' : 'mickledore'}}))
schedulers.append(sched.Nightly(name='nightly-metrics-nanbield', branch='nanbield', properties=parent_default_props('metrics', 'nanbield'), builderNames=['metrics'], hour=6, minute=45, codebases = {'' : {'branch' : 'nanbield'}}))
schedulers.append(sched.Nightly(name='nightly-metrics', branch='master', properties=parent_default_props('metrics'), builderNames=['metrics'], hour=7, minute=0))

# Run check-layer-nightly twice a week for nanbield
schedulers.append(sched.Nightly(name='nightly-check-layer-nanbield', properties=parent_default_props('check-layer-nightly', 'nanbield'),
                  builderNames=['check-layer-nightly'], dayOfWeek=[3, 7], hour=2, minute=0, codebases = {'' : {'branch' : 'nanbield'}}))
# Run meta-oe-mirror twice a month for nanbield
schedulers.append(sched.Nightly(name='nightly-meta-oe-mirror-nanbield', properties=parent_default_props('meta-oe-mirror', 'nanbield'),
                  builderNames=['meta-oe-mirror'], dayOfMonth=[1, 15], hour=2, minute=0, codebases = {'' : {'branch' : 'nanbield'}}))

# Run check-layer-nightly twice a week for kirkstone
schedulers.append(sched.Nightly(name='nightly-check-layer-kirkstone', properties=parent_default_props('check-layer-nightly', 'kirkstone'),
                  builderNames=['check-layer-nightly'], dayOfWeek=[0, 3], hour=2, minute=0, codebases = {'' : {'branch' : 'kirkstone'}}))
# Run meta-oe-mirror twice a month for kirkstone
schedulers.append(sched.Nightly(name='nightly-meta-oe-mirror-kirkstone', properties=parent_default_props('meta-oe-mirror', 'kirkstone'),
                  builderNames=['meta-oe-mirror'], dayOfMonth=[2, 16], hour=2, minute=0, codebases = {'' : {'branch' : 'kirkstone'}}))

# Run check-layer-nightly twice a week for dunfell
schedulers.append(sched.Nightly(name='nightly-check-layer-dunfell', properties=parent_default_props('check-layer-nightly', 'dunfell'),
                  builderNames=['check-layer-nightly'], dayOfWeek=[1, 4], hour=2, minute=0, codebases = {'' : {'branch' : 'dunfell'}}))
# Run meta-oe-mirror twice a month for dunfell
schedulers.append(sched.Nightly(name='nightly-meta-oe-mirror-dunfell', properties=parent_default_props('meta-oe-mirror', 'dunfell'),
                  builderNames=['meta-oe-mirror'], dayOfMonth=[3, 17], hour=2, minute=0, codebases = {'' : {'branch' : 'dunfell'}}))

# Run the build performance tests at 3am, 9am, 3pm and 9pm
schedulers.append(sched.Nightly(name='nightly-buildperf', branch='master', properties=parent_default_props('buildperf-debian11'),
                  builderNames=['buildperf-debian11', 'buildperf-alma8'], hour=[3,9,15,21], minute=0))

# Run the toaster tests daily
schedulers.append(sched.Nightly(name='nightly-toaster', branch='master', properties=parent_default_props('toaster'),
                  builderNames=['toaster'], hour=[3], minute=0))

# Run the AUH twice a month on 1st and 15th
schedulers.append(sched.Nightly(name='nightly-auh', branch='master', properties=parent_default_props('auh'),
                  builderNames=['auh'], dayOfMonth=[1, 15], hour=5, minute=0))

# If any of our sphinx docs branches change, trigger a build
schedulers.append(sched.AnyBranchScheduler(name="yocto-docs-changed",
            change_filter=util.ChangeFilter(project=["yocto-docs"], branch=[None, "master", "master-next", "mickledore", "langdale", "kirkstone", "honister", "hardknott", "gatesgarth", "dunfell", "transition"]),
            codebases = ['', 'yocto-docs', 'bitbake'],
            treeStableTimer=60,
            builderNames=["docs"]))

# If bitbake's sphinx docs change, trigger a build
def isbitbakeDocFile(change):
    for f in change.files:
        if "doc/" in f:
            return True
    return False
schedulers.append(sched.AnyBranchScheduler(name="bitbake-docs-changed",
            change_filter=util.ChangeFilter(project=["bitbake"], branch=["master", "1.52", "1.50", "1.48", "1.46"]),
            codebases = ['', 'yocto-docs', 'bitbake'],
            fileIsImportant=isbitbakeDocFile,
            onlyImportant=True,
            treeStableTimer=60,
            builderNames=["docs"]))