Merge remote-tracking branch 'upstream/who-broke-builds' into upstream-master
Include information about who changed the build status in notification emails, and enable optional per-input notification of said committers. Conflicts due to two branches modifying the database schema. Signed-off-by: Shea Levy <shea@shealevy.com> Conflicts: src/lib/Hydra/Schema/Jobsets.pm src/sql/upgrade-23.sql
This commit is contained in:
@ -229,7 +229,11 @@ sub updateJobset {
|
||||
error($c, "Invalid input name ‘$name’.") unless $name =~ /^[[:alpha:]][\w-]*$/;
|
||||
error($c, "Invalid input type ‘$type’.") unless defined $c->stash->{inputTypes}->{$type};
|
||||
|
||||
my $input = $jobset->jobsetinputs->create({ name => $name, type => $type });
|
||||
my $input = $jobset->jobsetinputs->create({
|
||||
name => $name,
|
||||
type => $type,
|
||||
emailresponsible => defined $c->stash->{params}->{"input-$baseName-emailresponsible"} ? 1 : 0
|
||||
});
|
||||
|
||||
# Set the values for this input.
|
||||
my @values = ref($values) eq 'ARRAY' ? @{$values} : ($values);
|
||||
|
@ -148,7 +148,7 @@ sub fetchInputSystemBuild {
|
||||
}
|
||||
|
||||
sub fetchInput {
|
||||
my ($plugins, $db, $project, $jobset, $name, $type, $value) = @_;
|
||||
my ($plugins, $db, $project, $jobset, $name, $type, $value, $emailresponsible) = @_;
|
||||
my @inputs;
|
||||
|
||||
if ($type eq "build") {
|
||||
@ -177,7 +177,10 @@ sub fetchInput {
|
||||
die "input `$name' has unknown type `$type'." unless $found;
|
||||
}
|
||||
|
||||
$_->{type} = $type foreach @inputs;
|
||||
foreach my $input (@inputs) {
|
||||
$input->{type} = $type;
|
||||
$input->{emailresponsible} = $emailresponsible;
|
||||
}
|
||||
|
||||
return @inputs;
|
||||
}
|
||||
@ -542,6 +545,7 @@ sub checkBuild {
|
||||
, uri => $input->{uri}
|
||||
, revision => $input->{revision}
|
||||
, value => $input->{value}
|
||||
, emailresponsible => $input->{emailresponsible}
|
||||
, dependency => $input->{id}
|
||||
, path => $input->{storePath} || "" # !!! temporary hack
|
||||
, sha256hash => $input->{sha256hash}
|
||||
|
@ -27,6 +27,7 @@ our @EXPORT = qw(
|
||||
parseJobsetName
|
||||
showJobName
|
||||
showStatus
|
||||
getResponsibleAuthors
|
||||
);
|
||||
|
||||
|
||||
@ -261,4 +262,42 @@ sub showStatus {
|
||||
}
|
||||
|
||||
|
||||
# Determine who broke/fixed the build.
|
||||
sub getResponsibleAuthors {
|
||||
my ($build, $plugins) = @_;
|
||||
|
||||
my $prevBuild = getPreviousBuild($build);
|
||||
|
||||
my $nrCommits = 0;
|
||||
my %authors;
|
||||
my @emailable_authors;
|
||||
|
||||
if ($prevBuild) {
|
||||
foreach my $curInput ($build->buildinputs_builds) {
|
||||
next unless ($curInput->type eq "git" || $curInput->type eq "hg");
|
||||
my $prevInput = $prevBuild->buildinputs_builds->find({ name => $curInput->name });
|
||||
next unless defined $prevInput;
|
||||
|
||||
next if $curInput->type ne $prevInput->type;
|
||||
next if $curInput->uri ne $prevInput->uri;
|
||||
next if $curInput->revision eq $prevInput->revision;
|
||||
|
||||
my @commits;
|
||||
foreach my $plugin (@{$plugins}) {
|
||||
push @commits, @{$plugin->getCommits($curInput->type, $curInput->uri, $prevInput->revision, $curInput->revision)};
|
||||
}
|
||||
|
||||
foreach my $commit (@commits) {
|
||||
#print STDERR "$commit->{revision} by $commit->{author}\n";
|
||||
$authors{$commit->{author}} = $commit->{email};
|
||||
push @emailable_authors, $commit->{email} if $curInput->emailresponsible;
|
||||
$nrCommits++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (\%authors, $nrCommits, \@emailable_authors);
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
@ -29,6 +29,11 @@ The following dependent jobs also failed:
|
||||
[% END -%]
|
||||
|
||||
[% END -%]
|
||||
|
||||
[% IF nrCommits > 0 -%]
|
||||
This is likely due to [% IF nrCommits > 1 -%][% nrCommits %] commits by [% END -%][% authorList %].
|
||||
[% END -%]
|
||||
|
||||
[% IF build.buildstatus == 0 -%]
|
||||
Yay!
|
||||
[% ELSE -%]
|
||||
@ -74,6 +79,14 @@ sub buildFinished {
|
||||
}
|
||||
}
|
||||
|
||||
my ($authors, $nrCommits, $emailable_authors) = getResponsibleAuthors($build, $self->{plugins});
|
||||
my $authorList;
|
||||
if (scalar keys %{authors} > 0) {
|
||||
my @x = map { "$_ <$authors->{$_}>" } (sort keys %{$authors});
|
||||
$authorList = join(" or ", scalar @x > 1 ? join(", ", @[0..scalar @x - 2]): (), $x[-1]);
|
||||
$addresses{$_} = { builds => [ $build ] } foreach (@{$emailable_authors});
|
||||
}
|
||||
|
||||
# Send an email to each interested address.
|
||||
# !!! should use the Template Toolkit here.
|
||||
|
||||
@ -89,6 +102,8 @@ sub buildFinished {
|
||||
, baseurl => $self->{config}->{'base_uri'} || "http://localhost:3000"
|
||||
, showJobName => \&showJobName, showStatus => \&showStatus
|
||||
, showSystem => index($build->job->name, $build->system) == -1
|
||||
, nrCommits => $nrCommits
|
||||
, authorList => $authorList
|
||||
};
|
||||
|
||||
my $body;
|
||||
|
@ -37,34 +37,7 @@ sub buildFinished {
|
||||
|
||||
return if scalar keys %rooms == 0;
|
||||
|
||||
# Determine who broke/fixed the build.
|
||||
my $prevBuild = getPreviousBuild($build);
|
||||
|
||||
my $nrCommits = 0;
|
||||
my %authors;
|
||||
|
||||
if ($prevBuild) {
|
||||
foreach my $curInput ($build->buildinputs_builds) {
|
||||
next unless ($curInput->type eq "git" || $curInput->type eq "hg");
|
||||
my $prevInput = $prevBuild->buildinputs_builds->find({ name => $curInput->name });
|
||||
next unless defined $prevInput;
|
||||
|
||||
next if $curInput->type ne $prevInput->type;
|
||||
next if $curInput->uri ne $prevInput->uri;
|
||||
next if $curInput->revision eq $prevInput->revision;
|
||||
|
||||
my @commits;
|
||||
foreach my $plugin (@{$self->{plugins}}) {
|
||||
push @commits, @{$plugin->getCommits($curInput->type, $curInput->uri, $prevInput->revision, $curInput->revision)};
|
||||
}
|
||||
|
||||
foreach my $commit (@commits) {
|
||||
#print STDERR "$commit->{revision} by $commit->{author}\n";
|
||||
$authors{$commit->{author}} = $commit->{email};
|
||||
$nrCommits++;
|
||||
}
|
||||
}
|
||||
}
|
||||
my ($authors, $nrCommits) = getResponsibleAuthors($build, $self->{plugins});
|
||||
|
||||
# Send a message to each room.
|
||||
foreach my $roomId (keys %rooms) {
|
||||
@ -84,9 +57,9 @@ sub buildFinished {
|
||||
$msg .= " (and ${\scalar @deps} others)" if scalar @deps > 0;
|
||||
$msg .= ": <a href='$baseurl/build/${\$build->id}'>" . showStatus($build) . "</a>";
|
||||
|
||||
if (scalar keys %authors > 0) {
|
||||
if (scalar keys %{$authors} > 0) {
|
||||
# FIXME: HTML escaping
|
||||
my @x = map { "<a href='mailto:$authors{$_}'>$_</a>" } (sort keys %authors);
|
||||
my @x = map { "<a href='mailto:$authors->{$_}'>$_</a>" } (sort keys %{$authors});
|
||||
$msg .= ", likely due to ";
|
||||
$msg .= "$nrCommits commits by " if $nrCommits > 1;
|
||||
$msg .= join(" or ", scalar @x > 1 ? join(", ", @x[0..scalar @x - 2]) : (), $x[-1]);
|
||||
|
@ -72,6 +72,12 @@ __PACKAGE__->table("BuildInputs");
|
||||
data_type: 'text'
|
||||
is_nullable: 1
|
||||
|
||||
=head2 emailresponsible
|
||||
|
||||
data_type: 'integer'
|
||||
default_value: 0
|
||||
is_nullable: 0
|
||||
|
||||
=head2 dependency
|
||||
|
||||
data_type: 'integer'
|
||||
@ -105,6 +111,8 @@ __PACKAGE__->add_columns(
|
||||
{ data_type => "text", is_nullable => 1 },
|
||||
"value",
|
||||
{ data_type => "text", is_nullable => 1 },
|
||||
"emailresponsible",
|
||||
{ data_type => "integer", default_value => 0, is_nullable => 0 },
|
||||
"dependency",
|
||||
{ data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
|
||||
"path",
|
||||
@ -168,7 +176,7 @@ __PACKAGE__->belongs_to(
|
||||
);
|
||||
|
||||
|
||||
# Created by DBIx::Class::Schema::Loader v0.07033 @ 2013-06-13 01:54:50
|
||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:tKZAybbNaRIMs9n5tHkqPw
|
||||
# Created by DBIx::Class::Schema::Loader v0.07033 @ 2013-10-08 13:08:15
|
||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:OaJPzRM+8XGsu3eIkqeYEw
|
||||
|
||||
1;
|
||||
|
@ -57,6 +57,12 @@ __PACKAGE__->table("JobsetInputs");
|
||||
data_type: 'text'
|
||||
is_nullable: 0
|
||||
|
||||
=head2 emailresponsible
|
||||
|
||||
data_type: 'integer'
|
||||
default_value: 0
|
||||
is_nullable: 0
|
||||
|
||||
=cut
|
||||
|
||||
__PACKAGE__->add_columns(
|
||||
@ -68,6 +74,8 @@ __PACKAGE__->add_columns(
|
||||
{ data_type => "text", is_nullable => 0 },
|
||||
"type",
|
||||
{ data_type => "text", is_nullable => 0 },
|
||||
"emailresponsible",
|
||||
{ data_type => "integer", default_value => 0, is_nullable => 0 },
|
||||
);
|
||||
|
||||
=head1 PRIMARY KEY
|
||||
@ -142,7 +150,7 @@ __PACKAGE__->has_many(
|
||||
);
|
||||
|
||||
|
||||
# Created by DBIx::Class::Schema::Loader v0.07033 @ 2013-06-13 01:54:50
|
||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:UXBzqO0vHPql4LYyXpgEQg
|
||||
# Created by DBIx::Class::Schema::Loader v0.07033 @ 2013-10-08 13:06:15
|
||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:+mZZqLjQNwblb/EWW1alLQ
|
||||
|
||||
1;
|
||||
|
Reference in New Issue
Block a user