From de89c566f8ccae427ad2491fc6a10acc652c61ad Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 9 May 2013 14:23:15 +0200 Subject: [PATCH] Use Template::Toolkit to generate email messages Also, make the messages much shorter by not including build details. --- src/lib/Hydra/Plugin/EmailNotification.pm | 157 +++++++++------------- 1 file changed, 62 insertions(+), 95 deletions(-) diff --git a/src/lib/Hydra/Plugin/EmailNotification.pm b/src/lib/Hydra/Plugin/EmailNotification.pm index b41f9e47..36606fa3 100644 --- a/src/lib/Hydra/Plugin/EmailNotification.pm +++ b/src/lib/Hydra/Plugin/EmailNotification.pm @@ -9,17 +9,17 @@ use Email::Sender::Transport::SMTP; use Email::Simple; use Email::Simple::Creator; use Sys::Hostname::Long; -use Text::Table; use File::Slurp; +use Template; use Hydra::Helper::Nix; use Hydra::Helper::CatalystUtils; -sub statusDescription { - my ($buildstatus) = @_; +sub showStatus { + my ($build) = @_; my $status = "Failed"; - given ($buildstatus) { + given ($build->buildstatus) { when (0) { $status = "Success"; } when (1) { $status = "Failed with non-zero exit code"; } when (2) { $status = "Dependency failed"; } @@ -30,25 +30,52 @@ sub statusDescription { } +sub showJobName { + my ($build) = @_; + return $build->project->name . ":" . $build->jobset->name . ":" . $build->job->name; +} + + sub getPrevBuild { my ($self, $build) = @_; return $self->{db}->resultset('Builds')->search( { project => $build->project->name - , jobset => $build->jobset->name - , job => $build->job->name - , system => $build->system - , finished => 1 - , id => { '<', $build->id } - , -not => { buildstatus => { -in => [4, 3]} } + , jobset => $build->jobset->name + , job => $build->job->name + , system => $build->system + , finished => 1 + , id => { '<', $build->id } + , -not => { buildstatus => { -in => [4, 3]} } }, { order_by => ["id DESC"], rows => 1 } )->single; } -sub showJobName { - my ($build) = @_; - return $build->project->name . ":" . $build->jobset->name . ":" . $build->job->name; -} +my $template = < 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 { @@ -91,97 +118,37 @@ sub buildFinished { print STDERR "sending mail notification to ", $to, "\n"; my @builds = @{$addresses{$to}->{builds}}; - my $jobName = showJobName $build; + my $tt = Template->new({}); - my $status = statusDescription($build->buildstatus); + my $vars = + { build => $build, prevBuild => getPrevBuild($self, $build) + , dependents => [grep { $_->id != $build->id } @builds] + , baseurl => $self->{config}->{'base_uri'} || "http://localhost:3000" + , showJobName => \&showJobName, showStatus => \&showStatus + }; - my $baseurl = hostname_long; - my $sender = $self->{config}->{'notification_sender'} || - (($ENV{'USER'} || "hydra") . "@" . $baseurl); - - my $selfURI = $self->{config}->{'base_uri'} || "http://localhost:3000"; - - sub showTime { my ($x) = @_; return strftime('%Y-%m-%d %H:%M:%S', localtime($x)); } - - my $infoTable = Text::Table->new({ align => "left" }, \ " | ", { align => "left" }); - my @lines = ( - [ "Build ID:", $build->id ], - [ "Nix name:", $build->nixname ], - [ "Short description:", $build->description || '(not given)' ], - [ "Maintainer(s):", $build->maintainers ], - [ "System:", $build->system ], - [ "Derivation store path:", $build->drvpath ], - [ "Output store path:", join(", ", map { $_->path } $build->buildoutputs) ], - [ "Time added:", showTime $build->timestamp ], - ); - push @lines, ( - [ "Build started:", showTime $build->starttime ], - [ "Build finished:", showTime $build->stoptime ], - [ "Duration:", $build->stoptime - $build->starttime . "s" ], - ) if $build->starttime; - $infoTable->load(@lines); - - my $inputsTable = Text::Table->new( - { title => "Name", align => "left" }, \ " | ", - { title => "Type", align => "left" }, \ " | ", - { title => "Value", align => "left" }); - @lines = (); - foreach my $input ($build->inputs) { - my $type = $input->type; - push @lines, - [ $input->name - , $input->type - , ( $input->type eq "build" || $input->type eq "sysbuild") - ? $input->dependency->id - : ($input->type eq "string" || $input->type eq "boolean") - ? $input->value : ($input->uri . ':' . $input->revision) - ]; - } - $inputsTable->load(@lines); - - my $loglines = 50; - my $logtext = logContents($build->drvpath, $loglines); - $logtext = removeAsciiEscapes($logtext); - - my $prevBuild = getPrevBuild($self, $build); - - my $foo = "\nIn addition, the following jobs failed:\n"; - foreach my $b (@builds) { - $foo .= " " . showJobName($b) . " ($selfURI/build/" . $b->id . ")\n"; - } - - my $body = "Hi,\n" - . "\n" - . "This is to let you know that Hydra build " . $build->id - . " of job " . $jobName . " " . (defined $prevBuild ? "has changed from '" . statusDescription($prevBuild->buildstatus) . "' to '$status'" : "is '$status'" ) .".\n" - . $foo - . "\n" - . "Complete build information can be found on this page: " - . "$selfURI/build/" . $build->id . "\n" - . ($build->buildstatus != 0 ? "\nThe last $loglines lines of the build log are shown at the bottom of this email.\n" : "") - . "\n" - . "A summary of the build information follows:\n" - . "\n" - . $infoTable->body - . "\n" - . "The build inputs were:\n" - . "\n" - . $inputsTable->title - . $inputsTable->rule('-', '+') - . $inputsTable->body - . "\n" - . "Regards,\n\nThe Hydra build daemon.\n" - . ($build->buildstatus != 0 ? "\n---\n$logtext" : ""); + my $body; + $tt->process(\$template, $vars, \$body) + or die "failed to generate email from template"; # stripping trailing spaces from lines $body =~ s/[\ ]+$//gm; + print "$body\n"; + + 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 => "$status: Hydra job $jobName on " . $build->system . ", build " . $build->id, - 'X-Hydra-Instance' => $baseurl, + Subject => showStatus($build) . ": Hydra job " . showJobName($build) . " on " . $build->system, + 'X-Hydra-Instance' => $vars->{baseurl}, 'X-Hydra-Project' => $build->project->name, 'X-Hydra-Jobset' => $build->jobset->name, 'X-Hydra-Job' => $build->job->name,