2 # ex: set syntax=python:
9 from buildbot import locks
11 # This is a sample buildmaster config file. It must be installed as
12 # 'master.cfg' in your buildmaster's base directory.
14 ini = ConfigParser.ConfigParser()
15 ini.read("./config.ini")
17 # This is the dictionary that the buildmaster pays attention to. We also use
18 # a shorter alias to save typing.
19 c = BuildmasterConfig = {}
21 ####### PROJECT IDENTITY
23 # the 'title' string will appear at the top of this buildbot
24 # installation's html.WebStatus home page (linked to the
25 # 'titleURL') and is embedded in the title of the waterfall HTML page.
27 c['title'] = ini.get("general", "title")
28 c['titleURL'] = ini.get("general", "title_url")
30 # the 'buildbotURL' string should point to the location where the buildbot's
31 # internal web server (usually the html.WebStatus page) is visible. This
32 # typically uses the port number set in the Waterfall 'status' entry, but
33 # with an externally-visible host name which the buildbot cannot figure out
36 c['buildbotURL'] = ini.get("general", "buildbot_url")
40 # The 'slaves' list defines the set of recognized buildslaves. Each element is
41 # a BuildSlave object, specifying a unique slave name and password. The same
42 # slave name and password must be configured on the slave.
43 from buildbot.buildslave import BuildSlave
47 if ini.has_option("general", "port"):
48 slave_port = ini.getint("general", "port")
53 for section in ini.sections():
54 if section.startswith("slave "):
55 if ini.has_option(section, "name") and ini.has_option(section, "password"):
56 sl_props = { 'dl_lock':None, 'ul_lock':None, 'do_cleanup':False, 'max_builds':1, 'shared_wd':False }
57 name = ini.get(section, "name")
58 password = ini.get(section, "password")
60 if ini.has_option(section, "builds"):
61 max_builds = ini.getint(section, "builds")
62 sl_props['max_builds'] = max_builds
63 if ini.has_option(section, "cleanup"):
64 sl_props['do_cleanup'] = ini.getboolean(section, "cleanup")
65 if ini.has_option(section, "dl_lock"):
66 lockname = ini.get(section, "dl_lock")
67 sl_props['dl_lock'] = lockname
68 if lockname not in NetLocks:
69 NetLocks[lockname] = locks.MasterLock(lockname)
70 if ini.has_option(section, "ul_lock"):
71 lockname = ini.get(section, "dl_lock")
72 sl_props['ul_lock'] = lockname
73 if lockname not in NetLocks:
74 NetLocks[lockname] = locks.MasterLock(lockname)
75 if ini.has_option(section, "shared_wd"):
76 shared_wd = ini.getboolean(section, "shared_wd")
77 sl_props['shared_wd'] = shared_wd
78 if shared_wd and (max_builds != 1):
79 raise ValueError('max_builds must be 1 with shared workdir!')
80 c['slaves'].append(BuildSlave(name, password, max_builds = max_builds, properties = sl_props))
82 # 'slavePortnum' defines the TCP port to listen on for connections from slaves.
83 # This must match the value configured into the buildslaves (with their
85 c['slavePortnum'] = slave_port
88 c['mergeRequests'] = True
90 # Reduce amount of backlog data
91 c['buildHorizon'] = 30
96 home_dir = os.path.abspath(ini.get("general", "homedir"))
104 if ini.has_option("general", "expire"):
105 tree_expire = ini.getint("general", "expire")
107 if ini.has_option("general", "other_builds"):
108 other_builds = ini.getint("general", "other_builds")
110 if ini.has_option("general", "cc_version"):
111 cc_version = ini.get("general", "cc_version").split()
112 if len(cc_version) == 1:
113 cc_version = ["eq", cc_version[0]]
115 repo_url = ini.get("repo", "url")
116 repo_branch = "master"
118 if ini.has_option("repo", "branch"):
119 repo_branch = ini.get("repo", "branch")
121 rsync_bin_url = ini.get("rsync", "binary_url")
122 rsync_bin_key = ini.get("rsync", "binary_password")
127 if ini.has_option("rsync", "source_url"):
128 rsync_src_url = ini.get("rsync", "source_url")
129 rsync_src_key = ini.get("rsync", "source_password")
131 gpg_home = "~/.gnupg"
133 gpg_comment = "Unattended build signature"
134 gpg_passfile = "/dev/null"
136 if ini.has_option("gpg", "home"):
137 gpg_home = ini.get("gpg", "home")
139 if ini.has_option("gpg", "keyid"):
140 gpg_keyid = ini.get("gpg", "keyid")
142 if ini.has_option("gpg", "comment"):
143 gpg_comment = ini.get("gpg", "comment")
145 if ini.has_option("gpg", "passfile"):
146 gpg_passfile = ini.get("gpg", "passfile")
148 enable_kmod_archive = True
154 if not os.path.isdir(home_dir+'/source.git'):
155 subprocess.call(["git", "clone", "--depth=1", "--branch="+repo_branch, repo_url, home_dir+'/source.git'])
157 subprocess.call(["git", "pull"], cwd = home_dir+'/source.git')
159 findtargets = subprocess.Popen([home_dir+'/dumpinfo.pl', 'targets'],
160 stdout = subprocess.PIPE, cwd = home_dir+'/source.git')
163 line = findtargets.stdout.readline()
166 ta = line.strip().split(' ')
167 targets.append(ta[0])
170 # the 'change_source' setting tells the buildmaster how it should find out
171 # about source code changes. Here we point to the buildbot clone of pyflakes.
173 from buildbot.changes.gitpoller import GitPoller
174 c['change_source'] = []
175 c['change_source'].append(GitPoller(
177 workdir=home_dir+'/work.git', branch=repo_branch,
182 # Configure the Schedulers, which decide how to react to incoming changes. In this
183 # case, just kick off a 'basebuild' build
185 from buildbot.schedulers.basic import SingleBranchScheduler
186 from buildbot.schedulers.forcesched import ForceScheduler
187 from buildbot.changes import filter
189 c['schedulers'].append(SingleBranchScheduler(
191 change_filter=filter.ChangeFilter(branch=repo_branch),
193 builderNames=targets))
195 c['schedulers'].append(ForceScheduler(
197 builderNames=targets))
201 # The 'builders' list defines the Builders, which tell Buildbot how to perform a build:
202 # what steps, and which slaves can execute them. Note that any particular build will
203 # only take place on one slave.
205 from buildbot.process.factory import BuildFactory
206 from buildbot.steps.source.git import Git
207 from buildbot.steps.shell import ShellCommand
208 from buildbot.steps.shell import SetPropertyFromCommand
209 from buildbot.steps.transfer import FileUpload
210 from buildbot.steps.transfer import FileDownload
211 from buildbot.steps.master import MasterShellCommand
212 from buildbot.process.properties import Interpolate
213 from buildbot.process import properties
217 [ "tools", "tools/clean" ],
218 [ "chain", "toolchain/clean" ],
219 [ "linux", "target/linux/clean" ],
220 [ "dir", "dirclean" ],
221 [ "dist", "distclean" ]
224 def IsMakeCleanRequested(pattern):
225 def CheckCleanProperty(step):
226 val = step.getProperty("clean")
227 if val and re.match(pattern, val):
232 return CheckCleanProperty
234 def IsCleanupRequested(step):
235 shared_wd = step.getProperty("shared_wd")
238 do_cleanup = step.getProperty("do_cleanup")
244 def IsExpireRequested(step):
245 shared_wd = step.getProperty("shared_wd")
249 return not IsCleanupRequested(step)
251 def IsGitFreshRequested(step):
252 do_cleanup = step.getProperty("do_cleanup")
258 def IsGitCleanRequested(step):
259 return not IsGitFreshRequested(step)
261 def IsTaggingRequested(step):
262 val = step.getProperty("tag")
263 if val and re.match("^[0-9]+\.[0-9]+\.[0-9]+(?:-rc[0-9]+)?$", val):
268 def IsNoTaggingRequested(step):
269 return not IsTaggingRequested(step)
271 def IsNoMasterBuild(step):
272 return repo_branch != "master"
274 def GetBaseVersion():
275 if re.match("^[^-]+-[0-9]+\.[0-9]+$", repo_branch):
276 return repo_branch.split('-')[1]
281 def GetVersionPrefix(props):
282 basever = GetBaseVersion()
283 if props.hasProperty("tag") and re.match("^[0-9]+\.[0-9]+\.[0-9]+(?:-rc[0-9]+)?$", props["tag"]):
284 return "%s/" % props["tag"]
285 elif basever != "master":
286 return "%s-SNAPSHOT/" % basever
291 def GetNumJobs(props):
292 if props.hasProperty("max_builds") and props.hasProperty("nproc"):
293 return str(int(props["nproc"]) / (props["max_builds"] + other_builds))
299 if props.hasProperty("cc_command"):
300 return props["cc_command"]
306 if props.hasProperty("cxx_command"):
307 return props["cxx_command"]
313 if props.hasProperty("builddir"):
314 return props["builddir"]
315 elif props.hasProperty("workdir"):
316 return props["workdir"]
321 def GetCCache(props):
322 if props.hasProperty("ccache_command") and "ccache" in props["ccache_command"]:
323 return props["ccache_command"] + " "
327 def GetNextBuild(builder, requests):
329 if r.properties and r.properties.hasProperty("tag"):
333 def MakeEnv(overrides=None, tryccache=False):
335 envcc = Interpolate("%(kw:ccache)s%(kw:cc)s", ccache=GetCCache, cc=GetCC)
336 envcxx = Interpolate("%(kw:ccache)s%(kw:cxx)s", ccache=GetCCache, cxx=GetCXX)
338 envcc = Interpolate("%(kw:cc)s", cc=GetCC)
339 envcxx = Interpolate("%(kw:cxx)s", cxx=GetCXX)
344 if overrides is not None:
345 env.update(overrides)
349 def NetLockDl(props):
351 if props.hasProperty("dl_lock"):
352 lock = NetLocks[props["dl_lock"]]
354 return [lock.access('exclusive')]
359 def NetLockUl(props):
361 if props.hasProperty("ul_lock"):
362 lock = NetLocks[props["ul_lock"]]
364 return [lock.access('exclusive')]
370 dlLock = locks.SlaveLock("slave_dl")
372 checkBuiltin = re.sub('[\t\n ]+', ' ', """
374 local symbol op path file;
375 for file in $CHANGED_FILES; do
381 while read symbol op path; do
382 case "$symbol" in package-*)
383 symbol="${symbol##*(}";
384 symbol="${symbol%)}";
385 for file in $CHANGED_FILES; do
386 case "$file" in "package/$path/"*)
387 grep -qsx "$symbol=y" .config && return 0
391 done < tmp/.packagedeps;
397 class IfBuiltinShellCommand(ShellCommand):
398 def _quote(self, str):
399 if re.search("[^a-zA-Z0-9/_.-]", str):
400 return "'%s'" %(re.sub("'", "'\"'\"'", str))
403 def setCommand(self, command):
404 if not isinstance(command, (str, unicode)):
405 command = ' '.join(map(self._quote, command))
408 '%s; if checkBuiltin; then %s; else exit 0; fi' %(checkBuiltin, command)
411 def setupEnvironment(self, cmd):
412 slaveEnv = self.slaveEnvironment
416 for request in self.build.requests:
417 for source in request.sources:
418 for change in source.changes:
419 for file in change.files:
420 changedFiles[file] = True
421 fullSlaveEnv = slaveEnv.copy()
422 fullSlaveEnv['CHANGED_FILES'] = ' '.join(changedFiles.keys())
423 cmd.args['env'] = fullSlaveEnv
427 for slave in c['slaves']:
428 slaveNames.append(slave.slavename)
430 for target in targets:
431 ts = target.split('/')
433 factory = BuildFactory()
435 # find number of cores
436 factory.addStep(SetPropertyFromCommand(
439 description = "Finding number of CPUs",
440 command = ["nproc"]))
442 # find gcc and g++ compilers
443 if cc_version is not None:
444 factory.addStep(FileDownload(
445 name = "dlfindbinpl",
446 mastersrc = "findbin.pl",
447 slavedest = "../findbin.pl",
450 factory.addStep(SetPropertyFromCommand(
452 property = "cc_command",
453 description = "Finding gcc command",
454 command = ["../findbin.pl", "gcc", cc_version[0], cc_version[1]],
455 haltOnFailure = True))
457 factory.addStep(SetPropertyFromCommand(
459 property = "cxx_command",
460 description = "Finding g++ command",
461 command = ["../findbin.pl", "g++", cc_version[0], cc_version[1]],
462 haltOnFailure = True))
464 # see if ccache is available
465 factory.addStep(SetPropertyFromCommand(
466 property = "ccache_command",
467 command = ["which", "ccache"],
468 description = "Testing for ccache command",
469 haltOnFailure = False,
470 flunkOnFailure = False,
471 warnOnFailure = False,
474 # expire tree if needed
476 factory.addStep(FileDownload(
478 doStepIf = IsExpireRequested,
479 mastersrc = "expire.sh",
480 slavedest = "../expire.sh",
483 factory.addStep(ShellCommand(
485 description = "Checking for build tree expiry",
486 command = ["./expire.sh", str(tree_expire)],
488 haltOnFailure = True,
489 doStepIf = IsExpireRequested,
492 # cleanup.sh if needed
493 factory.addStep(FileDownload(
494 name = "dlcleanupsh",
495 mastersrc = "cleanup.sh",
496 slavedest = "../cleanup.sh",
498 doStepIf = IsCleanupRequested))
500 factory.addStep(ShellCommand(
502 description = "Cleaning previous builds",
503 command = ["./cleanup.sh", c['buildbotURL'], Interpolate("%(prop:slavename)s"), Interpolate("%(prop:buildername)s"), "full"],
505 haltOnFailure = True,
506 doStepIf = IsCleanupRequested,
509 factory.addStep(ShellCommand(
511 description = "Cleaning work area",
512 command = ["./cleanup.sh", c['buildbotURL'], Interpolate("%(prop:slavename)s"), Interpolate("%(prop:buildername)s"), "single"],
514 haltOnFailure = True,
515 doStepIf = IsCleanupRequested,
518 # user-requested clean targets
519 for tuple in CleanTargetMap:
520 factory.addStep(ShellCommand(
522 description = 'User-requested "make %s"' % tuple[1],
523 command = ["make", tuple[1], "V=s"],
525 doStepIf = IsMakeCleanRequested(tuple[0])
528 # check out the source
530 # if repo doesn't exist: 'git clone repourl'
531 # method 'clean' runs 'git clean -d -f', method fresh runs 'git clean -d -f x'. Only works with mode='full'
532 # 'git fetch -t repourl branch; git reset --hard revision'
533 # Git() parameters can't take a renderer until buildbot 0.8.10, so we have to split the fresh and clean cases
534 # if buildbot is updated, one can use: method = Interpolate('%(prop:do_cleanup:#?|fresh|clean)s')
538 branch = repo_branch,
541 haltOnFailure = True,
542 doStepIf = IsGitCleanRequested,
548 branch = repo_branch,
551 haltOnFailure = True,
552 doStepIf = IsGitFreshRequested,
556 factory.addStep(ShellCommand(
558 description = "Fetching Git remote refs",
559 command = ["git", "fetch", "origin", "+refs/heads/%s:refs/remotes/origin/%s" %(repo_branch, repo_branch)],
564 factory.addStep(ShellCommand(
566 description = "Checking out Git tag",
567 command = ["git", "checkout", Interpolate("tags/v%(prop:tag:-)s")],
568 haltOnFailure = True,
569 doStepIf = IsTaggingRequested
572 factory.addStep(ShellCommand(
574 description = "Remove tmp folder",
575 command=["rm", "-rf", "tmp/"]))
578 # factory.addStep(ShellCommand(
579 # name = "feedsconf",
580 # description = "Copy the feeds.conf",
581 # command='''cp ~/feeds.conf ./feeds.conf''' ))
584 factory.addStep(ShellCommand(
585 name = "rmfeedlinks",
586 description = "Remove feed symlinks",
587 command=["rm", "-rf", "package/feeds/"]))
590 factory.addStep(ShellCommand(
591 name = "updatefeeds",
592 description = "Updating feeds",
593 command=["./scripts/feeds", "update"],
598 factory.addStep(ShellCommand(
599 name = "installfeeds",
600 description = "Installing feeds",
601 command=["./scripts/feeds", "install", "-a"],
605 factory.addStep(FileDownload(
606 name = "dlconfigseed",
607 mastersrc = "config.seed",
608 slavedest = ".config",
613 factory.addStep(ShellCommand(
615 description = "Seeding .config",
616 command = "printf 'CONFIG_TARGET_%s=y\\nCONFIG_TARGET_%s_%s=y\\n' >> .config" %(ts[0], ts[0], ts[1])
619 factory.addStep(ShellCommand(
621 description = "Removing output directory",
622 command = ["rm", "-rf", "bin/"]
625 factory.addStep(ShellCommand(
627 description = "Populating .config",
628 command = ["make", "defconfig"],
633 factory.addStep(ShellCommand(
635 description = "Checking architecture",
636 command = ["grep", "-sq", "CONFIG_TARGET_%s=y" %(ts[0]), ".config"],
644 factory.addStep(SetPropertyFromCommand(
647 description = "Finding libc suffix",
648 command = ["sed", "-ne", '/^CONFIG_LIBC=/ { s!^CONFIG_LIBC="\\(.*\\)"!\\1!; s!^musl$!!; s!.\\+!-&!p }', ".config"]))
651 factory.addStep(FileDownload(name="dlkeybuild", mastersrc=home_dir+'/key-build', slavedest="key-build", mode=0600))
652 factory.addStep(FileDownload(name="dlkeybuildpub", mastersrc=home_dir+'/key-build.pub', slavedest="key-build.pub", mode=0600))
655 factory.addStep(ShellCommand(
657 description = "Preparing dl/",
658 command = "mkdir -p $HOME/dl && rm -rf ./dl && ln -sf $HOME/dl ./dl",
664 factory.addStep(ShellCommand(
666 description = "Building and installing GNU tar",
667 command = ["make", Interpolate("-j%(kw:jobs)s", jobs=GetNumJobs), "tools/tar/compile", "V=s"],
668 env = MakeEnv(tryccache=True),
673 factory.addStep(ShellCommand(
675 description = "Populating dl/",
676 command = ["make", Interpolate("-j%(kw:jobs)s", jobs=GetNumJobs), "download", "V=s"],
679 locks = [dlLock.access('exclusive')],
682 factory.addStep(ShellCommand(
684 description = "Cleaning base-files",
685 command=["make", "package/base-files/clean", "V=s"]
689 factory.addStep(ShellCommand(
691 description = "Building and installing tools",
692 command = ["make", Interpolate("-j%(kw:jobs)s", jobs=GetNumJobs), "tools/install", "V=s"],
693 env = MakeEnv(tryccache=True),
697 factory.addStep(ShellCommand(
699 description = "Building and installing toolchain",
700 command=["make", Interpolate("-j%(kw:jobs)s", jobs=GetNumJobs), "toolchain/install", "V=s"],
705 factory.addStep(ShellCommand(
707 description = "Building kmods",
708 command=["make", Interpolate("-j%(kw:jobs)s", jobs=GetNumJobs), "target/compile", "V=s", "IGNORE_ERRORS=n m", "BUILD_LOG=1"],
710 #env={'BUILD_LOG_DIR': 'bin/%s' %(ts[0])},
714 # find kernel version
715 factory.addStep(SetPropertyFromCommand(
716 name = "kernelversion",
717 property = "kernelversion",
718 description = "Finding the effective Kernel version",
719 command = "make --no-print-directory -C target/linux/ val.LINUX_VERSION val.LINUX_RELEASE val.LINUX_VERMAGIC | xargs printf '%s-%s-%s\\n'",
720 env = { 'TOPDIR': Interpolate("%(kw:cwd)s/build", cwd=GetCwd) }
723 factory.addStep(ShellCommand(
725 description = "Cleaning up package build",
726 command=["make", "package/cleanup", "V=s"]
729 factory.addStep(ShellCommand(
731 description = "Building packages",
732 command=["make", Interpolate("-j%(kw:jobs)s", jobs=GetNumJobs), "package/compile", "V=s", "IGNORE_ERRORS=n m", "BUILD_LOG=1"],
734 #env={'BUILD_LOG_DIR': 'bin/%s' %(ts[0])},
738 # factory.addStep(IfBuiltinShellCommand(
739 factory.addStep(ShellCommand(
741 description = "Installing packages",
742 command=["make", Interpolate("-j%(kw:jobs)s", jobs=GetNumJobs), "package/install", "V=s"],
747 factory.addStep(ShellCommand(
749 description = "Indexing packages",
750 command=["make", Interpolate("-j%(kw:jobs)s", jobs=GetNumJobs), "package/index", "V=s"],
755 if enable_kmod_archive:
756 # embed kmod repository. Must happen before 'images'
758 # find rootfs staging directory
759 factory.addStep(SetPropertyFromCommand(
761 property = "stageroot",
762 description = "Finding the rootfs staging directory",
763 command=["make", "--no-print-directory", "val.STAGING_DIR_ROOT"],
764 env = { 'TOPDIR': Interpolate("%(kw:cwd)s/build", cwd=GetCwd) }
767 factory.addStep(ShellCommand(
769 description = "Creating file overlay directory",
770 command=["mkdir", "-p", "files/etc/opkg"],
774 factory.addStep(ShellCommand(
776 description = "Embedding kmod repository configuration",
777 command=Interpolate("sed -e 's#^\\(src/gz .*\\)_core \\(.*\\)/packages$#&\\n\\1_kmods \\2/kmods/%(prop:kernelversion)s#' " +
778 "%(prop:stageroot)s/etc/opkg/distfeeds.conf > files/etc/opkg/distfeeds.conf"),
782 #factory.addStep(IfBuiltinShellCommand(
783 factory.addStep(ShellCommand(
785 description = "Building and installing images",
786 command=["make", Interpolate("-j%(kw:jobs)s", jobs=GetNumJobs), "target/install", "V=s"],
791 factory.addStep(ShellCommand(
793 description = "Generating config.seed",
794 command=["make", "-j1", "diffconfig", "V=s"],
799 factory.addStep(ShellCommand(
801 description = "Calculating checksums",
802 command=["make", "-j1", "checksum", "V=s"],
807 if enable_kmod_archive:
808 factory.addStep(ShellCommand(
810 description = "Creating kmod directory",
811 command=["mkdir", "-p", Interpolate("bin/targets/%(kw:target)s/%(kw:subtarget)s%(prop:libc)s/kmods/%(prop:kernelversion)s", target=ts[0], subtarget=ts[1])],
815 factory.addStep(ShellCommand(
816 name = "kmodprepare",
817 description = "Preparing kmod archive",
818 command=["rsync", "--include=/kmod-*.ipk", "--exclude=*", "-va",
819 Interpolate("bin/targets/%(kw:target)s/%(kw:subtarget)s%(prop:libc)s/packages/", target=ts[0], subtarget=ts[1]),
820 Interpolate("bin/targets/%(kw:target)s/%(kw:subtarget)s%(prop:libc)s/kmods/%(prop:kernelversion)s/", target=ts[0], subtarget=ts[1])],
824 factory.addStep(ShellCommand(
826 description = "Indexing kmod archive",
827 command=["make", Interpolate("-j%(kw:jobs)s", jobs=GetNumJobs), "package/index", "V=s",
828 Interpolate("PACKAGE_SUBDIRS=bin/targets/%(kw:target)s/%(kw:subtarget)s%(prop:libc)s/kmods/%(prop:kernelversion)s/", target=ts[0], subtarget=ts[1])],
834 if gpg_keyid is not None:
835 factory.addStep(MasterShellCommand(
836 name = "signprepare",
837 description = "Preparing temporary signing directory",
838 command = ["mkdir", "-p", "%s/signing" %(home_dir)],
842 factory.addStep(ShellCommand(
844 description = "Packing files to sign",
845 command = Interpolate("find bin/targets/%(kw:target)s/%(kw:subtarget)s%(prop:libc)s/ bin/targets/%(kw:target)s/%(kw:subtarget)s%(prop:libc)s/kmods/ -mindepth 1 -maxdepth 2 -type f -name sha256sums -print0 -or -name Packages -print0 | xargs -0 tar -czf sign.tar.gz", target=ts[0], subtarget=ts[1]),
849 factory.addStep(FileUpload(
850 slavesrc = "sign.tar.gz",
851 masterdest = "%s/signing/%s.%s.tar.gz" %(home_dir, ts[0], ts[1]),
855 factory.addStep(MasterShellCommand(
857 description = "Signing files",
858 command = ["%s/signall.sh" %(home_dir), "%s/signing/%s.%s.tar.gz" %(home_dir, ts[0], ts[1]), gpg_keyid, gpg_comment],
859 env = {'GNUPGHOME': gpg_home, 'PASSFILE': gpg_passfile},
863 factory.addStep(FileDownload(
864 name = "dlsigntargz",
865 mastersrc = "%s/signing/%s.%s.tar.gz" %(home_dir, ts[0], ts[1]),
866 slavedest = "sign.tar.gz",
870 factory.addStep(ShellCommand(
872 description = "Unpacking signed files",
873 command = ["tar", "-xzf", "sign.tar.gz"],
878 factory.addStep(ShellCommand(
880 description = "Preparing upload directory structure",
881 command = ["mkdir", "-p", Interpolate("tmp/upload/%(kw:prefix)stargets/%(kw:target)s/%(kw:subtarget)s", target=ts[0], subtarget=ts[1], prefix=GetVersionPrefix)],
885 factory.addStep(ShellCommand(
886 name = "linkprepare",
887 description = "Preparing repository symlink",
888 command = ["ln", "-s", "-f", Interpolate("../packages-%(kw:basever)s", basever=GetBaseVersion()), Interpolate("tmp/upload/%(kw:prefix)spackages", prefix=GetVersionPrefix)],
889 doStepIf = IsNoMasterBuild,
893 if enable_kmod_archive:
894 factory.addStep(ShellCommand(
895 name = "kmoddirprepare",
896 description = "Preparing kmod archive upload directory",
897 command = ["mkdir", "-p", Interpolate("tmp/upload/%(kw:prefix)stargets/%(kw:target)s/%(kw:subtarget)s/kmods/%(prop:kernelversion)s", target=ts[0], subtarget=ts[1], prefix=GetVersionPrefix)],
901 factory.addStep(ShellCommand(
903 description = "Uploading directory structure",
904 command = ["rsync", "-4", "-az", "tmp/upload/", "%s/" %(rsync_bin_url)],
905 env={'RSYNC_PASSWORD': rsync_bin_key},
906 haltOnFailure = True,
910 factory.addStep(FileDownload(
912 mastersrc = "rsync.sh",
913 slavedest = "../rsync.sh",
917 factory.addStep(ShellCommand(
918 name = "targetupload",
919 description = "Uploading target files",
920 command=["../rsync.sh", "-4", "--exclude=/kmods/", "--delete", "--delay-updates", "--partial-dir=.~tmp~%s~%s" %(ts[0], ts[1]),
921 "-a", Interpolate("bin/targets/%(kw:target)s/%(kw:subtarget)s%(prop:libc)s/", target=ts[0], subtarget=ts[1]),
922 Interpolate("%(kw:rsyncbinurl)s/%(kw:prefix)stargets/%(kw:target)s/%(kw:subtarget)s/", rsyncbinurl=rsync_bin_url, target=ts[0], subtarget=ts[1], prefix=GetVersionPrefix)],
923 env={'RSYNC_PASSWORD': rsync_bin_key},
924 haltOnFailure = True,
928 if enable_kmod_archive:
929 factory.addStep(ShellCommand(
931 description = "Uploading kmod archive",
932 command=["../rsync.sh", "-4", "--delete", "--delay-updates", "--partial-dir=.~tmp~%s~%s" %(ts[0], ts[1]),
933 "-a", Interpolate("bin/targets/%(kw:target)s/%(kw:subtarget)s%(prop:libc)s/kmods/%(prop:kernelversion)s/", target=ts[0], subtarget=ts[1]),
934 Interpolate("%(kw:rsyncbinurl)s/%(kw:prefix)stargets/%(kw:target)s/%(kw:subtarget)s/kmods/%(prop:kernelversion)s/", rsyncbinurl=rsync_bin_url, target=ts[0], subtarget=ts[1], prefix=GetVersionPrefix)],
935 env={'RSYNC_PASSWORD': rsync_bin_key},
936 haltOnFailure = True,
940 if rsync_src_url is not None:
941 factory.addStep(ShellCommand(
942 name = "sourceupload",
943 description = "Uploading source archives",
944 command=["../rsync.sh", "-4", "--size-only", "--delay-updates",
945 Interpolate("--partial-dir=.~tmp~%(kw:target)s~%(kw:subtarget)s~%(prop:slavename)s", target=ts[0], subtarget=ts[1]), "-a", "dl/", "%s/" %(rsync_src_url)],
946 env={'RSYNC_PASSWORD': rsync_src_key},
947 haltOnFailure = True,
952 factory.addStep(ShellCommand(
953 name = "packageupload",
954 description = "Uploading package files",
955 command=["../rsync.sh", "-4", "--delete", "--delay-updates", "--partial-dir=.~tmp~%s~%s" %(ts[0], ts[1]), "-a", "bin/packages/", "%s/packages/" %(rsync_bin_url)],
956 env={'RSYNC_PASSWORD': rsync_bin_key},
957 haltOnFailure = False,
963 factory.addStep(ShellCommand(
965 description = "Uploading logs",
966 command=["../rsync.sh", "-4", "--delete", "--delay-updates", "--partial-dir=.~tmp~%s~%s" %(ts[0], ts[1]), "-az", "logs/", "%s/logs/%s/%s/" %(rsync_bin_url, ts[0], ts[1])],
967 env={'RSYNC_PASSWORD': rsync_bin_key},
968 haltOnFailure = False,
973 factory.addStep(ShellCommand(
975 description = "Reporting disk usage",
976 command=["df", "-h", "."],
978 haltOnFailure = False,
982 factory.addStep(ShellCommand(
984 description = "Reporting ccache stats",
985 command=["ccache", "-s"],
986 env = MakeEnv(overrides={ 'PATH': ["./staging_dir/host/bin", "${PATH}"] }),
988 haltOnFailure = False,
989 flunkOnFailure = False,
990 warnOnFailure = False,
994 from buildbot.config import BuilderConfig
996 c['builders'].append(BuilderConfig(name=target, slavenames=slaveNames, factory=factory, nextBuild=GetNextBuild))
999 ####### STATUS TARGETS
1001 # 'status' is a list of Status Targets. The results of each build will be
1002 # pushed to these targets. buildbot/status/*.py has a variety to choose from,
1003 # including web pages, email senders, and IRC bots.
1007 from buildbot.status import html
1008 from buildbot.status.web import authz, auth
1010 if ini.has_option("status", "bind"):
1011 if ini.has_option("status", "user") and ini.has_option("status", "password"):
1012 authz_cfg=authz.Authz(
1013 # change any of these to True to enable; see the manual for more
1015 auth=auth.BasicAuth([(ini.get("status", "user"), ini.get("status", "password"))]),
1016 gracefulShutdown = 'auth',
1017 forceBuild = 'auth', # use this to test your slave once it is set up
1018 forceAllBuilds = 'auth',
1019 pingBuilder = False,
1021 stopAllBuilds = 'auth',
1022 cancelPendingBuild = 'auth',
1024 c['status'].append(html.WebStatus(http_port=ini.get("status", "bind"), authz=authz_cfg))
1026 c['status'].append(html.WebStatus(http_port=ini.get("status", "bind")))
1029 from buildbot.status import words
1031 if ini.has_option("irc", "host") and ini.has_option("irc", "nickname") and ini.has_option("irc", "channel"):
1032 irc_host = ini.get("irc", "host")
1034 irc_chan = ini.get("irc", "channel")
1035 irc_nick = ini.get("irc", "nickname")
1038 if ini.has_option("irc", "port"):
1039 irc_port = ini.getint("irc", "port")
1041 if ini.has_option("irc", "password"):
1042 irc_pass = ini.get("irc", "password")
1044 irc = words.IRC(irc_host, irc_nick, port = irc_port, password = irc_pass,
1045 channels = [{ "channel": irc_chan }],
1048 'successToFailure': 1,
1049 'failureToSuccess': 1
1053 c['status'].append(irc)
1058 # This specifies what database buildbot uses to store its state. You can leave
1059 # this at its default for all but the largest installations.
1060 'db_url' : "sqlite:///state.sqlite",