# -*- python -*- # ex: set syntax=python: # 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'] = [BuildSlave("example-slave", "pass"), BuildSlave("example-slave-2", "pass"), BuildSlave("example-slave-KL25Z", "pass"), BuildSlave("example-slave-LPC1768", "pass"), BuildSlave("example-slave-LPC11U24", "pass"), ] # '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'] = 9989 ####### OFFICIAL_MBED_LIBRARY_BUILD OFFICIAL_MBED_LIBRARY_BUILD = ( ('LPC1768', ('ARM', 'GCC_ARM', 'GCC_CR', 'GCC_CS', 'IAR')), ('KL05Z', ('ARM', 'uARM', 'GCC_ARM')), ('KL25Z', ('ARM', 'GCC_ARM')), ('LPC11U24', ('ARM', 'uARM')), ('KL46Z', ('ARM', 'GCC_ARM')), ('LPC4088', ('ARM', 'GCC_ARM', 'GCC_CR')), ('LPC1347', ('ARM',)), ('LPC1549', ('uARM',)), ('LPC2368', ('ARM',)), ('LPC812', ('uARM',)), ('LPC11U35_401', ('ARM', 'uARM')), ('LPC1114', ('uARM',)), ('NUCLEO_F103RB', ('ARM', 'uARM')), ('NUCLEO_L152RE', ('ARM', 'uARM')), ('NUCLEO_F401RE', ('ARM', 'uARM')), ('NUCLEO_F030R8', ('ARM', 'uARM')), ('UBLOX_C027', ('ARM', 'GCC_ARM', 'GCC_CR', 'GCC_CS', 'IAR')), # ('NRF51822', ('ARM',)), ) # Which hardware platforms are supported for target testing OFFICIAL_MBED_TESTBED_SUPPORTED_HARDWARE = ( # 'KL25Z', # 'LPC1768', # 'LPC11U24', ) ####### CHANGESOURCES # the 'change_source' setting tells the buildmaster how it should find out # about source code changes. Here we point to the buildbot clone of pyflakes. from buildbot.changes.gitpoller import GitPoller c['change_source'] = [] """ c['change_source'].append(GitPoller( 'git://github.com/buildbot/pyflakes.git', workdir='gitpoller-workdir', branch='master', pollinterval=300)) """ ####### SCHEDULERS # Configure the Schedulers, which decide how to react to incoming changes. In this # case, just kick off a 'runtests' build from buildbot.schedulers.basic import SingleBranchScheduler from buildbot.schedulers.forcesched import ForceScheduler from buildbot.changes import filter c['schedulers'] = [] # Create builders to generate one target using all assigned toolchains release_builder_name = "BuildRelease" builder_names = [release_builder_name] for target_name, toolchains in OFFICIAL_MBED_LIBRARY_BUILD: builder_name = "All_TC_%s" % target_name builder_names.append(builder_name) c['schedulers'].append(ForceScheduler(name="force", builderNames=builder_names)) ####### 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.git import Git from buildbot.steps.shell import ShellCommand from buildbot.process.buildstep import LogLineObserver import buildbot.status.results import re import pprint class TestCommand(ShellCommand): failedTestsCount = 0 # FAIL passedTestsCount = 0 # OK errorsTestsCount = 0 # ERROR undefsTestsCount = 0 # UNDEF testsResults = [] def __init__(self, stage=None,module=None, moduleset=None, **kwargs): ShellCommand.__init__(self, **kwargs) self.failedTestsCount = 0 self.passedTestsCount = 0 self.errorsTestsCount = 0 self.tracebackPyCount = 0 self.testsResults = [] testFailuresObserver = UnitTestsObserver () self.addLogObserver('stdio', testFailuresObserver) def createSummary(self, log): if self.failedTestsCount >= 0 or self.passedTestsCount >= 0 or self.errorsTestsCount >= 0 or self.undefsTestsCount >= 0: self.addHTMLLog ('tests summary', self.createTestsSummary()) def getText(self, cmd, results): text = ShellCommand.getText(self, cmd, results) text.append("OK: " + str(self.passedTestsCount)) text.append("FAIL: " + str(self.failedTestsCount)) text.append("ERROR: " + str(self.errorsTestsCount)) text.append("UNDEF: " + str(self.undefsTestsCount)) text.append("Traceback: " + str(self.tracebackPyCount)) return text def evaluateCommand(self, cmd): if self.failedTestsCount > 0: return buildbot.status.results.WARNINGS elif self.errorsTestsCount > 0 or self.undefsTestsCount > 0 or self.tracebackPyCount > 0: return buildbot.status.results.FAILURE return buildbot.status.results.SUCCESS def find_unique_tc_result_value(self, index): """ Get unique values from each row in data parameter """ result = [] for tc_result_list in self.testsResults: if tc_result_list[index] not in result: result.append(tc_result_list[index]) return result def html_view_test_result(self, targets, tests, toolchain): """ Generates simple result table """ COLOR_OK = "LimeGreen" COLOR_FAIL = "LightCoral" COLOR_UNDEF = "LightSlateGray" COLOR_NEUTRAL = "Silver" STATUS_COLORS = { "OK" : COLOR_OK, "FAIL" : COLOR_FAIL, "UNDEF" : COLOR_UNDEF} result = "" result += "" for test in tests: result += "" result += "" for target in targets: result += "" for test in tests: for tc_result_list in self.testsResults: if tc_result_list[1] == target and tc_result_list[2] == toolchain and tc_result_list[3] == test: status = tc_result_list[4] bgcolor = STATUS_COLORS[status] result += "" break; else: result += "" result += "" result += "
" + toolchain + "" + test + "

