lib/autobuild/reporting.rb in autobuild-0.5.1 vs lib/autobuild/reporting.rb in autobuild-0.6
- old
+ new
@@ -2,57 +2,76 @@
require 'rmail/serialize'
require 'net/smtp'
require 'socket'
require 'etc'
+require 'autobuild/config'
require 'autobuild/exceptions'
module Autobuild
- class Reporting
+ ## The reporting module provides the framework
+ # to run commands in autobuild and report errors
+ # to the user
+ #
+ # It does not use a logging framework like Log4r, but it should ;-)
+ module Reporting
@@reporters = Array.new
+ ## Run a block and report known exception
+ # If an exception is fatal, the program is terminated using exit()
def self.report
begin
yield
rescue Autobuild::Exception => e
raise unless e.kind_of?(Autobuild::Exception)
error(e)
exit(1) if e.fatal?
end
end
+ ## Reports a successful build to the user
def self.success
@@reporters.each do |rep| rep.success end
end
+ ## Reports that the build failed to the user
def self.error(error)
@@reporters.each do |rep| rep.error(error) end
end
+ ## Add a new reporter
def self.<<(reporter)
@@reporters << reporter
end
+ def self.each_reporter(&iter)
+ @@reporters.each(&iter)
+ end
+
+ ## Iterate on all log files
def self.each_log(&iter)
- Dir.glob("#{$LOGDIR}/*.log", &iter)
+ Dir.glob("#{Autobuild.logdir}/*.log", &iter)
end
end
+ ## Base class for reporters
class Reporter
def error(error); end
def success; end
end
+ ## Display using stdout
class StdoutReporter < Reporter
def error(error)
puts "Build failed: #{error}"
end
def success
puts "Build finished successfully at #{Time.now}"
end
end
+ ## Report by mail
class MailReporter < Reporter
def default_mail
Etc::endpwent
uname = while (pwent = Etc::getpwent)
break (pwent.name) if pwent.uid == Process.uid
@@ -60,33 +79,40 @@
raise "FATAL: cannot find a user with uid=#{Process.uid}" unless uname
"#{pwent.name}@#{Socket.gethostname}"
end
+ attr_reader :from_email, :to_email, :smtp_hostname, :smtp_port, :subject, :only_errors
def initialize(config)
- @from = (config[:from] || default_mail)
- @to = (config[:to] || default_mail)
- @smtp = (config[:smtp] || "localhost" )
- @port = Integer(config[:port] || Socket.getservbyname('smtp'))
+ @from_email = (config[:from] || default_mail)
+ @to_email = (config[:to] || default_mail)
+ @subject = (config[:subject] || "Build %result% on #{Socket.gethostname} at %time%")
+ @only_errors = config[:only_errors]
+ @smtp_hostname = (config[:smtp] || "localhost" )
+ @smtp_port = Integer(config[:port] || Socket.getservbyname('smtp'))
end
def error(error)
if error.mail?
- send_mail("Build failed", error.to_s)
+ send_mail("failed", error.to_s)
end
end
def success
- send_mail("Build success", "finished successfully at #{Time.now}")
+ unless only_errors
+ send_mail("success")
+ end
end
- def send_mail(subject, body)
+ def send_mail(result, body = "")
mail = RMail::Message.new
mail.header.date = Time.now
- mail.header.from = @from
- mail.header.to = @to
- mail.header.subject = subject
+ mail.header.from = from_email
+ mail.header.subject = subject.
+ gsub('%result%', result).
+ gsub('%time%', Time.now.to_s).
+ gsub('%hostname%', Socket.gethostname)
part = RMail::Message.new
part.header.set('Content-Type', 'text/plain')
part.body = body
mail.add_part(part)
@@ -94,24 +120,27 @@
# Attach log files
Reporting.each_log do |file|
mail.add_file(file)
end
- # Send the mail
- smtp = Net::SMTP.new(@smtp, @port)
- smtp.start {
- smtp.send_mail RMail::Serialize.write('', mail), @from, @to
- }
+ # Send the mails
+ smtp = Net::SMTP.new(smtp_hostname, smtp_port)
+ smtp.start {
+ to_email.each do |email|
+ mail.header.to = email
+ smtp.send_mail RMail::Serialize.write('', mail), from_email, email
+ end
+ }
# Notify the sending
- puts "Sent notification mail to #{@to} with source #{@from}"
-
+ puts "Sent notification mail to #{to_email} with source #{from_email}"
end
end
end
module RMail
class Message
+ ## Attachs a file to a message
def add_file(path, content_type='text/plain')
part = RMail::Message.new
part.header.set('Content-Type', content_type)
part.header.set('Content-Disposition', 'attachment', 'filename' => File.basename(path))
part.body = ''