2 # run tests on all Samba subprojects and push to a git tree on success
3 # Copyright Andrew Tridgell 2010
4 # released under GNU GPL v3 or later
6 from __future__
import print_function
7 from subprocess
import call
, check_call
, Popen
, PIPE
12 from optparse
import OptionParser
15 from email
.mime
.text
import MIMEText
16 from email
.mime
.base
import MIMEBase
17 from email
.mime
.application
import MIMEApplication
18 from email
.mime
.multipart
import MIMEMultipart
19 from distutils
.sysconfig
import get_python_lib
23 from waflib
.Build
import CACHE_SUFFIX
25 sys
.path
.insert(0, "./third_party/waf")
26 from waflib
.Build
import CACHE_SUFFIX
29 os
.environ
["PYTHONUNBUFFERED"] = "1"
31 # This speeds up testing remarkably.
32 os
.environ
['TDB_NO_FSYNC'] = '1'
40 "samba-fileserver": ".",
41 "samba-ad-member": ".",
47 "samba-none-env": ".",
54 "samba-ad-dc-ntvfs": ".",
55 "samba-ad-dc-backup": ".",
56 "samba-systemkrb5": ".",
57 "samba-nopython": ".",
58 "samba-nopython-py2": ".",
59 "samba-schemaupgrade": ".",
62 "talloc": "lib/talloc",
63 "replace": "lib/replace",
64 "tevent": "lib/tevent",
68 defaulttasks
= builddirs
.keys()
70 if os
.environ
.get("AUTOBUILD_SKIP_SAMBA_O3", "0") == "1":
71 defaulttasks
.remove("samba-o3")
73 ctdb_configure_params
= " --enable-developer --picky-developer ${PREFIX}"
74 samba_configure_params
= " --picky-developer ${PREFIX} --with-profiling-data"
76 samba_libs_envvars
= "PYTHONPATH=${PYTHON_PREFIX}:$PYTHONPATH"
77 samba_libs_envvars
+= " PKG_CONFIG_PATH=$PKG_CONFIG_PATH:${PREFIX_DIR}/lib/pkgconfig"
78 samba_libs_envvars
+= " ADDITIONAL_CFLAGS='-Wmissing-prototypes'"
79 samba_libs_configure_base
= samba_libs_envvars
+ " ./configure --abi-check --enable-debug --picky-developer -C ${PREFIX}"
80 samba_libs_configure_libs
= samba_libs_configure_base
+ " --bundled-libraries=cmocka,popt,NONE"
81 samba_libs_configure_bundled_libs
= " --bundled-libraries=!talloc,!pytalloc-util,!tdb,!pytdb,!ldb,!pyldb,!pyldb-util,!tevent,!pytevent,!popt"
82 samba_libs_configure_samba
= samba_libs_configure_base
+ samba_libs_configure_bundled_libs
85 "ctdb": [("random-sleep", "../script/random-sleep.sh 300 900", "text/plain"),
86 ("configure", "./configure " + ctdb_configure_params
, "text/plain"),
87 ("make", "make all", "text/plain"),
88 ("install", "make install", "text/plain"),
89 ("test", "make autotest", "text/plain"),
90 ("check-clean-tree", "../script/clean-source-tree.sh", "text/plain"),
91 ("clean", "make clean", "text/plain")],
93 # We have 'test' before 'install' because, 'test' should work without 'install (runs all the other envs)'
95 ("random-sleep", "script/random-sleep.sh 300 900", "text/plain"),
96 ("configure", "./configure.developer --with-selftest-prefix=./bin/ab" + samba_configure_params
, "text/plain"),
97 ("make", "make -j", "text/plain"),
98 ("test", "make test FAIL_IMMEDIATELY=1 "
99 "TESTS='--exclude-env=none "
100 "--exclude-env=nt4_dc "
101 "--exclude-env=nt4_dc_schannel "
102 "--exclude-env=nt4_member "
103 "--exclude-env=ad_dc "
104 "--exclude-env=ad_dc_backup "
105 "--exclude-env=ad_dc_ntvfs "
106 "--exclude-env=ad_dc_default "
107 "--exclude-env=ad_dc_slowtests "
108 "--exclude-env=ad_dc_no_nss "
109 "--exclude-env=ad_dc_no_ntlm "
110 "--exclude-env=fl2003dc "
111 "--exclude-env=fl2008dc "
112 "--exclude-env=fl2008r2dc "
113 "--exclude-env=ad_member "
114 "--exclude-env=ad_member_idmap_rid "
115 "--exclude-env=ad_member_idmap_ad "
116 "--exclude-env=ad_member_rfc2307 "
117 "--exclude-env=chgdcpass "
118 "--exclude-env=vampire_2000_dc "
119 "--exclude-env=fl2000dc "
120 "--exclude-env=fileserver "
121 "--exclude-env=maptoguest "
122 "--exclude-env=simpleserver "
123 "--exclude-env=backupfromdc "
124 "--exclude-env=restoredc "
125 "--exclude-env=renamedc "
126 "--exclude-env=offlinebackupdc "
127 "--exclude-env=labdc "
128 "--exclude-env=preforkrestartdc "
129 "--exclude-env=proclimitdc "
130 "--exclude-env=promoted_dc "
131 "--exclude-env=vampire_dc "
132 "--exclude-env=rodc "
133 "--exclude-env=ad_dc_default "
134 "--exclude-env=ad_dc_slowtests "
135 "--exclude-env=schema_pair_dc "
136 "--exclude-env=schema_dc "
139 ("install", "make install", "text/plain"),
140 ("check-clean-tree", "script/clean-source-tree.sh", "text/plain"),
141 ("clean", "make clean", "text/plain")],
143 "samba-nt4": [("random-sleep", "script/random-sleep.sh 300 900", "text/plain"),
144 ("configure", "./configure.developer --without-ads --with-selftest-prefix=./bin/ab" + samba_configure_params
, "text/plain"),
145 ("make", "make -j", "text/plain"),
146 ("test", "make test FAIL_IMMEDIATELY=1 "
148 "--include-env=nt4_dc "
149 "--include-env=nt4_dc_schannel "
150 "--include-env=nt4_member "
152 ("install", "make install", "text/plain"),
153 ("check-clean-tree", "script/clean-source-tree.sh", "text/plain"),
154 ("clean", "make clean", "text/plain")],
156 "samba-fileserver": [("random-sleep", "script/random-sleep.sh 300 900", "text/plain"),
157 ("configure", "./configure.developer --without-ad-dc --without-ldap --without-ads --without-json --with-selftest-prefix=./bin/ab" + samba_configure_params
, "text/plain"),
158 ("make", "make -j", "text/plain"),
159 ("test", "make test FAIL_IMMEDIATELY=1 "
161 "--include-env=fileserver "
162 "--include-env=maptoguest "
163 "--include-env=simpleserver "
165 ("check-clean-tree", "script/clean-source-tree.sh", "text/plain")],
167 "samba-ad-member": [("random-sleep", "script/random-sleep.sh 300 900", "text/plain"),
168 ("configure", "./configure.developer --with-selftest-prefix=./bin/ab" + samba_configure_params
, "text/plain"),
169 ("make", "make -j", "text/plain"),
170 ("test", "make test FAIL_IMMEDIATELY=1 "
172 "--include-env=ad_member "
173 "--include-env=ad_member_idmap_rid "
174 "--include-env=ad_member_idmap_ad "
175 "--include-env=ad_member_rfc2307 "
177 ("check-clean-tree", "script/clean-source-tree.sh", "text/plain")],
179 "samba-ad-dc-1": [("random-sleep", "script/random-sleep.sh 1 1", "text/plain"),
180 ("configure", "./configure.developer --with-selftest-prefix=./bin/ab" + samba_configure_params
, "text/plain"),
181 ("make", "make -j", "text/plain"),
182 ("test", "make test FAIL_IMMEDIATELY=1 "
183 "TESTS='--include-env=ad_dc "
184 "--include-env=ad_dc_no_nss "
185 "--include-env=ad_dc_no_ntlm "
187 ("check-clean-tree", "script/clean-source-tree.sh", "text/plain")],
189 "samba-ad-dc-2": [("random-sleep", "script/random-sleep.sh 1 1", "text/plain"),
190 ("configure", "./configure.developer --with-selftest-prefix=./bin/ab" + samba_configure_params
, "text/plain"),
191 ("make", "make -j", "text/plain"),
192 ("test", "make test FAIL_IMMEDIATELY=1 "
194 "--include-env=vampire_dc "
195 "--include-env=vampire_2000_dc "
196 "--include-env=rodc "
198 ("check-clean-tree", "script/clean-source-tree.sh", "text/plain")],
200 "samba-ad-dc-3": [("random-sleep", "script/random-sleep.sh 1 1", "text/plain"),
201 ("configure", "./configure.developer --with-selftest-prefix=./bin/ab" + samba_configure_params
, "text/plain"),
202 ("make", "make -j", "text/plain"),
203 ("test", "make test FAIL_IMMEDIATELY=1 "
205 "--include-env=promoted_dc "
206 "--include-env=chgdcpass "
207 "--include-env=preforkrestartdc "
208 "--include-env=proclimitdc "
210 ("check-clean-tree", "script/clean-source-tree.sh", "text/plain")],
212 "samba-ad-dc-4": [("random-sleep", "script/random-sleep.sh 1 1", "text/plain"),
213 ("configure", "./configure.developer --with-selftest-prefix=./bin/ab" + samba_configure_params
, "text/plain"),
214 ("make", "make -j", "text/plain"),
215 ("test", "make test FAIL_IMMEDIATELY=1 "
217 "--include-env=fl2000dc "
218 "--include-env=fl2003dc "
219 "--include-env=fl2008dc "
220 "--include-env=fl2008r2dc "
222 ("check-clean-tree", "script/clean-source-tree.sh", "text/plain")],
224 "samba-ad-dc-5": [("random-sleep", "script/random-sleep.sh 1 1", "text/plain"),
225 ("configure", "./configure.developer --with-selftest-prefix=./bin/ab" + samba_configure_params
, "text/plain"),
226 ("make", "make -j", "text/plain"),
227 ("test", "make test FAIL_IMMEDIATELY=1 "
229 "--include-env=ad_dc_default "
231 ("check-clean-tree", "script/clean-source-tree.sh", "text/plain")],
233 "samba-ad-dc-6": [("random-sleep", "script/random-sleep.sh 1 1", "text/plain"),
234 ("configure", "./configure.developer --with-selftest-prefix=./bin/ab" + samba_configure_params
, "text/plain"),
235 ("make", "make -j", "text/plain"),
236 ("test", "make test FAIL_IMMEDIATELY=1 "
238 "--include-env=ad_dc_slowtests "
240 ("check-clean-tree", "script/clean-source-tree.sh", "text/plain")],
243 "samba-schemaupgrade": [("random-sleep", "script/random-sleep.sh 1 1", "text/plain"),
244 ("configure", "./configure.developer --with-selftest-prefix=./bin/ab" + samba_configure_params
, "text/plain"),
245 ("make", "make -j", "text/plain"),
246 ("test", "make test FAIL_IMMEDIATELY=1 "
248 "--include-env=schema_dc "
249 "--include-env=schema_pair_dc "
251 ("check-clean-tree", "script/clean-source-tree.sh", "text/plain")],
253 # We split out the ad_dc_ntvfs tests (which are long) so other test do not wait
254 # This is currently the longest task, so we don't randomly delay it.
255 "samba-ad-dc-ntvfs": [
256 ("random-sleep", "script/random-sleep.sh 1 1", "text/plain"),
257 ("configure", "./configure.developer --with-selftest-prefix=./bin/ab" + samba_configure_params
, "text/plain"),
258 ("make", "make -j", "text/plain"),
259 ("test", "make test FAIL_IMMEDIATELY=1 "
261 "--include-env=ad_dc_ntvfs "
263 ("check-clean-tree", "script/clean-source-tree.sh", "text/plain")],
265 # run the backup/restore testenvs separately as they're fairly standalone
266 # (and CI seems to max out at ~8 different DCs running at once)
267 "samba-ad-dc-backup": [("random-sleep", "script/random-sleep.sh 300 900", "text/plain"),
268 ("configure", "./configure.developer --with-selftest-prefix=./bin/ab" + samba_configure_params
, "text/plain"),
269 ("make", "make -j", "text/plain"),
270 ("test", "make test FAIL_IMMEDIATELY=1 "
271 "TESTS='--include-env=backupfromdc "
272 "--include-env=restoredc "
273 "--include-env=renamedc "
274 "--include-env=offlinebackupdc "
275 "--include-env=labdc "
276 "--include-env=ad_dc_backup "
278 ("check-clean-tree", "script/clean-source-tree.sh", "text/plain")],
280 "samba-test-only": [("configure", "./configure.developer --with-selftest-prefix=./bin/ab --abi-check-disable" + samba_configure_params
, "text/plain"),
281 ("make", "make -j", "text/plain"),
282 ("test", 'make test FAIL_IMMEDIATELY=1 TESTS="${TESTS}"', "text/plain")],
284 # Test cross-compile infrastructure
285 "samba-xc": [("random-sleep", "script/random-sleep.sh 900 1500", "text/plain"),
286 ("configure-native", "./configure.developer --with-selftest-prefix=./bin/ab" + samba_configure_params
, "text/plain"),
287 ("configure-cross-execute", "./configure.developer --out ./bin-xe --cross-compile --cross-execute=script/identity_cc.sh" \
288 " --cross-answers=./bin-xe/cross-answers.txt --with-selftest-prefix=./bin-xe/ab" + samba_configure_params
, "text/plain"),
289 ("configure-cross-answers", "./configure.developer --out ./bin-xa --cross-compile" \
290 " --cross-answers=./bin-xe/cross-answers.txt --with-selftest-prefix=./bin-xa/ab" + samba_configure_params
, "text/plain"),
291 ("compare-results", "script/compare_cc_results.py "
292 "./bin/c4che/default{} "
293 "./bin-xe/c4che/default{} "
294 "./bin-xa/c4che/default{}".format(*([CACHE_SUFFIX
]*3)), "text/plain")],
296 # test build with -O3 -- catches extra warnings and bugs, tests the ad_dc environments
297 "samba-o3": [("random-sleep", "script/random-sleep.sh 300 900", "text/plain"),
298 ("configure", "ADDITIONAL_CFLAGS='-O3 -Wp,-D_FORTIFY_SOURCE=2' ./configure.developer --with-selftest-prefix=./bin/ab --abi-check-disable" + samba_configure_params
, "text/plain"),
299 ("make", "make -j", "text/plain"),
300 ("test", "make quicktest FAIL_IMMEDIATELY=1 "
301 "TESTS='--include-env=ad_dc'", "text/plain"),
302 ("install", "make install", "text/plain"),
303 ("check-clean-tree", "script/clean-source-tree.sh", "text/plain"),
304 ("clean", "make clean", "text/plain")],
306 "samba-ctdb": [("random-sleep", "script/random-sleep.sh 900 1500", "text/plain"),
308 # make sure we have tdb around:
309 ("tdb-configure", "cd lib/tdb && PYTHONPATH=${PYTHON_PREFIX}:$PYTHONPATH PKG_CONFIG_PATH=$PKG_CONFIG_PATH:${PREFIX_DIR}/lib/pkgconfig ./configure --bundled-libraries=NONE --abi-check --enable-debug -C ${PREFIX}", "text/plain"),
310 ("tdb-make", "cd lib/tdb && make", "text/plain"),
311 ("tdb-install", "cd lib/tdb && make install", "text/plain"),
314 # build samba with cluster support (also building ctdb):
315 ("samba-configure", "PYTHONPATH=${PYTHON_PREFIX}:$PYTHONPATH PKG_CONFIG_PATH=${PREFIX_DIR}/lib/pkgconfig:${PKG_CONFIG_PATH} ./configure.developer --picky-developer ${PREFIX} --with-selftest-prefix=./bin/ab --with-cluster-support --bundled-libraries=!tdb", "text/plain"),
316 ("samba-make", "make", "text/plain"),
317 ("samba-check", "./bin/smbd -b | grep CLUSTER_SUPPORT", "text/plain"),
318 ("samba-install", "make install", "text/plain"),
319 ("ctdb-check", "test -e ${PREFIX_DIR}/sbin/ctdbd", "text/plain"),
322 ("check-clean-tree", "script/clean-source-tree.sh", "text/plain"),
323 ("clean", "make clean", "text/plain"),
324 ("ctdb-clean", "cd ./ctdb && make clean", "text/plain")],
327 ("random-sleep", "script/random-sleep.sh 300 900", "text/plain"),
328 ("talloc-configure", "cd lib/talloc && " + samba_libs_configure_libs
, "text/plain"),
329 ("talloc-make", "cd lib/talloc && make", "text/plain"),
330 ("talloc-install", "cd lib/talloc && make install", "text/plain"),
332 ("tdb-configure", "cd lib/tdb && " + samba_libs_configure_libs
, "text/plain"),
333 ("tdb-make", "cd lib/tdb && make", "text/plain"),
334 ("tdb-install", "cd lib/tdb && make install", "text/plain"),
336 ("tevent-configure", "cd lib/tevent && " + samba_libs_configure_libs
, "text/plain"),
337 ("tevent-make", "cd lib/tevent && make", "text/plain"),
338 ("tevent-install", "cd lib/tevent && make install", "text/plain"),
340 ("ldb-configure", "cd lib/ldb && " + samba_libs_configure_libs
, "text/plain"),
341 ("ldb-make", "cd lib/ldb && make", "text/plain"),
342 ("ldb-install", "cd lib/ldb && make install", "text/plain"),
344 ("nondevel-configure", "./configure ${PREFIX}", "text/plain"),
345 ("nondevel-make", "make -j", "text/plain"),
346 ("nondevel-check", "./bin/smbd -b | grep WITH_NTVFS_FILESERVER && exit 1; exit 0", "text/plain"),
347 ("nondevel-install", "make install", "text/plain"),
348 ("nondevel-dist", "make dist", "text/plain"),
350 # retry with all modules shared
351 ("allshared-distclean", "make distclean", "text/plain"),
352 ("allshared-configure", samba_libs_configure_samba
+ " --with-shared-modules=ALL", "text/plain"),
353 ("allshared-make", "make -j", "text/plain")],
356 ("random-sleep", "script/random-sleep.sh 1 1", "text/plain"),
357 ("configure", "./configure.developer --with-selftest-prefix=./bin/ab" + samba_configure_params
, "text/plain"),
358 ("make", "make -j", "text/plain"),
359 ("test", "make test "
360 "FAIL_IMMEDIATELY=1 "
361 "TESTS='--include-env=none'",
365 ("random-sleep", "script/random-sleep.sh 1 1", "text/plain"),
366 # build with all modules static
367 ("allstatic-configure", "./configure.developer " + samba_configure_params
+ " --with-static-modules=ALL", "text/plain"),
368 ("allstatic-make", "make -j", "text/plain"),
369 ("allstatic-test", "make test "
370 "FAIL_IMMEDIATELY=1 "
371 "TESTS='samba3.smb2.create.*nt4_dc'",
374 # retry without any required modules
375 ("none-distclean", "make distclean", "text/plain"),
376 ("none-configure", "./configure.developer " + samba_configure_params
+ " --with-static-modules=!FORCED,!DEFAULT --with-shared-modules=!FORCED,!DEFAULT", "text/plain"),
377 ("none-make", "make -j", "text/plain"),
379 # retry with nonshared smbd and smbtorture
380 ("nonshared-distclean", "make distclean", "text/plain"),
381 ("nonshared-configure", "./configure.developer " + samba_configure_params
+ " --bundled-libraries=talloc,tdb,pytdb,ldb,pyldb,tevent,pytevent --with-static-modules=ALL --nonshared-binary=smbtorture,smbd/smbd", "text/plain"),
382 ("nonshared-make", "make -j", "text/plain")],
384 "samba-systemkrb5": [
385 ("random-sleep", "script/random-sleep.sh 900 1500", "text/plain"),
386 ("configure", "./configure.developer " + samba_configure_params
+ " --with-system-mitkrb5 --with-experimental-mit-ad-dc", "text/plain"),
387 ("make", "make -j", "text/plain"),
388 # we currently cannot run a full make test, a limited list of tests could be run
389 # via "make test TESTS=sometests"
390 ("test", "make test FAIL_IMMEDIATELY=1 "
391 "TESTS='--include-env=ktest'", "text/plain"),
392 ("install", "make install", "text/plain"),
393 ("check-clean-tree", "script/clean-source-tree.sh", "text/plain"),
394 ("clean", "make clean", "text/plain")
397 # Test Samba without python still builds. When this test fails
398 # due to more use of Python, the expectations is that the newly
399 # failing part of the code should be disabled when
400 # --disable-python is set (rather than major work being done to
401 # support this environment). The target here is for vendors
402 # shipping a minimal smbd.
404 ("random-sleep", "script/random-sleep.sh 300 900", "text/plain"),
405 ("configure", "./configure.developer --picky-developer ${PREFIX} --with-profiling-data --disable-python --without-ad-dc", "text/plain"),
406 ("make", "make -j", "text/plain"),
407 ("install", "make install", "text/plain"),
408 ("find-python", "script/find_python.sh ${PREFIX}", "text/plain"),
409 ("test", "make test-nopython", "text/plain"),
410 ("check-clean-tree", "script/clean-source-tree.sh", "text/plain"),
411 ("clean", "make clean", "text/plain"),
413 ("talloc-configure", "cd lib/talloc && " + samba_libs_configure_base
+ " --bundled-libraries=cmocka,NONE --disable-python", "text/plain"),
414 ("talloc-make", "cd lib/talloc && make", "text/plain"),
415 ("talloc-install", "cd lib/talloc && make install", "text/plain"),
417 ("tdb-configure", "cd lib/tdb && " + samba_libs_configure_base
+ " --bundled-libraries=cmocka,NONE --disable-python", "text/plain"),
418 ("tdb-make", "cd lib/tdb && make", "text/plain"),
419 ("tdb-install", "cd lib/tdb && make install", "text/plain"),
421 ("tevent-configure", "cd lib/tevent && " + samba_libs_configure_base
+ " --bundled-libraries=cmocka,NONE --disable-python", "text/plain"),
422 ("tevent-make", "cd lib/tevent && make", "text/plain"),
423 ("tevent-install", "cd lib/tevent && make install", "text/plain"),
425 ("ldb-configure", "cd lib/ldb && " + samba_libs_configure_base
+ " --bundled-libraries=cmocka,NONE --disable-python", "text/plain"),
426 ("ldb-make", "cd lib/ldb && make", "text/plain"),
427 ("ldb-install", "cd lib/ldb && make install", "text/plain"),
429 # retry against installed library packages
430 ("libs-configure", samba_libs_configure_base
+ samba_libs_configure_bundled_libs
+ " --disable-python --without-ad-dc", "text/plain"),
431 ("libs-make", "make -j", "text/plain"),
432 ("libs-install", "make install", "text/plain"),
433 ("libs-check-clean-tree", "script/clean-source-tree.sh", "text/plain"),
434 ("libs-clean", "make clean", "text/plain")
437 # check we can do the same thing using python2
438 "samba-nopython-py2": [
439 ("random-sleep", "script/random-sleep.sh 300 900", "text/plain"),
440 ("configure", "PYTHON=python2 ./configure.developer --picky-developer ${PREFIX} --with-profiling-data --disable-python --without-ad-dc", "text/plain"),
441 ("make", "PYTHON=python2 make -j", "text/plain"),
442 ("install", "PYTHON=python2 make install", "text/plain"),
443 ("find-python", "script/find_python.sh ${PREFIX}", "text/plain"),
444 ("test", "make test-nopython", "text/plain"),
445 ("check-clean-tree", "script/clean-source-tree.sh", "text/plain"),
446 ("clean", "PYTHON=python2 make clean", "text/plain"),
448 ("talloc-configure", "cd lib/talloc && PYTHON=python2 " + samba_libs_configure_base
+ " --bundled-libraries=cmocka,NONE --disable-python", "text/plain"),
449 ("talloc-make", "cd lib/talloc && PYTHON=python2 make", "text/plain"),
450 ("talloc-install", "cd lib/talloc && PYTHON=python2 make install", "text/plain"),
452 ("tdb-configure", "cd lib/tdb && PYTHON=python2 " + samba_libs_configure_base
+ " --bundled-libraries=cmocka,NONE --disable-python", "text/plain"),
453 ("tdb-make", "cd lib/tdb && PYTHON=python2 make", "text/plain"),
454 ("tdb-install", "cd lib/tdb && PYTHON=python2 make install", "text/plain"),
456 ("tevent-configure", "cd lib/tevent && PYTHON=python2 " + samba_libs_configure_base
+ " --bundled-libraries=cmocka,NONE --disable-python", "text/plain"),
457 ("tevent-make", "cd lib/tevent && PYTHON=python2 make", "text/plain"),
458 ("tevent-install", "cd lib/tevent && PYTHON=python2 make install", "text/plain"),
460 ("ldb-configure", "cd lib/ldb && PYTHON=python2 " + samba_libs_configure_base
+ " --bundled-libraries=cmocka,NONE --disable-python", "text/plain"),
461 ("ldb-make", "cd lib/ldb && PYTHON=python2 make", "text/plain"),
462 ("ldb-install", "cd lib/ldb && PYTHON=python2 make install", "text/plain"),
464 # retry against installed library packages
465 ("libs-configure", "PYTHON=python2 " + samba_libs_configure_base
+ samba_libs_configure_bundled_libs
+ " --disable-python --without-ad-dc", "text/plain"),
466 ("libs-make", "PYTHON=python2 make -j", "text/plain"),
467 ("libs-install", "PYTHON=python2 make install", "text/plain"),
468 ("libs-check-clean-tree", "script/clean-source-tree.sh", "text/plain"),
469 ("libs-clean", "PYTHON=python2 make clean", "text/plain")
473 ("random-sleep", "../../script/random-sleep.sh 60 600", "text/plain"),
474 ("configure", "./configure --enable-developer -C ${PREFIX}", "text/plain"),
475 ("make", "make", "text/plain"),
476 ("install", "make install", "text/plain"),
477 ("test", "make test", "text/plain"),
478 ("configure-no-lmdb", "./configure --enable-developer --without-ldb-lmdb -C ${PREFIX}", "text/plain"),
479 ("make-no-lmdb", "make", "text/plain"),
480 ("install-no-lmdb", "make install", "text/plain"),
481 ("check-clean-tree", "../../script/clean-source-tree.sh", "text/plain"),
482 ("distcheck", "make distcheck", "text/plain"),
483 ("clean", "make clean", "text/plain")],
486 ("random-sleep", "../../script/random-sleep.sh 60 600", "text/plain"),
487 ("configure", "./configure --enable-developer -C ${PREFIX}", "text/plain"),
488 ("make", "make", "text/plain"),
489 ("install", "make install", "text/plain"),
490 ("test", "make test", "text/plain"),
491 ("check-clean-tree", "../../script/clean-source-tree.sh", "text/plain"),
492 ("distcheck", "make distcheck", "text/plain"),
493 ("clean", "make clean", "text/plain")],
496 ("random-sleep", "../../script/random-sleep.sh 60 600", "text/plain"),
497 ("configure", "./configure --enable-developer -C ${PREFIX}", "text/plain"),
498 ("make", "make", "text/plain"),
499 ("install", "make install", "text/plain"),
500 ("test", "make test", "text/plain"),
501 ("check-clean-tree", "../../script/clean-source-tree.sh", "text/plain"),
502 ("distcheck", "make distcheck", "text/plain"),
503 ("clean", "make clean", "text/plain")],
506 ("random-sleep", "../../script/random-sleep.sh 60 600", "text/plain"),
507 ("configure", "./configure --enable-developer -C ${PREFIX}", "text/plain"),
508 ("make", "make", "text/plain"),
509 ("install", "make install", "text/plain"),
510 ("test", "make test", "text/plain"),
511 ("check-clean-tree", "../../script/clean-source-tree.sh", "text/plain"),
512 ("distcheck", "make distcheck", "text/plain"),
513 ("clean", "make clean", "text/plain")],
516 ("random-sleep", "../../script/random-sleep.sh 60 600", "text/plain"),
517 ("configure", "./configure --enable-developer -C ${PREFIX}", "text/plain"),
518 ("make", "make", "text/plain"),
519 ("install", "make install", "text/plain"),
520 ("test", "make test", "text/plain"),
521 ("check-clean-tree", "../../script/clean-source-tree.sh", "text/plain"),
522 ("distcheck", "make distcheck", "text/plain"),
523 ("clean", "make clean", "text/plain")],
526 ("random-sleep", "../script/random-sleep.sh 60 600", "text/plain"),
527 ("configure", "perl Makefile.PL PREFIX=${PREFIX_DIR}", "text/plain"),
528 ("touch", "touch *.yp", "text/plain"),
529 ("make", "make", "text/plain"),
530 ("test", "make test", "text/plain"),
531 ("install", "make install", "text/plain"),
532 ("checkout-yapp-generated", "git checkout lib/Parse/Pidl/IDL.pm lib/Parse/Pidl/Expr.pm", "text/plain"),
533 ("check-clean-tree", "../script/clean-source-tree.sh", "text/plain"),
534 ("clean", "make clean", "text/plain")],
537 # these are useful for debugging autobuild
538 'pass': [("pass", 'echo passing && /bin/true', "text/plain")],
539 'fail': [("fail", 'echo failing && /bin/false', "text/plain")]
551 def run_cmd(cmd
, dir=".", show
=None, output
=False, checkfail
=True):
553 show
= options
.verbose
555 do_print("Running: '%s' in '%s'" % (cmd
, dir))
557 return Popen([cmd
], shell
=True, stdout
=PIPE
, cwd
=dir, close_fds
=True).communicate()[0]
559 return check_call(cmd
, shell
=True, cwd
=dir)
561 return call(cmd
, shell
=True, cwd
=dir)
564 class builder(object):
565 '''handle build of one directory'''
567 def __init__(self
, name
, sequence
, cp
=True):
569 if name
in builddirs
:
570 self
.dir = builddirs
[name
]
574 self
.tag
= self
.name
.replace('/', '_')
575 self
.sequence
= sequence
577 self
.stdout_path
= "%s/%s.stdout" % (gitroot
, self
.tag
)
578 self
.stderr_path
= "%s/%s.stderr" % (gitroot
, self
.tag
)
580 do_print("stdout for %s in %s" % (self
.name
, self
.stdout_path
))
581 do_print("stderr for %s in %s" % (self
.name
, self
.stderr_path
))
582 run_cmd("rm -f %s %s" % (self
.stdout_path
, self
.stderr_path
))
583 self
.stdout
= open(self
.stdout_path
, 'w')
584 self
.stderr
= open(self
.stderr_path
, 'w')
585 self
.stdin
= open("/dev/null", 'r')
586 self
.sdir
= "%s/%s" % (testbase
, self
.tag
)
587 self
.prefix
= "%s/%s" % (test_prefix
, self
.tag
)
588 run_cmd("rm -rf %s" % self
.sdir
)
589 run_cmd("rm -rf %s" % self
.prefix
)
591 run_cmd("cp --recursive --link --archive %s %s" % (test_master
, self
.sdir
), dir=test_master
, show
=True)
593 run_cmd("git clone --recursive --shared %s %s" % (test_master
, self
.sdir
), dir=test_master
, show
=True)
596 def start_next(self
):
597 if self
.next
== len(self
.sequence
):
598 if not options
.nocleanup
:
599 run_cmd("rm -rf %s" % self
.sdir
)
600 run_cmd("rm -rf %s" % self
.prefix
)
601 do_print('%s: Completed OK' % self
.name
)
604 (self
.stage
, self
.cmd
, self
.output_mime_type
) = self
.sequence
[self
.next
]
605 self
.cmd
= self
.cmd
.replace("${PYTHON_PREFIX}", get_python_lib(plat_specific
=1, standard_lib
=0, prefix
=self
.prefix
))
606 self
.cmd
= self
.cmd
.replace("${PREFIX}", "--prefix=%s" % self
.prefix
)
607 self
.cmd
= self
.cmd
.replace("${PREFIX_DIR}", "%s" % self
.prefix
)
608 self
.cmd
= self
.cmd
.replace("${TESTS}", options
.restrict_tests
)
609 # if self.output_mime_type == "text/x-subunit":
610 # self.cmd += " | %s --immediate" % (os.path.join(os.path.dirname(__file__), "selftest/format-subunit"))
612 os
.chdir("%s/%s" % (self
.sdir
, self
.dir))
613 do_print('%s: [%s] Running %s in %r' % (self
.name
, self
.stage
, self
.cmd
, os
.getcwd()))
614 self
.proc
= Popen(self
.cmd
, shell
=True,
616 stdout
=self
.stdout
, stderr
=self
.stderr
, stdin
=self
.stdin
)
621 class buildlist(object):
622 '''handle build of multiple directories'''
624 def __init__(self
, tasknames
, rebase_url
, rebase_branch
="master"):
627 self
.tail_proc
= None
630 if options
.restrict_tests
:
631 tasknames
= ["samba-test-only"]
633 tasknames
= defaulttasks
635 # If we are only running one test,
636 # do not sleep randomly to wait for it to start
637 os
.environ
['AUTOBUILD_RANDOM_SLEEP_OVERRIDE'] = '1'
640 b
= builder(n
, tasks
[n
], cp
=n
is not "pidl")
643 rebase_remote
= "rebaseon"
644 retry_task
= [("retry",
646 git remote add -t %s %s %s
650 git describe %s/%s > old_remote_branch.desc
652 git describe %s/%s > remote_branch.desc
653 diff old_remote_branch.desc remote_branch.desc
656 rebase_branch
, rebase_remote
, rebase_url
,
658 rebase_remote
, rebase_branch
,
660 rebase_remote
, rebase_branch
664 self
.retry
= builder('retry', retry_task
, cp
=False)
665 self
.need_retry
= False
668 if self
.tail_proc
is not None:
669 self
.tail_proc
.terminate()
670 self
.tail_proc
.wait()
671 self
.tail_proc
= None
672 if self
.retry
is not None:
673 self
.retry
.proc
.terminate()
674 self
.retry
.proc
.wait()
677 if b
.proc
is not None:
678 run_cmd("killbysubdir %s > /dev/null 2>&1" % b
.sdir
, checkfail
=False)
690 b
.status
= b
.proc
.poll()
696 ret
= self
.retry
.proc
.poll()
698 self
.need_retry
= True
708 if options
.retry
and self
.need_retry
:
710 do_print("retry needed")
711 return (0, None, None, None, "retry")
714 if os
.WIFSIGNALED(b
.status
) or os
.WEXITSTATUS(b
.status
) != 0:
716 return (b
.status
, b
.name
, b
.stage
, b
.tag
, "%s: [%s] failed '%s' with status %d" % (b
.name
, b
.stage
, b
.cmd
, b
.status
))
719 return (0, None, None, None, "All OK")
721 def write_system_info(self
):
722 filename
= 'system-info.txt'
723 f
= open(filename
, 'w')
724 for cmd
in ['uname -a',
731 'df -m %s' % testbase
]:
732 out
= run_cmd(cmd
, output
=True, checkfail
=False)
733 print('### %s' % cmd
, file=f
)
734 print(out
.decode('utf8', 'backslashreplace'), file=f
)
739 def tarlogs(self
, fname
):
740 tar
= tarfile
.open(fname
, "w:gz")
742 tar
.add(b
.stdout_path
, arcname
="%s.stdout" % b
.tag
)
743 tar
.add(b
.stderr_path
, arcname
="%s.stderr" % b
.tag
)
744 if os
.path
.exists("autobuild.log"):
745 tar
.add("autobuild.log")
746 sys_info
= self
.write_system_info()
750 def remove_logs(self
):
752 os
.unlink(b
.stdout_path
)
753 os
.unlink(b
.stderr_path
)
755 def start_tail(self
):
758 cmd
.append(b
.stdout_path
)
759 cmd
.append(b
.stderr_path
)
760 self
.tail_proc
= Popen(cmd
, close_fds
=True)
764 if options
.nocleanup
:
766 run_cmd("stat %s || true" % test_tmpdir
, show
=True)
767 run_cmd("stat %s" % testbase
, show
=True)
768 do_print("Cleaning up %r" % cleanup_list
)
769 for d
in cleanup_list
:
770 run_cmd("rm -rf %s" % d
)
774 '''get to the top of the git repo'''
777 if os
.path
.isdir(os
.path
.join(p
, ".git")):
779 p
= os
.path
.abspath(os
.path
.join(p
, '..'))
783 def daemonize(logfile
):
785 if pid
== 0: # Parent
788 if pid
!= 0: # Actual daemon
793 import resource
# Resource usage information.
794 maxfd
= resource
.getrlimit(resource
.RLIMIT_NOFILE
)[1]
795 if maxfd
== resource
.RLIM_INFINITY
:
796 maxfd
= 1024 # Rough guess at maximum number of open file descriptors.
797 for fd
in range(0, maxfd
):
802 os
.open(logfile
, os
.O_RDWR | os
.O_CREAT
)
807 def write_pidfile(fname
):
808 '''write a pid file, cleanup on exit'''
809 f
= open(fname
, mode
='w')
810 f
.write("%u\n" % os
.getpid())
814 def rebase_tree(rebase_url
, rebase_branch
="master"):
815 rebase_remote
= "rebaseon"
816 do_print("Rebasing on %s" % rebase_url
)
817 run_cmd("git describe HEAD", show
=True, dir=test_master
)
818 run_cmd("git remote add -t %s %s %s" %
819 (rebase_branch
, rebase_remote
, rebase_url
),
820 show
=True, dir=test_master
)
821 run_cmd("git fetch %s" % rebase_remote
, show
=True, dir=test_master
)
822 if options
.fix_whitespace
:
823 run_cmd("git rebase --force-rebase --whitespace=fix %s/%s" %
824 (rebase_remote
, rebase_branch
),
825 show
=True, dir=test_master
)
827 run_cmd("git rebase --force-rebase %s/%s" %
828 (rebase_remote
, rebase_branch
),
829 show
=True, dir=test_master
)
830 diff
= run_cmd("git --no-pager diff HEAD %s/%s" %
831 (rebase_remote
, rebase_branch
),
832 dir=test_master
, output
=True)
834 do_print("No differences between HEAD and %s/%s - exiting" %
835 (rebase_remote
, rebase_branch
))
837 run_cmd("git describe %s/%s" %
838 (rebase_remote
, rebase_branch
),
839 show
=True, dir=test_master
)
840 run_cmd("git describe HEAD", show
=True, dir=test_master
)
841 run_cmd("git --no-pager diff --stat HEAD %s/%s" %
842 (rebase_remote
, rebase_branch
),
843 show
=True, dir=test_master
)
846 def push_to(push_url
, push_branch
="master"):
847 push_remote
= "pushto"
848 do_print("Pushing to %s" % push_url
)
850 run_cmd("git config --replace-all core.editor script/commit_mark.sh", dir=test_master
)
851 run_cmd("git commit --amend -c HEAD", dir=test_master
)
852 # the notes method doesn't work yet, as metze hasn't allowed refs/notes/* in master
853 # run_cmd("EDITOR=script/commit_mark.sh git notes edit HEAD", dir=test_master)
854 run_cmd("git remote add -t %s %s %s" %
855 (push_branch
, push_remote
, push_url
),
856 show
=True, dir=test_master
)
857 run_cmd("git push %s +HEAD:%s" %
858 (push_remote
, push_branch
),
859 show
=True, dir=test_master
)
862 def_testbase
= os
.getenv("AUTOBUILD_TESTBASE", "/memdisk/%s" % os
.getenv('USER'))
864 gitroot
= find_git_root()
866 raise Exception("Failed to find git root")
868 parser
= OptionParser()
869 parser
.add_option("", "--tail", help="show output while running", default
=False, action
="store_true")
870 parser
.add_option("", "--keeplogs", help="keep logs", default
=False, action
="store_true")
871 parser
.add_option("", "--nocleanup", help="don't remove test tree", default
=False, action
="store_true")
872 parser
.add_option("", "--testbase", help="base directory to run tests in (default %s)" % def_testbase
,
873 default
=def_testbase
)
874 parser
.add_option("", "--passcmd", help="command to run on success", default
=None)
875 parser
.add_option("", "--verbose", help="show all commands as they are run",
876 default
=False, action
="store_true")
877 parser
.add_option("", "--rebase", help="rebase on the given tree before testing",
878 default
=None, type='str')
879 parser
.add_option("", "--pushto", help="push to a git url on success",
880 default
=None, type='str')
881 parser
.add_option("", "--mark", help="add a Tested-By signoff before pushing",
882 default
=False, action
="store_true")
883 parser
.add_option("", "--fix-whitespace", help="fix whitespace on rebase",
884 default
=False, action
="store_true")
885 parser
.add_option("", "--retry", help="automatically retry if master changes",
886 default
=False, action
="store_true")
887 parser
.add_option("", "--email", help="send email to the given address on failure",
888 type='str', default
=None)
889 parser
.add_option("", "--email-from", help="send email from the given address",
890 type='str', default
="autobuild@samba.org")
891 parser
.add_option("", "--email-server", help="send email via the given server",
892 type='str', default
='localhost')
893 parser
.add_option("", "--always-email", help="always send email, even on success",
895 parser
.add_option("", "--daemon", help="daemonize after initial setup",
897 parser
.add_option("", "--branch", help="the branch to work on (default=master)",
898 default
="master", type='str')
899 parser
.add_option("", "--log-base", help="location where the logs can be found (default=cwd)",
900 default
=gitroot
, type='str')
901 parser
.add_option("", "--attach-logs", help="Attach logs to mails sent on success/failure?",
902 default
=False, action
="store_true")
903 parser
.add_option("", "--restrict-tests", help="run as make test with this TESTS= regex",
907 def send_email(subject
, text
, log_tar
):
908 if options
.email
is None:
909 do_print("not sending email because the recipient is not set")
910 do_print("the text content would have been:\n\nSubject: %s\n\n%s" %
913 outer
= MIMEMultipart()
914 outer
['Subject'] = subject
915 outer
['To'] = options
.email
916 outer
['From'] = options
.email_from
917 outer
['Date'] = email
.utils
.formatdate(localtime
=True)
918 outer
.preamble
= 'Autobuild mails are now in MIME because we optionally attach the logs.\n'
919 outer
.attach(MIMEText(text
, 'plain'))
920 if options
.attach_logs
:
921 fp
= open(log_tar
, 'rb')
922 msg
= MIMEApplication(fp
.read(), 'gzip', email
.encoders
.encode_base64
)
924 # Set the filename parameter
925 msg
.add_header('Content-Disposition', 'attachment', filename
=os
.path
.basename(log_tar
))
927 content
= outer
.as_string()
928 s
= smtplib
.SMTP(options
.email_server
)
929 email_user
= os
.getenv('SMTP_USERNAME')
930 email_password
= os
.getenv('SMTP_PASSWORD')
931 if email_user
is not None:
933 s
.login(email_user
, email_password
)
935 s
.sendmail(options
.email_from
, [options
.email
], content
)
940 def email_failure(status
, failed_task
, failed_stage
, failed_tag
, errstr
,
941 elapsed_time
, log_base
=None, add_log_tail
=True):
942 '''send an email to options.email about the failure'''
943 elapsed_minutes
= elapsed_time
/ 60.0
949 Your autobuild on %s failed after %.1f minutes
950 when trying to test %s with the following error:
954 the autobuild has been abandoned. Please fix the error and resubmit.
956 A summary of the autobuild process is here:
959 ''' % (platform
.node(), elapsed_minutes
, failed_task
, errstr
, log_base
)
961 if options
.restrict_tests
:
963 The build was restricted to tests matching %s\n""" % options
.restrict_tests
965 if failed_task
!= 'rebase':
967 You can see logs of the failed task here:
972 or you can get full logs of all tasks in this job here:
976 The top commit for the tree that was built was:
980 ''' % (log_base
, failed_tag
, log_base
, failed_tag
, log_base
, top_commit_msg
)
983 f
= open("%s/%s.stdout" % (gitroot
, failed_tag
), 'r')
984 lines
= f
.readlines()
985 log_tail
= "".join(lines
[-50:])
986 num_lines
= len(lines
)
988 # Also include stderr (compile failures) if < 50 lines of stdout
989 f
= open("%s/%s.stderr" % (gitroot
, failed_tag
), 'r')
990 log_tail
+= "".join(f
.readlines()[-(50 - num_lines
):])
993 The last 50 lines of log messages:
999 logs
= os
.path
.join(gitroot
, 'logs.tar.gz')
1000 send_email('autobuild[%s] failure on %s for task %s during %s'
1001 % (options
.branch
, platform
.node(), failed_task
, failed_stage
),
1005 def email_success(elapsed_time
, log_base
=None):
1006 '''send an email to options.email about a successful build'''
1007 if log_base
is None:
1012 Your autobuild on %s has succeeded after %.1f minutes.
1014 ''' % (platform
.node(), elapsed_time
/ 60.)
1016 if options
.restrict_tests
:
1018 The build was restricted to tests matching %s\n""" % options
.restrict_tests
1020 if options
.keeplogs
:
1023 you can get full logs of all tasks in this job here:
1030 The top commit for the tree that was built was:
1033 ''' % top_commit_msg
1035 logs
= os
.path
.join(gitroot
, 'logs.tar.gz')
1036 send_email('autobuild[%s] success on %s' % (options
.branch
, platform
.node()),
1040 (options
, args
) = parser
.parse_args()
1043 if options
.rebase
is None:
1044 raise Exception('You can only use --retry if you also rebase')
1046 testbase
= "%s/b%u" % (options
.testbase
, os
.getpid())
1047 test_master
= "%s/master" % testbase
1048 test_prefix
= "%s/prefix" % testbase
1049 test_tmpdir
= "%s/tmp" % testbase
1050 os
.environ
['TMPDIR'] = test_tmpdir
1052 # get the top commit message, for emails
1053 top_commit_msg
= run_cmd("git log -1", dir=gitroot
, output
=True)
1054 top_commit_msg
= top_commit_msg
.decode('utf-8', 'backslashreplace')
1057 os
.makedirs(testbase
)
1058 except Exception as reason
:
1059 raise Exception("Unable to create %s : %s" % (testbase
, reason
))
1060 cleanup_list
.append(testbase
)
1063 logfile
= os
.path
.join(testbase
, "log")
1064 do_print("Forking into the background, writing progress to %s" % logfile
)
1067 write_pidfile(gitroot
+ "/autobuild.pid")
1069 start_time
= time
.time()
1073 run_cmd("rm -rf %s" % test_tmpdir
, show
=True)
1074 os
.makedirs(test_tmpdir
)
1075 # The waf uninstall code removes empty directories all the way
1076 # up the tree. Creating a file in test_tmpdir stops it from
1078 run_cmd("touch %s" % os
.path
.join(test_tmpdir
,
1079 ".directory-is-not-empty"), show
=True)
1080 run_cmd("stat %s" % test_tmpdir
, show
=True)
1081 run_cmd("stat %s" % testbase
, show
=True)
1082 run_cmd("git clone --recursive --shared %s %s" % (gitroot
, test_master
), show
=True, dir=gitroot
)
1089 if options
.rebase
is not None:
1090 rebase_tree(options
.rebase
, rebase_branch
=options
.branch
)
1092 cleanup_list
.append(gitroot
+ "/autobuild.pid")
1094 elapsed_time
= time
.time() - start_time
1095 email_failure(-1, 'rebase', 'rebase', 'rebase',
1096 'rebase on %s failed' % options
.branch
,
1097 elapsed_time
, log_base
=options
.log_base
)
1099 blist
= buildlist(args
, options
.rebase
, rebase_branch
=options
.branch
)
1102 (status
, failed_task
, failed_stage
, failed_tag
, errstr
) = blist
.run()
1103 if status
!= 0 or errstr
!= "retry":
1110 cleanup_list
.append(gitroot
+ "/autobuild.pid")
1116 do_print("waiting for tail to flush")
1119 elapsed_time
= time
.time() - start_time
1121 if options
.passcmd
is not None:
1122 do_print("Running passcmd: %s" % options
.passcmd
)
1123 run_cmd(options
.passcmd
, dir=test_master
)
1124 if options
.pushto
is not None:
1125 push_to(options
.pushto
, push_branch
=options
.branch
)
1126 if options
.keeplogs
or options
.attach_logs
:
1127 blist
.tarlogs("logs.tar.gz")
1128 do_print("Logs in logs.tar.gz")
1129 if options
.always_email
:
1130 email_success(elapsed_time
, log_base
=options
.log_base
)
1136 # something failed, gather a tar of the logs
1137 blist
.tarlogs("logs.tar.gz")
1139 if options
.email
is not None:
1140 email_failure(status
, failed_task
, failed_stage
, failed_tag
, errstr
,
1141 elapsed_time
, log_base
=options
.log_base
)
1143 elapsed_minutes
= elapsed_time
/ 60.0
1146 ####################################################################
1150 Your autobuild[%s] on %s failed after %.1f minutes
1151 when trying to test %s with the following error:
1155 the autobuild has been abandoned. Please fix the error and resubmit.
1157 ####################################################################
1159 ''' % (options
.branch
, platform
.node(), elapsed_minutes
, failed_task
, errstr
))
1163 do_print("Logs in logs.tar.gz")