" + target + "
" + status + "
" return result def createTestsSummary (self): targets = self.find_unique_tc_result_value(1) toolchains = self.find_unique_tc_result_value(2) tests = self.find_unique_tc_result_value(3) html_result = "" for toolchain in toolchains: html_result += self.html_view_test_result(targets, tests, toolchain) html_result += "
" return html_result class UnitTestsObserver(LogLineObserver): reGroupTestResult = [] reGroupPyResult = [] def __init__(self): LogLineObserver.__init__(self) if len(self.reGroupTestResult) == 0: self.reGroupTestResult.append(re.compile("^(\w+Test)::(\w+)::(\w+)::(\w+)::.* \[(\w+)\] in (\d+\.\d+) of (\d+) sec[\r\n]*$")) def outLineReceived(self, line): matched = False for r in self.reGroupTestResult: result = r.match(line) if result: self.step.testsResults.append(result.groups()) if result.group(5) == 'OK': self.step.passedTestsCount += 1 elif result.group(5) == 'FAIL': self.step.failedTestsCount += 1 elif result.group(5) == 'UNDEF': self.step.undefsTestsCount += 1 elif result.group(5) == 'ERROR': self.step.errorsTestsCount += 1 matched = True class BuildCommand(ShellCommand): warningsCount = 0 # [Warning] errorsCount = 0 # [Error] testsResults = [] def __init__(self, stage=None,module=None, moduleset=None, **kwargs): ShellCommand.__init__(self, **kwargs) self.warningsCount = 0 self.errorsCount = 0 self.testsResults = [] buildProcessObserver = BuildObserver () self.addLogObserver('stdio', buildProcessObserver) def createSummary(self, log): if self.warningsCount >= 0 or self.errorsCount >= 0: self.addHTMLLog ('tests summary', self.createTestsSummary()) def getText(self, cmd, results): text = ShellCommand.getText(self, cmd, results) if self.warningsCount > 0 or self.errorsCount > 0: text.append("warnings: " + str(self.warningsCount)) text.append("errors: " + str(self.errorsCount)) return text def evaluateCommand(self, cmd): if self.warningsCount > 0: return buildbot.status.results.WARNINGS elif self.errorsCount > 0: return buildbot.status.results.FAILURE else: return buildbot.status.results.SUCCESS def createTestsSummary (self): # Create a string with your html report and return it html = "

Report

