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 = ''