diff --git a/src/lib/Hydra/Plugin/RunCommand.pm b/src/lib/Hydra/Plugin/RunCommand.pm index 91a3087a..b4abc4dd 100644 --- a/src/lib/Hydra/Plugin/RunCommand.pm +++ b/src/lib/Hydra/Plugin/RunCommand.pm @@ -38,6 +38,37 @@ sub eventMatches { return 0; } +sub fanoutToCommands { + my ($config, $event, $project, $jobset, $job) = @_; + + my @commands; + + my $cfg = $config->{runcommand}; + my @config = defined $cfg ? ref $cfg eq "ARRAY" ? @$cfg : ($cfg) : (); + + foreach my $conf (@config) { + my $matcher = $conf->{job} // "*:*:*"; + next unless eventMatches($conf, $event); + next unless configSectionMatches( + $matcher, + $project, + $jobset, + $job); + + if (!defined($conf->{command})) { + warn " section for '$matcher' lacks a 'command' option"; + next; + } + + push(@commands, { + matcher => $matcher, + command => $conf->{command}, + }) + } + + return \@commands; +} + sub makeJsonPayload { my ($event, $build) = @_; my $json = { @@ -100,28 +131,25 @@ sub buildFinished { my ($self, $build, $dependents) = @_; my $event = "buildFinished"; - my $cfg = $self->{config}->{runcommand}; - my @config = defined $cfg ? ref $cfg eq "ARRAY" ? @$cfg : ($cfg) : (); + my $commandsToRun = fanoutToCommands( + $self->{config}, + $event, + $build->get_column('project'), + $build->get_column('jobset'), + $build->get_column('job') + ); - my $tmp; + if (@$commandsToRun == 0) { + # No matching jobs, don't bother generating the JSON + return; + } - foreach my $conf (@config) { - next unless eventMatches($conf, $event); - next unless configSectionMatches( - $conf->{job} // "*:*:*", - $build->get_column('project'), - $build->get_column('jobset'), - $build->get_column('job')); - - my $command = $conf->{command} // die " section lacks a 'command' option"; - - unless (defined $tmp) { - $tmp = File::Temp->new(SUFFIX => '.json'); - print $tmp encode_json(makeJsonPayload($event, $build)) or die; - } - - $ENV{"HYDRA_JSON"} = $tmp->filename; + my $tmp = File::Temp->new(SUFFIX => '.json'); + print $tmp encode_json(makeJsonPayload($event, $build)) or die; + $ENV{"HYDRA_JSON"} = $tmp->filename; + foreach my $commandToRun (@{$commandsToRun}) { + my $command = $commandToRun->{command}; system("$command") == 0 or warn "notification command '$command' failed with exit status $?\n"; } diff --git a/t/plugins/RunCommand/matcher.t b/t/plugins/RunCommand/matcher.t index eaa9b83d..bc40ba77 100644 --- a/t/plugins/RunCommand/matcher.t +++ b/t/plugins/RunCommand/matcher.t @@ -134,4 +134,44 @@ subtest "eventMatches" => sub { ); }; +subtest "fanoutToCommands" => sub { + my $config = { + runcommand => [ + { + job => "", + command => "foo" + }, + { + job => "project:*:*", + command => "bar" + }, + { + job => "project:jobset:nomatch", + command => "baz" + } + ] + }; + + is( + Hydra::Plugin::RunCommand::fanoutToCommands( + $config, + "buildFinished", + "project", + "jobset", + "job" + ), + [ + { + matcher => "", + command => "foo" + }, + { + matcher => "project:*:*", + command => "bar" + } + ], + "fanoutToCommands returns a command per matching job" + ); +}; + done_testing;