" #for result in self.testsResults: html += "
" return html class BuildObserver(LogLineObserver): regroupresult = [] def __init__(self): LogLineObserver.__init__(self) if len(self.regroupresult) == 0: self.regroupresult.append(re.compile("^\[([Ww]arning)\] (.*)")) self.regroupresult.append(re.compile("^\[([Ee]rror)\] (.*)")) def outLineReceived(self, line): matched = False for r in self.regroupresult: result = r.match(line) if result: self.step.testsResults.append(result.groups()) if result.group(1) == 'Warning': self.step.warningsCount += 1 elif result.group(1) == 'Error': self.step.errorsCount += 1 matched = True #if not matched: # [Future-Dev] Other check... ####### BUILDERS - mbed project git_clone = Git(repourl='https://github.com/mbedmicro/mbed.git', mode='incremental') # create the build factory for mbed and add the steps to it from buildbot.config import BuilderConfig c['builders'] = [] copy_private_settings = ShellCommand(name = "copy private_settings.py", command = "cp ../private_settings.py workspace_tools/private_settings.py", haltOnFailure = True, description = "Copy private_settings.py") mbed_build_release = BuildFactory() mbed_build_release.addStep(git_clone) mbed_build_release.addStep(copy_private_settings) for target_name, toolchains in OFFICIAL_MBED_LIBRARY_BUILD: builder_name = "All_TC_%s" % target_name mbed_build = BuildFactory() mbed_build.addStep(git_clone) mbed_build.addStep(copy_private_settings) # Adding all chains for target for toolchain in toolchains: build_py = BuildCommand(name = "Build %s using %s" % (target_name, toolchain), command = "python workspace_tools/build.py -m %s -t %s" % (target_name, toolchain), haltOnFailure = True, warnOnWarnings = True, description = "Building %s using %s" % (target_name, toolchain), descriptionDone = "Built %s using %s" % (target_name, toolchain)) mbed_build.addStep(build_py) mbed_build_release.addStep(build_py) # For build release we need all toolchains if target_name in OFFICIAL_MBED_TESTBED_SUPPORTED_HARDWARE: copy_example_test_spec_json = ShellCommand(name = "Copy example_test_spec.json", command = "cp ../example_test_spec.json workspace_tools/data/example_test_spec.json", haltOnFailure = True, description = "Copy example_test_spec.json") autotest_py = ShellCommand(name = "Running autotest.py for %s" % (target_name), command = "python workspace_tools/autotest.py workspace_tools/data/example_test_spec.json", haltOnFailure = True, description = "Running autotest.py") mbed_build.addStep(copy_example_test_spec_json) mbed_build.addStep(autotest_py) # Add builder with steps for each toolchain c['builders'].append(BuilderConfig(name=builder_name, slavenames=["example-slave-%s" % (target_name)], factory=mbed_build)) else: # Add builder with steps for each toolchain c['builders'].append(BuilderConfig(name=builder_name, slavenames=["example-slave"], factory=mbed_build)) # copy_example_test_spec_json = ShellCommand(name = "Copy example_test_spec.json", # command = "cp ../example_test_spec.json workspace_tools/data/example_test_spec.json", # haltOnFailure = True, # description = "Copy example_test_spec.json") singletest_py = TestCommand(name = "Running Target Tests", command = "python workspace_tools/singletest.py -i workspace_tools/test_spec.json -M workspace_tools/muts_all.json", haltOnFailure = True, warnOnWarnings = True, description = "Running Target Tests", descriptionDone = "Target Testing Finished") mbed_build_release.addStep(singletest_py) # Release build collects all building toolchains c['builders'].append(BuilderConfig(name=release_builder_name, slavenames=["example-slave"], factory=mbed_build_release)) ####### STATUS TARGETS # 'status' is a list of Status Targets. The results of each build will be # pushed to these targets. 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 authz_cfg=authz.Authz( # change any of these to True to enable; see the manual for more # options auth=auth.BasicAuth([("pyflakes","pyflakes")]), gracefulShutdown = False, forceBuild = 'auth', # use this to test your slave once it is set up forceAllBuilds = True, pingBuilder = True, stopBuild = True, stopAllBuilds = True, cancelPendingBuild = True, ) c['status'].append(html.WebStatus(http_port=8010, authz=authz_cfg, order_console_by_time=True)) ####### 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'] = "Green Tea" c['titleURL'] = "" # 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'] = "http://localhost:8010/" ####### 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", # 'db_url' : "mysql://buildbot:123456@localhost/buildbot_mbed?max_idle=300", }