Merge lp:~jimbaker/pyjuju/butler into lp:pyjuju/ftests

Proposed by Jim Baker
Status: Merged
Approved by: Gustavo Niemeyer
Approved revision: 19
Merged at revision: 3
Proposed branch: lp:~jimbaker/pyjuju/butler
Merge into: lp:pyjuju/ftests
Prerequisite: lp:~jimbaker/pyjuju/generate-html
Diff against target: 117 lines (+105/-0)
2 files modified
butler.py (+104/-0)
waterfall.py (+1/-0)
To merge this branch: bzr merge lp:~jimbaker/pyjuju/butler
Reviewer Review Type Date Requested Status
Gustavo Niemeyer Approve
Review via email: mp+74879@code.launchpad.net

Description of the change

Implements the opinionated driver as specified

To post a comment you must log in.
Revision history for this message
Gustavo Niemeyer (niemeyer) wrote :

Looks good, please merge on ftests Jim.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'butler.py'
2--- butler.py 1970-01-01 00:00:00 +0000
3+++ butler.py 2011-09-10 03:42:23 +0000
4@@ -0,0 +1,104 @@
5+#!/usr/bin/env python
6+# butler - Runs Emsemble's functional tests via churn and gens waterfall html
7+#
8+# A butler originally managed the buttery, which in part stores the
9+# results of the butter that was churned.
10+
11+import argparse
12+import os
13+import subprocess
14+import sys
15+
16+from subprocess import check_output, CalledProcessError
17+
18+
19+def main():
20+ """Checks out desired branch, runs tests, and summarizes results."""
21+ parser = argparse.ArgumentParser(
22+ description="Runs functional tests against desired Ensemble branch.")
23+ parser.add_argument("build", help="Directory to build the results")
24+ parser.add_argument("--branch", default="lp:ensemble")
25+ args = parser.parse_args()
26+
27+ build_path = os.path.abspath(args.build)
28+ ensemble_path = os.path.join(build_path, "ensemble")
29+ waterfall_path = os.path.join(build_path, "waterfall")
30+ if not os.path.exists(build_path):
31+ os.makedirs(build_path)
32+ update_bzr_to_tip(args.branch, ensemble_path)
33+ branch_max_revno = get_max_revno_in_branch(ensemble_path)
34+ waterfall_max_revno = get_max_revno_in_waterfall(waterfall_path)
35+ if not waterfall_max_revno:
36+ waterfall_max_revno = branch_max_revno
37+ for revno in xrange(waterfall_max_revno, branch_max_revno + 1):
38+ checkout_revision(ensemble_path, revno)
39+ churn(ensemble_path, waterfall_path, revno)
40+ generate_waterfall(build_path, waterfall_path)
41+
42+
43+def update_bzr_to_tip(branch, ensemble_path):
44+ if os.path.exists(ensemble_path):
45+ # Update to tip. Later we may go back through to previous versions
46+ print >> sys.stderr, "Updating checkout of %s to tip..." % branch,
47+ check_output(["/usr/bin/bzr", "update", ensemble_path],
48+ stderr=subprocess.STDOUT)
49+ print >> sys.stderr, "done."
50+ else:
51+ # Starting from scratch
52+ print >> sys.stderr, "Checking out %s..." % branch,
53+ check_output(["/usr/bin/bzr", "co", branch, ensemble_path],
54+ stderr=subprocess.STDOUT)
55+ print >> sys.stderr, "done."
56+
57+
58+def get_max_revno_in_waterfall(waterfall_path):
59+ if not os.path.exists(waterfall_path):
60+ os.makedirs(waterfall_path)
61+ return 0
62+ churns = os.listdir(waterfall_path)
63+ if not churns:
64+ return 0
65+ return max(int(churn) for churn in churns)
66+
67+
68+def get_max_revno_in_branch(ensemble_path):
69+ return int(check_output(["/usr/bin/bzr", "revno", ensemble_path]))
70+
71+
72+def checkout_revision(ensemble_path, revno):
73+ check_output(
74+ ["/usr/bin/bzr", "update", "--revision", str(revno), ensemble_path],
75+ stderr=subprocess.STDOUT)
76+
77+
78+def churn(ensemble_path, waterfall_path, revno):
79+ output_path = os.path.join(waterfall_path, str(revno))
80+ if os.path.exists(output_path):
81+ print >> sys.stderr, "Skipping tests for %s, %s already exists" % (
82+ revno, output_path)
83+ return
84+ os.makedirs(output_path)
85+ print >> sys.stderr, "Running functional tests for %s in %s..." % (
86+ revno, output_path),
87+ try:
88+ # For now, ignore non-zero exit codes here; churn will exit
89+ # with 1 if any of its tests fail
90+ check_output(
91+ ["./churn", "-o", output_path],
92+ env={"PYTHONPATH": ensemble_path,
93+ "PATH": "%s:%s" % (
94+ os.path.join(ensemble_path, "bin"),
95+ os.environ.get("PATH"))})
96+ except CalledProcessError:
97+ pass
98+ print >> sys.stderr, "done."
99+
100+
101+def generate_waterfall(build_path, waterfall_path):
102+ html_path = os.path.join(build_path, "waterfall.html")
103+ check_output(
104+ ["./waterfall.py %s > %s" % (waterfall_path, html_path)], shell=True)
105+
106+
107+if __name__ == "__main__":
108+ main()
109
110=== modified file 'waterfall.py' (properties changed: -x to +x)
111--- waterfall.py 2011-09-10 03:42:23 +0000
112+++ waterfall.py 2011-09-10 03:42:23 +0000
113@@ -1,3 +1,4 @@
114+#!/usr/bin/env python
115 # waterfall - Generate waterfall report from test runs
116
117 import argparse

Subscribers

People subscribed via source and target branches

to all changes: