hydra/src/lib/Hydra/Plugin/EmailNotification.pm
Shea Levy 93a14ccf32 Check if we want to send email for a build before iterating through its users
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-07-05 14:06:10 -04:00

137 lines
4.4 KiB
Perl

package Hydra::Plugin::EmailNotification;
use strict;
use parent 'Hydra::Plugin';
use POSIX qw(strftime);
use Email::Sender::Simple qw(sendmail);
use Email::Sender::Transport::SMTP;
use Email::Simple;
use Email::Simple::Creator;
use Sys::Hostname::Long;
use File::Slurp;
use Template;
use Hydra::Helper::Nix;
use Hydra::Helper::CatalystUtils;
my $template = <<EOF;
Hi,
The status of Hydra job [% showJobName(build) %] [% IF showSystem %](on [% build.system %]) [% END %][% IF prevBuild && build.buildstatus != prevBuild.buildstatus %]has changed from "[% showStatus(prevBuild) %]" to "[% showStatus(build) %]"[% ELSE %]is "[% showStatus(build) %]"[% END %]. For details, see
[% baseurl %]/build/[% build.id %]
[% IF dependents.size > 0 -%]
The following dependent jobs also failed:
[% FOREACH b IN dependents -%]
* [% showJobName(b) %] ([% baseurl %]/build/[% b.id %])
[% END -%]
[% END -%]
[% IF build.buildstatus == 0 -%]
Yay!
[% ELSE -%]
Go forth and fix [% IF dependents.size == 0 -%]it[% ELSE %]them[% END %].
[% END -%]
Regards,
The Hydra build daemon.
EOF
sub buildFinished {
my ($self, $build, $dependents) = @_;
die unless $build->finished;
# Figure out to whom to send notification for each build. For
# each email address, we send one aggregate email listing only the
# relevant builds for that address.
my %addresses;
foreach my $b ($build, @{$dependents}) {
my $prevBuild = getPreviousBuild($b);
# Do we want to send mail for this build?
unless ($ENV{'HYDRA_FORCE_SEND_MAIL'}) {
next unless $b->jobset->enableemail;
# If build is cancelled or aborted, do not send email.
next if $b->buildstatus == 4 || $b->buildstatus == 3;
# If there is a previous (that is not cancelled or aborted) build
# with same buildstatus, do not send email.
next if defined $prevBuild && ($b->buildstatus == $prevBuild->buildstatus);
}
my $to = $b->jobset->emailoverride ne "" ? $b->jobset->emailoverride : $b->maintainers;
foreach my $address (split ",", $to) {
$address = trim $address;
$addresses{$address} //= { builds => [] };
push @{$addresses{$address}->{builds}}, $b;
}
}
# Send an email to each interested address.
# !!! should use the Template Toolkit here.
for my $to (keys %addresses) {
print STDERR "sending mail notification to ", $to, "\n";
my @builds = @{$addresses{$to}->{builds}};
my $tt = Template->new({});
my $vars =
{ build => $build, prevBuild => getPreviousBuild($build)
, dependents => [grep { $_->id != $build->id } @builds]
, baseurl => $self->{config}->{'base_uri'} || "http://localhost:3000"
, showJobName => \&showJobName, showStatus => \&showStatus
, showSystem => index($build->job->name, $build->system) == -1
};
my $body;
$tt->process(\$template, $vars, \$body)
or die "failed to generate email from template";
# stripping trailing spaces from lines
$body =~ s/[\ ]+$//gm;
my $sender = $self->{config}->{'notification_sender'} ||
(($ENV{'USER'} || "hydra") . "@" . hostname_long);
#my $loglines = 50;
#my $logtext = logContents($build->drvpath, $loglines);
#$logtext = removeAsciiEscapes($logtext);
my $email = Email::Simple->create(
header => [
To => $to,
From => "Hydra Build Daemon <$sender>",
Subject =>
showStatus($build) . ": Hydra job " . showJobName($build)
. ($vars->{showSystem} ? " on " . $build->system : "")
. (scalar @{$vars->{dependents}} > 0 ? " (and " . scalar @{$vars->{dependents}} . " others)" : ""),
'X-Hydra-Instance' => $vars->{baseurl},
'X-Hydra-Project' => $build->project->name,
'X-Hydra-Jobset' => $build->jobset->name,
'X-Hydra-Job' => $build->job->name,
'X-Hydra-System' => $build->system
],
body => "",
);
$email->body_set($body);
if (defined $ENV{'HYDRA_MAIL_SINK'}) {
# For testing, redirect all mail to a file.
write_file($ENV{'HYDRA_MAIL_SINK'}, { append => 1 }, $email->as_string . "\n");
} else {
sendmail($email);
}
}
}
1;