Merge lp:~jml/launchpad/better-subunit-attachment into lp:launchpad

Proposed by Jonathan Lange
Status: Merged
Approved by: Brad Crittenden
Approved revision: no longer in the source branch.
Merged at revision: not available
Proposed branch: lp:~jml/launchpad/better-subunit-attachment
Merge into: lp:launchpad
Diff against target: 101 lines (+51/-14)
1 file modified
lib/devscripts/ec2test/ec2test-remote.py (+51/-14)
To merge this branch: bzr merge lp:~jml/launchpad/better-subunit-attachment
Reviewer Review Type Date Requested Status
Brad Crittenden (community) code Approve
Review via email: mp+23786@code.launchpad.net

Description of the change

This patch changes ec2 test and ec2 land so that they compress the subunit log before attaching it to the summary email. This works around bug 505078 in subunit by hiding the easily-mangleable newlines in a compressed binary file.

To do this, I extracted a send_email method. I stopped using bzrlib's convenience functions for sending mail, since they are all about text.

I've tested this by deliberately breaking a test, running it through ec2 and looking through the email it sent. It all works, and the attachment is 110k rather than 2M, which is nice.

jml

To post a comment you must log in.
Revision history for this message
Brad Crittenden (bac) wrote :

The branch looks good Jono. The only style issue I saw was your lack of punctuation on code comments. Please end them with full stops.

I look forward to using ec2 test to see the new output.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/devscripts/ec2test/ec2test-remote.py'
2--- lib/devscripts/ec2test/ec2test-remote.py 2010-04-13 19:36:49 +0000
3+++ lib/devscripts/ec2test/ec2test-remote.py 2010-04-21 11:19:28 +0000
4@@ -7,11 +7,15 @@
5 __metatype__ = type
6
7 import datetime
8+from email import MIMEMultipart, MIMEText
9+from email.mime.application import MIMEApplication
10+import gzip
11 import optparse
12 import os
13 import pickle
14 import subprocess
15 import sys
16+import tempfile
17 import textwrap
18 import time
19 import traceback
20@@ -169,7 +173,7 @@
21
22 self._gather_test_output(popen.stdout, summary_file, out_file)
23
24- # Grab the testrunner exit status
25+ # Grab the testrunner exit status.
26 result = popen.wait()
27
28 if self.pqm_message is not None:
29@@ -193,26 +197,59 @@
30 # It probably isn't safe to close the log files ourselves,
31 # since someone else might try to write to them later.
32 try:
33- summary_file.close()
34 if self.email is not None:
35- subject = 'Test results: %s' % (
36- result and 'FAILURE' or 'SUCCESS')
37- summary_file = open(self.logger.summary_filename, 'r')
38- out_file = open(self.logger.out_filename, 'r')
39- bzrlib.email_message.EmailMessage.send(
40- config, config.username(), self.email,
41- subject, summary_file.read(),
42- attachment=out_file.read(),
43- attachment_filename='%s.log' % self.get_nick(),
44- attachment_mime_subtype='subunit')
45- summary_file.close()
46+ self.send_email(
47+ result, self.logger.summary_filename,
48+ self.logger.out_filename, config)
49 finally:
50+ summary_file.close()
51 # we do this at the end because this is a trigger to
52 # ec2test.py back at home that it is OK to kill the process
53 # and take control itself, if it wants to.
54- out_file.close()
55 self.logger.close_logs()
56
57+ def send_email(self, result, summary_filename, out_filename, config):
58+ """Send an email summarizing the test results.
59+
60+ :param result: True for pass, False for failure.
61+ :param summary_filename: The path to the file where the summary
62+ information lives. This will be the body of the email.
63+ :param out_filename: The path to the file where the full output
64+ lives. This will be zipped and attached.
65+ :param config: A Bazaar configuration object with SMTP details.
66+ """
67+ message = MIMEMultipart.MIMEMultipart()
68+ message['To'] = ', '.join(self.email)
69+ message['From'] = config.username()
70+ subject = 'Test results: %s' % (result and 'FAILURE' or 'SUCCESS')
71+ message['Subject'] = subject
72+
73+ # Make the body.
74+ try:
75+ summary = open(summary_filename, 'r').read()
76+ finally:
77+ summary.close()
78+ body = MIMEText.MIMEText(summary, 'plain', 'utf8')
79+ body['Content-Disposition'] = 'inline'
80+ message.attach(body)
81+
82+ # gzip up the full log.
83+ fd, path = tempfile.mkstemp()
84+ os.close(fd)
85+ gz = gzip.open(path, 'wb')
86+ full_log = open(out_filename, 'rb')
87+ gz.writelines(full_log)
88+ gz.close()
89+
90+ # Attach the gzipped log.
91+ zipped_log = MIMEApplication(open(path, 'rb').read(), 'x-gzip')
92+ zipped_log.add_header(
93+ 'Content-Disposition', 'attachment',
94+ filename='%s.log.gz' % self.get_nick())
95+ message.attach(zipped_log)
96+
97+ bzrlib.smtp_connection.SMTPConnection(config).send_email(message)
98+
99 def get_nick(self):
100 """Return the nick name of the branch that we are testing."""
101 return self.public_branch.strip('/').split('/')[-1]