[pypy-svn] r58168 - in pypy/build/bot2: . pypybuildbot pypybuildbot/test

pedronis at codespeak.net pedronis at codespeak.net
Mon Sep 15 18:12:51 CEST 2008


Author: pedronis
Date: Mon Sep 15 18:12:48 2008
New Revision: 58168

Added:
   pypy/build/bot2/
   pypy/build/bot2/master.cfg   (contents, props changed)
   pypy/build/bot2/pypybuildbot/   (props changed)
   pypy/build/bot2/pypybuildbot/__init__.py   (contents, props changed)
   pypy/build/bot2/pypybuildbot/master.py   (contents, props changed)
   pypy/build/bot2/pypybuildbot/summary.py   (contents, props changed)
   pypy/build/bot2/pypybuildbot/test/   (props changed)
   pypy/build/bot2/pypybuildbot/test/test_summary.py   (contents, props changed)
   pypy/build/bot2/slaveinfo.py   (contents, props changed)
Log:
(iko, pedronis)

work in progress: display of results from FileLogSession gathered through buildbot

this is also the whole config of the buildbot we are running locally to experiment with this



Added: pypy/build/bot2/master.cfg
==============================================================================
--- (empty file)
+++ pypy/build/bot2/master.cfg	Mon Sep 15 18:12:48 2008
@@ -0,0 +1,11 @@
+import sys, os
+
+slavePortnum =  "tcp:10407"
+httpPortNumber = 8099
+
+# slavename -> password
+from slaveinfo import passwords
+
+# checkout bot2 in the home dir of the master
+sys.path.append(os.path.expanduser('~/bot2/'))
+execfile(os.path.expanduser('~/bot2/pypybuildbot/master.py'))

Added: pypy/build/bot2/pypybuildbot/__init__.py
==============================================================================

Added: pypy/build/bot2/pypybuildbot/master.py
==============================================================================
--- (empty file)
+++ pypy/build/bot2/pypybuildbot/master.py	Mon Sep 15 18:12:48 2008
@@ -0,0 +1,62 @@
+from buildbot.scheduler import Nightly
+from buildbot.buildslave import BuildSlave
+from buildbot.status.html import WebStatus
+
+from buildbot.process import factory
+from buildbot.steps import source, shell
+
+
+# I really wanted to pass logPath to Site
+from twisted.web.server import Site
+class LoggingSite(Site):
+    def __init__(self, *a, **kw):
+        Site.__init__(self, logPath='httpd.log', *a, **kw)
+from twisted.web import server
+if server.Site.__name__ == 'Site':
+    server.Site = LoggingSite
+# So I did.
+
+status = WebStatus(httpPortNumber, allowForce=True)
+
+pypyOwnFactory = factory.BuildFactory()
+pypyOwnFactory.addStep(source.SVN("https://codespeak.net/svn/pypy/branch/pypy-pytrunk"))
+pypyOwnFactory.addStep(shell.ShellCommand(
+    description="pytest",
+    command="py/bin/py.test pypy/module/__builtin__ pypy/module/operator --session=FileLogSession --filelog=pytest.log".split(),
+    logfiles={'pytestLog': 'pytest.log'}))
+
+BuildmasterConfig = {
+    'slavePortnum': slavePortnum,
+
+    'change_source': [],
+    'schedulers': [Nightly("nightly",
+                           ["pypy-own-linux", "pypy-own-other-linux"], hour=19)],
+    'status': [status],
+
+    'slaves': [BuildSlave(name, password)
+               for (name, password)
+               in passwords.iteritems()],
+
+    'builders': [
+                  {"name": "pypy-own-linux",
+                   "slavenames": ["vitaly"],
+                   "builddir": "pypy-own-linux",
+                   "factory": pypyOwnFactory
+                  },
+                  {"name": "pypy-own-other-linux",
+                   "slavenames": ["fido"],
+                   "builddir": "pypy-own-other-linux",
+                   "factory": pypyOwnFactory
+                  }
+                ],
+
+    'buildbotURL': 'http://localhost:%d/' % (httpPortNumber,),
+    'projectURL': 'http://codespeak.net/pypy/',
+    'projectName': 'PyPy'}
+
+import pypybuildbot.summary
+reload(pypybuildbot.summary)
+summary = pypybuildbot.summary
+
+# pypy test summary page
+status.putChild('summary', summary.Summary())

