package Hydra::Plugin::EmailNotification; use utf8; use strict; use warnings; use parent 'Hydra::Plugin'; use POSIX qw(strftime); use Template; use Hydra::Helper::Nix; use Hydra::Helper::CatalystUtils; use Hydra::Helper::Email; sub isEnabled { my ($self) = @_; return ($self->{config}->{email_notification} // 0) == 1; } my $template = < 0 -%] The following dependent jobs also failed: [% FOREACH b IN dependents -%] * [% showJobName(b) %] ([% baseurl %]/build/[% b.id %]) [% END -%] [% END -%] [% IF nrCommits > 0 && authorList -%] This may be due to [% IF nrCommits > 1 -%][% nrCommits %] commits[%- ELSE -%]a commit[%- END -%] by [% authorList %]. [% 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, $topbuild, $dependents) = @_; die unless $topbuild->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 $build ($topbuild, @{$dependents}) { my $prevBuild = getPreviousBuild($build); # Do we want to send mail for this build? unless ($ENV{'HYDRA_FORCE_SEND_MAIL'}) { next unless $build->jobset->enableemail; # If build is cancelled or aborted, do not send email. next if $build->buildstatus == 4 || $build->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 && ($build->buildstatus == $prevBuild->buildstatus); } my $to = $build->jobset->emailoverride ne "" ? $build->jobset->emailoverride : $build->maintainers; foreach my $address (split ",", ($to // "")) { $address = trim $address; $addresses{$address} //= { builds => [] }; push @{$addresses{$address}->{builds}}, $build; } } my ($authors, $nrCommits, $emailable_authors) = getResponsibleAuthors($topbuild, $self->{plugins}); my $authorList; my $prevBuild = getPreviousBuild($topbuild); if (scalar keys %{$authors} > 0 && ((!defined $prevBuild) || ($topbuild->buildstatus != $prevBuild->buildstatus))) { my @x = map { "$_ <$authors->{$_}>" } (sort keys %{$authors}); $authorList = join(" or ", scalar @x > 1 ? join(", ", @x[0..scalar @x - 2]): (), $x[-1]); $addresses{$_} = { builds => [ $topbuild ] } foreach (@{$emailable_authors}); } # Send an email to each interested address. 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 => $topbuild, prevBuild => getPreviousBuild($topbuild) , dependents => [grep { $_->id != $topbuild->id } @builds] , baseurl => getBaseUrl($self->{config}) , showJobName => \&showJobName, showStatus => \&showStatus , showSystem => index($topbuild->get_column('job'), $topbuild->system) == -1 , nrCommits => $nrCommits , authorList => $authorList }; my $body; $tt->process(\$template, $vars, \$body) or die "failed to generate email from template"; # stripping trailing spaces from lines $body =~ s/[\ ]+$//gm; my $subject = showStatus($topbuild) . ": Hydra job " . showJobName($topbuild) . ($vars->{showSystem} ? " on " . $topbuild->system : "") . (scalar @{$vars->{dependents}} > 0 ? " (and " . scalar @{$vars->{dependents}} . " others)" : ""); sendEmail( $self->{config}, $to, $subject, $body, [ 'X-Hydra-Project' => $topbuild->jobset->get_column('project'), , 'X-Hydra-Jobset' => $topbuild->jobset->get_column('name'), , 'X-Hydra-Job' => $topbuild->get_column('job'), , 'X-Hydra-System' => $topbuild->system ]); } } 1;