# -*- python -*- # ex: set syntax=python: import os import re import subprocess import ConfigParser from buildbot import locks ini = ConfigParser.ConfigParser() ini.read("./config.ini") # This is a sample buildmaster config file. It must be installed as # 'master.cfg' in your buildmaster's base directory. # This is the dictionary that the buildmaster pays attention to. We also use # a shorter alias to save typing. c = BuildmasterConfig = {} ####### BUILDSLAVES # The 'slaves' list defines the set of recognized buildslaves. Each element is # a BuildSlave object, specifying a unique slave name and password. The same # slave name and password must be configured on the slave. from buildbot.buildslave import BuildSlave c['slaves'] = [] for section in ini.sections(): if section.startswith("slave "): if ini.has_option(section, "name") and ini.has_option(section, "password"): name = ini.get(section, "name") password = ini.get(section, "password") max_builds = 1 if ini.has_option(section, "builds"): max_builds = ini.getint(section, "builds") c['slaves'].append(BuildSlave(name, password, max_builds = max_builds)) # 'slavePortnum' defines the TCP port to listen on for connections from slaves. # This must match the value configured into the buildslaves (with their # --master option) c['slavePortnum'] = 9990 # coalesce builds c['mergeRequests'] = True ####### CHANGESOURCES home_dir = os.path.abspath(ini.get("general", "homedir")) repo_url = ini.get("repo", "url") rsync_bin_url = ini.get("rsync", "binary_url") rsync_bin_key = ini.get("rsync", "binary_password") rsync_src_url = None rsync_src_key = None if ini.has_option("rsync", "source_url"): rsync_src_url = ini.get("rsync", "source_url") rsync_src_key = ini.get("rsync", "source_password") # find arches arches = [ ] archnames = [ ] findarches = subprocess.Popen([home_dir+'/dumpinfo.pl', 'architectures'], stdout = subprocess.PIPE, cwd = home_dir+'/source.git') while True: line = findarches.stdout.readline() if not line: break at = line.strip().split() arches.append(at) archnames.append(at[0]) # find feeds feeds = [] from buildbot.changes.gitpoller import GitPoller c['change_source'] = [] with open(home_dir+'/source.git/feeds.conf.default', 'r') as f: for line in f: parts = line.strip().split() if parts[0] == "src-git": feeds.append(parts) c['change_source'].append(GitPoller(parts[2], workdir='%s/%s.git' %(os.getcwd(), parts[1]), branch='master', pollinterval=300)) ####### SCHEDULERS # Configure the Schedulers, which decide how to react to incoming changes. In this # case, just kick off a 'basebuild' build from buildbot.schedulers.basic import SingleBranchScheduler from buildbot.schedulers.forcesched import ForceScheduler from buildbot.changes import filter c['schedulers'] = [] c['schedulers'].append(SingleBranchScheduler( name="all", change_filter=filter.ChangeFilter(branch='master'), treeStableTimer=60, builderNames=archnames)) c['schedulers'].append(ForceScheduler( name="force", builderNames=archnames)) ####### BUILDERS # The 'builders' list defines the Builders, which tell Buildbot how to perform a build: # what steps, and which slaves can execute them. Note that any particular build will # only take place on one slave. from buildbot.process.factory import BuildFactory from buildbot.steps.source import Git from buildbot.steps.shell import ShellCommand from buildbot.steps.shell import SetProperty from buildbot.steps.transfer import FileDownload from buildbot.process.properties import WithProperties c['builders'] = [] dlLock = locks.SlaveLock("slave_dl") slaveNames = [ ] for slave in c['slaves']: slaveNames.append(slave.slavename) for arch in arches: ts = arch[1].split('/') factory = BuildFactory() # find number of cores factory.addStep(SetProperty( name = "nproc", property = "nproc", description = "Finding number of CPUs", command = ["nproc"])) # prepare workspace factory.addStep(FileDownload(mastersrc="cleanup.sh", slavedest="cleanup.sh", mode=0755)) factory.addStep(ShellCommand( name = "cleanold", description = "Cleaning previous builds", command = ["./cleanup.sh", WithProperties("%(slavename)s"), WithProperties("%(buildername)s"), "full"], haltOnFailure = True, timeout = 2400)) factory.addStep(ShellCommand( name = "cleanup", description = "Cleaning work area", command = ["./cleanup.sh", WithProperties("%(slavename)s"), WithProperties("%(buildername)s"), "single"], haltOnFailure = True, timeout = 2400)) factory.addStep(ShellCommand( name = "mksdkdir", description = "Preparing SDK directory", command = ["mkdir", "sdk"], haltOnFailure = True)) factory.addStep(ShellCommand( name = "downloadsdk", description = "Downloading SDK archive", command = ["rsync", "-va", "downloads.lede-project.org::downloads/snapshots/targets/%s/%s/[Ll][Ee][Dd][Ee]-[Ss][Dd][Kk]-*.tar.bz2" %(ts[0], ts[1]), "sdk.tar.bz2"], haltOnFailure = True)) factory.addStep(ShellCommand( name = "unpacksdk", description = "Unpacking SDK archive", command = ["tar", "--strip-components=1", "-C", "sdk/", "-vxjf", "sdk.tar.bz2"], haltOnFailure = True)) factory.addStep(FileDownload(mastersrc=home_dir+'/key-build', slavedest="sdk/key-build", mode=0600)) factory.addStep(FileDownload(mastersrc=home_dir+'/key-build.pub', slavedest="sdk/key-build.pub", mode=0600)) factory.addStep(ShellCommand( name = "mkdldir", description = "Preparing download directory", command = ["sh", "-c", "mkdir -p $HOME/dl && rmdir ./sdk/dl && ln -sf $HOME/dl ./sdk/dl"])) factory.addStep(ShellCommand( name = "mkconf", description = "Preparing SDK configuration", workdir = "build/sdk", command = ["sh", "-c", "rm -f .config && make defconfig"])) factory.addStep(ShellCommand( name = "updatefeeds", description = "Updating feeds", workdir = "build/sdk", command = ["./scripts/feeds", "update"])) factory.addStep(ShellCommand( name = "installfeeds", description = "Installing feeds", workdir = "build/sdk", command = ["./scripts/feeds", "install", "-a"])) factory.addStep(ShellCommand( name = "compile", description = "Building packages", workdir = "build/sdk", command = ["make", WithProperties("-j%(nproc:~4)s"), "V=s", "IGNORE_ERRORS=n m y", "BUILD_LOG=1", "CONFIG_SIGNED_PACKAGES=y"])) factory.addStep(ShellCommand( name = "uploadprepare", description = "Preparing package directory", workdir = "build/sdk", command = ["rsync", "-av", "--include", "/%s/" %(arch[0]), "--exclude", "/*", "--exclude", "/%s/*" %(arch[0]), "bin/packages/", "%s/packages/" %(rsync_bin_url)], env={'RSYNC_PASSWORD': rsync_bin_key}, haltOnFailure = True, logEnviron = False )) factory.addStep(ShellCommand( name = "packageupload", description = "Uploading package files", workdir = "build/sdk", command = ["rsync", "--delete", "--delay-updates", "-avz", "bin/packages/%s/" %(arch[0]), "%s/packages/%s/" %(rsync_bin_url, arch[0])], env={'RSYNC_PASSWORD': rsync_bin_key}, haltOnFailure = True, logEnviron = False )) factory.addStep(ShellCommand( name = "logprepare", description = "Preparing log directory", workdir = "build/sdk", command = ["rsync", "-av", "--include", "/%s/" %(arch[0]), "--exclude", "/*", "--exclude", "/%s/*" %(arch[0]), "bin/packages/", "%s/faillogs/" %(rsync_bin_url)], env={'RSYNC_PASSWORD': rsync_bin_key}, haltOnFailure = True, logEnviron = False )) factory.addStep(ShellCommand( name = "logfind", description = "Finding failure logs", workdir = "build/sdk/logs/package/feeds", command = ["sh", "-c", "sed -ne 's!^ *ERROR: package/feeds/\\([^ ]*\\) .*$!\\1!p' ../error.txt | sort -u | xargs -r find > ../../../logs.txt"], haltOnFailure = False )) factory.addStep(ShellCommand( name = "logcollect", description = "Collecting failure logs", workdir = "build/sdk", command = ["rsync", "-av", "--files-from=logs.txt", "logs/package/feeds/", "faillogs/"], haltOnFailure = False )) factory.addStep(ShellCommand( name = "logupload", description = "Uploading failure logs", workdir = "build/sdk", command = ["rsync", "--delete", "--delay-updates", "-avz", "faillogs/", "%s/faillogs/%s/" %(rsync_bin_url, arch[0])], env={'RSYNC_PASSWORD': rsync_bin_key}, haltOnFailure = False, logEnviron = False )) if rsync_src_url is not None: factory.addStep(ShellCommand( name = "sourceupload", description = "Uploading source archives", workdir = "build/sdk", command = ["rsync", "--delay-updates", "-avz", "dl/", "%s/" %(rsync_src_url)], env={'RSYNC_PASSWORD': rsync_src_key}, haltOnFailure = False, logEnviron = False )) from buildbot.config import BuilderConfig c['builders'].append(BuilderConfig(name=arch[0], slavenames=slaveNames, factory=factory)) ####### STATUS arches # 'status' is a list of Status arches. The results of each build will be # pushed to these arches. buildbot/status/*.py has a variety to choose from, # including web pages, email senders, and IRC bots. c['status'] = [] from buildbot.status import html from buildbot.status.web import authz, auth if ini.has_option("status", "bind"): if ini.has_option("status", "user") and ini.has_option("status", "password"): authz_cfg=authz.Authz( # change any of these to True to enable; see the manual for more # options auth=auth.BasicAuth([(ini.get("status", "user"), ini.get("status", "password"))]), gracefulShutdown = False, forceBuild = 'auth', # use this to test your slave once it is set up forceAllBuilds = 'auth', pingBuilder = False, stopBuild = 'auth', stopAllBuilds = 'auth', cancelPendingBuild = 'auth', ) c['status'].append(html.WebStatus(http_port=ini.get("status", "bind"), authz=authz_cfg)) else: c['status'].append(html.WebStatus(http_port=ini.get("status", "bind"))) ####### PROJECT IDENTITY # the 'title' string will appear at the top of this buildbot # installation's html.WebStatus home page (linked to the # 'titleURL') and is embedded in the title of the waterfall HTML page. c['title'] = ini.get("general", "title") c['titleURL'] = ini.get("general", "title_url") # the 'buildbotURL' string should point to the location where the buildbot's # internal web server (usually the html.WebStatus page) is visible. This # typically uses the port number set in the Waterfall 'status' entry, but # with an externally-visible host name which the buildbot cannot figure out # without some help. c['buildbotURL'] = ini.get("general", "buildbot_url") ####### DB URL c['db'] = { # This specifies what database buildbot uses to store its state. You can leave # this at its default for all but the largest installations. 'db_url' : "sqlite:///state.sqlite", }