[% USE date; USE String; USE HTML; inputTypes = { "svn" = "Subversion export" , "svn-checkout" = "Subversion checkout" , "bzr" = "Bazaar export" , "bzr-checkout" = "Bazaar checkout" , "git" = "Git checkout" , "hg" = "Mercurial checkout" , "string" = "String value" , "boolean" = "Boolean" , "path" = "Local path" , "build" = "Build output" , "sysbuild" = "Build output (same system)" }; BLOCK renderDateTime; date.format(timestamp, '%Y-%m-%d %H:%M:%S'); END; BLOCK renderProjectName %] <a href="[% c.uri_for('/project' project) %]"><tt>[% project %]</tt></a> [% END; BLOCK renderJobsetName %] <a href="[% c.uri_for('/jobset' project jobset) %]"><tt>[% jobset %]</tt></a> [% END; BLOCK renderJobName %] <a href="[% c.uri_for('/job' project jobset job) %]"><tt>[% job %]</tt></a> [% END; BLOCK renderFullJobsetName %] <tt>[% INCLUDE renderProjectName %]:[% INCLUDE renderJobsetName %]</tt> [% END; BLOCK renderFullJobName %] <tt>[% IF !hideProjectName; INCLUDE renderProjectName %]:[% END; IF !hideJobsetName; INCLUDE renderJobsetName %]:[% END; INCLUDE renderJobName %]</tt> [% END; BLOCK renderFullJobNameOfBuild; INCLUDE renderFullJobName project=build.get_column("project") jobset = build.get_column("jobset") job = build.get_column("job"); END; BLOCK renderDuration; IF duration >= 24 * 60 * 60; duration div (24 * 60 * 60) %]d[% END; IF duration >= 60 * 60; duration div (60 * 60) % 24 %]h[% END; IF duration >= 60; duration div 60 % 60 %]m[% END; duration % 60 %]s[% END; BLOCK renderBuildListHeader %] <table class="buildList table table-striped table-condensed [% IF !unsortable %]tablesorter[% END %] [% IF !showSchedulingInfo %] clean[% END %]"> <thead> <tr> [% IF !hideResultInfo %] <th></th> [% END %] [% IF showSchedulingInfo %] <th></th> [% END %] <th>#</th> [% IF showSchedulingInfo %] <th>P</th> [% END %] [% IF !hideJobName %] <th>Job</th> [% END %] <th>Release Name</th> <th>System</th> <th>Timestamp</th> [% IF showStatusChange %] <th class="headerSortUp">Last status change</th> [% END %] [% IF showDescription %] <th>Description</th> [% END %] </tr> </thead> <tbody> [% END; BLOCK renderBuildListBody; odd = 0; FOREACH build IN builds; %] <tr class="clickable [% IF showSchedulingInfo %] [% IF build.busy %]runningBuild[% ELSIF build.disabled == 1 || build.get_column('enabled') == 0 %]disabledBuild[% END %] [% ELSE %] [% IF odd %] odd [% END; odd = !odd %] [% END %]" onclick="if(event.which == 2) return true; window.location = '[% c.uri_for('/build' build.id) %]'"> [% IF !hideResultInfo %] <td> [% INCLUDE renderBuildStatusIcon size=16 busy=(showSchedulingInfo ? 1 : 0) buildstatus=build.buildstatus %] </td> [% END %] [% IF showSchedulingInfo %] <td>[% IF build.busy %]<span class="label label-success">Started</span>[% ELSE %]<span class="label">Queued</span>[% END %]</td> [% END %] <td><a href="[% c.uri_for('/build' build.id) %]">[% build.id %]</a></td> [% IF showSchedulingInfo %] <td>[% build.priority %]</td> [% END %] [% IF !hideJobName %] <td>[% INCLUDE renderFullJobNameOfBuild %]</td> [% END %] <td>[% !showSchedulingInfo and build.get_column('releasename') ? build.get_column('releasename') : build.nixname %]</td> <td><tt>[% build.system %]</tt></td> <td>[% date.format(build.timestamp, '%Y-%m-%d %H:%M:%S') %]</td> [% IF showStatusChange %] <td> [% IF build.get_column('statusChangeTime') %] <a href="[% c.uri_for('/build' build.get_column('statusChangeId')) %]"> [% date.format(build.get_column('statusChangeTime'), '%Y-%m-%d %H:%M:%S') %] </a> [% ELSE %] <em>never</em> [% END %] </td> [% END %] [% IF showDescription %] <td>[% build.description %]</td> [% END %] </tr> [% END; END; BLOCK renderBuildListFooter %] </tbody> </table> [% END; BLOCK renderBuildList; INCLUDE renderBuildListHeader; INCLUDE renderBuildListBody; INCLUDE renderBuildListFooter; END; BLOCK renderLink %]<a href="[% uri %]">[% title %]</a>[% END; BLOCK showBuildStats %] <table class="layoutTable"> <tr> <th>Finished builds:</th> <td>[% finishedBuilds %]</td> </tr> <tr> <th><img src="/static/images/checkmark_16.png" alt="Succeeded" /> Succeeded builds:</th> <td>[% succeededBuilds %]</td> </tr> <tr> <th><img src="/static/images/error_16.png" alt="Failed" /> Failed builds:</th> <td>[% finishedBuilds - succeededBuilds %]</td> </tr> <tr> <th>Total build time:</th> <td>[% INCLUDE renderDuration duration = totalBuildTime %]</td> </tr> <tr> <th>Scheduled builds:</th> <td>[% scheduledBuilds %]</td> </tr> <tr> <th>Currently executing builds:</th> <td>[% busyBuilds %]</td> </tr> </table> [% END; BLOCK renderViewJobName; IF job.description; HTML.escape(job.description); ELSE %]<tt>[% job.job %]</tt> ([% job.attrs %])[% END; END; BLOCK maybeLink; IF uri %]<a [% HTML.attributes(href => uri, class => class) %][% IF confirmmsg %]onclick="javascript:return confirm('[% confirmmsg %]')"[% END %]>[% content %]</a>[% ELSE; content; END; END; BLOCK maybeButton; IF uri %]<a class="btn btn-mini" [% HTML.attributes(href => uri); IF confirmmsg %]onclick="javascript:return confirm('[% confirmmsg %]')"[% END; content %]</a>[% ELSE; content; END; END; BLOCK renderSelection; IF edit; IF radiobuttons; %] <div class="controls"> [% FOREACH name IN options.keys.sort %] <label class="radio inline"> <input type="radio" [% HTML.attributes(id => param, name => param, value => name) %] [% IF name == curValue; "checked='1'"; END %]> [% options.$name %] </input> </label> [% END %] </div> [% ELSE %] <select [% HTML.attributes(id => param, name => param) %]> [% FOREACH name IN options.keys.sort %] <option [% HTML.attributes(value => name) %] [% IF name == curValue; "selected='selected'"; END %]>[% options.$name %]</option> [% END %] </select> [% END; ELSE; options.$curValue; END; END; BLOCK maybeEditString; IF edit %] <input type="text" class="string [% extraClass %]" [% HTML.attributes(id => param, name => param, value => value) %] /> [% ELSE; HTML.escape(value); END; END; BLOCK renderFullBuildLink; INCLUDE renderFullJobNameOfBuild build=build %] <a href="[% c.uri_for('/build' build.id) %]">build [% build.id %]</a>[% END; BLOCK renderBuildStatusIcon; finished = build != undef ? build.finished : 1; busy = busy != undef ? busy : build.busy; buildstatus = buildstatus != undef ? buildstatus : build.buildstatus; IF finished; IF buildstatus == 0 %] <img src="/static/images/checkmark_[% size %].png" alt="Succeeded" /> [% ELSIF buildstatus == 1 %] <img src="/static/images/error_[% size %].png" alt="Failed" /> [% ELSIF buildstatus == 2 %] <img src="/static/images/dependency_[% size %].png" alt="Dependency failed" /> [% ELSIF buildstatus == 4 %] <img src="/static/images/cancelled_[% size %].png" alt="Cancelled" /> [% ELSIF buildstatus == 5 %] <img src="/static/images/error_[% size %].png" alt="Failed" /> [% ELSIF buildstatus == 6 %] <img src="/static/images/error_[% size %].png" alt="Failed (with result)" /> [% ELSE %] <img src="/static/images/error_[% size %].png" alt="Failed" /> [% END; ELSIF busy %] <img src="/static/images/help_[% size %].png" alt="Busy" /> [% ELSE %] <img src="/static/images/help_[% size %].png" alt="Scheduled" /> [% END; END; BLOCK renderStatus; IF build.finished; buildstatus = build.buildstatus; IF icon; INCLUDE renderBuildStatusIcon size=16; END; IF buildstatus == 0 %] <strong>Success</strong> [% ELSIF buildstatus == 1 %] <span class="error">Build returned a non-zero exit code</span> [% ELSIF buildstatus == 2 %] <span class="error">A dependency of the build failed</span> [% ELSIF buildstatus == 4 %] <span class="error">Cancelled by user</span> [% ELSIF buildstatus == 5 %] <span class="error">Build inhibited because a dependency previously failed to build</span> [% ELSIF buildstatus == 6 %] <span class="error">Build failed (with result)</span> [% ELSE %] <span class="error">Build failed</span> (see <a href="#nix-error">below</a>) [% END; ELSIF build.busy %] <strong>Build in progress</strong> since [% INCLUDE renderDateTime timestamp = build.starttime; ELSE %] <strong>Scheduled to be built</strong> [% END; END; BLOCK renderInputValue; IF input.type == "build" || input.type == "sysbuild"; INCLUDE renderFullBuildLink build=input.dependency; ELSIF input.type == "string" || input.type == "boolean" %] <tt>"[% input.value %]"</tt> [% ELSE %] <tt>[% input.uri %][% IF input.revision %] (r[% input.revision %])[% END %]</tt> [% END; END; BLOCK renderShortInputValue; IF input.type == "build" || input.type == "sysbuild" %] <a href="[% c.uri_for('/build' input.dependency.id) %]">[% input.dependency.id %]</a> [% ELSIF input.type == "string" || input.type == "boolean" %] <tt>"[% input.value %]"</tt> [% ELSE %] <tt>[% input.uri %][% IF input.revision %] (r[% input.revision %])[% END %]</tt> [% END %] [% END; BLOCK renderDiffUri; nouri = 1; FOREACH m IN mappers; base = m.baseuri; url = bi1.uri; path = url.replace(base, ''); IF url.match(base) %] <a target="_new" href="[% m.uri.replace('_path_', path).replace('_1_', bi1.revision).replace('_2_', bi2.revision) %]">[% contents %]</a> [% nouri = 0; END; END; IF nouri; res = bi1.uri.split(' '); url = res.0; branch = res.1; IF bi1.type == "hg" || bi1.type == "git" %] <a target="_new" href="[% HTML.escape("/api/scmdiff?uri=$url&rev1=$bi1.revision&rev2=$bi2.revision&type=$bi1.type&branch=$branch") %]">[% contents %]</a> [% ELSE; contents; END; END; END; BLOCK renderInputDiff; %] <table class="table table-striped table-condensed"> [% IF !nestedDiff %] <tr><th>Input</th><th>Changes</th></tr> [% END; IF !nestLevel; nestLevel = 0; END; IF nestLevel <= 3; FOREACH bi1 IN build1.inputs; deletedInput = 1; FOREACH bi2 IN build2.inputs; IF bi1.name == bi2.name; IF bi1.type == bi2.type; IF bi1.value != bi2.value || bi1.uri != bi2.uri %] <tr><td><b>[% bi1.name %]</b></td><td><tt>[% INCLUDE renderShortInputValue input=bi1 %]</tt> to <tt>[% INCLUDE renderShortInputValue input=bi2 %]</tt></td></tr> [% ELSIF bi1.uri == bi2.uri && bi1.revision != bi2.revision %] [% IF bi1.type == "git" %] <tr><td> <b>[% bi1.name %]</b></td><td><tt>[% INCLUDE renderDiffUri contents=(bi1.revision.substr(0, 6) _ ' to ' _ bi2.revision.substr(0, 6)) %]</tt> </td></tr> [% ELSE %] <tr><td> <b>[% bi1.name %]</b></td><td><tt>[% INCLUDE renderDiffUri contents=(bi1.revision _ ' to ' _ bi2.revision) %]</tt> </td></tr> [% END %] [% ELSIF bi1.dependency.id != bi2.dependency.id || bi1.path != bi2.path %] <tr><td> <b>[% bi1.name %]</b></td><td><tt>[% INCLUDE renderShortInputValue input=bi1 %]</tt> to <tt>[% INCLUDE renderShortInputValue input=bi2 %]</tt> <br/> <br/> [% INCLUDE renderInputDiff build1=bi1.dependency, build2=bi2.dependency, nestedDiff=1, nestLevel=nestLevel+1 %] </td></tr> [% END %] [% ELSE %] <tr><td><b>[% bi1.name %]</b></td><td>Changed input type from '[% type = bi1.type; inputTypes.$type %]' to '[% type = bi2.type; inputTypes.$type %]'</td></tr> [% END; deletedInput = 0; END; END; IF deletedInput == 1 %] <tr><td><b>[% bi1.name %]</b></td><td>Input not present in this build.</td></tr> [% END; END; END %] </table> [% END; BLOCK renderPager %] <div class="pagination"> <ul> <li><a href="[% "$baseUri?page=1" %]">First</a></li> <li [% IF page == 1 %]class="disabled"[% END %]><a href="[% "$baseUri?page="; (page - 1) %]">Previous</a></li> <li [% IF page * resultsPerPage >= total %]class="disabled"[% END %]><a href="[% "$baseUri?page="; (page + 1) %]">Next</a></li> <li><a href="[% "$baseUri?page="; (total - 1) div resultsPerPage + 1 %]">Last</a></li> </ul> </div> [% END; BLOCK renderShortEvalInput; IF input.type == "svn" || input.type == "svn-checkout" || input.type == "bzr" || input.type == "bzr-checkout" %] r[% input.revision %] [% ELSIF input.type == "git" %] <tt>[% input.revision.substr(0, 7) %]</tt> [% ELSIF input.type == "build" || input.type == "sysbuild" %] <tt>[% input.dependency.id %]</tt> [% ELSE %] <tt>[% input.revision %]</tt> [% END; END; BLOCK renderEvals %] <table class="tablesorter table table-condensed table-striped"> <thead> <tr> <th>#</th> <th>Date</th> <th>Input changes</th> <th colspan='2'>Success</th> </tr> </thead> <tbody> [% FOREACH e IN evals; eval = e.eval; link = c.uri_for(c.controller('JobsetEval').action_for('view'), [eval.id]) %] <tr class="clickable" onclick="window.location = '[% link %]'"> <td><a href="[% link %]">[% eval.id %]</a></td> <td>[% INCLUDE renderDateTime timestamp = eval.timestamp %]</td> <td> [% IF e.changedInputs.size > 0; sep=''; FOREACH input IN e.changedInputs; sep; %] [% input.name %] → [% INCLUDE renderShortEvalInput input=input; sep=','; END; ELSE %] - [% END %] </td> <td align='right'> <span class="label label-success">[% e.nrSucceeded %]</span> <span class="label label-important">[% e.nrFailed %]</span> [% IF e.nrScheduled > 0 %] <span class="label">[% e.nrScheduled %]</span> [% END %] </td> <td align='right'> [% IF e.diff > 0 %] <span class='label label-success'><strong>+[% e.diff %]</strong></span> [% ELSIF e.diff < 0 && e.nrScheduled == 0 %] <span class='label label-important'><strong>[% e.diff %]</strong></span> [% END %] </td> </tr> [% END; IF linkToAll %] <tr><td class="centered" colspan="54"><a href="[% linkToAll %]"><em>More...</em></a></td></tr> [% END %] </tbody> </table> [% END; BLOCK renderLogLinks %] (<a href="[% url %]">log</a>, <a href="[% "$url/raw" %]">raw</a>, <a href="[% "$url/tail-reload" %]">tail</a>) [% END %]