diff --git a/src/lib/Hydra/Plugin/SlackNotification.pm b/src/lib/Hydra/Plugin/SlackNotification.pm index 96933c51..a09fbe03 100644 --- a/src/lib/Hydra/Plugin/SlackNotification.pm +++ b/src/lib/Hydra/Plugin/SlackNotification.pm @@ -7,6 +7,53 @@ use LWP::UserAgent; use Hydra::Helper::CatalystUtils; use JSON; +=head1 NAME + +SlackNotification - hydra-notify plugin for sending Slack notifications about +build results + +=head1 DESCRIPTION + +This plugin reports build statuses to various Slack channels. One can configure +which builds are reported to which channels, and whether reports should be on +state change (regressions and improvements), or for each build. + +=head1 CONFIGURATION + +The module is configured using the C block in Hydra's config file. There +can be multiple such blocks in the config file, each configuring different (or +even the same) set of builds and how they report to Slack channels. + +The following entries are recognized in the C block: + +=over 4 + +=item jobs + +A pattern for job names. All builds whose job name matches this pattern will +emit a message to the designated Slack channel (see C). The pattern will +match the whole name, thus leaving this field empty will result in no +notifications being sent. To match on all builds, use C<.*>. + +=item url + +The URL to a L. + +Slack administrators have to prepare one incoming webhook for each channel. This +URL should be treated as secret, as anyone knowing the URL could post a message +to the Slack workspace (or more precisely, the channel behind it). + +=item force + +(Optional) An I indicating whether to report on every build or only on +changes in the status. If not provided, defaults to 0, that is, sending reports +only when build status changes from success to failure, and vice-versa. Any +other value results in reporting on every build. + +=back + +=cut + sub isEnabled { my ($self) = @_; return defined $self->{config}->{slack}; @@ -40,20 +87,32 @@ sub buildFinished { # we send one aggregate message. my %channels; foreach my $b ($build, @{$dependents}) { - my $prevBuild = getPreviousBuild($b); my $jobName = showJobName $b; + my $buildStatus = $b->buildstatus; + my $cancelledOrAborted = $buildStatus == 4 || $buildStatus == 3; + + my $prevBuild = getPreviousBuild($b); + my $sameAsPrevious = defined $prevBuild && ($buildStatus == $prevBuild->buildstatus); + my $prevBuildStatus = (defined $prevBuild) ? $prevBuild->buildstatus : -1; + my $prevBuildId = (defined $prevBuild) ? $prevBuild->id : -1; + + print STDERR "SlackNotification_Debug job name $jobName status $buildStatus (previous: $prevBuildStatus from $prevBuildId)\n"; foreach my $channel (@config) { - my $force = $channel->{force}; next unless $jobName =~ /^$channel->{jobs}$/; - # If build is cancelled or aborted, do not send email. - next if ! $force && ($b->buildstatus == 4 || $b->buildstatus == 3); + my $force = $channel->{force}; + + print STDERR "SlackNotification_Debug found match with '$channel->{jobs}' with force=$force\n"; + + # If build is cancelled or aborted, do not send Slack notification. + next if ! $force && $cancelledOrAborted; # If there is a previous (that is not cancelled or aborted) build - # with same buildstatus, do not send email. - next if ! $force && defined $prevBuild && ($b->buildstatus == $prevBuild->buildstatus); + # with same buildstatus, do not send Slack notification. + next if ! $force && $sameAsPrevious; + print STDERR "SlackNotification_Debug adding $jobName to the report list\n"; $channels{$channel->{url}} //= { channel => $channel, builds => [] }; push @{$channels{$channel->{url}}->{builds}}, $b; } @@ -93,6 +152,8 @@ sub buildFinished { $text .= join(" or ", scalar @x > 1 ? join(", ", @x[0..scalar @x - 2]) : (), $x[-1]); } + print STDERR "SlackNotification_Debug POSTing to url ending with: ${\substr $url, -8}\n"; + my $msg = { attachments => [{ fallback => "Job " . showJobName($build) . " build number " . $build->id . ": " . showStatus($build),