Add support for viewing jobset evaluations

[?]
Apr 2, 2012, 2:11 PM
U4TD3AIQXBJFFUORTMIC4IHZTVBORRKL2TZ2FSP4G665ECZOEMNAC

Dependencies

  • [2] G5YSUSNZ In build tables, hide the project, jobset and/or job name if they're constant
  • [3] 2AIIYGI5 * Show job status and all builds for a project.
  • [4] 4S4ZMFJK * Links on trs.
  • [5] GNIEG2GC * Disambiguate jobs by jobset name. I.e. jobs with the same name in
  • [6] 7Z3YOKCV * PROCESS -> INCLUDE in most cases. INCLUDE does proper scoping of
  • [7] ELABMHJI * hydra: layout changes
  • [8] PRNGXWJ3 * hydra: more minor css tweaks
  • [9] UWVMQIAC * Refactoring.
  • [10] ZI535LI6 * hydra: 'new' UI for project/jobset/job/build
  • [11] FPK5LF53 * Put the project-related actions in a separate controller. Put the
  • [12] S5PV6IIM * Represent jobs explicitly in the DB.
  • [13] SMCOU72F hydra: add some admin for adding/enabling/etc build machines
  • [14] 3HZY24CX * Make jobsets viewable under
  • [15] HPEG2RHV Merge the BuildResultInfo table into the Builds table
  • [16] SJN2QPWH * Big speed-up of the job status page and the channel generation (such
  • [17] DEMSSSB2 * Controller for jobs which inherits all actions in ListBuilds. So
  • [18] 6FXGLP7T * Render durations nicely.
  • [19] YTSIRIMK * Separate job status and all builds pages.
  • [20] QL55ECJ6 - adapted ui for hydra, more in line with nixos.org website
  • [21] AVOPQAF7 * Make the "all" page faster by not doing four identical `select
  • [22] J7EE2XZA Fix a huge performance regression in the jobstatus page
  • [23] T2232OBS * Add some DB indices to make the /releases page much faster.
  • [24] OZ5UBJEK
  • [25] 22JB5HNE make changes section more compact/readable
  • [26] E5DMQRPO Remove unnecessary whitespace in the HTML output
  • [27] E74FJWCF * Pass the page number in the URI query string.
  • [28] JLDUSNUO * Unify rendering of finished and scheduled builds.
  • [*] RSEGBU6C Hydra/20: Jobset clone feature
  • [*] D5QIOJGP * Move everything up one directory.
  • [*] IK53RV4V
  • [*] IE3SRMWZ * Show global and per-project statistics.
  • [*] ODNCGFQ5 * Improved the navigation bar: don't include all projects (since that
  • [*] J5UVLXOK * Start of a basic Catalyst web interface.

Change contents

  • replacement in src/lib/Hydra/Base/Controller/ListBuilds.pm at line 63
    [3.780][3.780:822]()
    $c->stash->{totalBuilds} = $nrBuilds;
    [3.780]
    [3.822]
    $c->stash->{total} = $nrBuilds;
  • edit in src/lib/Hydra/Controller/Jobset.pm at line 330
    [30.1562]
    [30.1562]
    sub evals : Chained('jobset') PathPart('evals') Args(0) {
    my ($self, $c) = @_;
    $c->stash->{template} = 'jobset-evals.tt';
  • edit in src/lib/Hydra/Controller/Jobset.pm at line 337
    [30.1563]
    [30.1563]
    my $page = int($c->req->param('page') || "1") || 1;
  • edit in src/lib/Hydra/Controller/Jobset.pm at line 339
    [30.1564]
    [30.1564]
    my $resultsPerPage = 20;
  • edit in src/lib/Hydra/Controller/Jobset.pm at line 341
    [30.1565]
    [3.1141]
    $c->stash->{page} = $page;
    $c->stash->{resultsPerPage} = $resultsPerPage;
    $c->stash->{total} = $c->stash->{jobset}->jobsetevals->search({hasnewbuilds => 1})->count;
    $c->stash->{evals} = [ $c->stash->{jobset}->jobsetevals->search(
    { hasnewbuilds => 1 },
    { order_by => "id DESC"
    , '+select' => # !!! Slow - should precompute this.
    [ "(select count(*) from JobsetEvalMembers where eval = me.id)"
    , "(select count(*) from JobsetEvalMembers where eval = me.id and exists(select 1 from Builds b where b.id = build and b.finished = 0))"
    , "(select count(*) from JobsetEvalMembers where eval = me.id and exists(select 1 from Builds b where b.id = build and b.finished = 1))"
    , "(select count(*) from JobsetEvalMembers where eval = me.id and exists(select 1 from Builds b where b.id = build and b.finished = 1 and b.buildStatus = 0))"
    ]
    , '+as' => [ "nrBuilds", "nrScheduled", "nrFinished", "nrSucceeded" ]
    , rows => $resultsPerPage
    , page => $page
    }
    ) ];
    }
  • file addition: JobsetEval.pm (----------)
    [31.188]
    package Hydra::Controller::JobsetEval;
    use strict;
    use warnings;
    use base 'Catalyst::Controller';
    use Hydra::Helper::Nix;
    use Hydra::Helper::CatalystUtils;
    sub eval : Chained('/') PathPart('eval') CaptureArgs(1) {
    my ($self, $c, $evalId) = @_;
    my $eval = $c->model('DB::JobsetEvals')->find($evalId)
    or notFound($c, "Evaluation $evalId doesn't exist.");
    $c->stash->{eval} = $eval;
    $c->stash->{project} = $eval->project;
    $c->stash->{jobset} = $eval->jobset;
    }
    sub view : Chained('eval') PathPart('') Args(0) {
    my ($self, $c) = @_;
    $c->stash->{template} = 'jobset-eval.tt';
    my $eval = $c->stash->{eval};
    my ($eval2) = $eval->jobset->jobsetevals->search(
    { hasnewbuilds => 1, id => { '<', $eval->id } },
    { order_by => "id DESC", rows => 1 });
    my @builds = $eval->builds->search({}, { order_by => ["job", "system", "id"], columns => [@buildListColumns] });
    my @builds2 = $eval2->builds->search({}, { order_by => ["job", "system", "id"], columns => [@buildListColumns] });
    print STDERR "EVAL IS ", $eval2->id, "\n";
    print STDERR scalar(@builds), "\n";
    print STDERR scalar(@builds2), "\n";
    $c->stash->{stillSucceed} = [];
    $c->stash->{stillFail} = [];
    $c->stash->{nowSucceed} = [];
    $c->stash->{nowFail} = [];
    my $n = 0;
    foreach my $build (@builds) {
    my $d;
    while ($n < scalar(@builds2)) {
    my $build2 = $builds2[$n];
    my $d = $build->get_column('job') cmp $build2->get_column('job')
    || $build->get_column('system') cmp $build2->get_column('system');
    #print STDERR $build->id, " ", $build->get_column('job'), " ", $build->system, " ", $d, "\n";
    last if $d == -1;
    if ($d == 0) {
    #print STDERR $build->buildstatus, "\n";
    #print STDERR $build2->buildstatus, "\n";
    if ($build->buildstatus == 0 && $build2->buildstatus == 0) {
    push @{$c->stash->{stillSucceed}}, $build;
    } elsif ($build->buildstatus != 0 && $build2->buildstatus != 0) {
    push @{$c->stash->{stillFail}}, $build;
    } elsif ($build->buildstatus == 0 && $build2->buildstatus != 0) {
    push @{$c->stash->{nowSucceed}}, $build;
    } elsif ($build->buildstatus != 0 && $build2->buildstatus == 0) {
    push @{$c->stash->{nowFail}}, $build;
    }
    last;
    }
    $n++;
    }
    }
    $c->stash->{full} = ($c->req->params->{full} || "0") eq "1";
    }
    1;
  • replacement in src/root/all.tt at line 10
    [3.1234][3.1234:1297]()
    out of [% totalBuilds %] in order of descending timestamp.</p>
    [3.1234]
    [3.1297]
    out of [% total %] in order of descending timestamp.</p>
  • replacement in src/root/all.tt at line 12
    [3.1298][3.30:52](),[3.52][3.107:111](),[3.1329][3.107:111](),[3.111][3.76:122](),[3.1329][3.76:122](),[3.122][3.1377:1395](),[3.1366][3.1377:1395](),[3.1377][3.1377:1395](),[3.1395][3.123:181](),[3.181][3.1453:1508](),[3.1420][3.1453:1508](),[3.1453][3.1453:1508](),[3.1508][3.182:240](),[3.240][3.1566:1576](),[3.1474][3.1566:1576](),[3.1566][3.1566:1576](),[3.1576][3.241:327](),[3.327][3.112:117](),[3.117][3.53:63](),[3.1663][3.64:89]()
    [% BLOCK renderNav %]
    <p>
    [<a href="[% "$baseUri?page=1" %]">First</a>]
    [% IF page > 1 %]
    [<a href="[% "$baseUri?page="; (page - 1) %]">Prev</a>]
    [% END %]
    [% IF page * resultsPerPage < totalBuilds %]
    [<a href="[% "$baseUri?page="; (page + 1) %]">Next</a>]
    [% END %]
    [<a href="[% "$baseUri?page="; (totalBuilds - 1) div resultsPerPage + 1 %]">Last</a>]
    </p>
    [% END %]
    [% INCLUDE renderNav %]
    [3.1298]
    [2.0]
    [% INCLUDE renderPager %]
  • replacement in src/root/all.tt at line 14
    [2.92][3.119:143](),[3.119][3.119:143]()
    [% INCLUDE renderNav %]
    [2.92]
    [3.143]
    [% INCLUDE renderPager %]
  • replacement in src/root/common.tt at line 65
    [3.5096][3.353:383](),[3.383][3.0:83](),[3.737][3.0:83]()
    [%- BLOCK renderBuildList -%]
    <table class="buildList tablesorter[% IF !showSchedulingInfo %] clean[% END %]">
    [3.5096]
    [3.767]
    [%- BLOCK renderBuildListHeader -%]
    <table class="buildList [% IF !unsortable %]tablesorter[% END %] [% IF !showSchedulingInfo %] clean[% END %]">
  • edit in src/root/common.tt at line 92
    [3.1125]
    [3.594]
    [%- END -%]
    [%- BLOCK renderBuildListBody -%]
  • edit in src/root/common.tt at line 136
    [3.1712]
    [3.2177]
    [%- END -%]
    [%- BLOCK renderBuildListFooter -%]
  • edit in src/root/common.tt at line 141
    [33.804]
    [3.1713]
    [%- END -%]
    [%- BLOCK renderBuildList -%]
    [%- INCLUDE renderBuildListHeader -%]
    [%- INCLUDE renderBuildListBody -%]
    [%- INCLUDE renderBuildListFooter -%]
  • edit in src/root/common.tt at line 149
    [33.815]
    [3.1726]
  • edit in src/root/common.tt at line 393
    [3.2605][3.2605:2629]()
    [% BLOCK buildsGraph %]
  • edit in src/root/common.tt at line 394
    [3.2630]
    [3.2630]
    [% BLOCK renderPager %]
    <p>
    [<a href="[% "$baseUri?page=1" %]">First</a>]
    [% IF page > 1 %]
    [<a href="[% "$baseUri?page="; (page - 1) %]">Prev</a>]
    [% END %]
    [% IF page * resultsPerPage < total %]
    [<a href="[% "$baseUri?page="; (page + 1) %]">Next</a>]
    [% END %]
    [<a href="[% "$baseUri?page="; (total - 1) div resultsPerPage + 1 %]">Last</a>]
    </p>
    [% END %]
  • edit in src/root/common.tt at line 408
    [3.2632][3.2632:2642]()
    [% END %]
  • file addition: jobset-eval.tt (----------)
    [31.1486]
    [% WRAPPER layout.tt title="Bla" %]
    [% PROCESS common.tt %]
    <h1>Jobset <tt>[% project.name %]:[% jobset.name %]</tt> Evaluation [% eval.id %]</h1>
    <!-- <p>Info on evaluation [% eval.id %]...<p> -->
    [%- BLOCK renderSome -%]
    [% size = builds.size; max = full ? size : 30; %]
    [% INCLUDE renderBuildListBody builds=builds.slice(0, (size > max ? max : size) - 1)
    hideProjectName=1 hideJobsetName=1 %]
    [% IF size > max %]
    <tr><td class="centered" colspan="0"><a href="[% c.uri_for(c.controller('JobsetEval').action_for('view'), [eval.id], full => 1) %]"><em>([% size - max %] more builds omitted)</em></a></td></tr>
    [% END %]
    [% END %]
    [% INCLUDE renderBuildListHeader unsortable=1 %]
    [% IF nowFail.size > 0 %]
    <tr><th class="subheader" colspan="0">Builds that now <strong>fail</strong></th></tr>
    [% INCLUDE renderSome builds=nowFail %]
    [% END %]
    [% IF nowSucceed.size > 0 %]
    <tr><th class="subheader" colspan="0">Builds that now <strong>succeed</strong></th></tr>
    [% INCLUDE renderSome builds=nowSucceed %]
    [% END %]
    [% IF stillFail.size > 0 %]
    <tr><th class="subheader" colspan="0">Builds that still <strong>fail</strong></th></tr>
    [% INCLUDE renderSome builds=stillFail %]
    [% END %]
    [% IF stillSucceed.size > 0 %]
    <tr><th class="subheader" colspan="0">Builds that still <strong>succeed</strong></th></tr>
    [% INCLUDE renderSome builds=stillSucceed %]
    [% END %]
    [% INCLUDE renderBuildListFooter %]
    [% END %]
  • file addition: jobset-evals.tt (----------)
    [31.1486]
    [% WRAPPER layout.tt title="Jobset ‘$project.name:$jobset.name’ evaluations" %]
    [% PROCESS common.tt %]
    <h1>Evaluations of Jobset <tt>[% INCLUDE renderLink
    uri = c.uri_for(c.controller('Project').action_for('view'), [project.name])
    title = project.name %]:[% jobset.name %]</tt></h1>
    <p>Showing evaluations [% (page - 1) * resultsPerPage + 1 %] - [%
    (page - 1) * resultsPerPage + evals.size %] out of [% total %].</p>
    [% INCLUDE renderPager %]
    <table class="tablesorter">
    <thead>
    <tr>
    <th>#</th>
    <th>Date</th>
    <th colspan='2'>Success</th>
    </tr>
    </thead>
    <tbody>
    [% last = evals.size - 2; FOREACH n IN [0..last]; eval = evals.$n; m = n + 1; next = evals.$m; %]
    <tr>
    <td><a href="[% c.uri_for(c.controller('JobsetEval').action_for('view'), [eval.id]) %]">[% eval.id %]</a>&nbsp;</td>
    <td>[% INCLUDE renderDateTime timestamp = eval.timestamp %]&nbsp;</td>
    <td align='right'>
    [% eval.get_column('nrSucceeded') %] / [% eval.get_column('nrBuilds') %]
    [% IF eval.get_column('nrScheduled') > 0 %]
    <br />[% eval.get_column('nrScheduled') %] scheduled
    [% END %]
    </td>
    <td align='right'>
    [% diff = eval.get_column('nrSucceeded') - next.get_column('nrSucceeded');
    IF diff > 0 %]
    <span class='green'><strong>+[% diff %]</strong></span>
    [% ELSIF diff < 0 && eval.get_column('nrScheduled') == 0 %]
    <span class='red'><strong>[% diff %]</strong></span>
    [% END %]
    </td>
    </tr>
    [% END %]
    </tbody>
    </table>
    [% INCLUDE renderPager %]
    [% END %]
  • edit in src/root/navbar.tt at line 48
    [34.17139]
    [34.17139]
    uri = c.uri_for(c.controller('Jobset').action_for('evals'), [project.name, jobset.name])
    title = "Evaluations" %]
    [% INCLUDE makeLink
  • replacement in src/root/static/css/hydra.css at line 41
    [3.1361][3.1361:1391]()
    background-color:#E6EEEE;
    [3.1361]
    [3.31086]
    background-color: #E6EEEE;
    }
    th.subheader {
    background-color: #f0f0f8;
    font-size: 120%;
    text-align: center;
    font-weight: normal;