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)
343 'CCACHE_BASEDIR': Interpolate("%(kw:cwd)s", cwd=GetCwd)
345 if overrides is not None:
346 env.update(overrides)
350 def NetLockDl(props):
352 if props.hasProperty("dl_lock"):
353 lock = NetLocks[props["dl_lock"]]
355 return [lock.access('exclusive')]
360 def NetLockUl(props):
362 if props.hasProperty("ul_lock"):
363 lock = NetLocks[props["ul_lock"]]
365 return [lock.access('exclusive')]
371 dlLock = locks.SlaveLock("slave_dl")
373 checkBuiltin = re.sub('[\t\n ]+', ' ', """
375 local symbol op path file;
376 for file in $CHANGED_FILES; do
382 while read symbol op path; do
383 case "$symbol" in package-*)
384 symbol="${symbol##*(}";
385 symbol="${symbol%)}";
386 for file in $CHANGED_FILES; do
387 case "$file" in "package/$path/"*)
388 grep -qsx "$symbol=y" .config && return 0
392 done < tmp/.packagedeps;
398 class IfBuiltinShellCommand(ShellCommand):
399 def _quote(self, str):
400 if re.search("[^a-zA-Z0-9/_.-]", str):
401 return "'%s'" %(re.sub("'", "'\"'\"'", str))
404 def setCommand(self, command):
405 if not isinstance(command, (str, unicode)):
406 command = ' '.join(map(self._quote, command))
409 '%s; if checkBuiltin; then %s; else exit 0; fi' %(checkBuiltin, command)
412 def setupEnvironment(self, cmd):
413 slaveEnv = self.slaveEnvironment
417 for request in self.build.requests:
418 for source in request.sources:
419 for change in source.changes:
420 for file in change.files:
421 changedFiles[file] = True
422 fullSlaveEnv = slaveEnv.copy()
423 fullSlaveEnv['CHANGED_FILES'] = ' '.join(changedFiles.keys())
424 cmd.args['env'] = fullSlaveEnv
428 for slave in c['slaves']:
429 slaveNames.append(slave.slavename)
431 for target in targets:
432 ts = target.split('/')
434 factory = BuildFactory()
436 # find number of cores
437 factory.addStep(SetPropertyFromCommand(
440 description = "Finding number of CPUs",
441 command = ["nproc"]))
443 # find gcc and g++ compilers
444 if cc_version is not None:
445 factory.addStep(FileDownload(
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(
477 doStepIf = IsExpireRequested,
478 mastersrc = "expire.sh",
479 slavedest = "../expire.sh",
482 factory.addStep(ShellCommand(
484 description = "Checking for build tree expiry",
485 command = ["./expire.sh", str(tree_expire)],
487 haltOnFailure = True,
488 doStepIf = IsExpireRequested,
491 # cleanup.sh if needed
492 factory.addStep(FileDownload(
493 mastersrc = "cleanup.sh",
494 slavedest = "../cleanup.sh",
496 doStepIf = IsCleanupRequested))
498 factory.addStep(ShellCommand(
500 description = "Cleaning previous builds",
501 command = ["./cleanup.sh", c['buildbotURL'], Interpolate("%(prop:slavename)s"), Interpolate("%(prop:buildername)s"), "full"],
503 haltOnFailure = True,
504 doStepIf = IsCleanupRequested,
507 factory.addStep(ShellCommand(
509 description = "Cleaning work area",
510 command = ["./cleanup.sh", c['buildbotURL'], Interpolate("%(prop:slavename)s"), Interpolate("%(prop:buildername)s"), "single"],
512 haltOnFailure = True,
513 doStepIf = IsCleanupRequested,
516 # user-requested clean targets
517 for tuple in CleanTargetMap:
518 factory.addStep(ShellCommand(
520 description = 'User-requested "make %s"' % tuple[1],
521 command = ["make", tuple[1], "V=s"],
523 doStepIf = IsMakeCleanRequested(tuple[0])
526 # check out the source
528 # if repo doesn't exist: 'git clone repourl'
529 # method 'clean' runs 'git clean -d -f', method fresh runs 'git clean -d -f x'. Only works with mode='full'
530 # 'git fetch -t repourl branch; git reset --hard revision'
531 # Git() parameters can't take a renderer until buildbot 0.8.10, so we have to split the fresh and clean cases
532 # if buildbot is updated, one can use: method = Interpolate('%(prop:do_cleanup:#?|fresh|clean)s')
535 branch = repo_branch,
539 haltOnFailure = True,
540 doStepIf = IsGitCleanRequested,
545 branch = repo_branch,
549 haltOnFailure = True,
550 doStepIf = IsGitFreshRequested,
554 factory.addStep(ShellCommand(
556 description = "Fetching Git remote refs",
557 command = ["git", "fetch", "origin", "+refs/heads/%s:refs/remotes/origin/%s" %(repo_branch, repo_branch)],
562 factory.addStep(ShellCommand(
564 description = "Checking out Git tag",
565 command = ["git", "checkout", Interpolate("tags/v%(prop:tag:-)s")],
566 haltOnFailure = True,
567 doStepIf = IsTaggingRequested
570 factory.addStep(ShellCommand(
572 description = "Remove tmp folder",
573 command=["rm", "-rf", "tmp/"]))
576 # factory.addStep(ShellCommand(
577 # name = "feedsconf",
578 # description = "Copy the feeds.conf",
579 # command='''cp ~/feeds.conf ./feeds.conf''' ))
582 factory.addStep(ShellCommand(
583 name = "rmfeedlinks",
584 description = "Remove feed symlinks",
585 command=["rm", "-rf", "package/feeds/"]))
588 factory.addStep(ShellCommand(
589 name = "updatefeeds",
590 description = "Updating feeds",
591 command=["./scripts/feeds", "update"],
597 factory.addStep(ShellCommand(
598 name = "installfeeds",
599 description = "Installing feeds",
600 command=["./scripts/feeds", "install", "-a"],
604 factory.addStep(FileDownload(
605 mastersrc = "config.seed",
606 slavedest = ".config",
611 factory.addStep(ShellCommand(
613 description = "Seeding .config",
614 command = "printf 'CONFIG_TARGET_%s=y\\nCONFIG_TARGET_%s_%s=y\\n' >> .config" %(ts[0], ts[0], ts[1])
617 factory.addStep(ShellCommand(
619 description = "Removing output directory",
620 command = ["rm", "-rf", "bin/"]
623 factory.addStep(ShellCommand(
625 description = "Populating .config",
626 command = ["make", "defconfig"],
631 factory.addStep(ShellCommand(
633 description = "Checking architecture",
634 command = ["grep", "-sq", "CONFIG_TARGET_%s=y" %(ts[0]), ".config"],
642 factory.addStep(SetPropertyFromCommand(
645 description = "Finding libc suffix",
646 command = ["sed", "-ne", '/^CONFIG_LIBC=/ { s!^CONFIG_LIBC="\\(.*\\)"!\\1!; s!^musl$!!; s!.\\+!-&!p }', ".config"]))
649 factory.addStep(FileDownload(
650 mastersrc = "ccache.sh",
651 slavedest = "../ccache.sh",
656 factory.addStep(ShellCommand(
658 description = "Preparing ccache",
659 command = ["../ccache.sh"]
663 factory.addStep(FileDownload(mastersrc=home_dir+'/key-build', slavedest="key-build", mode=0600))
664 factory.addStep(FileDownload(mastersrc=home_dir+'/key-build.pub', slavedest="key-build.pub", mode=0600))
667 factory.addStep(ShellCommand(
669 description = "Preparing dl/",
670 command = "mkdir -p $HOME/dl && rm -rf ./dl && ln -sf $HOME/dl ./dl",
676 factory.addStep(ShellCommand(
678 description = "Building and installing GNU tar",
679 command = ["make", Interpolate("-j%(kw:jobs)s", jobs=GetNumJobs), "tools/tar/compile", "V=s"],
680 env = MakeEnv(tryccache=True),
685 factory.addStep(ShellCommand(
687 description = "Populating dl/",
688 command = ["make", Interpolate("-j%(kw:jobs)s", jobs=GetNumJobs), "download", "V=s"],
691 locks = properties.FlattenList(NetLockDl, [dlLock.access('exclusive')]),
694 factory.addStep(ShellCommand(
696 description = "Cleaning base-files",
697 command=["make", "package/base-files/clean", "V=s"]
701 factory.addStep(ShellCommand(
703 description = "Building and installing tools",
704 command = ["make", Interpolate("-j%(kw:jobs)s", jobs=GetNumJobs), "tools/install", "V=s"],
705 env = MakeEnv(tryccache=True),
709 factory.addStep(ShellCommand(
711 description = "Building and installing toolchain",
712 command=["make", Interpolate("-j%(kw:jobs)s", jobs=GetNumJobs), "toolchain/install", "V=s"],
717 factory.addStep(ShellCommand(
719 description = "Building kmods",
720 command=["make", Interpolate("-j%(kw:jobs)s", jobs=GetNumJobs), "target/compile", "V=s", "IGNORE_ERRORS=n m", "BUILD_LOG=1"],
722 #env={'BUILD_LOG_DIR': 'bin/%s' %(ts[0])},
726 # find kernel version
727 factory.addStep(SetPropertyFromCommand(
728 name = "kernelversion",
729 property = "kernelversion",
730 description = "Finding the effective Kernel version",
731 command = "make --no-print-directory -C target/linux/ val.LINUX_VERSION val.LINUX_RELEASE val.LINUX_VERMAGIC | xargs printf '%s-%s-%s\\n'",
732 env = { 'TOPDIR': Interpolate("%(kw:cwd)s/build", cwd=GetCwd) }
735 factory.addStep(ShellCommand(
737 description = "Cleaning up package build",
738 command=["make", "package/cleanup", "V=s"]
741 factory.addStep(ShellCommand(
743 description = "Building packages",
744 command=["make", Interpolate("-j%(kw:jobs)s", jobs=GetNumJobs), "package/compile", "V=s", "IGNORE_ERRORS=n m", "BUILD_LOG=1"],
746 #env={'BUILD_LOG_DIR': 'bin/%s' %(ts[0])},
750 # factory.addStep(IfBuiltinShellCommand(
751 factory.addStep(ShellCommand(
753 description = "Installing packages",
754 command=["make", Interpolate("-j%(kw:jobs)s", jobs=GetNumJobs), "package/install", "V=s"],
759 factory.addStep(ShellCommand(
761 description = "Indexing packages",
762 command=["make", Interpolate("-j%(kw:jobs)s", jobs=GetNumJobs), "package/index", "V=s"],
767 if enable_kmod_archive:
768 factory.addStep(ShellCommand(
770 description = "Creating kmod directory",
771 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])],
775 factory.addStep(ShellCommand(
776 name = "kmodprepare",
777 description = "Preparing kmod archive",
778 command=["rsync", "--include=/kmod-*.ipk", "--exclude=*", "-va",
779 Interpolate("bin/targets/%(kw:target)s/%(kw:subtarget)s%(prop:libc)s/packages/", target=ts[0], subtarget=ts[1]),
780 Interpolate("bin/targets/%(kw:target)s/%(kw:subtarget)s%(prop:libc)s/kmods/%(prop:kernelversion)s/", target=ts[0], subtarget=ts[1])],
784 factory.addStep(ShellCommand(
786 description = "Indexing kmod archive",
787 command=["make", Interpolate("-j%(kw:jobs)s", jobs=GetNumJobs), "package/index", "V=s",
788 Interpolate("PACKAGE_SUBDIRS=bin/targets/%(kw:target)s/%(kw:subtarget)s%(prop:libc)s/kmods/%(prop:kernelversion)s/", target=ts[0], subtarget=ts[1])],
793 # find rootfs staging directory
794 factory.addStep(SetPropertyFromCommand(
796 property = "stageroot",
797 description = "Finding the rootfs staging directory",
798 command=["make", "--no-print-directory", "val.STAGING_DIR_ROOT"],
799 env = { 'TOPDIR': Interpolate("%(kw:cwd)s/build", cwd=GetCwd) }
802 factory.addStep(ShellCommand(
804 description = "Creating file overlay directory",
805 command=["mkdir", "-p", "files/etc/opkg"],
809 factory.addStep(ShellCommand(
811 description = "Embedding kmod repository configuration",
812 command=Interpolate("sed -e 's#^\\(src/gz .*\\)_core \\(.*\\)/packages$#&\\n\\1_kmods \\2/kmods/%(prop:kernelversion)s#' " +
813 "%(prop:stageroot)s/etc/opkg/distfeeds.conf > files/etc/opkg/distfeeds.conf"),
817 #factory.addStep(IfBuiltinShellCommand(
818 factory.addStep(ShellCommand(
820 description = "Building and installing images",
821 command=["make", Interpolate("-j%(kw:jobs)s", jobs=GetNumJobs), "target/install", "V=s"],
826 factory.addStep(ShellCommand(
828 description = "Generating config.seed",
829 command=["make", "-j1", "diffconfig", "V=s"],
834 factory.addStep(ShellCommand(
836 description = "Calculating checksums",
837 command=["make", "-j1", "checksum", "V=s"],
843 if gpg_keyid is not None:
844 factory.addStep(MasterShellCommand(
845 name = "signprepare",
846 description = "Preparing temporary signing directory",
847 command = ["mkdir", "-p", "%s/signing" %(home_dir)],
851 factory.addStep(ShellCommand(
853 description = "Packing files to sign",
854 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]),
858 factory.addStep(FileUpload(
859 slavesrc = "sign.tar.gz",
860 masterdest = "%s/signing/%s.%s.tar.gz" %(home_dir, ts[0], ts[1]),
864 factory.addStep(MasterShellCommand(
866 description = "Signing files",
867 command = ["%s/signall.sh" %(home_dir), "%s/signing/%s.%s.tar.gz" %(home_dir, ts[0], ts[1]), gpg_keyid, gpg_comment],
868 env = {'GNUPGHOME': gpg_home, 'PASSFILE': gpg_passfile},
872 factory.addStep(FileDownload(
873 mastersrc = "%s/signing/%s.%s.tar.gz" %(home_dir, ts[0], ts[1]),
874 slavedest = "sign.tar.gz",
878 factory.addStep(ShellCommand(
880 description = "Unpacking signed files",
881 command = ["tar", "-xzf", "sign.tar.gz"],
886 factory.addStep(ShellCommand(
888 description = "Preparing upload directory structure",
889 command = ["mkdir", "-p", Interpolate("tmp/upload/%(kw:prefix)stargets/%(kw:target)s/%(kw:subtarget)s", target=ts[0], subtarget=ts[1], prefix=GetVersionPrefix)],
893 factory.addStep(ShellCommand(
894 name = "linkprepare",
895 description = "Preparing repository symlink",
896 command = ["ln", "-s", "-f", Interpolate("../packages-%(kw:basever)s", basever=GetBaseVersion()), Interpolate("tmp/upload/%(kw:prefix)spackages", prefix=GetVersionPrefix)],
897 doStepIf = IsNoMasterBuild,
901 if enable_kmod_archive:
902 factory.addStep(ShellCommand(
903 name = "kmoddirprepare",
904 description = "Preparing kmod archive upload directory",
905 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)],
909 factory.addStep(ShellCommand(
911 description = "Uploading directory structure",
912 command = ["rsync", "-4", "--info=name", "-az", "tmp/upload/", "%s/" %(rsync_bin_url)],
913 env={'RSYNC_PASSWORD': rsync_bin_key},
914 haltOnFailure = True,
919 factory.addStep(FileDownload(
920 mastersrc = "rsync.sh",
921 slavedest = "../rsync.sh",
924 factory.addStep(ShellCommand(
925 name = "targetupload",
926 description = "Uploading target files",
927 command=["../rsync.sh", "-4", "--info=name", "--exclude=/kmods/", "--delete", "--size-only", "--delay-updates", "--partial-dir=.~tmp~%s~%s" %(ts[0], ts[1]),
928 "-a", Interpolate("bin/targets/%(kw:target)s/%(kw:subtarget)s%(prop:libc)s/", target=ts[0], subtarget=ts[1]),
929 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)],
930 env={'RSYNC_PASSWORD': rsync_bin_key},
931 haltOnFailure = True,
936 if enable_kmod_archive:
937 factory.addStep(ShellCommand(
939 description = "Uploading kmod archive",
940 command=["../rsync.sh", "-4", "--info=name", "--delete", "--size-only", "--delay-updates", "--partial-dir=.~tmp~%s~%s" %(ts[0], ts[1]),
941 "-a", Interpolate("bin/targets/%(kw:target)s/%(kw:subtarget)s%(prop:libc)s/kmods/%(prop:kernelversion)s/", target=ts[0], subtarget=ts[1]),
942 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)],
943 env={'RSYNC_PASSWORD': rsync_bin_key},
944 haltOnFailure = True,
949 if rsync_src_url is not None:
950 factory.addStep(ShellCommand(
951 name = "sourceupload",
952 description = "Uploading source archives",
953 command=["../rsync.sh", "-4", "--info=name", "--size-only", "--delay-updates",
954 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)],
955 env={'RSYNC_PASSWORD': rsync_src_key},
956 haltOnFailure = True,
962 factory.addStep(ShellCommand(
963 name = "packageupload",
964 description = "Uploading package files",
965 command=["../rsync.sh", "-4", "--info=name", "--delete", "--delay-updates", "--partial-dir=.~tmp~%s~%s" %(ts[0], ts[1]), "-a", "bin/packages/", "%s/packages/" %(rsync_bin_url)],
966 env={'RSYNC_PASSWORD': rsync_bin_key},
967 haltOnFailure = False,
974 factory.addStep(ShellCommand(
976 description = "Uploading logs",
977 command=["../rsync.sh", "-4", "-info=name", "--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])],
978 env={'RSYNC_PASSWORD': rsync_bin_key},
979 haltOnFailure = False,
985 factory.addStep(ShellCommand(
987 description = "Reporting disk usage",
988 command=["df", "-h", "."],
990 haltOnFailure = False,
994 factory.addStep(ShellCommand(
996 description = "Reporting ccache stats",
997 command=["ccache", "-s"],
998 env = MakeEnv(overrides={ 'PATH': ["./staging_dir/host/bin", "${PATH}"] }),
1000 haltOnFailure = False,
1001 flunkOnFailure = False,
1002 warnOnFailure = False,
1006 from buildbot.config import BuilderConfig
1008 c['builders'].append(BuilderConfig(name=target, slavenames=slaveNames, factory=factory, nextBuild=GetNextBuild))
1011 ####### STATUS TARGETS
1013 # 'status' is a list of Status Targets. The results of each build will be
1014 # pushed to these targets. buildbot/status/*.py has a variety to choose from,
1015 # including web pages, email senders, and IRC bots.
1019 from buildbot.status import html
1020 from buildbot.status.web import authz, auth
1022 if ini.has_option("status", "bind"):
1023 if ini.has_option("status", "user") and ini.has_option("status", "password"):
1024 authz_cfg=authz.Authz(
1025 # change any of these to True to enable; see the manual for more
1027 auth=auth.BasicAuth([(ini.get("status", "user"), ini.get("status", "password"))]),
1028 gracefulShutdown = 'auth',
1029 forceBuild = 'auth', # use this to test your slave once it is set up
1030 forceAllBuilds = 'auth',
1031 pingBuilder = False,
1033 stopAllBuilds = 'auth',
1034 cancelPendingBuild = 'auth',
1036 c['status'].append(html.WebStatus(http_port=ini.get("status", "bind"), authz=authz_cfg))
1038 c['status'].append(html.WebStatus(http_port=ini.get("status", "bind")))
1041 from buildbot.status import words
1043 if ini.has_option("irc", "host") and ini.has_option("irc", "nickname") and ini.has_option("irc", "channel"):
1044 irc_host = ini.get("irc", "host")
1046 irc_chan = ini.get("irc", "channel")
1047 irc_nick = ini.get("irc", "nickname")
1050 if ini.has_option("irc", "port"):
1051 irc_port = ini.getint("irc", "port")
1053 if ini.has_option("irc", "password"):
1054 irc_pass = ini.get("irc", "password")
1056 irc = words.IRC(irc_host, irc_nick, port = irc_port, password = irc_pass,
1057 channels = [{ "channel": irc_chan }],
1060 'successToFailure': 1,
1061 'failureToSuccess': 1
1065 c['status'].append(irc)
1070 # This specifies what database buildbot uses to store its state. You can leave
1071 # this at its default for all but the largest installations.
1072 'db_url' : "sqlite:///state.sqlite",