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
=== modified file 'lib/devscripts/ec2test/ec2test-remote.py'
--- lib/devscripts/ec2test/ec2test-remote.py 2010-04-13 19:36:49 +0000
+++ lib/devscripts/ec2test/ec2test-remote.py 2010-04-21 11:19:28 +0000
@@ -7,11 +7,15 @@
7__metatype__ = type7__metatype__ = type
88
9import datetime9import datetime
10from email import MIMEMultipart, MIMEText
11from email.mime.application import MIMEApplication
12import gzip
10import optparse13import optparse
11import os14import os
12import pickle15import pickle
13import subprocess16import subprocess
14import sys17import sys
18import tempfile
15import textwrap19import textwrap
16import time20import time
17import traceback21import traceback
@@ -169,7 +173,7 @@
169173
170 self._gather_test_output(popen.stdout, summary_file, out_file)174 self._gather_test_output(popen.stdout, summary_file, out_file)
171175
172 # Grab the testrunner exit status176 # Grab the testrunner exit status.
173 result = popen.wait()177 result = popen.wait()
174178
175 if self.pqm_message is not None:179 if self.pqm_message is not None:
@@ -193,26 +197,59 @@
193 # It probably isn't safe to close the log files ourselves,197 # It probably isn't safe to close the log files ourselves,
194 # since someone else might try to write to them later.198 # since someone else might try to write to them later.
195 try:199 try:
196 summary_file.close()
197 if self.email is not None:200 if self.email is not None:
198 subject = 'Test results: %s' % (201 self.send_email(
199 result and 'FAILURE' or 'SUCCESS')202 result, self.logger.summary_filename,
200 summary_file = open(self.logger.summary_filename, 'r')203 self.logger.out_filename, config)
201 out_file = open(self.logger.out_filename, 'r')
202 bzrlib.email_message.EmailMessage.send(
203 config, config.username(), self.email,
204 subject, summary_file.read(),
205 attachment=out_file.read(),
206 attachment_filename='%s.log' % self.get_nick(),
207 attachment_mime_subtype='subunit')
208 summary_file.close()
209 finally:204 finally:
205 summary_file.close()
210 # we do this at the end because this is a trigger to206 # we do this at the end because this is a trigger to
211 # ec2test.py back at home that it is OK to kill the process207 # ec2test.py back at home that it is OK to kill the process
212 # and take control itself, if it wants to.208 # and take control itself, if it wants to.
213 out_file.close()
214 self.logger.close_logs()209 self.logger.close_logs()
215210
211 def send_email(self, result, summary_filename, out_filename, config):
212 """Send an email summarizing the test results.
213
214 :param result: True for pass, False for failure.
215 :param summary_filename: The path to the file where the summary
216 information lives. This will be the body of the email.
217 :param out_filename: The path to the file where the full output
218 lives. This will be zipped and attached.
219 :param config: A Bazaar configuration object with SMTP details.
220 """
221 message = MIMEMultipart.MIMEMultipart()
222 message['To'] = ', '.join(self.email)
223 message['From'] = config.username()
224 subject = 'Test results: %s' % (result and 'FAILURE' or 'SUCCESS')
225 message['Subject'] = subject
226
227 # Make the body.
228 try:
229 summary = open(summary_filename, 'r').read()
230 finally:
231 summary.close()
232 body = MIMEText.MIMEText(summary, 'plain', 'utf8')
233 body['Content-Disposition'] = 'inline'
234 message.attach(body)
235
236 # gzip up the full log.
237 fd, path = tempfile.mkstemp()
238 os.close(fd)
239 gz = gzip.open(path, 'wb')
240 full_log = open(out_filename, 'rb')
241 gz.writelines(full_log)
242 gz.close()
243
244 # Attach the gzipped log.
245 zipped_log = MIMEApplication(open(path, 'rb').read(), 'x-gzip')
246 zipped_log.add_header(
247 'Content-Disposition', 'attachment',
248 filename='%s.log.gz' % self.get_nick())
249 message.attach(zipped_log)
250
251 bzrlib.smtp_connection.SMTPConnection(config).send_email(message)
252
216 def get_nick(self):253 def get_nick(self):
217 """Return the nick name of the branch that we are testing."""254 """Return the nick name of the branch that we are testing."""
218 return self.public_branch.strip('/').split('/')[-1]255 return self.public_branch.strip('/').split('/')[-1]