* hydra: 'new' UI for project/jobset/job/build

[?]
Feb 5, 2010, 2:48 PM
ZI535LI6PJMKSOBJE33B3RRZ5S2JVTR3XPUDTSXJW6BZNTAHS3GQC

Dependencies

  • [2] 6FXGLP7T * Render durations nicely.
  • [3] BHJ62LYE * Allow authorised users to create projects.
  • [4] SFUSIKUY * Use isCurrent to determine the inactive jobs.
  • [5] BYWJLUJF * Move the links to the channels up in the page.
  • [6] KRVD4EW7 * Only non-garbage collected builds can be added to a release.
  • [7] C4RV47LW
  • [8] FYO6NECE hydra
  • [9] HUH62VDL show current builds on job page
  • [10] YFPZ46YK * hydra: added variant of build input type, 'build output (same system)' to allow better continous integration in one jobset for multiple system. it makes sure that the system of the build that is passed as input for a job has the same system as the job.
  • [11] H47WLVAT * Handle the case where there is no cached build step that produced
  • [12] XDDCO6CH * hydra: add dependency list with links to logfiles
  • [13] LP66DSH2 * hydra: updated jquery version, needed for tabs (to be added later)
  • [14] L2E6EVE2 * Merged the Build and Job tables.
  • [15] PBFZEQLZ
  • [16] FEMR2C5W
  • [17] 37R34XJO * Negative caching: don't perform a build if a dependency already
  • [18] TQKGQ5R3
  • [19] HJLYC753 * Adding input value alternatives.
  • [20] 7YBYT2LQ
  • [21] CMU3YKOU * Store the release name.
  • [22] WZ3AEJ67 * hydra_update_gc_roots.pl registers build outputs that should be kept
  • [23] A52HEFHQ * Allow builds to be restarted (if they failed with a transient error,
  • [24] FPK5LF53 * Put the project-related actions in a separate controller. Put the
  • [25] UVMFS73T * Some jQuery / CSS hackery.
  • [26] K5BEBWKM
  • [27] Z6MDQIGO * A quick (non-Web 2.0) interface to manually add builds to a release.
  • [28] VJHIHMEH * Store the meta.longDescription and meta.license attributes in the
  • [29] W6DC6K4I * Happy Javascript hacking.
  • [30] GCHNNFZP
  • [31] HB3OHPJL hydra: in case of cached build, add link to build that built the storepath
  • [32] BD3GRK4B * Get rid of "positive failures" and separate log phases.
  • [33] UMBR3VG3
  • [34] 6ULJO5NI * Urgh. `-' had special significance in HTML form parameters...
  • [35] BTUDUY6F * Provide some redirects to the latest successful build for a job (or
  • [36] H7CNGK4O * Log evaluation errors etc. in the DB.
  • [37] QL55ECJ6 - adapted ui for hydra, more in line with nixos.org website
  • [38] IK53RV4V
  • [39] V4RNHJNR * Add a link to each project's homepage. Suggested by karltk.
  • [40] NDL67SQT * XHTML validity.
  • [41] GWCV3TQV * BuildInputs table: link to dependencies, include store paths.
  • [42] GNIEG2GC * Disambiguate jobs by jobset name. I.e. jobs with the same name in
  • [43] 2AUODJBT
  • [44] 7Z3YOKCV * PROCESS -> INCLUDE in most cases. INCLUDE does proper scoping of
  • [45] BVOPAMLS
  • [46] NEWDDAOF * Allow users to change the value of a build's "keep" flag, which
  • [47] 7LKUAIGC
  • [48] WRIU3S5E * UI for cloning builds (not functional yet).
  • [49] LQNBKF3D
  • [50] EYNG4EL4 * Regenerate the bindings from a clean sqlite database.
  • [51] JD27RBKM
  • [52] 3E6IP3R3 * Add the name of the jobset to ReleaseSetJobs, otherwise we can't
  • [53] OD5FSS5A * Quick hack to allow viewing of dependency graphs (via nix-store -q
  • [54] QE253KG4 * Option to show the tail of a log.
  • [55] L7LFU6IQ * Make build steps clickable as well.
  • [56] 67P45PY4
  • [57] RBNQKATL * Adding persistant releases. A release is a named set of builds.
  • [58] WHAFVCEI
  • [59] J5UVLXOK * Start of a basic Catalyst web interface.
  • [60] M552HLIA * Support variant builds.
  • [61] IE3SRMWZ * Show global and per-project statistics.
  • [62] SHZLOM5M * eval-jobs -> hydra_eval_jobs.
  • [63] 6F4UNDTC * Provide access to the raw, non-pretty-printed logfiles.
  • [64] ODNCGFQ5 * Improved the navigation bar: don't include all projects (since that
  • [65] TEZTE7QT bigger min-height, max-width for page
  • [66] ABEOQU7T
  • [67] PHX2HIVG * Store info about the build inputs in the build record.
  • [68] AS5PAYLI
  • [69] 6BLUKEQ2 * Caching of "path" inputs, and fake a revision number for those.
  • [70] WYN733ST * Store build duration, handle cached builds.
  • [71] CLJQCY2X * Store info about all the build actions and allow them to be
  • [72] YTSIRIMK * Separate job status and all builds pages.
  • [73] I35CIZI7
  • [74] R5D7DZPE
  • [75] JFZNAYJX * Showing releases.
  • [76] KOTB7BKV
  • [77] RU7AQO7U * Role-based access control. Only admins can create projects. Only
  • [78] DGVPFNCU * Grabbed a logo. TODO: check copyright status.
  • [79] SMM4HQTP * Put actions related to builds under /build (e.g. /log/<buildid>
  • [80] LBNVQXUB * Build the /build stuff in a separate controller.
  • [81] DEMSSSB2 * Controller for jobs which inherits all actions in ListBuilds. So
  • [82] ZILILXXK * Allow scheduled builds to be cancelled. They're not removed from
  • [83] TW5ZQX5Z * Move up the build products in the builds page, since they're more
  • [84] SZZ3PFYF
  • [85] FKK2ZSTL * Split the CSS.
  • [86] Z4KRJX4Q * In the last succeeded / job status queries, use the Builds.isCurrent
  • [87] 5MNUNZWR * Store meta.maintainers.
  • [88] VCOSLZRP
  • [89] S5PV6IIM * Represent jobs explicitly in the DB.
  • [90] P5X4P6VK * Renaming "release sets" to "views" (not finished yet). Having
  • [91] BA46C5LN * Pretty-print the logs.
  • [92] IMY5UQE3
  • [93] UWVMQIAC * Refactoring.
  • [94] YAPITGB3 * Boolean inputs.
  • [95] 4D4U5IPY * Allow jobsets to be disabled.
  • [96] S66BOMVU * Added authentication.
  • [97] PPAMEWPR
  • [*] 3HZY24CX * Make jobsets viewable under
  • [*] SJLEZFC4 check getHydraPath in stead of Envvar HYDRA_DBI directly
  • [*] SZYY2EQQ * Make the queries more readable.
  • [*] X27GNHDV * Basic job info in the database.
  • [*] 2GK5DOU7 * Downloading closures.
  • [*] D5QIOJGP * Move everything up one directory.

Change contents

  • edit in src/lib/Hydra/Controller/Jobset.pm at line 41
    [4.405]
    [99.819]
    $c->stash->{systems} = [$c->stash->{jobset}->builds->search({iscurrent => 1}, {select => ["system"], distinct => 1})];
    # status per system
    my @systems = ();
    foreach my $system (@{$c->stash->{systems}}) {
    push(@systems, $system->system);
    }
    if(scalar(@{$c->stash->{activeJobs}}) <= 20) {
    my @select = ();
    my @as = ();
    push(@select, "job"); push(@as, "job");
    foreach my $system (@systems) {
    push(@select, "(SELECT buildstatus FROM BuildResultInfo bri NATURAL JOIN Builds b WHERE b.id = (SELECT MAX(id) FROM Builds t WHERE t.project = me.project AND t.jobset = me.jobset AND t.job = me.job AND t.system = '$system'))");
    push(@as, $system);
    push(@select, "(SELECT b.id FROM BuildResultInfo bri NATURAL JOIN Builds b WHERE b.id = (SELECT MAX(id) FROM Builds t WHERE t.project = me.project AND t.jobset = me.jobset AND t.job = me.job AND t.system = '$system'))");
    push(@as, $system."-build");
    }
    $c->stash->{activeJobsStatus} = [$c->model('DB')->resultset('ActiveJobsForJobset')
    ->search( {}
    , { bind => [$c->stash->{project}->name, $c->stash->{jobset}->name]
    , select => \@select
    , as => \@as
    , order_by => ["job"]
    })];
    }
    # last builds for jobset
    my $tmp = $c->stash->{jobset}->builds;
    $c->stash->{lastBuilds} = [joinWithResultInfo($c, $tmp)
    ->search({finished => 1}, {order_by => "timestamp DESC", rows => 5 })] ;
  • edit in src/lib/Hydra/Schema/Builds.pm at line 193
    [100.87]
    [14.3377]
    # order buildsteps
    __PACKAGE__->has_many(
    "buildsteps",
    "Hydra::Schema::BuildSteps",
    { "foreign.build" => "self.id" },
    { order_by => "stepnr" },
    );
  • edit in src/lib/Hydra/Schema/Builds.pm at line 284
    [101.1135]
    [101.1135]
    makeSource("ActiveJobs$name", "(select distinct project, jobset, job from Builds where isCurrent = 1 $constraint)");
  • edit in src/lib/Hydra/Schema/Projects.pm at line 100
    [102.3828]
    [102.3828]
    __PACKAGE__->has_many(
    "jobsets",
    "Hydra::Schema::Jobsets",
    { "foreign.project" => "self.name" },
    { order_by => "name" },
    );
  • edit in src/root/build.tt at line 5
    [103.1440]
    [14.3465]
    [% USE Date %]
  • edit in src/root/build.tt at line 10
    [14.6589]
    [14.7413]
    [% BLOCK renderBuildSteps %]
    <h2 id="buildsteps">Build steps</h2>
    <table class="tablesorter">
    <thead>
    <tr><th>Nr</th><th>What</th><th>Duration</th><th>Status</th></tr>
    </thead>
    <tbody>
    [% FOREACH step IN build.buildsteps -%]
    [% IF (onlyFailed != 1) || (step.status != 0) -%]
    [% log = c.uri_for('/build' build.id 'nixlog' step.stepnr) %]
    <tr class="[% IF step.logfile %]clickable[% END %]"
    [% IF step.logfile %] onclick="window.location = '[% log %]'" [% END %]>
    <td>[% step.stepnr %]</td>
    <td>
    [% IF step.type == 0 %]
    Build of <tt>[% step.outpath %]</tt>
    [% ELSE %]
    Substitution of <tt>[% step.outpath %]</tt>
    [% END %]
    </td>
    <td>
    [% IF step.busy == 0 %]
    [% INCLUDE renderDuration duration = step.stoptime - step.starttime %]
    [% ELSE %]
    [% IF build.finished %]
    [% INCLUDE renderDuration duration = build.resultInfo.stoptime - step.starttime %]
    [% ELSE %]
    [% INCLUDE renderDuration duration = curTime - step.starttime %]
    [% END %]
    [% END %]
    </td>
    <td>
    [% IF step.busy == 1 %]
    [% IF build.finished %]
    <span class="error">Aborted</span>
    [% ELSE %]
    <strong>Building</strong>
    [% END %]
    [% ELSIF step.status == 0 %]
    Succeeded
    [% ELSE %]
    <span class="error">Failed: [% HTML.escape(step.errormsg) %]</span>
    [% END %]
    [% IF step.logfile %]
    (<a href="[% log %]">log</a>, <a href="[% "$log/raw" %]">raw</a>, <a href="[% "$log/tail" %]">tail</a>)
    [% END %]
    </td>
    </tr>
    [% END %]
    [% END %]
    </tbody>
    </table>
  • edit in src/root/build.tt at line 65
    [14.7414]
    [14.5615]
    [% END %]
  • edit in src/root/build.tt at line 85
    [14.7439][14.7439:7460]()
    <h2>Information</h2>
  • replacement in src/root/build.tt at line 86
    [14.7461][14.4332:4360](),[14.4360][14.7469:7527](),[14.7469][14.7469:7527](),[14.7527][14.414:429](),[14.300][14.300:411](),[14.411][14.0:67](),[14.67][14.462:551](),[14.462][14.462:551](),[14.551][14.68:132](),[14.132][14.2876:2949](),[14.1780][14.2176:2230](),[14.2949][14.2176:2230](),[14.2176][14.2176:2230](),[14.2230][14.133:197](),[14.197][14.2281:2351](),[14.2281][14.2281:2351](),[14.2351][14.1326:1499](),[14.1499][14.2950:3224](),[14.3224][14.3382:3520](),[14.1499][14.665:684](),[14.2351][14.665:684](),[14.3359][14.665:684](),[14.3520][14.665:684](),[14.3888][14.665:684](),[14.665][14.665:684](),[14.684][14.198:262](),[14.262][14.2352:2449](),[14.735][14.2352:2449](),[14.2449][14.1500:1518](),[14.1518][14.598:705](),[14.705][14.1781:1881](),[14.1606][14.1781:1881](),[14.2449][14.1781:1881](),[14.1881][14.1607:1671](),[14.1671][14.1952:1970](),[14.1952][14.1952:1970](),[14.1970][14.775:880](),[14.2449][14.775:880](),[14.3947][14.775:880](),[14.775][14.775:880](),[14.880][14.31:117](),[14.117][14.880:944](),[14.2509][14.880:944](),[14.880][14.880:944](),[14.944][14.1672:1900](),[14.1900][14.944:970](),[14.944][14.944:970](),[14.970][14.5852:5867](),[14.5852][14.5852:5867](),[14.5867][14.429:451](),[14.429][14.429:451](),[14.451][14.6673:6739](),[14.163][14.493:529](),[14.616][14.493:529](),[14.2929][14.493:529](),[14.3702][14.493:529](),[14.6739][14.493:529](),[14.493][14.493:529](),[14.529][14.6740:6824](),[14.208][14.7527:7565](),[14.570][14.7527:7565](),[14.2976][14.7527:7565](),[14.3747][14.7527:7565](),[14.6824][14.7527:7565](),[14.7527][14.7527:7565](),[14.7565][14.6825:6919](),[14.6919][7.90:284](),[14.250][14.2225:2233](),[7.284][14.2225:2233](),[14.1242][14.2225:2233](),[14.3636][14.2225:2233](),[14.3789][14.2225:2233](),[14.6919][14.2225:2233](),[14.2225][14.2225:2233](),[14.2233][7.285:297](),[7.297][14.2233:2305](),[14.2233][14.2233:2305](),[14.614][14.7595:7603](),[14.727][14.7595:7603](),[14.1469][14.7595:7603](),[14.2305][14.7595:7603](),[14.7595][14.7595:7603](),[14.7603][14.0:172](),[14.172][14.7603:7610](),[14.7603][14.7603:7610](),[14.7610][14.2729:3189](),[14.3189][14.3790:3990](),[14.3990][14.511:678](),[14.678][14.7673:7688](),[14.3189][14.7673:7688](),[14.3990][14.7673:7688](),[14.7673][14.7673:7688](),[14.7688][14.5868:5981](),[14.5981][14.1510:1582](),[14.1582][12.1328:1508](),[12.1508][14.1682:1708](),[14.1682][14.1682:1708](),[14.1708][14.6023:6070](),[14.6023][14.6023:6070](),[14.6070][14.1709:1778](),[14.1778][12.1509:1682](),[12.1682][14.1873:1899](),[14.1873][14.1873:1899](),[14.1899][14.1470:1478](),[14.6112][14.1470:1478](),[14.7782][14.1470:1478](),[14.1478][14.173:205](),[14.205][14.251:321](),[14.321][14.6621:6629](),[14.449][14.6621:6629](),[14.6629][14.1901:1964](),[14.1964][11.89:148](),[11.148][14.295:462](),[14.295][14.295:462](),[14.462][14.1964:2003](),[14.1964][14.1964:2003](),[14.2003][14.322:482](),[14.482][14.2163:2213](),[14.2163][14.2163:2213](),[14.2213][14.483:641](),[14.641][14.2371:2381](),[14.2371][14.2371:2381](),[14.2381][14.2486:2495](),[14.2486][14.2486:2495](),[14.2495][14.237:262](),[14.262][14.2519:2530](),[14.2417][14.2519:2530](),[14.2519][14.2519:2530](),[14.2530][14.2418:2519](),[14.2519][2.0:105](),[2.105][14.2590:2608](),[14.335][14.2590:2608](),[14.2590][14.2590:2608](),[14.1834][14.2612:2634](),[14.2608][14.2612:2634](),[14.3922][14.2612:2634](),[14.2612][14.2612:2634](),[14.2634][14.2609:2789](),[14.2789][14.309:465](),[14.465][14.2789:2829](),[14.955][14.2789:2829](),[14.2789][14.2789:2829](),[14.2829][14.2634:2646](),[14.2634][14.2634:2646](),[14.2646][14.2830:2942](),[14.2942][14.706:1604](),[14.1604][14.3083:3093](),[14.3083][14.3083:3093](),[14.1093][14.6722:6734](),[14.3107][14.6722:6734](),[14.7972][14.6722:6734](),[14.1106][14.7972:7981](),[14.6734][14.7972:7981](),[14.7972][14.7972:7981]()
    <table class="layoutTable">
    <tr>
    <th>Build ID:</th>
    <td>[% build.id %]</td>
    </tr>
    <tr>
    <th>Status:</th>
    <td>
    [% IF build.finished %]
    [% IF build.resultInfo.buildstatus == 0 %]
    <img src="/static/images/success.gif" alt="Succeeded" />
    <strong>Success</strong>
    [% ELSIF build.resultInfo.buildstatus == 1 %]
    <img src="/static/images/failure.gif" alt="Failed" />
    <span class="error">Build returned a non-zero exit code</span>
    [% ELSIF build.resultInfo.buildstatus == 2 %]
    <img src="/static/images/failure.gif" alt="Failed" />
    <span class="error">A dependency of the build failed</span>
    [% ELSIF build.resultInfo.buildstatus == 4 %]
    <img src="/static/images/failure.gif" alt="Failed" />
    <span class="error">Cancelled by user</span>
    [% ELSIF build.resultInfo.buildstatus == 5 %]
    <img src="/static/images/failure.gif" alt="Failed" />
    <span class="error">Build inhibited because a dependency previously failed to build</span>
    [% failedDep = build.resultInfo.failedDep %]
    (namely, <a href="[% c.uri_for('/build' failedDep.build.id 'nixlog' failedDep.stepnr) %]"><tt>[% failedDep.outpath %]</tt></a>)
    [% ELSE %]
    <img src="/static/images/failure.gif" alt="Failed" />
    <span class="error">Build failed</span>
    (see <a href="#nix-error">below</a>)
    [% END %]
    [% IF c.user_exists && (build.resultInfo.buildstatus == 3 || build.resultInfo.buildstatus == 4) %]
    <form action="[% c.uri_for('/build' build.id 'restart') %]" method="post" class="inline">
    <button id="restart" type="submit">Restart</button>
    </form>
    [% END %]
    [% ELSIF build.schedulingInfo.busy %]
    <strong>Build in progress</strong>
    since [% INCLUDE renderDateTime timestamp = build.schedulingInfo.starttime %]
    [% ELSE %]
    <strong>Scheduled to be built</strong>
    [% IF c.user_exists %]
    <form action="[% c.uri_for('/build' build.id 'cancel') %]" method="post" class="inline">
    <button id="cancel" type="submit">Cancel</button>
    </form>
    [% END %]
    [% END %]
    </td>
    </tr>
    <tr>
    <th>Project:</th>
    <td>[% INCLUDE renderProjectName project=project.name %]</td>
    </tr>
    <tr>
    <th>Jobset:</th>
    <td>[% INCLUDE renderJobsetName project=project.name jobset=jobset.name %]</td>
    </tr>
    <tr>
    <th>Job name:</th>
    <td>[% INCLUDE renderJobName project=project.name jobset=jobset.name job=job.name %]</td>
    </tr>
    [% IF build.nixexprinput %]
    <tr>
    <th>Nix expression:</th>
    <td>file <tt>[% HTML.escape(build.nixexprpath) %]</tt> in input <tt>[% HTML.escape(build.nixexprinput) %]</tt></td>
    </tr>
    [% END %]
    <tr>
    <th>Nix name:</th>
    <td><tt>[% build.nixname %]</tt></td>
    </tr>
    [% IF build.resultInfo.releasename %]
    <tr>
    <th>Release name:</th>
    <td><tt>[% HTML.escape(build.resultInfo.releasename) %]</tt></td>
    </tr>
    [% END %]
    <tr>
    <th>Short description:</th>
    <td>[% IF build.description %][% HTML.escape(build.description) %][% ELSE %]<em>(not given)</em>[% END %]</td>
    </tr>
    <tr>
    <th>Long description:</th>
    <td>[% IF build.longdescription %][% HTML.escape(build.longdescription) %][% ELSE %]<em>(not given)</em>[% END %]</td>
    </tr>
    <tr>
    <th>License:</th>
    <td>[% IF build.license %][% HTML.escape(build.license) %][% ELSE %]<em>(not given)</em>[% END %]</td>
    </tr>
    <tr>
    <th>Homepage:</th>
    <td>[% IF build.homepage %]<a [% HTML.attributes(href => build.homepage) %]>[% HTML.escape(build.homepage) %]</a>[% ELSE %]<em>(not given)</em>[% END %]</td>
    </tr>
    <tr>
    <th>Maintainer(s):</th>
    <td>[% IF build.maintainers %]<tt>[% HTML.escape(build.maintainers) %]</tt>[% ELSE %]<em>(not given)</em>[% END %]</td>
    </tr>
    <tr>
    <th>System:</th>
    <td><tt>[% build.system %]</tt></td>
    </tr>
    <tr>
    <th>Derivation store path:</th>
    <td>
    <tt>[% build.drvpath %]</tt>
    [% IF drvAvailable %]
    (build-time dependencies: <a href="[% c.uri_for('/build' build.id 'buildtime-deps') %]">graph</a> | <a href="[% c.uri_for('/build' build.id 'deps') %]#buildtime">list</a>)
    [% END %]
    </td>
    </tr>
    <tr>
    <th>Output store path:</th>
    <td>
    <tt>[% build.outpath %]</tt>
    [% IF available %]
    (runtime dependencies: <a href="[% c.uri_for('/build' build.id 'runtime-deps') %]">graph</a> | <a href="[% c.uri_for('/build' build.id 'deps') %]#runtime">list</a>)
    [% END %]
    </td>
    </tr>
    <tr>
    <th>Time added:</th>
    <td>[% INCLUDE renderDateTime timestamp = build.timestamp %]</td>
    </tr>
    [% IF build.finished && build.resultInfo.buildstatus != 4 %]
    [% IF build.resultInfo.iscachedbuild && cachedBuild %]
    <tr>
    <th>Cached build:</th>
    <td><a href="[% c.uri_for('/build' cachedBuild.id ) %]">[% cachedBuild.id %]</a></td>
    </tr>
    [% END %]
    <tr>
    <th>Build started:</th>
    <td>[% IF build.resultInfo.starttime %][% INCLUDE renderDateTime timestamp = build.resultInfo.starttime %][% ELSE %]<em>(cached build)</em>[% END %]</td>
    </tr>
    <tr>
    <th>Build finished:</th>
    <td>[% IF build.resultInfo.stoptime %][% INCLUDE renderDateTime timestamp = build.resultInfo.stoptime %][% ELSE %]<em>(cached build)</em>[% END %]</td>
    </tr>
    <tr>
    <th>Duration:</th>
    <td>
    [% IF build.resultInfo.iscachedbuild %]
    <em>(cached build)</em>
    [% ELSE %]
    [% INCLUDE renderDuration duration = build.resultInfo.stoptime - build.resultInfo.starttime %]
    [% END %]
    </td>
    </tr>
    [% IF build.resultInfo.logfile %]
    <tr>
    <th>Logfile:</th>
    <td>
    <a href="[% c.uri_for('/build' build.id 'log') %]"><strong>Available</strong></a>
    (<a href="[% c.uri_for('/build' build.id 'log' 'raw') %]">raw</a>,
    <a href="[% c.uri_for('/build' build.id 'log' 'tail') %]">tail</a>)
    </td>
    </tr>
    [% END %]
    [% END %]
    [% IF !build.finished %]
    <tr>
    <th>Priority:</th>
    <td>[% build.schedulingInfo.priority %]</td>
    </tr>
    [% END %]
    [% IF build.finished && build.buildproducts %]
    <tr>
    <th>Availability:</th>
    <td>
    [% IF !available %]
    <em>Build output is no longer available</em>
    [% ELSIF build.resultInfo.keep %]
    <em>Build output will be kept permanently</em>
    [% IF c.user_exists %]
    <form action="[% c.uri_for('/build' build.id 'keep' 0) %]" method="post" class="inline">
    <button id="unkeep" type="submit">Unkeep</button>
    </form>
    [% END %]
    [% ELSE %]
    <em>Build output is available, but may be garbage-collected</em>
    [% IF c.user_exists %]
    <form action="[% c.uri_for('/build' build.id 'keep' 1) %]" method="post" class="inline">
    <button id="keep" type="submit">Keep</button>
    </form>
    [% END %]
    [% END %]
    </td>
    </tr>
    [% END %]
    </table>
    [14.7461]
    [14.1]
    <div id="generic-tabs">
    <ul>
    <li><a href="#tabs-summary">Summary</a></li>
    <li><a href="#tabs-information">Information</a></li>
    <li><a href="#tabs-buildinputs">Build Inputs</a></li>
    [% IF build.buildsteps %]<li><a href="#tabs-buildsteps">Build Steps</a></li>[% END %]
    [% IF build.dependents %]<li><a href="#tabs-usedby">Used by</a></li>[% END%]
    </ul>
    <div id="tabs-summary">
    <table class="statusTable">
    <tr>
    <td>
    [% INCLUDE renderBuildStatusIcon size=128, build=build %]
    </td>
    <td>
    <table class="layoutTable">
    <tr>
    <th>Build ID:</th>
    <td>[% build.id %]</td>
    </tr>
    [% IF build.resultInfo.releasename %]
    <tr>
    <th>Release name:</th>
    <td><tt>[% HTML.escape(build.resultInfo.releasename) %]</tt></td>
    </tr>
    [% ELSE %]
    <tr>
    <th>Nix name:</th>
    <td><tt>[% build.nixname %]</tt></td>
    </tr>
    [% END %]
    <tr>
    <th>Status:</th>
    <td>
    [% INCLUDE renderStatus build=build %]
    </td>
    </tr>
    <tr>
    <th>System:</th>
    <td><tt>[% build.system %]</tt></td>
    </tr>
    [% IF !build.schedulingInfo %]
    <tr>
    <th>Duration:</th>
    <td>
    [% IF build.resultInfo.iscachedbuild %]
    (cached from [% INCLUDE renderFullBuildLink build=cachedBuild %])
    [% ELSE %]
    [% INCLUDE renderDuration duration = build.resultInfo.stoptime - build.resultInfo.starttime %]
    [% END %]
    </td>
    </tr>
    [% END %]
    [% IF build.resultInfo.logfile %]
    <tr>
    <th>Logfile:</th>
    <td>
    <a href="[% c.uri_for('/build' build.id 'log') %]"><strong>Available</strong></a>
    (<a href="[% c.uri_for('/build' build.id 'log' 'raw') %]">raw</a>,
    <a href="[% c.uri_for('/build' build.id 'log' 'tail') %]">tail</a>)
    </td>
    </tr>
    [% END %]
    </table>
    </td>
    </tr>
    </table>
    [% IF c.user_exists && available %]
    <form action="[% c.uri_for('/build' build.id 'add-to-release') %]" method="post">
    <p>Add to release: <input type="text" class="string" name="name" />
    <button type="submit"><img src="/static/images/success.gif" />Apply</button></p>
    </form>
    [% END %]
    [% IF c.user_exists %]
    <p>[<a href="[% c.uri_for('/build' build.id 'clone') %]">Clone this build</a>]</p>
    [% END %]
  • replacement in src/root/build.tt at line 165
    [14.2][6.130:166](),[6.166][14.852:1105](),[14.852][14.852:1105]()
    [% IF c.user_exists && available %]
    <form action="[% c.uri_for('/build' build.id 'add-to-release') %]" method="post">
    <p>Add to release: <input type="text" class="string" name="name" />
    <button type="submit"><img src="/static/images/success.gif" />Apply</button></p>
    </form>
    [% END %]
    [14.2]
    [14.1105]
    [% IF build.buildproducts %]
  • replacement in src/root/build.tt at line 167
    [14.1106][14.610:726]()
    [% IF c.user_exists %]
    <p>[<a href="[% c.uri_for('/build' build.id 'clone') %]">Clone this build</a>]</p>
    [% END %]
    [14.1106]
    [14.1106]
    <h2>Build products</h2>
    [% IF !available %]
    <p class="error">Note: this build is no longer available.</p>
    [% END %]
    [% INCLUDE renderProductList latestRoot=['/job' build.project.name build.jobset.name build.job.name 'latest'] %]
    [% END %]
  • edit in src/root/build.tt at line 178
    [14.1108][14.2:31](),[14.2][14.2:31]()
    [% IF build.buildproducts %]
  • replacement in src/root/build.tt at line 179
    [14.32][14.32:56]()
    <h2>Build products</h2>
    [14.32]
    [14.56]
    [% IF build.finished %]
    [% IF build.buildsteps && (build.resultInfo.buildstatus == 2 || build.resultInfo.buildstatus == 5)%]
    [% INCLUDE renderBuildSteps onlyFailed=1 %]
    [% END %]
  • replacement in src/root/build.tt at line 184
    [14.57][14.57:151]()
    [% IF !available %]
    <p class="error">Note: this build is no longer available.</p>
    [% END %]
    [14.57]
    [14.151]
    [% IF build.resultInfo.errormsg && build.resultInfo.buildstatus != 5 %]
    <h2 id="nix-error">Nix error output</h2>
    <pre class="buildlog">
    [% HTML.escape(build.resultInfo.errormsg) -%]
    </pre>
    [% END %]
    [% ELSIF build.schedulingInfo.busy %]
    <h2>Log</h2>
    <pre class="buildlog">
    [% HTML.escape(logtext) -%]
    </pre>
    [% END %]
    </div>
    <div id="tabs-information">
  • replacement in src/root/build.tt at line 202
    [14.152][14.152:265]()
    [% INCLUDE renderProductList latestRoot=['/job' build.project.name build.jobset.name build.job.name 'latest'] %]
    [14.152]
    [14.265]
    <h2>Information</h2>
    <table class="layoutTable">
    <tr>
    <th>Build ID:</th>
    <td>[% build.id %]</td>
    </tr>
    <tr>
    <th>Status:</th>
    <td>
    [% INCLUDE renderStatus build=build %]
    </td>
    </tr>
    <tr>
    <th>Project:</th>
    <td>[% INCLUDE renderProjectName project=project.name %]</td>
    </tr>
    <tr>
    <th>Jobset:</th>
    <td>[% INCLUDE renderJobsetName project=project.name jobset=jobset.name %]</td>
    </tr>
    <tr>
    <th>Job name:</th>
    <td>[% INCLUDE renderJobName project=project.name jobset=jobset.name job=job.name %]</td>
    </tr>
    [% IF build.nixexprinput %]
    <tr>
    <th>Nix expression:</th>
    <td>file <tt>[% HTML.escape(build.nixexprpath) %]</tt> in input <tt>[% HTML.escape(build.nixexprinput) %]</tt></td>
    </tr>
    [% END %]
    <tr>
    <th>Nix name:</th>
    <td><tt>[% build.nixname %]</tt></td>
    </tr>
    [% IF build.resultInfo.releasename %]
    <tr>
    <th>Release name:</th>
    <td><tt>[% HTML.escape(build.resultInfo.releasename) %]</tt></td>
    </tr>
    [% END %]
    <tr>
    <th>Short description:</th>
    <td>[% IF build.description %][% HTML.escape(build.description) %][% ELSE %]<em>(not given)</em>[% END %]</td>
    </tr>
    <tr>
    <th>Long description:</th>
    <td>[% IF build.longdescription %][% HTML.escape(build.longdescription) %][% ELSE %]<em>(not given)</em>[% END %]</td>
    </tr>
    <tr>
    <th>License:</th>
    <td>[% IF build.license %][% HTML.escape(build.license) %][% ELSE %]<em>(not given)</em>[% END %]</td>
    </tr>
    <tr>
    <th>Homepage:</th>
    <td>[% IF build.homepage %]<a [% HTML.attributes(href => build.homepage) %]>[% HTML.escape(build.homepage) %]</a>[% ELSE %]<em>(not given)</em>[% END %]</td>
    </tr>
    <tr>
    <th>Maintainer(s):</th>
    <td>[% IF build.maintainers %]<tt>[% HTML.escape(build.maintainers) %]</tt>[% ELSE %]<em>(not given)</em>[% END %]</td>
    </tr>
    <tr>
    <th>System:</th>
    <td><tt>[% build.system %]</tt></td>
    </tr>
    <tr>
    <th>Derivation store path:</th>
    <td>
    <tt>[% build.drvpath %]</tt>
    [% IF drvAvailable %]
    (build-time dependencies: <a href="[% c.uri_for('/build' build.id 'buildtime-deps') %]">graph</a> | <a href="[% c.uri_for('/build' build.id 'deps') %]#buildtime">list</a>)
    [% END %]
    </td>
    </tr>
    <tr>
    <th>Output store path:</th>
    <td>
    <tt>[% build.outpath %]</tt>
    [% IF available %]
    (runtime dependencies: <a href="[% c.uri_for('/build' build.id 'runtime-deps') %]">graph</a> | <a href="[% c.uri_for('/build' build.id 'deps') %]#runtime">list</a>)
    [% END %]
    </td>
    </tr>
    <tr>
    <th>Time added:</th>
    <td>[% INCLUDE renderDateTime timestamp = build.timestamp %]</td>
    </tr>
    [% IF build.finished && build.resultInfo.buildstatus != 4 %]
    [% IF build.resultInfo.iscachedbuild && cachedBuild %]
    <tr>
    <th>Cached build:</th>
    <td>[% INCLUDE renderFullBuildLink build=cachedBuild %]</td>
    </tr>
    [% END %]
    <tr>
    <th>Build started:</th>
    <td>[% IF build.resultInfo.starttime %][% INCLUDE renderDateTime timestamp = build.resultInfo.starttime %][% ELSE %]<em>(cached build)</em>[% END %]</td>
    </tr>
    <tr>
    <th>Build finished:</th>
    <td>[% IF build.resultInfo.stoptime %][% INCLUDE renderDateTime timestamp = build.resultInfo.stoptime %][% ELSE %]<em>(cached build)</em>[% END %]</td>
    </tr>
    <tr>
    <th>Duration:</th>
    <td>
    [% IF build.resultInfo.iscachedbuild %]
    <em>(cached build)</em>
    [% ELSE %]
    [% INCLUDE renderDuration duration = build.resultInfo.stoptime - build.resultInfo.starttime %]
    [% END %]
    </td>
    </tr>
    [% IF build.resultInfo.logfile %]
    <tr>
    <th>Logfile:</th>
    <td>
    <a href="[% c.uri_for('/build' build.id 'log') %]"><strong>Available</strong></a>
    (<a href="[% c.uri_for('/build' build.id 'log' 'raw') %]">raw</a>,
    <a href="[% c.uri_for('/build' build.id 'log' 'tail') %]">tail</a>)
    </td>
    </tr>
    [% END %]
    [% END %]
    [% IF !build.finished %]
    <tr>
    <th>Priority:</th>
    <td>[% build.schedulingInfo.priority %]</td>
    </tr>
    [% END %]
    [% IF build.finished && build.buildproducts %]
    <tr>
    <th>Availability:</th>
    <td>
    [% IF !available %]
    <em>Build output is no longer available</em>
    [% ELSIF build.resultInfo.keep %]
    <em>Build output will be kept permanently</em>
    [% IF c.user_exists %]
    <form action="[% c.uri_for('/build' build.id 'keep' 0) %]" method="post" class="inline">
    <button id="unkeep" type="submit">Unkeep</button>
    </form>
    [% END %]
    [% ELSE %]
    <em>Build output is available, but may be garbage-collected</em>
    [% IF c.user_exists %]
    <form action="[% c.uri_for('/build' build.id 'keep' 1) %]" method="post" class="inline">
    <button id="keep" type="submit">Keep</button>
    </form>
    [% END %]
    [% END %]
    </td>
    </tr>
    [% END %]
    </table>
    </div>
    <div id="tabs-buildinputs">
    <h2>Build inputs</h2>
    <table class="tablesorter">
    <thead>
    <tr><th>Name</th><th>Type</th><th>Value</th><th>Revision</th><th>Store path</th></tr>
    </thead>
    <tbody>
    [% FOREACH input IN build.inputs -%]
    <tr>
    <td><tt>[% input.name %]</tt></td>
    <td><tt>[% type = input.type; inputTypes.$type %]</tt></td>
    <td>
    [% IF input.type == "build" || input.type == "sysbuild" %]
    [% INCLUDE renderFullBuildLink build=input.dependency %]</a>
    [% ELSIF input.type == "string" || input.type == "boolean" %]
    <tt>"[% input.value %]"</tt>
    [% ELSE %]
    <tt>[% input.uri %]</tt>
    [% END %]
    </td>
    <td>[% IF input.revision %][% input.revision %][% END %]</td>
    <td><tt>[% input.path %]</tt></td>
    </tr>
    [% END -%]
    </tbody>
    </table>
    </div>
  • edit in src/root/build.tt at line 388
    [14.266][14.266:276]()
    [% END %]
  • edit in src/root/build.tt at line 389
    [14.7982][14.7982:7983](),[14.7983][14.2184:2245](),[14.2245][14.4160:4250](),[14.1442][14.2297:2318](),[14.4250][14.2297:2318](),[14.2297][14.2297:2318](),[14.2318][14.3961:4002](),[14.4002][14.2364:2375](),[14.2364][14.2364:2375](),[14.2375][14.1443:1486](),[14.1486][14.2305:2373](),[14.2373][14.1529:1542](),[14.1529][14.1529:1542](),[14.1542][10.2135:2204](),[10.2204][14.642:812](),[14.1583][14.642:812](),[14.812][14.2786:2858](),[14.3817][14.2786:2858](),[14.4735][14.2786:2858](),[14.3162][14.2786:2858](),[14.2858][14.9:50](),[14.3227][14.9:50](),[14.50][14.1675:1767](),[14.256][14.1675:1767](),[14.3272][14.1675:1767](),[14.1675][14.1675:1767](),[14.1767][14.4251:4321](),[14.4321][14.1767:1810](),[14.1767][14.1767:1810](),[14.1810][14.2476:2523](),[14.2476][14.2476:2523](),[14.2523][14.3948:3949](),[14.3949][14.6735:6736](),[14.2523][14.6735:6736]()
    <h2>Build inputs</h2>
    <table class="tablesorter">
    <thead>
    <tr><th>Name</th><th>Type</th><th>Value</th><th>Revision</th><th>Store path</th></tr>
    </thead>
    <tbody>
    [% FOREACH input IN build.inputs -%]
    <tr>
    <td><tt>[% input.name %]</tt></td>
    <td><tt>[% type = input.type; inputTypes.$type %]</tt></td>
    <td>
    [% IF input.type == "build" || input.type == "sysbuild" %]
    Job [% INCLUDE renderFullJobNameOfBuild build=input.dependency %] <a href="[% c.uri_for('/build' input.dependency.id) %]">build [% input.dependency.id %]</a>
    [% ELSIF input.type == "string" || input.type == "boolean" %]
    <tt>"[% input.value %]"</tt>
    [% ELSE %]
    <tt>[% input.uri %]</tt>
    [% END %]
    </td>
    <td>[% IF input.revision %][% input.revision %][% END %]</td>
    <td><tt>[% input.path %]</tt></td>
    </tr>
    [% END -%]
    </tbody>
    </table>
  • replacement in src/root/build.tt at line 390
    [14.3976][14.2523:2524](),[14.6736][14.2523:2524](),[14.2523][14.2523:2524](),[14.2524][14.2647:2684](),[14.2684][14.3998:4037](),[14.3998][14.3998:4037](),[14.4037][14.1013:1083](),[14.1083][14.4090:4155](),[14.4090][14.4090:4155](),[14.4155][14.3923:3991](),[14.1902][14.0:58](),[14.3991][14.0:58](),[14.4155][14.0:58](),[14.58][14.1903:1986](),[14.179][14.4166:4214](),[14.1986][14.4166:4214](),[14.4166][14.4166:4214](),[14.4214][14.109:289](),[14.289][14.4261:4288](),[14.4261][14.4261:4288](),[14.4288][14.1084:1118](),[14.1118][2.106:189](),[2.189][14.1168:1189](),[14.1168][14.1168:1189](),[14.1189][14.2685:2721](),[14.2721][2.190:287](),[2.287][14.2785:2808](),[14.2785][14.2785:2808](),[14.2808][2.288:367](),[2.367][14.2854:2876](),[14.2854][14.2854:2876](),[14.2876][14.1233:1280](),[14.1233][14.1233:1280](),[14.1280][14.4288:4322](),[14.4288][14.4288:4322](),[14.4322][14.2877:3047](),[14.3047][14.4360:4442](),[14.4360][14.4360:4442](),[14.4442][14.3048:3128](),[14.3128][14.4517:4537](),[14.4517][14.4517:4537](),[14.4537][14.290:322](),[14.322][14.466:582](),[14.582][14.402:422](),[14.1034][14.402:422](),[14.2029][14.402:422](),[14.402][14.402:422](),[14.422][14.4615:4676](),[14.4615][14.4615:4676]()
    <h2 id="buildsteps">Build steps</h2>
    <table class="tablesorter">
    <thead>
    <tr><th>Nr</th><th>What</th><th>Duration</th><th>Status</th></tr>
    </thead>
    <tbody>
    [% FOREACH step IN build.buildsteps -%]
    [% log = c.uri_for('/build' build.id 'nixlog' step.stepnr) %]
    <tr class="[% IF step.logfile %]clickable[% END %]"
    [% IF step.logfile %] onclick="window.location = '[% log %]'" [% END %]>
    <td>[% step.stepnr %]</td>
    <td>
    [% IF step.type == 0 %]
    Build of <tt>[% step.outpath %]</tt>
    [% ELSE %]
    Substitution of <tt>[% step.outpath %]</tt>
    [% END %]
    </td>
    <td>
    [% IF step.busy == 0 %]
    [% INCLUDE renderDuration duration = step.stoptime - step.starttime %]
    [% ELSE %]
    [% IF build.finished %]
    [% INCLUDE renderDuration duration = build.resultInfo.stoptime - step.starttime %]
    [% ELSE %]
    [% INCLUDE renderDuration duration = curTime - step.starttime %]
    [% END %]
    [% END %]
    </td>
    <td>
    [% IF step.busy == 1 %]
    [% IF build.finished %]
    <span class="error">Aborted</span>
    [% ELSE %]
    <strong>Building</strong>
    [% END %]
    [% ELSIF step.status == 0 %]
    Succeeded
    [% ELSE %]
    <span class="error">Failed: [% HTML.escape(step.errormsg) %]</span>
    [% END %]
    [% IF step.logfile %]
    (<a href="[% log %]">log</a>, <a href="[% "$log/raw" %]">raw</a>, <a href="[% "$log/tail" %]">tail</a>)
    [% END %]
    </td>
    </tr>
    [% END %]
    </tbody>
    </table>
    [14.3976]
    [14.4676]
    <div id="tabs-buildsteps">
    [% INCLUDE renderBuildSteps onlyFailed=0 %]
    </div>
  • replacement in src/root/build.tt at line 394
    [14.4686][14.4686:4687]()
    [14.4686]
    [14.4687]
  • edit in src/root/build.tt at line 396
    [14.4688][14.6737:6761](),[14.2524][14.6737:6761](),[14.6761][14.3129:3130](),[14.3130][14.1107:1108](),[14.6761][14.1107:1108](),[14.1108][14.3360:3432](),[14.3166][14.1108:1109](),[14.3432][14.1108:1109](),[14.1108][14.1108:1109](),[14.1109][14.3167:3296](),[14.1139][14.2524:2525](),[14.6761][14.2524:2525](),[14.2524][14.2524:2525](),[14.8007][14.375:376]()
    [% IF build.finished %]
    [% IF build.resultInfo.errormsg && build.resultInfo.buildstatus != 5 %]
    <h2 id="nix-error">Nix error output</h2>
    <pre class="buildlog">
    [% HTML.escape(build.resultInfo.errormsg) -%]
    </pre>
    [% END %]
  • edit in src/root/build.tt at line 397
    [14.4210]
    [14.145]
    <div id="tabs-usedby">
  • replacement in src/root/build.tt at line 399
    [14.146][14.146:265](),[14.265][14.3273:3353](),[14.3353][14.330:351](),[14.330][14.330:351](),[14.351][14.4211:4256](),[14.4256][14.406:417](),[14.406][14.406:417](),[14.417][14.846:1006](),[14.1006][14.590:633](),[14.3333][14.590:633](),[14.3983][14.590:633](),[14.4422][14.590:633](),[14.4896][14.590:633](),[14.590][14.590:633](),[14.633][14.4423:4474](),[14.4474][14.1007:1087](),[14.1087][14.714:752](),[14.4553][14.714:752](),[14.5203][14.714:752](),[14.714][14.714:752](),[14.752][14.8433:8443](),[14.8433][14.8433:8443]()
    <h2>Used by</h2>
    <p>The following builds have used this build as an input:</p>
    <table class="tablesorter">
    <thead>
    <tr><th>Build</th><th>Input name</th><th>System</th><th>Timestamp</th></tr>
    </thead>
    <tbody>
    [% FOREACH input IN build.dependents -%]
    <tr>
    <td>Job [% INCLUDE renderFullJobNameOfBuild build=input.build %] <a href="[% c.uri_for('/build' input.build.id) %]">build [% input.build.id %]</a></td>
    <td><tt>[% input.name %]</tt></td>
    <td><tt>[% input.build.system %]</tt></td>
    <td>[% INCLUDE renderDateTime timestamp = input.build.timestamp %]</td>
    </tr>
    [% END -%]
    </tbody>
    </table>
    [14.146]
    [14.753]
    <h2>Used by</h2>
    <p>The following builds have used this build as an input:</p>
    <table class="tablesorter">
    <thead>
    <tr><th>Build</th><th>Input name</th><th>System</th><th>Timestamp</th></tr>
    </thead>
    <tbody>
    [% FOREACH input IN build.dependents -%]
    <tr>
    <td>[% INCLUDE renderFullBuildLink build=input.build %]</td>
    <td><tt>[% input.name %]</tt></td>
    <td><tt>[% input.build.system %]</tt></td>
    <td>[% INCLUDE renderDateTime timestamp = input.build.timestamp %]</td>
    </tr>
    [% END -%]
    </tbody>
    </table>
    </div>
  • edit in src/root/build.tt at line 420
    [14.763][14.1152:1192]()
    [% ELSIF build.schedulingInfo.busy %]
  • edit in src/root/build.tt at line 421
    [14.8444]
    [14.764]
    </div>
  • replacement in src/root/build.tt at line 423
    [14.765][14.1193:1206]()
    <h2>Log</h2>
    [14.765]
    [14.1206]
    <script type="text/javascript">
    $("#generic-tabs").tabs();
    </script>
  • edit in src/root/build.tt at line 427
    [14.1229][14.1229:1252](),[14.1252][14.3299:3327](),[14.3327][14.1267:1274](),[14.1267][14.1267:1274]()
    <pre class="buildlog">
    [% HTML.escape(logtext) -%]
    </pre>
  • edit in src/root/build.tt at line 431
    [14.8455][14.6762:6774]()
    [% END %]
  • edit in src/root/common.tt at line 199
    [14.2986]
    [% BLOCK renderFullBuildLink; %]
    Job [% INCLUDE renderFullJobNameOfBuild build=build %] <a href="[% c.uri_for('/build' build.id) %]">build [% build.id %]
    [% END %]
    [% BLOCK renderBuildStatusIcon; %]
    [% IF build.finished %]
    [% IF build.resultInfo.buildstatus == 0 %]
    <img src="/static/images/checkmark_[% size %].png" alt="Succeeded" />
    [% ELSIF build.resultInfo.buildstatus == 1 %]
    <img src="/static/images/error_[% size %].png" alt="Failed" />
    [% ELSIF build.resultInfo.buildstatus == 2 %]
    <img src="/static/images/error_[% size %].png" alt="Failed" />
    [% ELSIF build.resultInfo.buildstatus == 4 %]
    <img src="/static/images/error_[% size %].png" alt="Failed" />
    [% ELSIF build.resultInfo.buildstatus == 5 %]
    <img src="/static/images/error_[% size %].png" alt="Failed" />
    [% ELSE %]
    <img src="/static/images/error_[% size %].png" alt="Failed" />
    [% END %]
    [% ELSIF build.schedulingInfo.busy %]
    <img src="/static/images/help_[% size %].png" alt="Budy" />
    [% ELSE %]
    <img src="/static/images/help_[% size %].png" alt="Scheduled" />
    [% END %]
    [% END %]
    [% BLOCK renderStatus; %]
    [% IF build.finished %]
    [% IF build.resultInfo.buildstatus == 0 %]
    <img src="/static/images/success.gif" alt="Succeeded" />
    <strong>Success</strong>
    [% ELSIF build.resultInfo.buildstatus == 1 %]
    <img src="/static/images/failure.gif" alt="Failed" />
    <span class="error">Build returned a non-zero exit code</span>
    [% ELSIF build.resultInfo.buildstatus == 2 %]
    <img src="/static/images/failure.gif" alt="Failed" />
    <span class="error">A dependency of the build failed</span>
    [% ELSIF build.resultInfo.buildstatus == 4 %]
    <img src="/static/images/failure.gif" alt="Failed" />
    <span class="error">Cancelled by user</span>
    [% ELSIF build.resultInfo.buildstatus == 5 %]
    <img src="/static/images/failure.gif" alt="Failed" />
    <span class="error">Build inhibited because a dependency previously failed to build</span>
    [% failedDep = build.resultInfo.failedDep %]
    (namely, <a href="[% c.uri_for('/build' failedDep.build.id 'nixlog' failedDep.stepnr) %]"><tt>[% failedDep.outpath %]</tt></a>)
    [% ELSE %]
    <img src="/static/images/failure.gif" alt="Failed" />
    <span class="error">Build failed</span>
    (see <a href="#nix-error">below</a>)
    [% END %]
    [% IF c.user_exists && (build.resultInfo.buildstatus == 3 || build.resultInfo.buildstatus == 4) %]
    <form action="[% c.uri_for('/build' build.id 'restart') %]" method="post" class="inline">
    <button id="restart" type="submit">Restart</button>
    </form>
    [% END %]
    [% ELSIF build.schedulingInfo.busy %]
    <strong>Build in progress</strong>
    since [% INCLUDE renderDateTime timestamp = build.schedulingInfo.starttime %]
    [% ELSE %]
    <strong>Scheduled to be built</strong>
    [% IF c.user_exists %]
    <form action="[% c.uri_for('/build' build.id 'cancel') %]" method="post" class="inline">
    <button id="cancel" type="submit">Cancel</button>
    </form>
    [% END %]
    [% END %]
    [% END -%]
  • replacement in src/root/job.tt at line 12
    [9.332][9.332:348]()
    <h2>Status</h2>
    [9.332]
    [14.7855]
    <div id="generic-tabs">
    <ul>
    <li><a href="#tabs-status">Status</a></li>
    <li><a href="#tabs-channels">Channels</a></li>
    <li><a href="#tabs-latestbuilds">Latest builds</a></li>
    <li><a href="#tabs-statistics">Statistics</a></li>
    </ul>
    <div id="tabs-status">
    <h2>Finished builds</h2>
    [% INCLUDE renderBuildList builds=currentBuilds showStatusChange=0 %]
    [% IF runningBuilds %]
    <h2>Running builds</h2>
    [% INCLUDE renderBuildList builds=runningBuilds showStatusChange=0 %]
    [% END %]
    </div>
    <div id="tabs-channels">
    <p>This job provides the following Nix channels:</p>
    <ul>
    <li>
    <a href="[% c.uri_for('/job' project.name jobset.name job.name
    'channel' 'latest') %]"><tt>latest</tt></a> — contains the latest
    successful build for each platform.
    </li>
    <li>
    <a href="[% c.uri_for('/job' project.name jobset.name job.name
    'channel' 'all') %]"><tt>all</tt></a> — contains every successful
    build of this job.
    </li>
    </ul>
    </div>
    <div id="tabs-latestbuilds">
    <ul>
    <li><a href="[% c.uri_for('/job' project.name jobset.name job.name
    'latest') %]">Latest successful build.</a></li>
    [% FOREACH system IN systems %]
    <li><a href="[% c.uri_for('/job' project.name jobset.name job.name
    'latest-for' system.system) %]">Latest successful build for <tt>[%
    system.system %]</tt>.</a></li>
    [% END %]
    </ul>
    </div>
    <div id="tabs-statistics">
    [% INCLUDE showBuildStats %]
    </div>
    </div>
    <script type="text/javascript">
    $("#generic-tabs").tabs();
    </script>
  • edit in src/root/job.tt at line 62
    [14.7856][9.349:419](),[9.419][14.7856:7929](),[14.7856][14.7856:7929]()
    [% INCLUDE renderBuildList builds=currentBuilds showStatusChange=0 %]
    <h2>Channels</h2>
    <p>This job provides the following Nix channels:</p>
  • edit in src/root/job.tt at line 63
    [14.7930][14.7930:8312](),[14.8312][14.1252:1253](),[14.1253][14.8312:8313](),[14.8312][14.8312:8313](),[14.8313][14.1254:1277](),[14.1277][14.8313:8314](),[14.8313][14.8313:8314](),[14.8314][14.1278:1634](),[14.1634][14.8314:8366](),[14.8314][14.8314:8366]()
    <ul>
    <li>
    <a href="[% c.uri_for('/job' project.name jobset.name job.name
    'channel' 'latest') %]"><tt>latest</tt></a> — contains the latest
    successful build for each platform.
    </li>
    <li>
    <a href="[% c.uri_for('/job' project.name jobset.name job.name
    'channel' 'all') %]"><tt>all</tt></a> — contains every successful
    build of this job.
    </li>
    </ul>
    <h2>Latest builds</h2>
    <ul>
    <li><a href="[% c.uri_for('/job' project.name jobset.name job.name
    'latest') %]">Latest successful build.</a></li>
    [% FOREACH system IN systems %]
    <li><a href="[% c.uri_for('/job' project.name jobset.name job.name
    'latest-for' system.system) %]">Latest successful build for <tt>[%
    system.system %]</tt>.</a></li>
    [% END %]
    </ul>
    <h2>Statistics</h2>
    [% INCLUDE showBuildStats %]
  • replacement in src/root/jobset.tt at line 56
    [14.10376][14.10376:10518]()
    <h2>Information[% IF !edit %] <a class="smallLink" href="[% c.uri_for('/jobset' project.name jobset.name 'edit') %]">[Edit]</a>[% END %]</h2>
    [14.10376]
    [14.10518]
    [% BLOCK renderInputs %]
    <h3>Inputs</h3>
    <table class="tablesorter">
    <thead>
    <tr><th>Input name</th><th>Type</th><th>Values</th></tr>
    </thead>
    <tbody class="inputs">
    [% FOREACH input IN jobset.jobsetinputs -%]
    [% INCLUDE renderInput input=input baseName="input-$input.name" %]
    [% END %]
    [% IF edit %]
    <tr>
    <td colspan="3"><button type="button" class="add-input">Add a new input</button></td>
    </tr>
    [% END %]
    </tbody>
    </table>
  • replacement in src/root/jobset.tt at line 75
    [14.10519][14.10519:11104](),[14.11104][14.3017:3183](),[14.3183][8.3380:3720](),[14.3183][14.11104:11581](),[8.3720][14.11104:11581](),[14.11104][14.11104:11581]()
    <table class="layoutTable">
    [% IF edit %]
    <tr>
    <th>Identifier:</th>
    <td>[% INCLUDE maybeEditString param="name" value=jobset.name %]</td>
    </tr>
    [% END %]
    <tr>
    <th>Description:</th>
    <td>[% INCLUDE maybeEditString param="description" value=jobset.description %]</td>
    </tr>
    <tr>
    <th>Nix expression:</th>
    <td>
    <tt>[% INCLUDE maybeEditString param="nixexprpath" value=jobset.nixexprpath extraClass="shortString" %]</tt> in input
    <tt>[% INCLUDE maybeEditString param="nixexprinput" value=jobset.nixexprinput extraClass="shortString" %]</tt>
    </td>
    </tr>
    <tr>
    <th>Enabled:</th>
    <td>
    [% INCLUDE renderSelection param="enabled" curValue=jobset.enabled options={"1" = "Yes", "0" = "No"} %]
    </td>
    </tr>
    <tr>
    <th>Enable email notification:</th>
    <td>
    [% INCLUDE renderSelection param="enableemail" curValue=jobset.enableemail options={"1" = "Yes", "0" = "No"} %]
    </td>
    </tr>
    <tr>
    <th>Email override:</th>
    <td>
    [% INCLUDE maybeEditString param="emailoverride" value=jobset.emailoverride %]
    </td>
    </tr>
    [% IF !edit %]
    <tr>
    <th>Last checked:</th>
    <td>
    [% IF jobset.lastcheckedtime %]
    [% INCLUDE renderDateTime timestamp = jobset.lastcheckedtime -%][% IF jobset.errormsg -%]<em>, evaluation error</em>:
    <pre class="multiLineMsg error">[% HTML.escape(jobset.errormsg) %]</pre>
    [% ELSE %], <em>no errors</em>
    [% END %]
    [% ELSE %]
    <em>never</em>
    [% END %]
    </td>
    </tr>
    [% END %]
    </table>
    [14.10519]
    [14.11581]
    [% END %]
  • replacement in src/root/jobset.tt at line 78
    [14.11583][14.11583:11599]()
    <h3>Inputs</h3>
    [14.11583]
    [14.11599]
    <div id="generic-tabs">
    <ul>
    [% IF !edit -%]
    <li><a href="#tabs-information">Jobset</a></li>
    [% IF jobset.errormsg -%]<li><a href="#tabs-errors">Errors</a></li>[% END %]
    <li><a href="#tabs-jobs">Jobs ([% activeJobs.size %])</a></li>
    [% END %]
    <li><a href="#tabs-setup">Setup</a></li>
    [% IF !edit -%]
    <li><a href="#tabs-channels">Channels</a></li>
    <li><a href="#tabs-statistics">Statistics</a></li>
    [% END %]
    </ul>
    <div id="tabs-information">
    [% IF lastBuilds %]
    <h2>Most recent builds</h2>
    [% INCLUDE renderBuildList builds=lastBuilds %]
    [% END %]
    [% IF !edit && activeJobsStatus -%]
    <h2>Status</h2>
    <table class="activeJobsStatus">
    <thead><tr><th>Job</th>[% FOREACH s IN systems %]<th>[% s.system %]</th>[% END %]</tr></thead>
    <tbody>
    [% odd = 0 %]
    [% FOREACH j IN activeJobsStatus %]
    <tr class="[% IF odd %] odd [% END; odd = !odd -%]">
    <td>[% INCLUDE renderJobName project=project.name jobset = jobset.name job = j.get_column('job') %]</td>
    [% FOREACH s IN systems %]
    [% system = s.system %]
    [% systemStatus = j.get_column(system) %]
    <td>
    [% IF systemStatus != undef %]
    <a href="[% c.uri_for('/build' j.get_column(system _ '-build') ) %]">
    [% IF systemStatus == 0 %]
    <img src="/static/images/success.gif" alt="Succeeded" />
    [% ELSE %]
    <img src="/static/images/failure.gif" alt="Failed" />
    [% END %]
    </a>
    [% END %]
    </td>
    [% END %]
    </tr>
    [% END %]
    </tbody>
    </table>
    [% END %]
  • replacement in src/root/jobset.tt at line 127
    [14.11600][14.11600:12039](),[14.12039][5.0:498](),[5.498][14.12039:12223](),[14.12039][14.12039:12223](),[14.12223][14.1067:1203](),[14.1203][14.12346:12519](),[14.12346][14.12346:12519](),[14.12519][4.406:544](),[4.544][14.12644:12666](),[14.12644][14.12644:12666](),[14.13164][14.13164:13216]()
    <table class="tablesorter">
    <thead>
    <tr><th>Input name</th><th>Type</th><th>Values</th></tr>
    </thead>
    <tbody class="inputs">
    [% FOREACH input IN jobset.jobsetinputs -%]
    [% INCLUDE renderInput input=input baseName="input-$input.name" %]
    [% END %]
    [% IF edit %]
    <tr>
    <td colspan="3"><button type="button" class="add-input">Add a new input</button></td>
    </tr>
    [% END %]
    </tbody>
    </table>
    <h2>Channels</h2>
    <p>This jobset provides the following Nix channels:</p>
    <ul>
    <li>
    <a href="[% c.uri_for('/jobset' project.name jobset.name 'channel'
    'latest') %]"><tt>latest</tt></a> — contains the latest successful
    build of every job in this jobset.
    </li>
    <li>
    <a href="[% c.uri_for('/jobset' project.name jobset.name 'channel'
    'all') %]"><tt>all</tt></a> — contains every successful,
    non-garbage-collected build of every job in this project.
    </li>
    </ul>
    [% IF !edit %]
    <h2>Jobs</h2>
    <p>This jobset currently contains the following [% activeJobs.size %] jobs:
    <blockquote>
    [% IF activeJobs.size == 0 %]<em>(none)</em>[% END %]
    [% FOREACH j IN activeJobs %] [% INCLUDE renderJobName project=project.name jobset=jobset.name job=j.get_column('job') %] [% END %]
    </blockquote>
    </p>
    <p>This jobset used to contain the following [% inactiveJobs.size %] jobs:
    <blockquote>
    [% IF inactiveJobs.size == 0 %]<em>(none)</em>[% END %]
    [% FOREACH j IN inactiveJobs %] [% INCLUDE renderJobName project=project.name jobset=jobset.name job=j.get_column('job') %] [% END %]
    </blockquote>
    </p>
    <h2>Statistics</h2>
    [% INCLUDE showBuildStats %]
    [14.11600]
    [14.13216]
    </div>
    [% IF !edit -%]
    [% IF jobset.errormsg -%]
    <div id="tabs-errors">
    <h3>Evaluation error</h3>
    <pre class="multiLineMsg error">[% HTML.escape(jobset.errormsg) %]</pre>
    </div>
    [% END %]
    [% END %]
    <div id="tabs-setup">
    <h2>Information[% IF !edit %] <a class="smallLink" href="[% c.uri_for('/jobset' project.name jobset.name 'edit') %]">[Edit]</a>[% END %]</h2>
    <table class="layoutTable">
    [% IF edit %]
    <tr>
    <th>Identifier:</th>
    <td>[% INCLUDE maybeEditString param="name" value=jobset.name %]</td>
    </tr>
    [% END %]
    <tr>
    <th>Description:</th>
    <td>[% INCLUDE maybeEditString param="description" value=jobset.description %]</td>
    </tr>
    <tr>
    <th>Nix expression:</th>
    <td>
    <tt>[% INCLUDE maybeEditString param="nixexprpath" value=jobset.nixexprpath extraClass="shortString" %]</tt> in input
    <tt>[% INCLUDE maybeEditString param="nixexprinput" value=jobset.nixexprinput extraClass="shortString" %]</tt>
    </td>
    </tr>
    <tr>
    <th>Enabled:</th>
    <td>
    [% INCLUDE renderSelection param="enabled" curValue=jobset.enabled options={"1" = "Yes", "0" = "No"} %]
    </td>
    </tr>
    <tr>
    <th>Enable email notification:</th>
    <td>
    [% INCLUDE renderSelection param="enableemail" curValue=jobset.enableemail options={"1" = "Yes", "0" = "No"} %]
    </td>
    </tr>
    <tr>
    <th>Email override:</th>
    <td>
    [% INCLUDE maybeEditString param="emailoverride" value=jobset.emailoverride %]
    </td>
    </tr>
    [% IF !edit %]
    <tr>
    <th>Last checked:</th>
    <td>
    [% IF jobset.lastcheckedtime %]
    [% INCLUDE renderDateTime timestamp = jobset.lastcheckedtime -%][% IF jobset.errormsg -%]<em>, with errors!</em>
    [% ELSE %], <em>no errors</em>
    [% END %]
    [% ELSE %]
    <em>never</em>
    [% END %]
    </td>
    </tr>
    [% END %]
    </table>
  • edit in src/root/jobset.tt at line 192
    [14.13217]
    [14.13217]
    [% INCLUDE renderInputs %]
    </div>
    [% IF !edit -%]
    <div id="tabs-channels">
    <h2>Channels</h2>
    <p>This jobset provides the following Nix channels:</p>
    <ul>
    <li>
    <a href="[% c.uri_for('/jobset' project.name jobset.name 'channel'
    'latest') %]"><tt>latest</tt></a> — contains the latest successful
    build of every job in this jobset.
    </li>
    <li>
    <a href="[% c.uri_for('/jobset' project.name jobset.name 'channel'
    'all') %]"><tt>all</tt></a> — contains every successful,
    non-garbage-collected build of every job in this project.
    </li>
    </ul>
    </div>
    <div id="tabs-jobs">
    <h2>Jobs</h2>
    <p>This jobset currently contains the following [% activeJobs.size %] jobs:
    <blockquote>
    [% IF activeJobs.size == 0 %]<em>(none)</em>[% END %]
    [% FOREACH j IN activeJobs %] [% INCLUDE renderJobName project=project.name jobset=jobset.name job=j.get_column('job') %] [% END %]
    </blockquote>
    </p>
    <p>This jobset used to contain the following [% inactiveJobs.size %] jobs:
    <blockquote>
    [% IF inactiveJobs.size == 0 %]<em>(none)</em>[% END %]
    [% FOREACH j IN inactiveJobs %] [% INCLUDE renderJobName project=project.name jobset=jobset.name job=j.get_column('job') %] [% END %]
    </blockquote>
    </p>
    </div>
    <div id="tabs-statistics">
    <h2>Statistics</h2>
    [% INCLUDE showBuildStats %]
    </div>
    [% END %]
  • replacement in src/root/jobset.tt at line 247
    [14.13218][14.13218:13228]()
    [% END %]
    [14.13218]
    [14.13228]
    </div>
  • edit in src/root/jobset.tt at line 249
    [14.13229]
    [14.13229]
    <script type="text/javascript">
    $("#generic-tabs").tabs();
    </script>
  • edit in src/root/layout.tt at line 13
    [14.2185]
    [14.232]
    <link type="text/css" href="/static/js/jquery/css/smoothness/jquery-ui-1.7.2.custom.css" rel="Stylesheet" />
  • edit in src/root/layout.tt at line 18
    [14.384][13.249:362]()
    <link type="text/css" href="/static/js/jquery/css/smoothness/jquery-ui-1.7.2.custom.css" rel="Stylesheet" />
  • edit in src/root/overview.tt at line 3
    [14.19139][14.19139:19140]()
  • edit in src/root/overview.tt at line 4
    [14.19141][14.19141:19416]()
    <h1>Hydra Overview</h1>
    <p>Welcome to Hydra, the <a href="http://nixos.org/">Nix-based</a>
    continuous build system. Hydra continuously builds, tests and
    releases software packages from source repositories. <a
    href="http://nixos.org/hydra"><em>[Read more...]</em></a></p>
  • edit in src/root/project.tt at line 3
    [14.3053][14.3053:3054](),[14.3054][14.1715:1716](),[14.1715][14.1715:1716](),[14.2870][14.2870:2884](),[14.2884][14.2523:2680](),[14.2680][14.3043:3053](),[14.11899][14.3043:3053](),[14.3043][14.3043:3053]()
    [% IF edit %]
    <form action="[% IF create %][% c.uri_for('/create-project/submit') %][% ELSE %][% c.uri_for('/project' project.name 'submit') %][% END %]" method="post">
    [% END %]
  • edit in src/root/project.tt at line 4
    [14.3054][14.3054:3055]()
  • edit in src/root/project.tt at line 10
    [14.3166]
    [14.3166]
    <div id="generic-tabs">
    <ul>
    [% IF !edit %]
    <li><a href="#tabs-project">Project</a></li>
    [% END %]
    <li><a href="#tabs-settings">Settings</a></li>
    [% IF !edit %]
    <li><a href="#tabs-views">Views</a></li>
    <li><a href="#tabs-channels">Channels</a></li>
    <li><a href="#tabs-statistics">Statistics</a></li>
    [% END %]
    </ul>
  • replacement in src/root/project.tt at line 23
    [14.3167][14.20555:20686]()
    <h2>Information[% IF !edit %] <a class="smallLink" href="[% c.uri_for('/project' project.name 'edit') %]">[Edit]</a>[% END %]</h2>
    [14.3167]
    [14.3196]
    [% IF !edit %]
    <div id="tabs-project">
    <h2>Jobsets</h2>
    [% IF project.jobsets.size > 0 %]
    <p>This project has the following jobsets:</p>
    <table class="tablesorter">
    <thead>
    <tr>
    <th>Id</th>
    <th>Description</th>
    <th>Last evaluated</th>
    </tr>
    </thead>
    <tbody>
    [% FOREACH j IN project.jobsets %]
    <tr class="clickable [% IF odd %] odd [% END; odd = !odd %]"
    onclick="window.location = '[% c.uri_for('/jobset' project.name j.name) %]'">
    <td>[% INCLUDE renderJobsetName project = project.name jobset = j.name %]</td>
    <td>[% HTML.escape(j.description) %]</td>
    <td>[% INCLUDE renderDateTime timestamp = j.lastcheckedtime %]</td>
    </tr>
    [% END %]
    </tbody>
    </table>
    [% ELSE %]
    <p>No jobsets have been defined yet.</p>
    [% END %]
    <p><a href="[% c.uri_for(c.controller('Project').action_for('create_jobset'), [project.name]) %]">[Create a new jobset]</a></p>
    </div>
    [% END %]
    <div id="tabs-settings">
    [% IF edit %]
    <form action="[% IF create %][% c.uri_for('/create-project/submit') %][% ELSE %][% c.uri_for('/project' project.name 'submit') %][% END %]" method="post">
    [% END %]
    <h2>Information[% IF !edit %] <a class="smallLink" href="[% c.uri_for('/project' project.name 'edit') %]">[Edit]</a>[% END %]</h2>
    <table class="layoutTable">
    [% IF edit %]
    <tr>
    <th>Identifier:</th>
    <td><tt>[% INCLUDE maybeEditString param="name" value=project.name %]</tt></td>
    </tr>
    [% END %]
    <tr>
    <th>Display name:</th>
    <td>[% INCLUDE maybeEditString param="displayname" value=project.displayname %]</td>
    </tr>
    <tr>
    <th>Description:</th>
    <td>[% INCLUDE maybeEditString param="description" value=project.description %]</td>
    </tr>
    <tr>
    <th>Homepage:</th>
    <td>
    [% IF edit %]
    [% INCLUDE maybeEditString param="homepage" value=project.homepage %]
    [% ELSE %]
    [% IF project.homepage %]
    <a [% HTML.attributes(href => project.homepage) %]>[% HTML.escape(project.homepage) %]</a>
    [% ELSE %]
    <em>(not specified)</em>
    [% END %]
    [% END %]
    </td>
    </tr>
    <tr>
    <th>Owner:</th>
    <td><tt>[% INCLUDE maybeEditString param="owner" value=(project.owner.username || c.user.username) edit=(edit && c.check_user_roles('admin')) %]</tt></td>
    </tr>
    <tr>
    <th>Enabled:</th>
    <td>
    [% INCLUDE renderSelection param="enabled" curValue=project.enabled options={"1" = "Yes", "0" = "No"} %]
    </td>
    </tr>
    </table>
    [% IF edit %]
    <p><button type="submit"><img src="/static/images/success.gif" />[%IF create %]Create[% ELSE %]Apply changes[% END %]</button></p>
    </form>
    [% IF !create %]
    <form action="[% c.uri_for('/project' project.name 'delete') %]" method="post">
    <p><button id="delete-project" type="submit"><img src="/static/images/failure.gif" />Delete this project</button></p>
    </form>
    <script type="text/javascript">
    $("#delete-project").click(function() {
    return confirm("Are you sure you want to delete this project?");
    });
    </script>
    [% END %]
    [% END %]
    </div>
  • replacement in src/root/project.tt at line 134
    [14.3197][14.4856:4884](),[14.4884][14.3205:3253](),[14.3205][14.3205:3253](),[14.3253][14.2729:2813](),[14.2813][14.3340:3394](),[14.3340][14.3340:3394](),[14.3394][14.2814:2903](),[14.2903][14.3486:3527](),[14.3486][14.3486:3527](),[14.3527][14.2904:2993](),[14.2993][14.2712:2779](),[14.3619][14.2712:2779](),[14.2779][14.2994:3072](),[14.3072][14.2860:2877](),[14.2860][14.2860:2877](),[14.2877][14.3073:3208](),[14.3208][14.3021:3119](),[14.3021][14.3021:3119](),[14.3119][14.5255:5290](),[14.3619][14.5255:5290](),[14.5290][3.538:697](),[3.697][14.3619:3627](),[14.3347][14.3619:3627](),[14.3650][14.3619:3627](),[14.5422][14.3619:3627](),[14.3619][14.3619:3627](),[14.3627][14.3971:4009](),[14.4009][14.3348:3459](),[14.3459][14.4123:4141](),[14.4123][14.4123:4141](),[14.4141][14.3627:3636](),[14.3627][14.3627:3636](),[14.3636][14.20687:20688](),[14.20688][14.2459:2477](),[14.3636][14.2459:2477](),[14.2497][14.2497:2498](),[14.2498][14.20689:20706](),[14.1666][14.2527:2528](),[14.20706][14.2527:2528](),[14.2527][14.2527:2528](),[14.2528][14.20707:20741](),[14.2538][14.3636:3637](),[14.20741][14.3636:3637](),[14.3636][14.3636:3637](),[14.3637][14.20742:20789](),[14.20789][14.3637:3638](),[14.3637][14.3637:3638](),[14.3638][14.20790:21384](),[14.21384][14.3655:3656](),[14.3655][14.3655:3656](),[14.3521][14.3723:3724](),[14.3723][14.3723:3724](),[14.3724][14.21385:21396](),[14.1220][14.3801:3802](),[14.21396][14.3801:3802](),[14.3801][14.3801:3802](),[14.3802][14.21397:21438](),[14.21438][14.1602:1603](),[14.3924][14.1602:1603](),[14.1603][14.21439:21449](),[14.21449][14.1750:1751](),[14.1798][14.1750:1751](),[14.1751][14.2261:2389](),[14.2389][14.3091:3092](),[14.21571][14.3091:3092](),[14.3091][14.3091:3092](),[14.2479][14.2479:2480](),[14.2673][14.10686:10701](),[14.10701][14.21590:21591](),[14.21590][14.21590:21591](),[14.21591][14.10702:10726](),[14.10726][14.21621:21622](),[14.21621][14.21621:21622](),[14.21622][14.10727:10795](),[14.10795][14.21697:21703](),[14.21697][14.21697:21703](),[14.21703][14.10796:10826](),[14.10826][14.21745:21754](),[14.21745][14.21745:21754](),[14.21754][14.10827:11002](),[14.11002][14.21955:21983](),[14.21955][14.21955:21983](),[14.21983][14.4720:4721](),[14.4720][14.4720:4721](),[14.4721][14.1462:1473](),[14.2673][14.1462:1473](),[14.1473][14.2673:2674](),[14.2673][14.2673:2674](),[14.2674][14.11003:11060](),[14.11060][14.1515:1526](),[14.22048][14.1515:1526](),[14.1515][14.1515:1526](),[14.1526][14.22049:22050](),[14.22050][14.11061:11157](),[14.11157][14.1527:1528](),[14.22149][14.1527:1528](),[14.1527][14.1527:1528](),[14.2688][14.2688:2689](),[14.2689][14.22150:22168](),[14.22168][14.4761:4762](),[14.5251][14.4761:4762](),[14.4762][14.22169:22702](),[14.4771][14.5251:5252](),[14.22702][14.5251:5252](),[14.5251][14.5251:5252](),[14.5252][14.4142:4275](),[14.4275][14.5299:5311](),[14.4867][14.5299:5311](),[14.5299][14.5299:5311](),[14.5311][14.4868:4888](),[14.4888][14.3566:3650](),[14.3650][14.4276:4400](),[14.4975][14.4276:4400](),[14.4400][14.5060:5072](),[14.5060][14.5060:5072](),[14.5072][14.5469:5476](),[14.5469][14.5469:5476](),[14.5476][14.2822:2858](),[14.2858][14.5086:5229](),[14.5086][14.5086:5229]()
    <table class="layoutTable">
    [% IF edit %]
    <tr>
    <th>Identifier:</th>
    <td><tt>[% INCLUDE maybeEditString param="name" value=project.name %]</tt></td>
    </tr>
    [% END %]
    <tr>
    <th>Display name:</th>
    <td>[% INCLUDE maybeEditString param="displayname" value=project.displayname %]</td>
    </tr>
    <tr>
    <th>Description:</th>
    <td>[% INCLUDE maybeEditString param="description" value=project.description %]</td>
    </tr>
    <tr>
    <th>Homepage:</th>
    <td>
    [% IF edit %]
    [% INCLUDE maybeEditString param="homepage" value=project.homepage %]
    [% ELSE %]
    [% IF project.homepage %]
    <a [% HTML.attributes(href => project.homepage) %]>[% HTML.escape(project.homepage) %]</a>
    [% ELSE %]
    <em>(not specified)</em>
    [% END %]
    [% END %]
    </td>
    </tr>
    <tr>
    <th>Owner:</th>
    <td><tt>[% INCLUDE maybeEditString param="owner" value=(project.owner.username || c.user.username) edit=(edit && c.check_user_roles('admin')) %]</tt></td>
    </tr>
    <tr>
    <th>Enabled:</th>
    <td>
    [% INCLUDE renderSelection param="enabled" curValue=project.enabled options={"1" = "Yes", "0" = "No"} %]
    </td>
    </tr>
    </table>
    [% IF !edit %]
    <h2>Jobsets</h2>
    [% IF project.jobsets.size > 0 %]
    <p>This project has the following jobsets:</p>
    <table class="tablesorter">
    <thead>
    <tr>
    <th>Id</th>
    <th>Description</th>
    <th>Last evaluated</th>
    </tr>
    </thead>
    <tbody>
    [% FOREACH j IN project.jobsets %]
    <tr class="clickable [% IF odd %] odd [% END; odd = !odd %]"
    onclick="window.location = '[% c.uri_for('/jobset' project.name j.name) %]'">
    <td>[% INCLUDE renderJobsetName project = project.name jobset = j.name %]</td>
    <td>[% HTML.escape(j.description) %]</td>
    <td>[% INCLUDE renderDateTime timestamp = j.lastcheckedtime %]</td>
    </tr>
    [% END %]
    </tbody>
    </table>
    [% ELSE %]
    <p>No jobsets have been defined yet.</p>
    [% END %]
    <p><a href="[% c.uri_for(c.controller('Project').action_for('create_jobset'), [project.name]) %]">[Create a new jobset]</a></p>
    <h2>Views</h2>
    [% IF views.size > 0 %]
    <p>Project <tt>[% project.name %]</tt> has the following views:</p>
    <ul>
    [% FOREACH view IN views %]
    <li>
    <a href="[% c.uri_for('/view' project.name view.name) %]"><tt>[% view.name %]</tt></a>
    [<a href="[% c.uri_for('/view' project.name view.name "edit") %]">Edit</a>]
    </li>
    [% END %]
    </ul>
    [% ELSE %]
    <p>Project <tt>[% project.name %]</tt> has no views.</p>
    [% END %]
    <p><a href="[% c.uri_for('/project' project.name 'create-view') %]">[Create a new view]</a></p>
    <h2>Channels</h2>
    <p>This project provides the following Nix channels:</p>
    <ul>
    <li>
    <a href="[% c.uri_for('/project' project.name 'channel' 'latest') %]"><tt>latest</tt></a> —
    contains the latest successful build of every job in this project.
    </li>
    <li>
    <a href="[% c.uri_for('/project' project.name 'channel' 'all') %]"><tt>all</tt></a> —
    contains every successful, non-garbage-collected build of every
    job in this project.
    </li>
    </ul>
    <h2>Statistics</h2>
    [% INCLUDE showBuildStats %]
    [% END %]
    [% IF edit %]
    <p><button type="submit"><img src="/static/images/success.gif" />[%IF create %]Create[% ELSE %]Apply changes[% END %]</button></p>
    </form>
    [% IF !create %]
    <form action="[% c.uri_for('/project' project.name 'delete') %]" method="post">
    <p><button id="delete-project" type="submit"><img src="/static/images/failure.gif" />Delete this project</button></p>
    </form>
    <script type="text/javascript">
    $("#delete-project").click(function() {
    return confirm("Are you sure you want to delete this project?");
    });
    </script>
    [14.3197]
    [14.5229]
    [% IF !edit %]
    <div id="tabs-views">
    <h2>Views</h2>
    [% IF views.size > 0 %]
    <p>Project <tt>[% project.name %]</tt> has the following views:</p>
    <ul>
    [% FOREACH view IN views %]
    <li>
    <a href="[% c.uri_for('/view' project.name view.name) %]"><tt>[% view.name %]</tt></a>
    [<a href="[% c.uri_for('/view' project.name view.name "edit") %]">Edit</a>]
    </li>
    [% END %]
    </ul>
    [% ELSE %]
    <p>Project <tt>[% project.name %]</tt> has no views.</p>
    [% END %]
    <p><a href="[% c.uri_for('/project' project.name 'create-view') %]">[Create a new view]</a></p>
    </div>
    <div id="tabs-channels">
    <h2>Channels</h2>
    <p>This project provides the following Nix channels:</p>
    <ul>
    <li>
    <a href="[% c.uri_for('/project' project.name 'channel' 'latest') %]"><tt>latest</tt></a> —
    contains the latest successful build of every job in this project.
    </li>
    <li>
    <a href="[% c.uri_for('/project' project.name 'channel' 'all') %]"><tt>all</tt></a> —
    contains every successful, non-garbage-collected build of every
    job in this project.
    </li>
    </ul>
    </div>
    <div id="tabs-statistics">
    <h2>Statistics</h2>
    [% INCLUDE showBuildStats %]
    </div>
    [% END %]
    </div>
  • replacement in src/root/project.tt at line 189
    [14.5230][14.5230:5247](),[14.5247][14.5476:5486](),[14.5476][14.5476:5486]()
    [% END %]
    [% END %]
    [14.5230]
    [14.2863]
    <script type="text/javascript">
    $("#generic-tabs").tabs();
    </script>
  • edit in src/root/static/css/hydra.css at line 1
    [14.8691]
    [14.157]
    #generic-tabs li {
    height : 30px;
    font-size : 90%;
    }
    #generic-tabs {
    min-height: 30em;
    }
    #generic-tabs div {
    font-size : 90%;
    }
  • edit in src/root/static/css/hydra.css at line 16
    [14.8900]
    [14.265]
    .statusTable td, .statusTable th {
    border-style: none;
    }
  • edit in src/root/static/css/hydra.css at line 27
    [14.4976]
    [14.8702]
    text-align: left;
  • edit in src/root/static/css/hydra.css at line 32
    [14.8787]
    [14.9167]
    }
    .activeJobsStatus td, .activeJobsStatus th {
    border-style: 1px dotted #CCCCCC;
    }
    .activeJobsStatus tbody tr td {
    align: center;
  • edit in src/root/static/css/hydra.css at line 152
    [14.112][14.112:113]()
  • replacement in src/root/static/css/nixos-site.css at line 96
    [14.5356][14.5356:5378]()
    min-height: 10em;
    [14.5356]
    [14.5378]
    min-height: 20em;
    }
    div#content {
    min-height: 20em;
  • replacement in src/root/static/css/nixos-site.css at line 107
    [14.5451][14.5451:5473]()
    min-height: 10em;
    [14.5451]
    [14.5473]
    min-height: 20em;
  • file addition: checkmark_128.png (----------)
    [104.2196]
  • file addition: checkmark_256.png (----------)
    [104.2196]
  • file addition: checkmark_32.png (----------)
    [104.2196]
  • file addition: checkmark_64.png (----------)
    [104.2196]
  • file addition: error_128.png (----------)
    [104.2196]
  • file addition: error_256.png (----------)
    [104.2196]
  • file addition: error_32.png (----------)
    [104.2196]
  • file addition: error_64.png (----------)
    [104.2196]
  • file addition: forbidden_128.png (----------)
    [104.2196]
  • file addition: forbidden_256.png (----------)
    [104.2196]
  • file addition: forbidden_32.png (----------)
    [104.2196]
  • file addition: forbidden_64.png (----------)
    [104.2196]
  • file addition: help_128.png (----------)
    [104.2196]
  • file addition: help_256.png (----------)
    [104.2196]
  • file addition: help_32.png (----------)
    [104.2196]
  • file addition: help_64.png (----------)
    [104.2196]
  • file addition: information_128.png (----------)
    [104.2196]
  • file addition: information_256.png (----------)
    [104.2196]
  • file addition: information_32.png (----------)
    [104.2196]
  • file addition: information_64.png (----------)
    [104.2196]
  • file addition: warning_128.png (----------)
    [104.2196]
  • file addition: warning_256.png (----------)
    [104.2196]
  • file addition: warning_32.png (----------)
    [104.2196]
  • file addition: warning_64.png (----------)
    [104.2196]
  • edit in src/root/topbar.tt at line 36
    [14.7675]
    [14.7675]
    [% INCLUDE makeLink
    uri = "http://nixos.org/hydra"
    title = "About" %]