Commits

dready  committed 58879c2

* new "email_build_summary" management command
* "schedule" command takes an optional suffix useful for distinguishing multiple daily builds

  • Participants
  • Parent commits 9eafa58

Comments (0)

Files changed (4)

File src/factory/mail.py

 
 
 DEFAULT_SUBJECT_TEMPLATE = "%(build)s Build Results (%(status)s)"
+DEFAULT_BUILD_SUMMARY_SUBJECT = "Daily Build Summary"
 
 def send_build_email(instance, **kwargs):
     if not instance.executed:
                                      text_content,
                                      settings.SERVER_EMAIL,
                                      recipients)
-        msg.attach_alternative(format_html(text_content), 'text/html')
+        msg.attach_alternative(format_html(text_content, hilite=True), 'text/html')
     else:
         msg = EmailMessage(subject,
                            text_content,
         logging.getLogger(__name__).exception("unable to send build email")
 
 
+def send_summary_email(builds, recipients=None, subject=None):
+    # render email content
+    if not recipients:
+        recipients = map(lambda x: x[1], settings.ADMINS)
 
+    build_dicts = []
+    for b in builds:
+        build_dicts.append(dict(
+            name=b.name,
+            status=("success" if b.success else "FAILED") if b.executed else "not executed",
+            time=b.execution_time,
+        ))
 
-def format_html(text):
+    ctx = dict(
+        builds=build_dicts,
+    )
+    if not subject:
+        subject = getattr(settings, 'FF_BUILD_SUMMARY_EMAIL_SUBJECT', DEFAULT_BUILD_SUMMARY_SUBJECT)
+
+    text_content = render_to_string("factory/build_summary_mail.txt", ctx)
+    if getattr(settings, 'FF_BUILD_SUMMARY_EMAIL_HTML', True):
+        msg = EmailMultiAlternatives(subject,
+                                     text_content,
+                                     settings.SERVER_EMAIL,
+                                     recipients)
+        msg.attach_alternative(format_html(text_content), 'text/html')
+    else:
+        msg = EmailMessage(subject,
+                           text_content,
+                           settings.SERVER_EMAIL,
+                           recipients)
+
+    try:
+        msg.send()
+    except:
+        # in production, if sending this email fails, django is unlikely to send the error mail.
+        # in debug, we can't really tell if this came from loaddata (fixtures)..
+        # so we just ignore the error
+        logging.getLogger(__name__).exception("unable to send summary email")
+
+
+def format_html(text, hilite=False):
     # TODO: implement our replacement for markdown.extensions.codehilite that passes ``noclasses`` to ``HtmlFormatter``
     #       so that the output code will use inline styles, for better compatibility with mail clients esp. Gmail
-    html = markdown.markdown(text, ['codehilite'])
-    css = HtmlFormatter().get_style_defs('.codehilite')
+    md_extensions = ['tables']
+    css = ''
+    if hilite:
+        md_extensions.append('codehilite')
+        css = HtmlFormatter().get_style_defs('.codehilite')
+
+    html = markdown.markdown(text, md_extensions)
     return """<html>
     <head><style>%s</style></head>
     <body>%s</body>

File src/factory/management/commands/email_build_summary.py

+"""
+email_build_summary management command.
+"""
+
+from django.core.management.base import BaseCommand, CommandError
+from factory.models import FabfileRecipe, Build
+from factory.mail import send_summary_email
+from datetime import datetime, timedelta
+from optparse import make_option
+
+
+
+class Command(BaseCommand):
+    args = '[date]'
+    help = 'send an email with a summary of recent builds'
+
+    def handle(self, *recipe_slugs, **options):
+        builds = Build.objects \
+                    .filter(created_datetime__gt=datetime.now() - timedelta(days=1)) \
+                    .order_by('created_datetime')
+        send_summary_email(builds)

File src/factory/management/commands/schedule.py

 """
-Migrate management command.
+schedule management command.
 """
 
 from django.core.management.base import BaseCommand, CommandError
                 default='',
                 help='revision to check out')
     )
+    make_option('-s', '--suffix',
+                dest='suffix',
+                default='',
+                help='suffix to add to build name')
+    )
 
 
     def handle(self, *recipe_slugs, **options):
             recipes = qs.filter(schedule=True)
 
         for recipe in recipes:
-            name = "%s %s" % (recipe.name, datetime.now().strftime("%d/%m/%Y"))
+            name = "%s %s%s" % (recipe.name, datetime.now().strftime("%d/%m/%Y"), options.suffix)
             extra_fields = {}
             if options['branch']:
                 extra_fields['branch'] = options['branch']

File src/project/templates/factory/build_summary_mail.txt

+Daily Fabric Factory Build Summary
+==================================
+
+Recipe                 | Execution Status | Build Time
+---------------------- |:----------------:| -------------
+{% for b in builds %}{{ b.name|stringformat:"-22.22s" }} | {{ b.status|stringformat:"16s" }} | {{ b.time }}
+{% endfor %}
+
+{% url build_list_all %}