From 7725038821337dfd2557dda85b18b3fc3b0fd9d2 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra <eelco.dolstra@logicblox.com> Date: Mon, 26 Aug 2013 18:58:04 +0200 Subject: [PATCH] On aggregate job pages, show a matrix showing all the constituent builds --- src/lib/Hydra/Controller/Job.pm | 26 ++++++++++++- src/root/job.tt | 68 +++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 2 deletions(-) diff --git a/src/lib/Hydra/Controller/Job.pm b/src/lib/Hydra/Controller/Job.pm index 50b6b875..2e272395 100644 --- a/src/lib/Hydra/Controller/Job.pm +++ b/src/lib/Hydra/Controller/Job.pm @@ -20,15 +20,16 @@ sub job : Chained('/') PathPart('job') CaptureArgs(3) { sub overview : Chained('job') PathPart('') Args(0) { my ($self, $c) = @_; + my $job = $c->stash->{job}; $c->stash->{template} = 'job.tt'; $c->stash->{lastBuilds} = - [ $c->stash->{job}->builds->search({ finished => 1 }, + [ $job->builds->search({ finished => 1 }, { order_by => 'id DESC', rows => 10, columns => [@buildListColumns] }) ]; $c->stash->{queuedBuilds} = [ - $c->stash->{job}->builds->search( + $job->builds->search( { finished => 0 }, { join => ['project'] , order_by => ["priority DESC", "id"] @@ -36,6 +37,27 @@ sub overview : Chained('job') PathPart('') Args(0) { , '+as' => ['enabled'] } ) ]; + + # If this is an aggregate job, then get its constituents. + my @constituents = $c->model('DB::Builds')->search( + { aggregate => { -in => $job->builds->search({}, { columns => ["id"], order_by => "id desc", rows => 10 })->as_query } }, + { join => 'aggregateconstituents_constituents', + columns => ['id', 'job', 'finished', 'buildstatus'], + +select => ['aggregateconstituents_constituents.aggregate'], + +as => ['aggregate'] + }); + + my $aggregates = {}; + my %constituentJobs; + foreach my $b (@constituents) { + my $jobName = $b->get_column('job'); + $aggregates->{$b->get_column('aggregate')}->{$jobName} = + { id => $b->id, finished => $b->finished, buildstatus => $b->buildstatus}; + $constituentJobs{$jobName} = 1; + } + + $c->stash->{aggregates} = $aggregates; + $c->stash->{constituentJobs} = [sort (keys %constituentJobs)]; } diff --git a/src/root/job.tt b/src/root/job.tt index 8722d3df..c9c4b6cb 100644 --- a/src/root/job.tt +++ b/src/root/job.tt @@ -4,6 +4,9 @@ <ul class="nav nav-tabs"> <li class="active"><a href="#tabs-status" data-toggle="tab">Status</a></li> + [% IF constituentJobs.size > 0 %] + <li><a href="#tabs-constituents" data-toggle="tab">Constituents</a></li> + [% END %] <li><a href="#tabs-links" data-toggle="tab">Links</a></li> </ul> @@ -21,6 +24,71 @@ [% END %] </div> + [% IF constituentJobs.size > 0 %] + + <div id="tabs-constituents" class="tab-pane"> + + <table class="table table-striped table-condensed"> + <thead> + <tr> + <th>#</th> + [% FOREACH j IN constituentJobs %] + <th>[% HTML.escape(j) %]</th> + [% END %] + </tr> + </thead> + <tbody> + [% FOREACH agg IN aggregates.keys.nsort.reverse %] + <tr> + <td><a class="row-link" href="[% c.uri_for('/build' agg) %]">[% agg %]</a></td> + [% FOREACH j IN constituentJobs %] + <td> + [% r = aggregates.$agg.$j; IF r.id %] + <a href="[% c.uri_for('/build' r.id) %]"> + [% INCLUDE renderBuildStatusIcon size=16 build=r %] + </a> + [% END %] + </td> + [% END %] + </tr> + [% END %] + </tbody> + </table> + + <hr/> + + <table class="table table-striped table-condensed"> + <thead> + <tr> + <th>#</th> + [% FOREACH j IN constituentJobs %] + <th>[% HTML.escape(j) %]</th> + [% END %] + </tr> + </thead> + <tbody> + [% FOREACH agg IN aggregates.keys.nsort.reverse %] + <tr> + <td><a class="row-link" href="[% c.uri_for('/build' agg) %]">[% agg %]</a></td> + [% FOREACH j IN constituentJobs %] + <td> + [% r = aggregates.$agg.$j; IF r.id %] + <a href="[% c.uri_for('/build' r.id) %]"> + [% INCLUDE renderBuildStatusIcon size=16 build=r %] + </a> + [% END %] + </td> + [% END %] + </tr> + [% END %] + </tbody> + </table> + + + </div> + + [% END %] + <div id="tabs-links" class="tab-pane"> <ul> <li><a href="[% c.uri_for('/job' project.name jobset.name job.name 'latest') %]">Latest successful build</a></li>