forked from lix-project/hydra
web: replace 'errormsg' with 'errormsg IS NULL' in most cases
This is implement in an extremely hacky way due to poor DBIx feature support. Ideally, what we'd need is a way to tell DBIx to ignore the errormsg column unless explicitly requested, and to automatically add a computed 'errormsg IS NULL' column in others. Since it does not support that, this commit instead hacks some support via method overrides while taking care to not break anything obvious.
This commit is contained in:
parent
258e9314a9
commit
6189ba9c5e
|
@ -87,6 +87,7 @@ let
|
||||||
DateTime
|
DateTime
|
||||||
DBDPg
|
DBDPg
|
||||||
DBDSQLite
|
DBDSQLite
|
||||||
|
DBIxClassHelpers
|
||||||
DigestSHA1
|
DigestSHA1
|
||||||
EmailMIME
|
EmailMIME
|
||||||
EmailSender
|
EmailSender
|
||||||
|
|
|
@ -371,6 +371,12 @@ sub errors_GET {
|
||||||
|
|
||||||
$c->stash->{template} = 'eval-error.tt';
|
$c->stash->{template} = 'eval-error.tt';
|
||||||
|
|
||||||
|
my $jobsetName = $c->stash->{params}->{name};
|
||||||
|
$c->stash->{jobset} = $c->stash->{project}->jobsets->find(
|
||||||
|
{ name => $jobsetName },
|
||||||
|
{ '+columns' => { 'errormsg' => 'errormsg' } }
|
||||||
|
);
|
||||||
|
|
||||||
$self->status_ok($c, entity => $c->stash->{jobset});
|
$self->status_ok($c, entity => $c->stash->{jobset});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,8 @@ sub errors_GET {
|
||||||
|
|
||||||
$c->stash->{template} = 'eval-error.tt';
|
$c->stash->{template} = 'eval-error.tt';
|
||||||
|
|
||||||
|
$c->stash->{eval} = $c->model('DB::JobsetEvals')->find($c->stash->{eval}->id, { prefetch => 'evaluationerror' });
|
||||||
|
|
||||||
$self->status_ok($c, entity => $c->stash->{eval});
|
$self->status_ok($c, entity => $c->stash->{eval});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -286,8 +286,7 @@ sub getEvals {
|
||||||
|
|
||||||
my @evals = $evals_result_set->search(
|
my @evals = $evals_result_set->search(
|
||||||
{ hasnewbuilds => 1 },
|
{ hasnewbuilds => 1 },
|
||||||
{ order_by => "$me.id DESC", rows => $rows, offset => $offset
|
{ order_by => "$me.id DESC", rows => $rows, offset => $offset });
|
||||||
, prefetch => { evaluationerror => [ ] } });
|
|
||||||
my @res = ();
|
my @res = ();
|
||||||
my $cache = {};
|
my $cache = {};
|
||||||
|
|
||||||
|
|
|
@ -105,4 +105,6 @@ __PACKAGE__->add_column(
|
||||||
"+id" => { retrieve_on_insert => 1 }
|
"+id" => { retrieve_on_insert => 1 }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
__PACKAGE__->mk_group_accessors('column' => 'has_error');
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
|
@ -386,6 +386,8 @@ __PACKAGE__->add_column(
|
||||||
"+id" => { retrieve_on_insert => 1 }
|
"+id" => { retrieve_on_insert => 1 }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
__PACKAGE__->mk_group_accessors('column' => 'has_error');
|
||||||
|
|
||||||
sub supportsDynamicRunCommand {
|
sub supportsDynamicRunCommand {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
|
|
||||||
|
|
30
src/lib/Hydra/Schema/ResultSet/EvaluationErrors.pm
Normal file
30
src/lib/Hydra/Schema/ResultSet/EvaluationErrors.pm
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package Hydra::Schema::ResultSet::EvaluationErrors;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use utf8;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use parent 'DBIx::Class::ResultSet';
|
||||||
|
|
||||||
|
use Storable qw(dclone);
|
||||||
|
|
||||||
|
__PACKAGE__->load_components('Helper::ResultSet::RemoveColumns');
|
||||||
|
|
||||||
|
# Exclude expensive error message values unless explicitly requested, and
|
||||||
|
# replace them with a summary field describing their presence/absence.
|
||||||
|
sub search_rs {
|
||||||
|
my ( $class, $query, $attrs ) = @_;
|
||||||
|
|
||||||
|
if ($attrs) {
|
||||||
|
$attrs = dclone($attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
unless (exists $attrs->{'select'} || exists $attrs->{'columns'}) {
|
||||||
|
$attrs->{'+columns'}->{'has_error'} = "errormsg != ''";
|
||||||
|
}
|
||||||
|
unless (exists $attrs->{'+columns'}->{'errormsg'}) {
|
||||||
|
push @{ $attrs->{'remove_columns'} }, 'errormsg';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $class->next::method($query, $attrs);
|
||||||
|
}
|
30
src/lib/Hydra/Schema/ResultSet/Jobsets.pm
Normal file
30
src/lib/Hydra/Schema/ResultSet/Jobsets.pm
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package Hydra::Schema::ResultSet::Jobsets;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use utf8;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use parent 'DBIx::Class::ResultSet';
|
||||||
|
|
||||||
|
use Storable qw(dclone);
|
||||||
|
|
||||||
|
__PACKAGE__->load_components('Helper::ResultSet::RemoveColumns');
|
||||||
|
|
||||||
|
# Exclude expensive error message values unless explicitly requested, and
|
||||||
|
# replace them with a summary field describing their presence/absence.
|
||||||
|
sub search_rs {
|
||||||
|
my ( $class, $query, $attrs ) = @_;
|
||||||
|
|
||||||
|
if ($attrs) {
|
||||||
|
$attrs = dclone($attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
unless (exists $attrs->{'select'} || exists $attrs->{'columns'}) {
|
||||||
|
$attrs->{'+columns'}->{'has_error'} = "errormsg != ''";
|
||||||
|
}
|
||||||
|
unless (exists $attrs->{'+columns'}->{'errormsg'}) {
|
||||||
|
push @{ $attrs->{'remove_columns'} }, 'errormsg';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $class->next::method($query, $attrs);
|
||||||
|
}
|
|
@ -513,7 +513,7 @@ BLOCK renderEvals %]
|
||||||
ELSE %]
|
ELSE %]
|
||||||
-
|
-
|
||||||
[% END %]
|
[% END %]
|
||||||
[% IF eval.evaluationerror.errormsg %]
|
[% IF eval.evaluationerror.has_error %]
|
||||||
<span class="badge badge-warning">Eval Errors</span>
|
<span class="badge badge-warning">Eval Errors</span>
|
||||||
[% END %]
|
[% END %]
|
||||||
</td>
|
</td>
|
||||||
|
@ -639,7 +639,7 @@ BLOCK renderJobsetOverview %]
|
||||||
<td>[% HTML.escape(j.description) %]</td>
|
<td>[% HTML.escape(j.description) %]</td>
|
||||||
<td>[% IF j.lastcheckedtime;
|
<td>[% IF j.lastcheckedtime;
|
||||||
INCLUDE renderDateTime timestamp = j.lastcheckedtime;
|
INCLUDE renderDateTime timestamp = j.lastcheckedtime;
|
||||||
IF j.errormsg || j.fetcherrormsg; %] <span class = 'badge badge-warning'>Error</span>[% END;
|
IF j.has_error || j.fetcherrormsg; %] <span class = 'badge badge-warning'>Error</span>[% END;
|
||||||
ELSE; "-";
|
ELSE; "-";
|
||||||
END %]</td>
|
END %]</td>
|
||||||
[% IF j.get_column('nrtotal') > 0 %]
|
[% IF j.get_column('nrtotal') > 0 %]
|
||||||
|
|
|
@ -90,7 +90,7 @@ c.uri_for(c.controller('JobsetEval').action_for('view'),
|
||||||
[% END %]
|
[% END %]
|
||||||
<li class="nav-item"><a class="nav-link" href="#tabs-inputs" data-toggle="tab">Inputs</a></li>
|
<li class="nav-item"><a class="nav-link" href="#tabs-inputs" data-toggle="tab">Inputs</a></li>
|
||||||
|
|
||||||
[% IF eval.evaluationerror.errormsg %]
|
[% IF eval.evaluationerror.has_error %]
|
||||||
<li class="nav-item"><a class="nav-link" href="#tabs-errors" data-toggle="tab"><span class="text-warning">Evaluation Errors</span></a></li>
|
<li class="nav-item"><a class="nav-link" href="#tabs-errors" data-toggle="tab"><span class="text-warning">Evaluation Errors</span></a></li>
|
||||||
[% END %]
|
[% END %]
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -165,7 +165,7 @@ c.uri_for(c.controller('JobsetEval').action_for('view'),
|
||||||
[% END %]
|
[% END %]
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
[% IF eval.evaluationerror.errormsg %]
|
[% IF eval.evaluationerror.has_error %]
|
||||||
<div id="tabs-errors" class="tab-pane">
|
<div id="tabs-errors" class="tab-pane">
|
||||||
<iframe src="[% c.uri_for(c.controller('JobsetEval').action_for('errors'), [eval.id], params) %]" loading="lazy" frameBorder="0" width="100%"></iframe>
|
<iframe src="[% c.uri_for(c.controller('JobsetEval').action_for('errors'), [eval.id], params) %]" loading="lazy" frameBorder="0" width="100%"></iframe>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -61,7 +61,7 @@
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
<li class="nav-item"><a class="nav-link active" href="#tabs-evaluations" data-toggle="tab">Evaluations</a></li>
|
<li class="nav-item"><a class="nav-link active" href="#tabs-evaluations" data-toggle="tab">Evaluations</a></li>
|
||||||
[% IF jobset.errormsg || jobset.fetcherrormsg %]
|
[% IF jobset.has_error || jobset.fetcherrormsg %]
|
||||||
<li class="nav-item"><a class="nav-link" href="#tabs-errors" data-toggle="tab"><span class="text-warning">Evaluation Errors</span></a></li>
|
<li class="nav-item"><a class="nav-link" href="#tabs-errors" data-toggle="tab"><span class="text-warning">Evaluation Errors</span></a></li>
|
||||||
[% END %]
|
[% END %]
|
||||||
<li class="nav-item"><a class="nav-link" href="#tabs-jobs" data-toggle="tab">Jobs</a></li>
|
<li class="nav-item"><a class="nav-link" href="#tabs-jobs" data-toggle="tab">Jobs</a></li>
|
||||||
|
@ -79,7 +79,7 @@
|
||||||
<th>Last checked:</th>
|
<th>Last checked:</th>
|
||||||
<td>
|
<td>
|
||||||
[% IF jobset.lastcheckedtime %]
|
[% IF jobset.lastcheckedtime %]
|
||||||
[% INCLUDE renderDateTime timestamp = jobset.lastcheckedtime %], [% IF jobset.errormsg || jobset.fetcherrormsg %]<em class="text-warning">with errors!</em>[% ELSE %]<em>no errors</em>[% END %]
|
[% INCLUDE renderDateTime timestamp = jobset.lastcheckedtime %], [% IF jobset.has_error || jobset.fetcherrormsg %]<em class="text-warning">with errors!</em>[% ELSE %]<em>no errors</em>[% END %]
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
<em>never</em>
|
<em>never</em>
|
||||||
[% END %]
|
[% END %]
|
||||||
|
@ -117,7 +117,7 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
[% IF jobset.errormsg || jobset.fetcherrormsg %]
|
[% IF jobset.has_error || jobset.fetcherrormsg %]
|
||||||
<div id="tabs-errors" class="tab-pane">
|
<div id="tabs-errors" class="tab-pane">
|
||||||
<iframe src="[% c.uri_for('/jobset' project.name jobset.name "errors") %]" loading="lazy" frameBorder="0" width="100%"></iframe>
|
<iframe src="[% c.uri_for('/jobset' project.name jobset.name "errors") %]" loading="lazy" frameBorder="0" width="100%"></iframe>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -22,7 +22,7 @@ like(
|
||||||
"The stderr record includes a relevant error message"
|
"The stderr record includes a relevant error message"
|
||||||
);
|
);
|
||||||
|
|
||||||
$jobset->discard_changes; # refresh from DB
|
$jobset->discard_changes({ '+columns' => {'errormsg' => 'errormsg'} }); # refresh from DB
|
||||||
like(
|
like(
|
||||||
$jobset->errormsg,
|
$jobset->errormsg,
|
||||||
qr/aggregate job ‘mixed_aggregate’ failed with the error: constituentA: does not exist/,
|
qr/aggregate job ‘mixed_aggregate’ failed with the error: constituentA: does not exist/,
|
||||||
|
|
|
@ -14,7 +14,7 @@ our @EXPORT = qw(
|
||||||
sub evalSucceeds {
|
sub evalSucceeds {
|
||||||
my ($jobset) = @_;
|
my ($jobset) = @_;
|
||||||
my ($res, $stdout, $stderr) = captureStdoutStderr(60, ("hydra-eval-jobset", $jobset->project->name, $jobset->name));
|
my ($res, $stdout, $stderr) = captureStdoutStderr(60, ("hydra-eval-jobset", $jobset->project->name, $jobset->name));
|
||||||
$jobset->discard_changes; # refresh from DB
|
$jobset->discard_changes({ '+columns' => {'errormsg' => 'errormsg'} }); # refresh from DB
|
||||||
if ($res) {
|
if ($res) {
|
||||||
chomp $stdout; chomp $stderr;
|
chomp $stdout; chomp $stderr;
|
||||||
utf8::decode($stdout) or die "Invalid unicode in stdout.";
|
utf8::decode($stdout) or die "Invalid unicode in stdout.";
|
||||||
|
@ -29,7 +29,7 @@ sub evalSucceeds {
|
||||||
sub evalFails {
|
sub evalFails {
|
||||||
my ($jobset) = @_;
|
my ($jobset) = @_;
|
||||||
my ($res, $stdout, $stderr) = captureStdoutStderr(60, ("hydra-eval-jobset", $jobset->project->name, $jobset->name));
|
my ($res, $stdout, $stderr) = captureStdoutStderr(60, ("hydra-eval-jobset", $jobset->project->name, $jobset->name));
|
||||||
$jobset->discard_changes; # refresh from DB
|
$jobset->discard_changes({ '+columns' => {'errormsg' => 'errormsg'} }); # refresh from DB
|
||||||
if (!$res) {
|
if (!$res) {
|
||||||
chomp $stdout; chomp $stderr;
|
chomp $stdout; chomp $stderr;
|
||||||
utf8::decode($stdout) or die "Invalid unicode in stdout.";
|
utf8::decode($stdout) or die "Invalid unicode in stdout.";
|
||||||
|
|
|
@ -13,7 +13,7 @@ my $constituentBuildA = $builds->{"constituentA"};
|
||||||
my $constituentBuildB = $builds->{"constituentB"};
|
my $constituentBuildB = $builds->{"constituentB"};
|
||||||
|
|
||||||
my $eval = $constituentBuildA->jobsetevals->first();
|
my $eval = $constituentBuildA->jobsetevals->first();
|
||||||
is($eval->evaluationerror->errormsg, "");
|
is($eval->evaluationerror->has_error, 0);
|
||||||
|
|
||||||
subtest "Verifying the direct aggregate" => sub {
|
subtest "Verifying the direct aggregate" => sub {
|
||||||
my $aggBuild = $builds->{"direct_aggregate"};
|
my $aggBuild = $builds->{"direct_aggregate"};
|
||||||
|
|
Loading…
Reference in a new issue