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 subprocess
import call
, check_call
,Popen
, PIPE
7 import os
, tarfile
, sys
, time
8 from optparse
import OptionParser
11 from email
.mime
.text
import MIMEText
12 from email
.mime
.base
import MIMEBase
13 from email
.mime
.application
import MIMEApplication
14 from email
.mime
.multipart
import MIMEMultipart
15 from distutils
.sysconfig
import get_python_lib
18 # This speeds up testing remarkably.
19 os
.environ
['TDB_NO_FSYNC'] = '1'
31 "talloc" : "lib/talloc",
32 "replace" : "lib/replace",
33 "tevent" : "lib/tevent",
40 defaulttasks
= [ "ctdb", "samba", "samba-xc", "samba-ctdb", "samba-libs", "ldb", "tdb", "talloc", "replace", "tevent", "pidl" ]
42 samba_configure_params
= " --picky-developer ${PREFIX} --with-profiling-data"
45 "ctdb" : [ ("random-sleep", "../script/random-sleep.sh 60 600", "text/plain"),
46 ("configure", "./configure ${PREFIX}", "text/plain"),
47 ("make", "make all", "text/plain"),
48 ("install", "make install", "text/plain"),
49 ("test", "make autotest", "text/plain"),
50 ("check-clean-tree", "../script/clean-source-tree.sh", "text/plain"),
51 ("clean", "make clean", "text/plain") ],
53 # We have 'test' before 'install' because, 'test' should work without 'install'
54 "samba" : [ ("configure", "./configure.developer --with-selftest-prefix=./bin/ab" + samba_configure_params
, "text/plain"),
55 ("make", "make -j", "text/plain"),
56 ("test", "make test FAIL_IMMEDIATELY=1", "text/plain"),
57 ("install", "make install", "text/plain"),
58 ("check-clean-tree", "script/clean-source-tree.sh", "text/plain"),
59 ("clean", "make clean", "text/plain") ],
61 # Test cross-compile infrastructure
62 "samba-xc" : [ ("configure-native", "./configure.developer --with-selftest-prefix=./bin/ab" + samba_configure_params
, "text/plain"),
63 ("configure-cross-execute", "./configure.developer -b ./bin-xe --cross-compile --cross-execute=script/identity_cc.sh" \
64 " --cross-answers=./bin-xe/cross-answers.txt --with-selftest-prefix=./bin-xe/ab" + samba_configure_params
, "text/plain"),
65 ("configure-cross-answers", "./configure.developer -b ./bin-xa --cross-compile" \
66 " --cross-answers=./bin-xe/cross-answers.txt --with-selftest-prefix=./bin-xa/ab" + samba_configure_params
, "text/plain"),
67 ("compare-results", "script/compare_cc_results.py ./bin/c4che/default.cache.py ./bin-xe/c4che/default.cache.py ./bin-xa/c4che/default.cache.py", "text/plain")],
70 "samba-ctdb" : [ ("random-sleep", "script/random-sleep.sh 60 600", "text/plain"),
72 # make sure we have tdb around:
73 ("tdb-configure", "cd lib/tdb && PYTHONPATH=${PYTHON_PREFIX}/site-packages:$PYTHONPATH PKG_CONFIG_PATH=$PKG_CONFIG_PATH:${PREFIX_DIR}/lib/pkgconfig ./configure --bundled-libraries=NONE --abi-check --enable-debug -C ${PREFIX}", "text/plain"),
74 ("tdb-make", "cd lib/tdb && make", "text/plain"),
75 ("tdb-install", "cd lib/tdb && make install", "text/plain"),
78 # build samba with cluster support (also building ctdb):
79 ("samba-configure", "PYTHONPATH=${PYTHON_PREFIX}/site-packages:$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"),
80 ("samba-make", "make", "text/plain"),
81 ("samba-check", "./bin/smbd -b | grep CLUSTER_SUPPORT", "text/plain"),
82 ("samba-install", "make install", "text/plain"),
83 ("ctdb-check", "test -e ${PREFIX_DIR}/sbin/ctdbd", "text/plain"),
86 ("check-clean-tree", "script/clean-source-tree.sh", "text/plain"),
87 ("clean", "make clean", "text/plain"),
88 ("ctdb-clean", "cd ./ctdb && make clean", "text/plain") ],
91 ("random-sleep", "script/random-sleep.sh 60 600", "text/plain"),
92 ("talloc-configure", "cd lib/talloc && PYTHONPATH=${PYTHON_PREFIX}/site-packages:$PYTHONPATH PKG_CONFIG_PATH=$PKG_CONFIG_PATH:${PREFIX_DIR}/lib/pkgconfig ./configure --bundled-libraries=NONE --abi-check --enable-debug -C ${PREFIX}", "text/plain"),
93 ("talloc-make", "cd lib/talloc && make", "text/plain"),
94 ("talloc-install", "cd lib/talloc && make install", "text/plain"),
96 ("tdb-configure", "cd lib/tdb && PYTHONPATH=${PYTHON_PREFIX}/site-packages:$PYTHONPATH PKG_CONFIG_PATH=$PKG_CONFIG_PATH:${PREFIX_DIR}/lib/pkgconfig ./configure --bundled-libraries=NONE --abi-check --enable-debug -C ${PREFIX}", "text/plain"),
97 ("tdb-make", "cd lib/tdb && make", "text/plain"),
98 ("tdb-install", "cd lib/tdb && make install", "text/plain"),
100 ("tevent-configure", "cd lib/tevent && PYTHONPATH=${PYTHON_PREFIX}/site-packages:$PYTHONPATH PKG_CONFIG_PATH=$PKG_CONFIG_PATH:${PREFIX_DIR}/lib/pkgconfig ./configure --bundled-libraries=NONE --abi-check --enable-debug -C ${PREFIX}", "text/plain"),
101 ("tevent-make", "cd lib/tevent && make", "text/plain"),
102 ("tevent-install", "cd lib/tevent && make install", "text/plain"),
104 ("ldb-configure", "cd lib/ldb && PYTHONPATH=${PYTHON_PREFIX}/site-packages:$PYTHONPATH PKG_CONFIG_PATH=$PKG_CONFIG_PATH:${PREFIX_DIR}/lib/pkgconfig ./configure --bundled-libraries=NONE --abi-check --enable-debug -C ${PREFIX}", "text/plain"),
105 ("ldb-make", "cd lib/ldb && make", "text/plain"),
106 ("ldb-install", "cd lib/ldb && make install", "text/plain"),
108 ("configure", "PYTHONPATH=${PYTHON_PREFIX}/site-packages:$PYTHONPATH PKG_CONFIG_PATH=$PKG_CONFIG_PATH:${PREFIX_DIR}/lib/pkgconfig ./configure --bundled-libraries=!talloc,!tdb,!pytdb,!ldb,!pyldb,!tevent,!pytevent --minimum-library-version=ldb:1.1.21,pyldb-util:1.1.21 --abi-check --enable-debug -C ${PREFIX}", "text/plain"),
109 ("make", "make", "text/plain"),
110 ("install", "make install", "text/plain"),
111 ("dist", "make dist", "text/plain")],
114 ("random-sleep", "../../script/random-sleep.sh 60 600", "text/plain"),
115 ("configure", "./configure --enable-developer -C ${PREFIX}", "text/plain"),
116 ("make", "make", "text/plain"),
117 ("install", "make install", "text/plain"),
118 ("test", "make test", "text/plain"),
119 ("check-clean-tree", "../../script/clean-source-tree.sh", "text/plain"),
120 ("distcheck", "make distcheck", "text/plain"),
121 ("clean", "make clean", "text/plain") ],
124 ("random-sleep", "../../script/random-sleep.sh 60 600", "text/plain"),
125 ("configure", "./configure --enable-developer -C ${PREFIX}", "text/plain"),
126 ("make", "make", "text/plain"),
127 ("install", "make install", "text/plain"),
128 ("test", "make test", "text/plain"),
129 ("check-clean-tree", "../../script/clean-source-tree.sh", "text/plain"),
130 ("distcheck", "make distcheck", "text/plain"),
131 ("clean", "make clean", "text/plain") ],
134 ("random-sleep", "../../script/random-sleep.sh 60 600", "text/plain"),
135 ("configure", "./configure --enable-developer -C ${PREFIX}", "text/plain"),
136 ("make", "make", "text/plain"),
137 ("install", "make install", "text/plain"),
138 ("test", "make test", "text/plain"),
139 ("check-clean-tree", "../../script/clean-source-tree.sh", "text/plain"),
140 ("distcheck", "make distcheck", "text/plain"),
141 ("clean", "make clean", "text/plain") ],
144 ("random-sleep", "../../script/random-sleep.sh 60 600", "text/plain"),
145 ("configure", "./configure --enable-developer -C ${PREFIX}", "text/plain"),
146 ("make", "make", "text/plain"),
147 ("install", "make install", "text/plain"),
148 ("test", "make test", "text/plain"),
149 ("check-clean-tree", "../../script/clean-source-tree.sh", "text/plain"),
150 ("distcheck", "make distcheck", "text/plain"),
151 ("clean", "make clean", "text/plain") ],
154 ("random-sleep", "../../script/random-sleep.sh 60 600", "text/plain"),
155 ("configure", "./configure --enable-developer -C ${PREFIX}", "text/plain"),
156 ("make", "make", "text/plain"),
157 ("install", "make install", "text/plain"),
158 ("test", "make test", "text/plain"),
159 ("check-clean-tree", "../../script/clean-source-tree.sh", "text/plain"),
160 ("distcheck", "make distcheck", "text/plain"),
161 ("clean", "make clean", "text/plain") ],
164 ("random-sleep", "../script/random-sleep.sh 60 600", "text/plain"),
165 ("configure", "perl Makefile.PL PREFIX=${PREFIX_DIR}", "text/plain"),
166 ("touch", "touch *.yp", "text/plain"),
167 ("make", "make", "text/plain"),
168 ("test", "make test", "text/plain"),
169 ("install", "make install", "text/plain"),
170 ("checkout-yapp-generated", "git checkout lib/Parse/Pidl/IDL.pm lib/Parse/Pidl/Expr.pm", "text/plain"),
171 ("check-clean-tree", "../script/clean-source-tree.sh", "text/plain"),
172 ("clean", "make clean", "text/plain") ],
174 # these are useful for debugging autobuild
175 'pass' : [ ("pass", 'echo passing && /bin/true', "text/plain") ],
176 'fail' : [ ("fail", 'echo failing && /bin/false', "text/plain") ]
179 def run_cmd(cmd
, dir=".", show
=None, output
=False, checkfail
=True):
181 show
= options
.verbose
183 print("Running: '%s' in '%s'" % (cmd
, dir))
185 return Popen([cmd
], shell
=True, stdout
=PIPE
, cwd
=dir).communicate()[0]
187 return check_call(cmd
, shell
=True, cwd
=dir)
189 return call(cmd
, shell
=True, cwd
=dir)
192 class builder(object):
193 '''handle build of one directory'''
195 def __init__(self
, name
, sequence
):
197 self
.dir = builddirs
[name
]
199 self
.tag
= self
.name
.replace('/', '_')
200 self
.sequence
= sequence
202 self
.stdout_path
= "%s/%s.stdout" % (gitroot
, self
.tag
)
203 self
.stderr_path
= "%s/%s.stderr" % (gitroot
, self
.tag
)
205 print("stdout for %s in %s" % (self
.name
, self
.stdout_path
))
206 print("stderr for %s in %s" % (self
.name
, self
.stderr_path
))
207 run_cmd("rm -f %s %s" % (self
.stdout_path
, self
.stderr_path
))
208 self
.stdout
= open(self
.stdout_path
, 'w')
209 self
.stderr
= open(self
.stderr_path
, 'w')
210 self
.stdin
= open("/dev/null", 'r')
211 self
.sdir
= "%s/%s" % (testbase
, self
.tag
)
212 self
.prefix
= "%s/prefix/%s" % (testbase
, self
.tag
)
213 run_cmd("rm -rf %s" % self
.sdir
)
214 cleanup_list
.append(self
.sdir
)
215 cleanup_list
.append(self
.prefix
)
216 os
.makedirs(self
.sdir
)
217 run_cmd("rm -rf %s" % self
.sdir
)
218 run_cmd("git clone --recursive --shared %s %s" % (test_master
, self
.sdir
), dir=test_master
, show
=True)
221 def start_next(self
):
222 if self
.next
== len(self
.sequence
):
223 print '%s: Completed OK' % self
.name
226 (self
.stage
, self
.cmd
, self
.output_mime_type
) = self
.sequence
[self
.next
]
227 self
.cmd
= self
.cmd
.replace("${PYTHON_PREFIX}", get_python_lib(standard_lib
=1, prefix
=self
.prefix
))
228 self
.cmd
= self
.cmd
.replace("${PREFIX}", "--prefix=%s" % self
.prefix
)
229 self
.cmd
= self
.cmd
.replace("${PREFIX_DIR}", "%s" % self
.prefix
)
230 # if self.output_mime_type == "text/x-subunit":
231 # self.cmd += " | %s --immediate" % (os.path.join(os.path.dirname(__file__), "selftest/format-subunit"))
232 print '%s: [%s] Running %s' % (self
.name
, self
.stage
, self
.cmd
)
234 os
.chdir("%s/%s" % (self
.sdir
, self
.dir))
235 self
.proc
= Popen(self
.cmd
, shell
=True,
236 stdout
=self
.stdout
, stderr
=self
.stderr
, stdin
=self
.stdin
)
241 class buildlist(object):
242 '''handle build of multiple directories'''
244 def __init__(self
, tasklist
, tasknames
, rebase_url
, rebase_branch
="master"):
247 self
.tail_proc
= None
250 tasknames
= defaulttasks
252 # If we are only running one test,
253 # do not sleep randomly to wait for it to start
254 os
.environ
['AUTOBUILD_RANDOM_SLEEP_OVERRIDE'] = '1'
257 b
= builder(n
, tasks
[n
])
260 rebase_remote
= "rebaseon"
261 retry_task
= [ ("retry",
263 git remote add -t %s %s %s
267 git describe %s/%s > old_remote_branch.desc
269 git describe %s/%s > remote_branch.desc
270 diff old_remote_branch.desc remote_branch.desc
273 rebase_branch
, rebase_remote
, rebase_url
,
275 rebase_remote
, rebase_branch
,
277 rebase_remote
, rebase_branch
281 self
.retry
= builder('retry', retry_task
)
282 self
.need_retry
= False
285 if self
.tail_proc
is not None:
286 self
.tail_proc
.terminate()
287 self
.tail_proc
.wait()
288 self
.tail_proc
= None
289 if self
.retry
is not None:
290 self
.retry
.proc
.terminate()
291 self
.retry
.proc
.wait()
294 if b
.proc
is not None:
295 run_cmd("killbysubdir %s > /dev/null 2>&1" % b
.sdir
, checkfail
=False)
307 b
.status
= b
.proc
.poll()
313 ret
= self
.retry
.proc
.poll()
315 self
.need_retry
= True
325 if options
.retry
and self
.need_retry
:
327 print("retry needed")
328 return (0, None, None, None, "retry")
331 if os
.WIFSIGNALED(b
.status
) or os
.WEXITSTATUS(b
.status
) != 0:
333 return (b
.status
, b
.name
, b
.stage
, b
.tag
, "%s: [%s] failed '%s' with status %d" % (b
.name
, b
.stage
, b
.cmd
, b
.status
))
336 return (0, None, None, None, "All OK")
338 def tarlogs(self
, fname
):
339 tar
= tarfile
.open(fname
, "w:gz")
341 tar
.add(b
.stdout_path
, arcname
="%s.stdout" % b
.tag
)
342 tar
.add(b
.stderr_path
, arcname
="%s.stderr" % b
.tag
)
343 if os
.path
.exists("autobuild.log"):
344 tar
.add("autobuild.log")
347 def remove_logs(self
):
349 os
.unlink(b
.stdout_path
)
350 os
.unlink(b
.stderr_path
)
352 def start_tail(self
):
354 cmd
= "tail -f *.stdout *.stderr"
356 self
.tail_proc
= Popen(cmd
, shell
=True)
361 if options
.nocleanup
:
363 print("Cleaning up ....")
364 for d
in cleanup_list
:
365 run_cmd("rm -rf %s" % d
)
369 '''get to the top of the git repo'''
372 if os
.path
.isdir(os
.path
.join(p
, ".git")):
374 p
= os
.path
.abspath(os
.path
.join(p
, '..'))
378 def daemonize(logfile
):
380 if pid
== 0: # Parent
383 if pid
!= 0: # Actual daemon
388 import resource
# Resource usage information.
389 maxfd
= resource
.getrlimit(resource
.RLIMIT_NOFILE
)[1]
390 if maxfd
== resource
.RLIM_INFINITY
:
391 maxfd
= 1024 # Rough guess at maximum number of open file descriptors.
392 for fd
in range(0, maxfd
):
397 os
.open(logfile
, os
.O_RDWR | os
.O_CREAT
)
401 def write_pidfile(fname
):
402 '''write a pid file, cleanup on exit'''
403 f
= open(fname
, mode
='w')
404 f
.write("%u\n" % os
.getpid())
408 def rebase_tree(rebase_url
, rebase_branch
= "master"):
409 rebase_remote
= "rebaseon"
410 print("Rebasing on %s" % rebase_url
)
411 run_cmd("git describe HEAD", show
=True, dir=test_master
)
412 run_cmd("git remote add -t %s %s %s" %
413 (rebase_branch
, rebase_remote
, rebase_url
),
414 show
=True, dir=test_master
)
415 run_cmd("git fetch %s" % rebase_remote
, show
=True, dir=test_master
)
416 if options
.fix_whitespace
:
417 run_cmd("git rebase --force-rebase --whitespace=fix %s/%s" %
418 (rebase_remote
, rebase_branch
),
419 show
=True, dir=test_master
)
421 run_cmd("git rebase --force-rebase %s/%s" %
422 (rebase_remote
, rebase_branch
),
423 show
=True, dir=test_master
)
424 diff
= run_cmd("git --no-pager diff HEAD %s/%s" %
425 (rebase_remote
, rebase_branch
),
426 dir=test_master
, output
=True)
428 print("No differences between HEAD and %s/%s - exiting" %
429 (rebase_remote
, rebase_branch
))
431 run_cmd("git describe %s/%s" %
432 (rebase_remote
, rebase_branch
),
433 show
=True, dir=test_master
)
434 run_cmd("git describe HEAD", show
=True, dir=test_master
)
435 run_cmd("git --no-pager diff --stat HEAD %s/%s" %
436 (rebase_remote
, rebase_branch
),
437 show
=True, dir=test_master
)
439 def push_to(push_url
, push_branch
= "master"):
440 push_remote
= "pushto"
441 print("Pushing to %s" % push_url
)
443 run_cmd("git config --replace-all core.editor script/commit_mark.sh", dir=test_master
)
444 run_cmd("git commit --amend -c HEAD", dir=test_master
)
445 # the notes method doesn't work yet, as metze hasn't allowed refs/notes/* in master
446 # run_cmd("EDITOR=script/commit_mark.sh git notes edit HEAD", dir=test_master)
447 run_cmd("git remote add -t %s %s %s" %
448 (push_branch
, push_remote
, push_url
),
449 show
=True, dir=test_master
)
450 run_cmd("git push %s +HEAD:%s" %
451 (push_remote
, push_branch
),
452 show
=True, dir=test_master
)
454 def_testbase
= os
.getenv("AUTOBUILD_TESTBASE", "/memdisk/%s" % os
.getenv('USER'))
456 gitroot
= find_git_root()
458 raise Exception("Failed to find git root")
460 parser
= OptionParser()
461 parser
.add_option("", "--tail", help="show output while running", default
=False, action
="store_true")
462 parser
.add_option("", "--keeplogs", help="keep logs", default
=False, action
="store_true")
463 parser
.add_option("", "--nocleanup", help="don't remove test tree", default
=False, action
="store_true")
464 parser
.add_option("", "--testbase", help="base directory to run tests in (default %s)" % def_testbase
,
465 default
=def_testbase
)
466 parser
.add_option("", "--passcmd", help="command to run on success", default
=None)
467 parser
.add_option("", "--verbose", help="show all commands as they are run",
468 default
=False, action
="store_true")
469 parser
.add_option("", "--rebase", help="rebase on the given tree before testing",
470 default
=None, type='str')
471 parser
.add_option("", "--pushto", help="push to a git url on success",
472 default
=None, type='str')
473 parser
.add_option("", "--mark", help="add a Tested-By signoff before pushing",
474 default
=False, action
="store_true")
475 parser
.add_option("", "--fix-whitespace", help="fix whitespace on rebase",
476 default
=False, action
="store_true")
477 parser
.add_option("", "--retry", help="automatically retry if master changes",
478 default
=False, action
="store_true")
479 parser
.add_option("", "--email", help="send email to the given address on failure",
480 type='str', default
=None)
481 parser
.add_option("", "--email-from", help="send email from the given address",
482 type='str', default
="autobuild@samba.org")
483 parser
.add_option("", "--email-server", help="send email via the given server",
484 type='str', default
='localhost')
485 parser
.add_option("", "--always-email", help="always send email, even on success",
487 parser
.add_option("", "--daemon", help="daemonize after initial setup",
489 parser
.add_option("", "--branch", help="the branch to work on (default=master)",
490 default
="master", type='str')
491 parser
.add_option("", "--log-base", help="location where the logs can be found (default=cwd)",
492 default
=gitroot
, type='str')
493 parser
.add_option("", "--attach-logs", help="Attach logs to mails sent on success/failure?",
494 default
=False, action
="store_true")
496 def send_email(subject
, text
, log_tar
):
497 outer
= MIMEMultipart()
498 outer
['Subject'] = subject
499 outer
['To'] = options
.email
500 outer
['From'] = options
.email_from
501 outer
['Date'] = email
.utils
.formatdate(localtime
= True)
502 outer
.preamble
= 'Autobuild mails are now in MIME because we optionally attach the logs.\n'
503 outer
.attach(MIMEText(text
, 'plain'))
504 if options
.attach_logs
:
505 fp
= open(log_tar
, 'rb')
506 msg
= MIMEApplication(fp
.read(), 'gzip', email
.encoders
.encode_base64
)
508 # Set the filename parameter
509 msg
.add_header('Content-Disposition', 'attachment', filename
=os
.path
.basename(log_tar
))
511 content
= outer
.as_string()
512 s
= smtplib
.SMTP(options
.email_server
)
513 s
.sendmail(options
.email_from
, [options
.email
], content
)
517 def email_failure(status
, failed_task
, failed_stage
, failed_tag
, errstr
,
518 elapsed_time
, log_base
=None):
519 '''send an email to options.email about the failure'''
520 elapsed_minutes
= elapsed_time
/ 60.0
521 user
= os
.getenv("USER")
527 Your autobuild on %s failed after %.1f minutes
528 when trying to test %s with the following error:
532 the autobuild has been abandoned. Please fix the error and resubmit.
534 A summary of the autobuild process is here:
537 ''' % (platform
.node(), elapsed_minutes
, failed_task
, errstr
, log_base
)
539 if failed_task
!= 'rebase':
541 You can see logs of the failed task here:
546 or you can get full logs of all tasks in this job here:
550 The top commit for the tree that was built was:
554 ''' % (log_base
, failed_tag
, log_base
, failed_tag
, log_base
, top_commit_msg
)
556 logs
= os
.path
.join(gitroot
, 'logs.tar.gz')
557 send_email('autobuild failure on %s for task %s during %s'
558 % (platform
.node(), failed_task
, failed_stage
),
561 def email_success(elapsed_time
, log_base
=None):
562 '''send an email to options.email about a successful build'''
563 user
= os
.getenv("USER")
569 Your autobuild on %s has succeeded after %.1f minutes.
571 ''' % (platform
.node(), elapsed_time
/ 60.)
576 you can get full logs of all tasks in this job here:
583 The top commit for the tree that was built was:
588 logs
= os
.path
.join(gitroot
, 'logs.tar.gz')
589 send_email('autobuild sucess on %s ' % platform
.node(),
593 (options
, args
) = parser
.parse_args()
596 if options
.rebase
is None:
597 raise Exception('You can only use --retry if you also rebase')
599 testbase
= "%s/b%u" % (options
.testbase
, os
.getpid())
600 test_master
= "%s/master" % testbase
602 # get the top commit message, for emails
603 top_commit_msg
= run_cmd("git log -1", dir=gitroot
, output
=True)
606 os
.makedirs(testbase
)
607 except Exception, reason
:
608 raise Exception("Unable to create %s : %s" % (testbase
, reason
))
609 cleanup_list
.append(testbase
)
612 logfile
= os
.path
.join(testbase
, "log")
613 print "Forking into the background, writing progress to %s" % logfile
616 write_pidfile(gitroot
+ "/autobuild.pid")
618 start_time
= time
.time()
622 run_cmd("rm -rf %s" % test_master
)
623 cleanup_list
.append(test_master
)
624 run_cmd("git clone --recursive --shared %s %s" % (gitroot
, test_master
), show
=True, dir=gitroot
)
631 if options
.rebase
is not None:
632 rebase_tree(options
.rebase
, rebase_branch
=options
.branch
)
634 cleanup_list
.append(gitroot
+ "/autobuild.pid")
636 elapsed_time
= time
.time() - start_time
637 email_failure(-1, 'rebase', 'rebase', 'rebase',
638 'rebase on %s failed' % options
.branch
,
639 elapsed_time
, log_base
=options
.log_base
)
641 blist
= buildlist(tasks
, args
, options
.rebase
, rebase_branch
=options
.branch
)
644 (status
, failed_task
, failed_stage
, failed_tag
, errstr
) = blist
.run()
645 if status
!= 0 or errstr
!= "retry":
652 cleanup_list
.append(gitroot
+ "/autobuild.pid")
656 print("waiting for tail to flush")
659 elapsed_time
= time
.time() - start_time
662 if options
.passcmd
is not None:
663 print("Running passcmd: %s" % options
.passcmd
)
664 run_cmd(options
.passcmd
, dir=test_master
)
665 if options
.pushto
is not None:
666 push_to(options
.pushto
, push_branch
=options
.branch
)
667 if options
.keeplogs
or options
.attach_logs
:
668 blist
.tarlogs("logs.tar.gz")
669 print("Logs in logs.tar.gz")
670 if options
.always_email
:
671 email_success(elapsed_time
, log_base
=options
.log_base
)
677 # something failed, gather a tar of the logs
678 blist
.tarlogs("logs.tar.gz")
680 if options
.email
is not None:
681 email_failure(status
, failed_task
, failed_stage
, failed_tag
, errstr
,
682 elapsed_time
, log_base
=options
.log_base
)
686 print("Logs in logs.tar.gz")