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"
44 samba_libs_envvars
= "PYTHONPATH=${PYTHON_PREFIX}/site-packages:$PYTHONPATH"
45 samba_libs_envvars
+= " PKG_CONFIG_PATH=$PKG_CONFIG_PATH:${PREFIX_DIR}/lib/pkgconfig"
46 samba_libs_envvars
+= " ADDITIONAL_CFLAGS='-Wmissing-prototypes'"
47 samba_libs_configure_base
= samba_libs_envvars
+ " ./configure --abi-check --enable-debug --picky-developer -C ${PREFIX}"
48 samba_libs_configure_libs
= samba_libs_configure_base
+ " --bundled-libraries=NONE"
49 samba_libs_configure_samba
= samba_libs_configure_base
+ " --bundled-libraries=!talloc,!tdb,!pytdb,!ldb,!pyldb,!tevent,!pytevent"
52 "ctdb" : [ ("random-sleep", "../script/random-sleep.sh 60 600", "text/plain"),
53 ("configure", "./configure ${PREFIX}", "text/plain"),
54 ("make", "make all", "text/plain"),
55 ("install", "make install", "text/plain"),
56 ("test", "make autotest", "text/plain"),
57 ("check-clean-tree", "../script/clean-source-tree.sh", "text/plain"),
58 ("clean", "make clean", "text/plain") ],
60 # We have 'test' before 'install' because, 'test' should work without 'install'
61 "samba" : [ ("configure", "./configure.developer --with-selftest-prefix=./bin/ab" + samba_configure_params
, "text/plain"),
62 ("make", "make -j", "text/plain"),
63 ("test", "make test FAIL_IMMEDIATELY=1", "text/plain"),
64 ("install", "make install", "text/plain"),
65 ("check-clean-tree", "script/clean-source-tree.sh", "text/plain"),
66 ("clean", "make clean", "text/plain") ],
68 # Test cross-compile infrastructure
69 "samba-xc" : [ ("configure-native", "./configure.developer --with-selftest-prefix=./bin/ab" + samba_configure_params
, "text/plain"),
70 ("configure-cross-execute", "./configure.developer -b ./bin-xe --cross-compile --cross-execute=script/identity_cc.sh" \
71 " --cross-answers=./bin-xe/cross-answers.txt --with-selftest-prefix=./bin-xe/ab" + samba_configure_params
, "text/plain"),
72 ("configure-cross-answers", "./configure.developer -b ./bin-xa --cross-compile" \
73 " --cross-answers=./bin-xe/cross-answers.txt --with-selftest-prefix=./bin-xa/ab" + samba_configure_params
, "text/plain"),
74 ("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")],
77 "samba-ctdb" : [ ("random-sleep", "script/random-sleep.sh 60 600", "text/plain"),
79 # make sure we have tdb around:
80 ("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"),
81 ("tdb-make", "cd lib/tdb && make", "text/plain"),
82 ("tdb-install", "cd lib/tdb && make install", "text/plain"),
85 # build samba with cluster support (also building ctdb):
86 ("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"),
87 ("samba-make", "make", "text/plain"),
88 ("samba-check", "./bin/smbd -b | grep CLUSTER_SUPPORT", "text/plain"),
89 ("samba-install", "make install", "text/plain"),
90 ("ctdb-check", "test -e ${PREFIX_DIR}/sbin/ctdbd", "text/plain"),
93 ("check-clean-tree", "script/clean-source-tree.sh", "text/plain"),
94 ("clean", "make clean", "text/plain"),
95 ("ctdb-clean", "cd ./ctdb && make clean", "text/plain") ],
98 ("random-sleep", "script/random-sleep.sh 60 600", "text/plain"),
99 ("talloc-configure", "cd lib/talloc && " + samba_libs_configure_libs
, "text/plain"),
100 ("talloc-make", "cd lib/talloc && make", "text/plain"),
101 ("talloc-install", "cd lib/talloc && make install", "text/plain"),
103 ("tdb-configure", "cd lib/tdb && " + samba_libs_configure_libs
, "text/plain"),
104 ("tdb-make", "cd lib/tdb && make", "text/plain"),
105 ("tdb-install", "cd lib/tdb && make install", "text/plain"),
107 ("tevent-configure", "cd lib/tevent && " + samba_libs_configure_libs
, "text/plain"),
108 ("tevent-make", "cd lib/tevent && make", "text/plain"),
109 ("tevent-install", "cd lib/tevent && make install", "text/plain"),
111 ("ldb-configure", "cd lib/ldb && " + samba_libs_configure_libs
, "text/plain"),
112 ("ldb-make", "cd lib/ldb && make", "text/plain"),
113 ("ldb-install", "cd lib/ldb && make install", "text/plain"),
115 ("configure", samba_libs_configure_samba
, "text/plain"),
116 ("make", "make", "text/plain"),
117 ("install", "make install", "text/plain"),
118 ("dist", "make dist", "text/plain"),
120 # retry with all modules shared
121 ("allshared-distclean", "make distclean", "text/plain"),
122 ("allshared-configure", samba_libs_configure_samba
+ " --with-shared-modules=ALL", "text/plain"),
123 ("allshared-make", "make", "text/plain"),
125 # retry with all modules static
126 ("allstatic-distclean", "make distclean", "text/plain"),
127 ("allstatic-configure", samba_libs_configure_samba
+ " --with-static-modules=ALL", "text/plain"),
128 ("allstatic-make", "make", "text/plain"),
130 # retry without any required modules
131 ("none-distclean", "make distclean", "text/plain"),
132 ("none-configure", samba_libs_configure_samba
+ " --with-static-modules=!FORCED,!DEFAULT --with-shared-modules=!FORCED,!DEFAULT", "text/plain"),
133 ("none-make", "make", "text/plain"),
135 # retry with nonshared smbd and smbtorture
136 ("nonshared-distclean", "make distclean", "text/plain"),
137 ("nonshared-configure", samba_libs_configure_base
+ " --bundled-libraries=talloc,tdb,pytdb,ldb,pyldb,tevent,pytevent --with-static-modules=ALL --nonshared-binary=smbtorture,smbd/smbd", "text/plain"),
138 ("nonshared-make", "make", "text/plain")],
141 ("random-sleep", "../../script/random-sleep.sh 60 600", "text/plain"),
142 ("configure", "./configure --enable-developer -C ${PREFIX}", "text/plain"),
143 ("make", "make", "text/plain"),
144 ("install", "make install", "text/plain"),
145 ("test", "make test", "text/plain"),
146 ("check-clean-tree", "../../script/clean-source-tree.sh", "text/plain"),
147 ("distcheck", "make distcheck", "text/plain"),
148 ("clean", "make clean", "text/plain") ],
151 ("random-sleep", "../../script/random-sleep.sh 60 600", "text/plain"),
152 ("configure", "./configure --enable-developer -C ${PREFIX}", "text/plain"),
153 ("make", "make", "text/plain"),
154 ("install", "make install", "text/plain"),
155 ("test", "make test", "text/plain"),
156 ("check-clean-tree", "../../script/clean-source-tree.sh", "text/plain"),
157 ("distcheck", "make distcheck", "text/plain"),
158 ("clean", "make clean", "text/plain") ],
161 ("random-sleep", "../../script/random-sleep.sh 60 600", "text/plain"),
162 ("configure", "./configure --enable-developer -C ${PREFIX}", "text/plain"),
163 ("make", "make", "text/plain"),
164 ("install", "make install", "text/plain"),
165 ("test", "make test", "text/plain"),
166 ("check-clean-tree", "../../script/clean-source-tree.sh", "text/plain"),
167 ("distcheck", "make distcheck", "text/plain"),
168 ("clean", "make clean", "text/plain") ],
171 ("random-sleep", "../../script/random-sleep.sh 60 600", "text/plain"),
172 ("configure", "./configure --enable-developer -C ${PREFIX}", "text/plain"),
173 ("make", "make", "text/plain"),
174 ("install", "make install", "text/plain"),
175 ("test", "make test", "text/plain"),
176 ("check-clean-tree", "../../script/clean-source-tree.sh", "text/plain"),
177 ("distcheck", "make distcheck", "text/plain"),
178 ("clean", "make clean", "text/plain") ],
181 ("random-sleep", "../../script/random-sleep.sh 60 600", "text/plain"),
182 ("configure", "./configure --enable-developer -C ${PREFIX}", "text/plain"),
183 ("make", "make", "text/plain"),
184 ("install", "make install", "text/plain"),
185 ("test", "make test", "text/plain"),
186 ("check-clean-tree", "../../script/clean-source-tree.sh", "text/plain"),
187 ("distcheck", "make distcheck", "text/plain"),
188 ("clean", "make clean", "text/plain") ],
191 ("random-sleep", "../script/random-sleep.sh 60 600", "text/plain"),
192 ("configure", "perl Makefile.PL PREFIX=${PREFIX_DIR}", "text/plain"),
193 ("touch", "touch *.yp", "text/plain"),
194 ("make", "make", "text/plain"),
195 ("test", "make test", "text/plain"),
196 ("install", "make install", "text/plain"),
197 ("checkout-yapp-generated", "git checkout lib/Parse/Pidl/IDL.pm lib/Parse/Pidl/Expr.pm", "text/plain"),
198 ("check-clean-tree", "../script/clean-source-tree.sh", "text/plain"),
199 ("clean", "make clean", "text/plain") ],
201 # these are useful for debugging autobuild
202 'pass' : [ ("pass", 'echo passing && /bin/true', "text/plain") ],
203 'fail' : [ ("fail", 'echo failing && /bin/false', "text/plain") ]
206 def run_cmd(cmd
, dir=".", show
=None, output
=False, checkfail
=True):
208 show
= options
.verbose
210 print("Running: '%s' in '%s'" % (cmd
, dir))
212 return Popen([cmd
], shell
=True, stdout
=PIPE
, cwd
=dir).communicate()[0]
214 return check_call(cmd
, shell
=True, cwd
=dir)
216 return call(cmd
, shell
=True, cwd
=dir)
219 class builder(object):
220 '''handle build of one directory'''
222 def __init__(self
, name
, sequence
):
224 self
.dir = builddirs
[name
]
226 self
.tag
= self
.name
.replace('/', '_')
227 self
.sequence
= sequence
229 self
.stdout_path
= "%s/%s.stdout" % (gitroot
, self
.tag
)
230 self
.stderr_path
= "%s/%s.stderr" % (gitroot
, self
.tag
)
232 print("stdout for %s in %s" % (self
.name
, self
.stdout_path
))
233 print("stderr for %s in %s" % (self
.name
, self
.stderr_path
))
234 run_cmd("rm -f %s %s" % (self
.stdout_path
, self
.stderr_path
))
235 self
.stdout
= open(self
.stdout_path
, 'w')
236 self
.stderr
= open(self
.stderr_path
, 'w')
237 self
.stdin
= open("/dev/null", 'r')
238 self
.sdir
= "%s/%s" % (testbase
, self
.tag
)
239 self
.prefix
= "%s/prefix/%s" % (testbase
, self
.tag
)
240 run_cmd("rm -rf %s" % self
.sdir
)
241 cleanup_list
.append(self
.sdir
)
242 cleanup_list
.append(self
.prefix
)
243 os
.makedirs(self
.sdir
)
244 run_cmd("rm -rf %s" % self
.sdir
)
245 run_cmd("git clone --recursive --shared %s %s" % (test_master
, self
.sdir
), dir=test_master
, show
=True)
248 def start_next(self
):
249 if self
.next
== len(self
.sequence
):
250 print '%s: Completed OK' % self
.name
253 (self
.stage
, self
.cmd
, self
.output_mime_type
) = self
.sequence
[self
.next
]
254 self
.cmd
= self
.cmd
.replace("${PYTHON_PREFIX}", get_python_lib(standard_lib
=1, prefix
=self
.prefix
))
255 self
.cmd
= self
.cmd
.replace("${PREFIX}", "--prefix=%s" % self
.prefix
)
256 self
.cmd
= self
.cmd
.replace("${PREFIX_DIR}", "%s" % self
.prefix
)
257 # if self.output_mime_type == "text/x-subunit":
258 # self.cmd += " | %s --immediate" % (os.path.join(os.path.dirname(__file__), "selftest/format-subunit"))
259 print '%s: [%s] Running %s' % (self
.name
, self
.stage
, self
.cmd
)
261 os
.chdir("%s/%s" % (self
.sdir
, self
.dir))
262 self
.proc
= Popen(self
.cmd
, shell
=True,
263 stdout
=self
.stdout
, stderr
=self
.stderr
, stdin
=self
.stdin
)
268 class buildlist(object):
269 '''handle build of multiple directories'''
271 def __init__(self
, tasklist
, tasknames
, rebase_url
, rebase_branch
="master"):
274 self
.tail_proc
= None
277 tasknames
= defaulttasks
279 # If we are only running one test,
280 # do not sleep randomly to wait for it to start
281 os
.environ
['AUTOBUILD_RANDOM_SLEEP_OVERRIDE'] = '1'
284 b
= builder(n
, tasks
[n
])
287 rebase_remote
= "rebaseon"
288 retry_task
= [ ("retry",
290 git remote add -t %s %s %s
294 git describe %s/%s > old_remote_branch.desc
296 git describe %s/%s > remote_branch.desc
297 diff old_remote_branch.desc remote_branch.desc
300 rebase_branch
, rebase_remote
, rebase_url
,
302 rebase_remote
, rebase_branch
,
304 rebase_remote
, rebase_branch
308 self
.retry
= builder('retry', retry_task
)
309 self
.need_retry
= False
312 if self
.tail_proc
is not None:
313 self
.tail_proc
.terminate()
314 self
.tail_proc
.wait()
315 self
.tail_proc
= None
316 if self
.retry
is not None:
317 self
.retry
.proc
.terminate()
318 self
.retry
.proc
.wait()
321 if b
.proc
is not None:
322 run_cmd("killbysubdir %s > /dev/null 2>&1" % b
.sdir
, checkfail
=False)
334 b
.status
= b
.proc
.poll()
340 ret
= self
.retry
.proc
.poll()
342 self
.need_retry
= True
352 if options
.retry
and self
.need_retry
:
354 print("retry needed")
355 return (0, None, None, None, "retry")
358 if os
.WIFSIGNALED(b
.status
) or os
.WEXITSTATUS(b
.status
) != 0:
360 return (b
.status
, b
.name
, b
.stage
, b
.tag
, "%s: [%s] failed '%s' with status %d" % (b
.name
, b
.stage
, b
.cmd
, b
.status
))
363 return (0, None, None, None, "All OK")
365 def tarlogs(self
, fname
):
366 tar
= tarfile
.open(fname
, "w:gz")
368 tar
.add(b
.stdout_path
, arcname
="%s.stdout" % b
.tag
)
369 tar
.add(b
.stderr_path
, arcname
="%s.stderr" % b
.tag
)
370 if os
.path
.exists("autobuild.log"):
371 tar
.add("autobuild.log")
374 def remove_logs(self
):
376 os
.unlink(b
.stdout_path
)
377 os
.unlink(b
.stderr_path
)
379 def start_tail(self
):
381 cmd
= "tail -f *.stdout *.stderr"
383 self
.tail_proc
= Popen(cmd
, shell
=True)
388 if options
.nocleanup
:
390 print("Cleaning up ....")
391 for d
in cleanup_list
:
392 run_cmd("rm -rf %s" % d
)
396 '''get to the top of the git repo'''
399 if os
.path
.isdir(os
.path
.join(p
, ".git")):
401 p
= os
.path
.abspath(os
.path
.join(p
, '..'))
405 def daemonize(logfile
):
407 if pid
== 0: # Parent
410 if pid
!= 0: # Actual daemon
415 import resource
# Resource usage information.
416 maxfd
= resource
.getrlimit(resource
.RLIMIT_NOFILE
)[1]
417 if maxfd
== resource
.RLIM_INFINITY
:
418 maxfd
= 1024 # Rough guess at maximum number of open file descriptors.
419 for fd
in range(0, maxfd
):
424 os
.open(logfile
, os
.O_RDWR | os
.O_CREAT
)
428 def write_pidfile(fname
):
429 '''write a pid file, cleanup on exit'''
430 f
= open(fname
, mode
='w')
431 f
.write("%u\n" % os
.getpid())
435 def rebase_tree(rebase_url
, rebase_branch
= "master"):
436 rebase_remote
= "rebaseon"
437 print("Rebasing on %s" % rebase_url
)
438 run_cmd("git describe HEAD", show
=True, dir=test_master
)
439 run_cmd("git remote add -t %s %s %s" %
440 (rebase_branch
, rebase_remote
, rebase_url
),
441 show
=True, dir=test_master
)
442 run_cmd("git fetch %s" % rebase_remote
, show
=True, dir=test_master
)
443 if options
.fix_whitespace
:
444 run_cmd("git rebase --force-rebase --whitespace=fix %s/%s" %
445 (rebase_remote
, rebase_branch
),
446 show
=True, dir=test_master
)
448 run_cmd("git rebase --force-rebase %s/%s" %
449 (rebase_remote
, rebase_branch
),
450 show
=True, dir=test_master
)
451 diff
= run_cmd("git --no-pager diff HEAD %s/%s" %
452 (rebase_remote
, rebase_branch
),
453 dir=test_master
, output
=True)
455 print("No differences between HEAD and %s/%s - exiting" %
456 (rebase_remote
, rebase_branch
))
458 run_cmd("git describe %s/%s" %
459 (rebase_remote
, rebase_branch
),
460 show
=True, dir=test_master
)
461 run_cmd("git describe HEAD", show
=True, dir=test_master
)
462 run_cmd("git --no-pager diff --stat HEAD %s/%s" %
463 (rebase_remote
, rebase_branch
),
464 show
=True, dir=test_master
)
466 def push_to(push_url
, push_branch
= "master"):
467 push_remote
= "pushto"
468 print("Pushing to %s" % push_url
)
470 run_cmd("git config --replace-all core.editor script/commit_mark.sh", dir=test_master
)
471 run_cmd("git commit --amend -c HEAD", dir=test_master
)
472 # the notes method doesn't work yet, as metze hasn't allowed refs/notes/* in master
473 # run_cmd("EDITOR=script/commit_mark.sh git notes edit HEAD", dir=test_master)
474 run_cmd("git remote add -t %s %s %s" %
475 (push_branch
, push_remote
, push_url
),
476 show
=True, dir=test_master
)
477 run_cmd("git push %s +HEAD:%s" %
478 (push_remote
, push_branch
),
479 show
=True, dir=test_master
)
481 def_testbase
= os
.getenv("AUTOBUILD_TESTBASE", "/memdisk/%s" % os
.getenv('USER'))
483 gitroot
= find_git_root()
485 raise Exception("Failed to find git root")
487 parser
= OptionParser()
488 parser
.add_option("", "--tail", help="show output while running", default
=False, action
="store_true")
489 parser
.add_option("", "--keeplogs", help="keep logs", default
=False, action
="store_true")
490 parser
.add_option("", "--nocleanup", help="don't remove test tree", default
=False, action
="store_true")
491 parser
.add_option("", "--testbase", help="base directory to run tests in (default %s)" % def_testbase
,
492 default
=def_testbase
)
493 parser
.add_option("", "--passcmd", help="command to run on success", default
=None)
494 parser
.add_option("", "--verbose", help="show all commands as they are run",
495 default
=False, action
="store_true")
496 parser
.add_option("", "--rebase", help="rebase on the given tree before testing",
497 default
=None, type='str')
498 parser
.add_option("", "--pushto", help="push to a git url on success",
499 default
=None, type='str')
500 parser
.add_option("", "--mark", help="add a Tested-By signoff before pushing",
501 default
=False, action
="store_true")
502 parser
.add_option("", "--fix-whitespace", help="fix whitespace on rebase",
503 default
=False, action
="store_true")
504 parser
.add_option("", "--retry", help="automatically retry if master changes",
505 default
=False, action
="store_true")
506 parser
.add_option("", "--email", help="send email to the given address on failure",
507 type='str', default
=None)
508 parser
.add_option("", "--email-from", help="send email from the given address",
509 type='str', default
="autobuild@samba.org")
510 parser
.add_option("", "--email-server", help="send email via the given server",
511 type='str', default
='localhost')
512 parser
.add_option("", "--always-email", help="always send email, even on success",
514 parser
.add_option("", "--daemon", help="daemonize after initial setup",
516 parser
.add_option("", "--branch", help="the branch to work on (default=master)",
517 default
="master", type='str')
518 parser
.add_option("", "--log-base", help="location where the logs can be found (default=cwd)",
519 default
=gitroot
, type='str')
520 parser
.add_option("", "--attach-logs", help="Attach logs to mails sent on success/failure?",
521 default
=False, action
="store_true")
523 def send_email(subject
, text
, log_tar
):
524 outer
= MIMEMultipart()
525 outer
['Subject'] = subject
526 outer
['To'] = options
.email
527 outer
['From'] = options
.email_from
528 outer
['Date'] = email
.utils
.formatdate(localtime
= True)
529 outer
.preamble
= 'Autobuild mails are now in MIME because we optionally attach the logs.\n'
530 outer
.attach(MIMEText(text
, 'plain'))
531 if options
.attach_logs
:
532 fp
= open(log_tar
, 'rb')
533 msg
= MIMEApplication(fp
.read(), 'gzip', email
.encoders
.encode_base64
)
535 # Set the filename parameter
536 msg
.add_header('Content-Disposition', 'attachment', filename
=os
.path
.basename(log_tar
))
538 content
= outer
.as_string()
539 s
= smtplib
.SMTP(options
.email_server
)
540 s
.sendmail(options
.email_from
, [options
.email
], content
)
544 def email_failure(status
, failed_task
, failed_stage
, failed_tag
, errstr
,
545 elapsed_time
, log_base
=None):
546 '''send an email to options.email about the failure'''
547 elapsed_minutes
= elapsed_time
/ 60.0
548 user
= os
.getenv("USER")
554 Your autobuild on %s failed after %.1f minutes
555 when trying to test %s with the following error:
559 the autobuild has been abandoned. Please fix the error and resubmit.
561 A summary of the autobuild process is here:
564 ''' % (platform
.node(), elapsed_minutes
, failed_task
, errstr
, log_base
)
566 if failed_task
!= 'rebase':
568 You can see logs of the failed task here:
573 or you can get full logs of all tasks in this job here:
577 The top commit for the tree that was built was:
581 ''' % (log_base
, failed_tag
, log_base
, failed_tag
, log_base
, top_commit_msg
)
583 logs
= os
.path
.join(gitroot
, 'logs.tar.gz')
584 send_email('autobuild failure on %s for task %s during %s'
585 % (platform
.node(), failed_task
, failed_stage
),
588 def email_success(elapsed_time
, log_base
=None):
589 '''send an email to options.email about a successful build'''
590 user
= os
.getenv("USER")
596 Your autobuild on %s has succeeded after %.1f minutes.
598 ''' % (platform
.node(), elapsed_time
/ 60.)
603 you can get full logs of all tasks in this job here:
610 The top commit for the tree that was built was:
615 logs
= os
.path
.join(gitroot
, 'logs.tar.gz')
616 send_email('autobuild sucess on %s ' % platform
.node(),
620 (options
, args
) = parser
.parse_args()
623 if options
.rebase
is None:
624 raise Exception('You can only use --retry if you also rebase')
626 testbase
= "%s/b%u" % (options
.testbase
, os
.getpid())
627 test_master
= "%s/master" % testbase
629 # get the top commit message, for emails
630 top_commit_msg
= run_cmd("git log -1", dir=gitroot
, output
=True)
633 os
.makedirs(testbase
)
634 except Exception, reason
:
635 raise Exception("Unable to create %s : %s" % (testbase
, reason
))
636 cleanup_list
.append(testbase
)
639 logfile
= os
.path
.join(testbase
, "log")
640 print "Forking into the background, writing progress to %s" % logfile
643 write_pidfile(gitroot
+ "/autobuild.pid")
645 start_time
= time
.time()
649 run_cmd("rm -rf %s" % test_master
)
650 cleanup_list
.append(test_master
)
651 run_cmd("git clone --recursive --shared %s %s" % (gitroot
, test_master
), show
=True, dir=gitroot
)
658 if options
.rebase
is not None:
659 rebase_tree(options
.rebase
, rebase_branch
=options
.branch
)
661 cleanup_list
.append(gitroot
+ "/autobuild.pid")
663 elapsed_time
= time
.time() - start_time
664 email_failure(-1, 'rebase', 'rebase', 'rebase',
665 'rebase on %s failed' % options
.branch
,
666 elapsed_time
, log_base
=options
.log_base
)
668 blist
= buildlist(tasks
, args
, options
.rebase
, rebase_branch
=options
.branch
)
671 (status
, failed_task
, failed_stage
, failed_tag
, errstr
) = blist
.run()
672 if status
!= 0 or errstr
!= "retry":
679 cleanup_list
.append(gitroot
+ "/autobuild.pid")
683 print("waiting for tail to flush")
686 elapsed_time
= time
.time() - start_time
689 if options
.passcmd
is not None:
690 print("Running passcmd: %s" % options
.passcmd
)
691 run_cmd(options
.passcmd
, dir=test_master
)
692 if options
.pushto
is not None:
693 push_to(options
.pushto
, push_branch
=options
.branch
)
694 if options
.keeplogs
or options
.attach_logs
:
695 blist
.tarlogs("logs.tar.gz")
696 print("Logs in logs.tar.gz")
697 if options
.always_email
:
698 email_success(elapsed_time
, log_base
=options
.log_base
)
704 # something failed, gather a tar of the logs
705 blist
.tarlogs("logs.tar.gz")
707 if options
.email
is not None:
708 email_failure(status
, failed_task
, failed_stage
, failed_tag
, errstr
,
709 elapsed_time
, log_base
=options
.log_base
)
713 print("Logs in logs.tar.gz")