s4: Add convenience script for building and landing a tree in the
[ira/wip.git] / source4 / script / land.py
1 #!/usr/bin/python
2 # Compile a Samba 4 branch from scratch and land it onto master.
3 # (C) 2010 Jelmer Vernooij <jelmer@samba.org>
4 # Published under the GPL, v3 or later.
5
6 from email.mime.text import MIMEText
7 import optparse
8 import os
9 import shutil
10 import smtplib
11 import subprocess
12 import sys
13 import tempfile
14
15 parser = optparse.OptionParser("land [options] <repo>")
16 parser.add_option("--branch", help="Branch to land", type=str, default=None, metavar="BRANCH")
17 parser.add_option("--dry-run", help="Dry run (don't actually land)", action="store_true", default=False)
18 parser.add_option("--daemon", help="Daemonize", action="store_true", default=False)
19 parser.add_option("--mail-to", help="Email address to send build/test output to", type=str, default=None, metavar="MAIL-TO")
20
21 (opts, args) = parser.parse_args()
22
23 if opts.mail_to:
24     from_addr = opts.mail_to
25     smtp = smtplib.SMTP()
26
27 if len(args) != 1:
28     parser.print_usage()
29     sys.exit(1)
30
31 [repo] = args
32 tmpdir = tempfile.mkdtemp()
33 rootpath = os.path.join(tmpdir, "repo")
34
35 if subprocess.call(["git", "clone", repo, rootpath]) != 0:
36     print "Unable to clone repository at %s" % repo
37     sys.exit(1)
38
39 if opts.branch:
40     if subprocess.call(["git", "checkout", opts.branch], cwd=rootpath) != 0:
41         sys.exit(1)
42 if subprocess.call(["git", "remote", "add", "upstream", "git://git.samba.org/samba.git"], cwd=rootpath) != 0:
43     sys.exit(1)
44 if subprocess.call(["git", "fetch", "upstream"], cwd=rootpath) != 0:
45     sys.exit(1)
46 if subprocess.call(["git", "rebase", "upstream/master"], cwd=rootpath) != 0:
47     sys.exit(1)
48
49 if opts.daemon:
50     pid = os.fork()
51     if pid == 0: # Parent
52         os.setsid()
53         pid = os.fork()
54         if pid != 0: # Actual daemon
55             os._exit(0)
56     else: # Grandparent
57         os._exit(0)
58
59     import resource      # Resource usage information.
60     maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
61     if maxfd == resource.RLIM_INFINITY:
62         maxfd = 1024 # Rough guess at maximum number of open file descriptors.
63     for fd in range(0, maxfd):
64         try:
65             os.close(fd)
66         except OSError:
67             pass
68     os.open(os.devnull, os.O_RDWR)
69     os.dup2(0, 1)
70     os.dup2(0, 2)
71
72 if opts.mail_to:
73     (outfd, name) = tempfile.mkstemp()
74     outf = os.fdopen(outfd, 'w')
75 else:
76     outf = sys.stdout
77
78 def fail(stage):
79     if opts.mail_to:
80         outf.close()
81         f = open(name, 'r')
82         msg = MIMEText(f.read())
83         f.close()
84         msg["Subject"] = "Failure for %s during %s" % (repo, stage)
85         msg["To"] = opts.mail_to
86         msg["From"] = from_addr
87         smtp.connect()
88         smtp.sendmail(from_addr, [opts.mail_to], msg.as_string())
89         smtp.quit()
90     shutil.rmtree(tmpdir)
91     sys.exit(1)
92
93 s4path = os.path.join(rootpath, "source4")
94
95 if subprocess.call(["./autogen.sh"], cwd=s4path, stdout=outf, stderr=outf) != 0:
96     fail("Generating configure")
97 if subprocess.call(["./configure.developer"], cwd=s4path, stdout=outf, stderr=outf) != 0:
98     fail("Running configure")
99 if subprocess.call(["make"], cwd=s4path, stderr=outf, stdout=outf) != 0:
100     fail("Building")
101 if subprocess.call(["make", "check"], cwd=s4path, stderr=outf, stdout=outf) != 0:
102     fail("Running testsuite")
103 if not opts.dry_run:
104     if subprocess.call(["git", "push", "git+ssh://git.samba.org/data/git/samba.git", "HEAD:master"], cwd=rootpath, stderr=outf, stdout=outf) != 0:
105         fail("Pushing to master")
106 shutil.rmtree(tmpdir)
107
108 if opts.mail_to:
109     outf.close()
110     f = open(name, 'r')
111     msg = MIMEText(f.read())
112     f.close()
113     msg["Subject"] = "Success landing %s" % repo
114     msg["To"] = opts.mail_to
115     msg["From"] = from_addr
116     smtp.connect()
117     smtp.sendmail(from_addr, [opts.mail_to], msg.as_string())
118     smtp.quit()