diff options
author | Andrew Gerrand <adg@golang.org> | 2011-05-30 11:27:31 +1000 |
---|---|---|
committer | Andrew Gerrand <adg@golang.org> | 2011-05-30 11:27:31 +1000 |
commit | 4afd973ff54020fbcef476ddaf71f3ec381df2c9 (patch) | |
tree | 937177d899a15568ad6abf316edb727a9a2b14d5 /misc | |
parent | 452ea669f861041463a75962fe1028ffd65ee41c (diff) | |
download | go-4afd973ff54020fbcef476ddaf71f3ec381df2c9.tar.gz |
dashboard: send notification emails when the build breaks
R=bradfitz, rsc
CC=golang-dev
http://codereview.appspot.com/4530061
Diffstat (limited to 'misc')
-rw-r--r-- | misc/dashboard/godashboard/app.yaml | 2 | ||||
-rw-r--r-- | misc/dashboard/godashboard/gobuild.py | 91 |
2 files changed, 86 insertions, 7 deletions
diff --git a/misc/dashboard/godashboard/app.yaml b/misc/dashboard/godashboard/app.yaml index 455da57f0..4fd05f259 100644 --- a/misc/dashboard/godashboard/app.yaml +++ b/misc/dashboard/godashboard/app.yaml @@ -1,5 +1,5 @@ application: godashboard -version: 6 +version: 7 runtime: python api_version: 1 diff --git a/misc/dashboard/godashboard/gobuild.py b/misc/dashboard/godashboard/gobuild.py index baddb0e9b..ee700c73b 100644 --- a/misc/dashboard/godashboard/gobuild.py +++ b/misc/dashboard/godashboard/gobuild.py @@ -12,15 +12,12 @@ from google.appengine.ext import db from google.appengine.ext import webapp from google.appengine.ext.webapp import template from google.appengine.ext.webapp.util import run_wsgi_app -import binascii import datetime import hashlib import hmac import logging import os import re -import struct -import time import bz2 # local imports @@ -346,16 +343,98 @@ class Build(webapp.RequestHandler): key = 'todo-%s' % builder memcache.delete(key) - # TODO: Send mail for build breakage. + c = getBrokenCommit(node, builder) + if c is not None and not c.fail_notification_sent: + notifyBroken(c, builder) self.response.set_status(200) -def failed(c, builder): + +def getBrokenCommit(node, builder): + """ + getBrokenCommit returns a Commit that breaks the build. + The Commit will be either the one specified by node or the one after. + """ + + # Squelch mail if already fixed. + head = firstResult(builder) + if broken(head, builder) == False: + return + + # Get current node and node before, after. + cur = nodeByHash(node) + if cur is None: + return + before = nodeBefore(cur) + after = nodeAfter(cur) + + if broken(before, builder) == False and broken(cur, builder): + return cur + if broken(cur, builder) == False and broken(after, builder): + return after + + return + +def firstResult(builder): + q = Commit.all().order('-__key__').limit(20) + for c in q: + for i, b in enumerate(c.builds): + p = b.split('`', 1) + if p[0] == builder: + return c + return None + +def nodeBefore(c): + return nodeByHash(c.parentnode) + +def nodeAfter(c): + return Commit.all().filter('parenthash', c.node).get() + +def notifyBroken(c, builder): + def send(): + n = Commit.get_by_key_name('%08x-%s' % (c.num, c.node)) + if n.fail_notification_sent: + return False + n.fail_notification_sent = True + return n.put() + if not db.run_in_transaction(send): + return + + subject = const.mail_fail_subject % (builder, c.desc.split('\n')[0]) + path = os.path.join(os.path.dirname(__file__), 'fail-notify.txt') + body = template.render(path, { + "builder": builder, + "node": c.node, + "user": c.user, + "desc": c.desc, + "loghash": logHash(c, builder) + }) + mail.send_mail( + sender=const.mail_from, + to=const.mail_fail_to, + subject=subject, + body=body + ) + +def logHash(c, builder): + for i, b in enumerate(c.builds): + p = b.split('`', 1) + if p[0] == builder: + return p[1] + return "" + +def broken(c, builder): + """ + broken returns True if commit c breaks the build for the specified builder, + False if it is a good build, and None if no results exist for this builder. + """ + if c is None: + return None for i, b in enumerate(c.builds): p = b.split('`', 1) if p[0] == builder: return len(p[1]) > 0 - return False + return None def node(num): q = Commit.all() |