Added: pypy/build/bot2/pypybuildbot/summary.py
==============================================================================
--- (empty file)
+++ pypy/build/bot2/pypybuildbot/summary.py	Mon Sep 15 18:12:48 2008
@@ -0,0 +1,95 @@
+
+from buildbot.status.web.base import HtmlResource
+
+# xxx caching?
+class RevOutcome(object):
+
+    def __init__(self, rev):
+        self.rev = rev
+        self._outcomes = {}
+        self.failed = set()
+        self.skipped = set()
+        # xxx failure tracebacks
+
+    def populate_one(self, name, shortrepr):
+        namekey = name.split(':', 1)
+        if namekey[0].endswith('.py'):
+            namekey[0] = namekey[0][:-3].replace('/', '.')
+
+        namekey = tuple(namekey)
+        self._outcomes[namekey] = shortrepr
+        if shortrepr == 's':
+            self.skipped.add(namekey)
+        elif shortrepr == '.':
+            pass
+        else:
+            self.failed.add(namekey)
+
+    def populate(self, log):
+        for line in log.readlines():
+            kind = line[0]
+            if kind == ' ':
+                continue
+            name = line[2:].rstrip()
+            self.populate_one(name, kind)
+
+    def get_outcome(self, namekey):
+        return self._outcomes[namekey]
+
+
+class GatherOutcome(object):
+
+    def __init__(self, map):
+        self.map = map
+        self._failed = None
+        self._skipped = None
+
+    @property
+    def failed(self):
+        if self._failed is None:
+            self._failed = set()
+            for prefix, outcome in self.map.items():
+                self._failed.update([(prefix,)+ namekey for namekey in
+                                     outcome.failed])
+        return self._failed
+
+    @property
+    def skipped(self):
+        if self._skipped is None:
+            self._skipped = set()
+            for prefix, outcome in self.map.items():
+                self._skipped.update([(prefix,) + namekey for namekey in
+                                     outcome.skipped])
+        return self._skipped
+
+    def get_outcome(self, namekey):
+        return self.map[namekey[0]].get_outcome(namekey[1:])
+         
+
+
+N = 10
+
+class Summary(HtmlResource):
+
+    def recentRevisions(self, request):
+        # xxx branches
+        status = self.getStatus(request)
+        revs = {}
+        for builderName in status.getBuilderNames():
+            builderStatus = status.getBuilder(builderName)
+            for build in builderStatus.generateFinishedBuilds(num_builds=N):
+                rev = build.getProperty("got_revision")
+                revBuilds = revs.setdefault(rev, {})
+                if builderName not in revBuilds: # pick the most recent or ?
+                    # xxx hack, go through the steps and make sure
+                    # the log is there
+                    log = [log for log in build.getLogs()
+                           if log.getName() == "pytestLog"][0]
+                    revBuilds[builderName] = RevOutcome(log)
+        revs = revs.items()
+        revs.sort()
+        return revs
+                            
+    def body(self, request):
+        revs = self.recentRevisions(request)
+        return repr(len(revs))

Added: pypy/build/bot2/pypybuildbot/test/test_summary.py
==============================================================================
--- (empty file)
+++ pypy/build/bot2/pypybuildbot/test/test_summary.py	Mon Sep 15 18:12:48 2008
@@ -0,0 +1,75 @@
+from pypybuildbot import summary
+from StringIO import StringIO
+
+class TestOutcomes(object):
+
+    def test_populate(self):
+        rev_outcome = summary.RevOutcome(50000)
+        log = StringIO("""F a/b.py:test_one
+. a/b.py:test_two
+s a/b.py:test_three
+""")
+        
+        rev_outcome.populate(log)
+
+        assert rev_outcome.skipped == set([("a.b","test_three")])
+        assert rev_outcome.failed == set([("a.b", "test_one")])
+
+        res = rev_outcome.get_outcome(("a.b", "test_one"))
+        assert res == 'F'
+
+        res = rev_outcome.get_outcome(("a.b", "test_three"))
+        assert res == 's'
+
+        res = rev_outcome.get_outcome(("a.b", "test_two"))
+        assert res == '.'
+
+
+    def test_GatherOutcome(self):
+        rev_outcome_foo = summary.RevOutcome(50000)
+        log = StringIO("""F a/b.py:test_one
+. a/b.py:test_two
+s a/b.py:test_three
+""")
+        
+        rev_outcome_foo.populate(log)
+
+        
+        rev_outcome_bar = summary.RevOutcome(50000)
+        log = StringIO(""". a/b.py:test_one
+. a/b.py:test_two
+s a/b.py:test_three
+""")
+        
+        rev_outcome_bar.populate(log)
+
+        d = {'foo': rev_outcome_foo,
+             'bar': rev_outcome_bar}
+
+        goutcome = summary.GatherOutcome(d)
+
+        
+        assert goutcome.failed == set([('foo', 'a.b', 'test_one')])
+        assert goutcome.failed == set([('foo', 'a.b', 'test_one')])
+
+        assert goutcome.skipped == set([('foo', 'a.b', 'test_three'),
+                                        ('bar', 'a.b', 'test_three'),
+                                        ])
+        assert goutcome.skipped == set([('foo', 'a.b', 'test_three'),
+                                        ('bar', 'a.b', 'test_three'),
+                                        ])
+
+        for prefix in ('foo', 'bar'):
+            for mod, testname in (("a.b", "test_one"), ("a.b", "test_two"),
+                                  ("a.b", "test_three")):
+
+                outcome1 = d[prefix].get_outcome((mod, testname))
+                outcome2 = goutcome.get_outcome((prefix, mod, testname))
+                assert outcome2 == outcome1
+
+        goutcome_top = summary.GatherOutcome({'sub': goutcome})
+
+        assert goutcome_top.failed == set([('sub', 'foo', 'a.b', 'test_one')])
+
+        res = goutcome_top.get_outcome(('sub', 'foo', 'a.b', 'test_one'))
+        assert res == 'F'

Added: pypy/build/bot2/slaveinfo.py
==============================================================================
--- (empty file)
+++ pypy/build/bot2/slaveinfo.py	Mon Sep 15 18:12:48 2008
@@ -0,0 +1,3 @@
+
+# Mapping from slave name to slave password
+passwords = {}



More information about the Pypy-commit mailing list