2 # ex: set syntax=python:
4 # This is a sample buildmaster config file. It must be installed as
5 # 'master.cfg' in your buildmaster's base directory.
7 # This is the dictionary that the buildmaster pays attention to. We also use
8 # a shorter alias to save typing.
9 c = BuildmasterConfig = {}
13 # The 'slaves' list defines the set of recognized buildslaves. Each element is
14 # a BuildSlave object, specifying a unique slave name and password. The same
15 # slave name and password must be configured on the slave.
16 from buildbot.buildslave import BuildSlave
17 c['slaves'] = [BuildSlave("example-slave", "pass"),
18 BuildSlave("example-slave-2", "pass"),
19 BuildSlave("example-slave-KL25Z", "pass"),
20 BuildSlave("example-slave-LPC1768", "pass"),
21 BuildSlave("example-slave-LPC11U24", "pass"),
24 # 'slavePortnum' defines the TCP port to listen on for connections from slaves.
25 # This must match the value configured into the buildslaves (with their
27 c['slavePortnum'] = 9989
29 ####### OFFICIAL_MBED_LIBRARY_BUILD
31 OFFICIAL_MBED_LIBRARY_BUILD = (
32 ('LPC1768', ('ARM', 'GCC_ARM', 'GCC_CR', 'GCC_CS', 'IAR')),
33 ('KL05Z', ('ARM', 'uARM', 'GCC_ARM')),
34 ('KL25Z', ('ARM', 'GCC_ARM')),
35 ('LPC11U24', ('ARM', 'uARM')),
36 ('KL46Z', ('ARM', 'GCC_ARM')),
37 ('LPC4088', ('ARM', 'GCC_ARM', 'GCC_CR')),
38 ('LPC1347', ('ARM',)),
39 ('LPC1549', ('uARM',)),
40 ('LPC2368', ('ARM',)),
41 ('LPC812', ('uARM',)),
42 ('LPC11U35_401', ('ARM', 'uARM')),
43 ('LPC1114', ('uARM',)),
44 ('NUCLEO_F103RB', ('ARM', 'uARM')),
45 ('NUCLEO_L152RE', ('ARM', 'uARM')),
46 ('NUCLEO_F401RE', ('ARM', 'uARM')),
47 ('NUCLEO_F030R8', ('ARM', 'uARM')),
48 ('UBLOX_C027', ('ARM', 'GCC_ARM', 'GCC_CR', 'GCC_CS', 'IAR')),
49 # ('NRF51822', ('ARM',)),
52 # Which hardware platforms are supported for target testing
53 OFFICIAL_MBED_TESTBED_SUPPORTED_HARDWARE = (
61 # the 'change_source' setting tells the buildmaster how it should find out
62 # about source code changes. Here we point to the buildbot clone of pyflakes.
64 from buildbot.changes.gitpoller import GitPoller
65 c['change_source'] = []
67 c['change_source'].append(GitPoller(
68 'git://github.com/buildbot/pyflakes.git',
69 workdir='gitpoller-workdir', branch='master',
74 # Configure the Schedulers, which decide how to react to incoming changes. In this
75 # case, just kick off a 'runtests' build
77 from buildbot.schedulers.basic import SingleBranchScheduler
78 from buildbot.schedulers.forcesched import ForceScheduler
79 from buildbot.changes import filter
82 # Create builders to generate one target using all assigned toolchains
83 release_builder_name = "BuildRelease"
84 builder_names = [release_builder_name]
85 for target_name, toolchains in OFFICIAL_MBED_LIBRARY_BUILD:
86 builder_name = "All_TC_%s" % target_name
87 builder_names.append(builder_name)
88 c['schedulers'].append(ForceScheduler(name="force", builderNames=builder_names))
92 # The 'builders' list defines the Builders, which tell Buildbot how to perform a build:
93 # what steps, and which slaves can execute them. Note that any particular build will
94 # only take place on one slave.
96 from buildbot.process.factory import BuildFactory
97 from buildbot.steps.source.git import Git
98 from buildbot.steps.shell import ShellCommand
99 from buildbot.process.buildstep import LogLineObserver
100 import buildbot.status.results
104 class TestCommand(ShellCommand):
105 failedTestsCount = 0 # FAIL
106 passedTestsCount = 0 # OK
107 errorsTestsCount = 0 # ERROR
108 undefsTestsCount = 0 # UNDEF
111 def __init__(self, stage=None,module=None, moduleset=None, **kwargs):
112 ShellCommand.__init__(self, **kwargs)
113 self.failedTestsCount = 0
114 self.passedTestsCount = 0
115 self.errorsTestsCount = 0
116 self.tracebackPyCount = 0
117 self.testsResults = []
118 testFailuresObserver = UnitTestsObserver ()
119 self.addLogObserver('stdio', testFailuresObserver)
121 def createSummary(self, log):
122 if self.failedTestsCount >= 0 or self.passedTestsCount >= 0 or self.errorsTestsCount >= 0 or self.undefsTestsCount >= 0:
123 self.addHTMLLog ('tests summary', self.createTestsSummary())
125 def getText(self, cmd, results):
126 text = ShellCommand.getText(self, cmd, results)
127 text.append("OK: " + str(self.passedTestsCount))
128 text.append("FAIL: " + str(self.failedTestsCount))
129 text.append("ERROR: " + str(self.errorsTestsCount))
130 text.append("UNDEF: " + str(self.undefsTestsCount))
131 text.append("Traceback: " + str(self.tracebackPyCount))
134 def evaluateCommand(self, cmd):
135 if self.failedTestsCount > 0:
136 return buildbot.status.results.WARNINGS
137 elif self.errorsTestsCount > 0 or self.undefsTestsCount > 0 or self.tracebackPyCount > 0:
138 return buildbot.status.results.FAILURE
139 return buildbot.status.results.SUCCESS
141 def find_unique_tc_result_value(self, index):
142 """ Get unique values from each row in data parameter """
144 for tc_result_list in self.testsResults:
145 if tc_result_list[index] not in result:
146 result.append(tc_result_list[index])
149 def html_view_test_result(self, targets, tests, toolchain):
150 """ Generates simple result table """
151 COLOR_OK = "LimeGreen"
152 COLOR_FAIL = "LightCoral"
153 COLOR_UNDEF = "LightSlateGray"
154 COLOR_NEUTRAL = "Silver"
156 STATUS_COLORS = { "OK" : COLOR_OK,
158 "UNDEF" : COLOR_UNDEF}
161 result += "<tr valign='center'><td align='center'><b>" + toolchain + "</b></td>"
163 result += "<td align='center'>" + test + "<br></td>"
166 for target in targets:
167 result += "<tr><td width='110px'><br>" + target + "<br></td>"
169 for tc_result_list in self.testsResults:
170 if tc_result_list[1] == target and tc_result_list[2] == toolchain and tc_result_list[3] == test:
171 status = tc_result_list[4]
172 bgcolor = STATUS_COLORS[status]
173 result += "<td align='center' bgcolor='" + bgcolor + "'>" + status + "</td>"
176 result += "<td bgcolor='" + COLOR_NEUTRAL + "'></td>"
181 def createTestsSummary (self):
182 targets = self.find_unique_tc_result_value(1)
183 toolchains = self.find_unique_tc_result_value(2)
184 tests = self.find_unique_tc_result_value(3)
186 for toolchain in toolchains:
187 html_result += self.html_view_test_result(targets, tests, toolchain)
188 html_result += "<br>"
192 class UnitTestsObserver(LogLineObserver):
193 reGroupTestResult = []
197 LogLineObserver.__init__(self)
198 if len(self.reGroupTestResult) == 0:
199 self.reGroupTestResult.append(re.compile("^(\w+Test)::(\w+)::(\w+)::(\w+)::.* \[(\w+)\] in (\d+\.\d+) of (\d+) sec[\r\n]*$"))
201 def outLineReceived(self, line):
203 for r in self.reGroupTestResult:
204 result = r.match(line)
206 self.step.testsResults.append(result.groups())
207 if result.group(5) == 'OK':
208 self.step.passedTestsCount += 1
209 elif result.group(5) == 'FAIL':
210 self.step.failedTestsCount += 1
211 elif result.group(5) == 'UNDEF':
212 self.step.undefsTestsCount += 1
213 elif result.group(5) == 'ERROR':
214 self.step.errorsTestsCount += 1
218 class BuildCommand(ShellCommand):
219 warningsCount = 0 # [Warning]
220 errorsCount = 0 # [Error]
223 def __init__(self, stage=None,module=None, moduleset=None, **kwargs):
224 ShellCommand.__init__(self, **kwargs)
225 self.warningsCount = 0
227 self.testsResults = []
228 buildProcessObserver = BuildObserver ()
229 self.addLogObserver('stdio', buildProcessObserver)
231 def createSummary(self, log):
232 if self.warningsCount >= 0 or self.errorsCount >= 0:
233 self.addHTMLLog ('tests summary', self.createTestsSummary())
235 def getText(self, cmd, results):
236 text = ShellCommand.getText(self, cmd, results)
237 if self.warningsCount > 0 or self.errorsCount > 0:
238 text.append("warnings: " + str(self.warningsCount))
239 text.append("errors: " + str(self.errorsCount))
242 def evaluateCommand(self, cmd):
243 if self.warningsCount > 0:
244 return buildbot.status.results.WARNINGS
245 elif self.errorsCount > 0:
246 return buildbot.status.results.FAILURE
248 return buildbot.status.results.SUCCESS
250 def createTestsSummary (self):
251 # Create a string with your html report and return it
252 html = "<h4>Report</h4><table>"
253 #for result in self.testsResults:
257 class BuildObserver(LogLineObserver):
261 LogLineObserver.__init__(self)
262 if len(self.regroupresult) == 0:
263 self.regroupresult.append(re.compile("^\[([Ww]arning)\] (.*)"))
264 self.regroupresult.append(re.compile("^\[([Ee]rror)\] (.*)"))
266 def outLineReceived(self, line):
268 for r in self.regroupresult:
269 result = r.match(line)
271 self.step.testsResults.append(result.groups())
272 if result.group(1) == 'Warning':
273 self.step.warningsCount += 1
274 elif result.group(1) == 'Error':
275 self.step.errorsCount += 1
278 # [Future-Dev] Other check...
281 ####### BUILDERS - mbed project
282 git_clone = Git(repourl='https://github.com/mbedmicro/mbed.git', mode='incremental')
284 # create the build factory for mbed and add the steps to it
285 from buildbot.config import BuilderConfig
289 copy_private_settings = ShellCommand(name = "copy private_settings.py",
290 command = "cp ../private_settings.py workspace_tools/private_settings.py",
291 haltOnFailure = True,
292 description = "Copy private_settings.py")
294 mbed_build_release = BuildFactory()
295 mbed_build_release.addStep(git_clone)
296 mbed_build_release.addStep(copy_private_settings)
298 for target_name, toolchains in OFFICIAL_MBED_LIBRARY_BUILD:
299 builder_name = "All_TC_%s" % target_name
300 mbed_build = BuildFactory()
301 mbed_build.addStep(git_clone)
302 mbed_build.addStep(copy_private_settings)
303 # Adding all chains for target
304 for toolchain in toolchains:
305 build_py = BuildCommand(name = "Build %s using %s" % (target_name, toolchain),
306 command = "python workspace_tools/build.py -m %s -t %s" % (target_name, toolchain),
307 haltOnFailure = True,
308 warnOnWarnings = True,
309 description = "Building %s using %s" % (target_name, toolchain),
310 descriptionDone = "Built %s using %s" % (target_name, toolchain))
312 mbed_build.addStep(build_py)
313 mbed_build_release.addStep(build_py) # For build release we need all toolchains
315 if target_name in OFFICIAL_MBED_TESTBED_SUPPORTED_HARDWARE:
316 copy_example_test_spec_json = ShellCommand(name = "Copy example_test_spec.json",
317 command = "cp ../example_test_spec.json workspace_tools/data/example_test_spec.json",
318 haltOnFailure = True,
319 description = "Copy example_test_spec.json")
321 autotest_py = ShellCommand(name = "Running autotest.py for %s" % (target_name),
322 command = "python workspace_tools/autotest.py workspace_tools/data/example_test_spec.json",
323 haltOnFailure = True,
324 description = "Running autotest.py")
326 mbed_build.addStep(copy_example_test_spec_json)
327 mbed_build.addStep(autotest_py)
329 # Add builder with steps for each toolchain
330 c['builders'].append(BuilderConfig(name=builder_name,
331 slavenames=["example-slave-%s" % (target_name)],
334 # Add builder with steps for each toolchain
335 c['builders'].append(BuilderConfig(name=builder_name,
336 slavenames=["example-slave"],
339 # copy_example_test_spec_json = ShellCommand(name = "Copy example_test_spec.json",
340 # command = "cp ../example_test_spec.json workspace_tools/data/example_test_spec.json",
341 # haltOnFailure = True,
342 # description = "Copy example_test_spec.json")
344 singletest_py = TestCommand(name = "Running Target Tests",
345 command = "python workspace_tools/singletest.py -i workspace_tools/test_spec.json -M workspace_tools/muts_all.json",
346 haltOnFailure = True,
347 warnOnWarnings = True,
348 description = "Running Target Tests",
349 descriptionDone = "Target Testing Finished")
351 mbed_build_release.addStep(singletest_py)
352 # Release build collects all building toolchains
353 c['builders'].append(BuilderConfig(name=release_builder_name,
354 slavenames=["example-slave"],
355 factory=mbed_build_release))
357 ####### STATUS TARGETS
359 # 'status' is a list of Status Targets. The results of each build will be
360 # pushed to these targets. buildbot/status/*.py has a variety to choose from,
361 # including web pages, email senders, and IRC bots.
365 from buildbot.status import html
366 from buildbot.status.web import authz, auth
368 authz_cfg=authz.Authz(
369 # change any of these to True to enable; see the manual for more
371 auth=auth.BasicAuth([("pyflakes","pyflakes")]),
372 gracefulShutdown = False,
373 forceBuild = 'auth', # use this to test your slave once it is set up
374 forceAllBuilds = True,
377 stopAllBuilds = True,
378 cancelPendingBuild = True,
380 c['status'].append(html.WebStatus(http_port=8010, authz=authz_cfg, order_console_by_time=True))
382 ####### PROJECT IDENTITY
384 # the 'title' string will appear at the top of this buildbot
385 # installation's html.WebStatus home page (linked to the
386 # 'titleURL') and is embedded in the title of the waterfall HTML page.
388 c['title'] = "Green Tea"
391 # the 'buildbotURL' string should point to the location where the buildbot's
392 # internal web server (usually the html.WebStatus page) is visible. This
393 # typically uses the port number set in the Waterfall 'status' entry, but
394 # with an externally-visible host name which the buildbot cannot figure out
397 c['buildbotURL'] = "http://localhost:8010/"
402 # This specifies what database buildbot uses to store its state. You can leave
403 # this at its default for all but the largest installations.
404 'db_url' : "sqlite:///state.sqlite",
405 # 'db_url' : "mysql://buildbot:123456@localhost/buildbot_mbed?max_idle=300",