hydra/src/root/common.tt

588 lines
20 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[%
USE date;
USE String;
USE HTML;
USE Math;
USE mibs=format("%.2f");
BLOCK renderDateTime;
date.format(timestamp, '%Y-%m-%d %H:%M:%S');
END;
BLOCK renderRelativeDate;
ago = date.now - timestamp;
IF ago >= 0 && ago < 60; THEN;
ago _ 's ago';
ELSIF ago >= 0 && ago < 60 * 60; THEN;
Math.int(ago / 60) _ 'm ago';
ELSIF ago >= 0 && ago < 24 * 60 * 60; THEN;
Math.int(ago / (60 * 60)) _ 'h ago';
ELSIF ago >= 0 && ago < 7 * 24 * 60 * 60; THEN;
Math.int(ago / (24 * 60 * 60)) _ 'd ago';
ELSE;
date.format(timestamp, '%Y-%m-%d');
END;
END;
BLOCK renderProjectName %]
<a [% IF inRow %]class="row-link"[% END %] href="[% c.uri_for('/project' project) %]"><tt>[% project %]</tt></a>
[% END;
BLOCK renderJobsetName %]
<a [% IF inRow %]class="row-link"[% END %] href="[% c.uri_for('/jobset' project jobset) %]"><tt>[% jobset %]</tt></a>
[% END;
BLOCK renderJobName %]
<a [% IF inRow %]class="row-link"[% END %] href="[% c.uri_for('/job' project jobset job) %]">[% job %]</a>
[% END;
BLOCK renderFullJobsetName %]
<tt>[% INCLUDE renderProjectName inRow=0 %]:[% INCLUDE renderJobsetName %]</tt>
[% END;
BLOCK renderFullJobName %]
<tt>[% IF !hideProjectName; INCLUDE renderProjectName inRow=0 %]:[% END; IF !hideJobsetName; INCLUDE renderJobsetName inRow=0 %]:[% 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&nbsp;[% END;
IF duration >= 60 * 60; duration div (60 * 60) % 24 %]h&nbsp;[% END;
IF duration >= 60; duration div 60 % 60 %]m&nbsp;[% END;
duration % 60 %]s[%
END;
BLOCK renderBuildListHeader %]
<table class="table table-striped table-condensed clickable-rows">
<thead>
<tr>
[% IF !hideResultInfo %]
<th></th>
[% END %]
[% IF showSchedulingInfo %]
<th></th>
[% END %]
<th>#</th>
[% IF !hideJobName %]
<th>Job</th>
[% END %]
<th>[% IF showSchedulingInfo %]Queued at[% ELSE %]Finished at[% END %]</th>
<th>Package/release name</th>
<th>System</th>
[% IF showDescription %]
<th>Description</th>
[% END %]
</tr>
</thead>
<tbody>
[% END;
BLOCK renderBuildListBody;
FOREACH build IN builds; link = c.uri_for('/build' build.id) %]
<tr>
[% IF !hideResultInfo %]
<td>
[% INCLUDE renderBuildStatusIcon size=16 buildstatus=build.buildstatus %]
</td>
[% END %]
[% IF showSchedulingInfo %]
<td>[% IF busy %]<span class="label label-success">Started</span>[% ELSE %]<span class="label">Queued</span>[% END %]</td>
[% END %]
<td><a class="row-link" href="[% link %]">[% build.id %]</a></td>
[% IF !hideJobName %]
<td><a href="[%link%]">[% IF !hideJobsetName %][%build.get_column("project")%]:[%build.get_column("jobset")%]:[% END %][%build.get_column("job")%]</td>
[% END %]
<td class="nowrap">[% t = showSchedulingInfo ? build.timestamp : build.stoptime; IF t; INCLUDE renderRelativeDate timestamp=(showSchedulingInfo ? build.timestamp : build.stoptime); ELSE; "-"; END %]</td>
<td>[% !showSchedulingInfo and build.get_column('releasename') ? build.get_column('releasename') : build.nixname %]</td>
<td class="nowrap"><tt>[% build.system %]</tt></td>
[% IF showDescription %]
<td>[% build.description %]</td>
[% END %]
</tr>
[% END;
IF linkToAll %]
<tr><td class="centered" colspan="5"><a href="[% linkToAll %]"><em>More...</em></a></td></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 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 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 style='width: 15em;' [% HTML.attributes(id => param, name => param) %]>
[% FOREACH name IN options.keys.sort %]
<option [% IF name == curValue; "selected='selected'"; END; " "; HTML.attributes(value => name) %]>[% options.$name %]</option>
[% END %]
</select>
[% END;
ELSE;
options.$curValue;
END;
END;
BLOCK editString; %]
<input type="text" class="string" [% HTML.attributes(id => param, name => param, value => value) %] />
[% END;
BLOCK renderFullBuildLink;
INCLUDE renderFullJobNameOfBuild build=build %] <a href="[% c.uri_for('/build' build.id) %]">build [% build.id %]</a>[%
END;
BLOCK renderBuildIdLink; %]
<a href="[% c.uri_for('/build' id) %]">build [% id %]</a>
[% END;
BLOCK renderBuildLink; INCLUDE renderBuildIdLink id=build.id; END;
BLOCK renderBuildStatusIcon;
finished = build != undef ? build.finished : 1;
buildstatus = buildstatus != undef ? buildstatus : build.buildstatus;
IF finished;
IF buildstatus == 0 %]
<img src="[% c.uri_for("/static/images/checkmark_${size}.png") %]" alt="Succeeded" class="build-status" />
[% ELSIF buildstatus == 1 %]
<img src="[% c.uri_for("/static/images/error_${size}.png") %]" alt="Failed" class="build-status" />
[% ELSIF buildstatus == 2 %]
<img src="[% c.uri_for("/static/images/dependency_${size}.png") %]" alt="Dependency failed" class="build-status" />
[% ELSIF buildstatus == 3 || buildstatus == 9 %]
<img src="[% c.uri_for("/static/images/warning_${size}.png") %]" alt="Aborted" class="build-status" />
[% ELSIF buildstatus == 4 %]
<img src="[% c.uri_for("/static/images/forbidden_${size}.png") %]" alt="Cancelled" class="build-status" />
[% ELSIF buildstatus == 6 %]
<img src="[% c.uri_for("/static/images/error_${size}.png") %]" alt="Failed with output" class="build-status" />
[% ELSIF buildstatus == 7 %]
<img src="[% c.uri_for("/static/images/warning_${size}.png") %]" alt="Timed out" class="build-status" />
[% ELSIF buildstatus == 10 %]
<img src="[% c.uri_for("/static/images/warning_${size}.png") %]" alt="Log limit exceeded" class="build-status" />
[% ELSIF buildstatus == 11 %]
<img src="[% c.uri_for("/static/images/warning_${size}.png") %]" alt="Output size limit exceeded" class="build-status" />
[% ELSE %]
<img src="[% c.uri_for("/static/images/error_${size}.png") %]" alt="Failed" class="build-status" />
[% END;
ELSE %]
<img src="[% c.uri_for("/static/images/help_${size}.png") %]" alt="Queued" class="build-status" />
[% 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 == 6 %]
<span class="error">Build failed with output</span>
[% ELSIF buildstatus == 7 %]
<span class="error">Timed out</span>
[% ELSIF buildstatus == 9 %]
<span class="error">Unsupported system type</span>
[% ELSIF buildstatus == 10 %]
<span class="error">Log limit exceeded</span>
[% ELSIF buildstatus == 11 %]
<span class="error">Output limit exceeded</span>
[% ELSE %]
<span class="error">Aborted</span>
(Hydra failure; see <a href="#nix-error">below</a>)
[% END;
ELSIF busy %]
<strong>Build in progress</strong>[%-
ELSE %]
<strong>Scheduled to be built</strong>
[% 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" %]
<tt>"[% HTML.escape(input.value) %]"</tt>
[% ELSIF input.type == "nix" || input.type == "boolean" %]
<tt>[% HTML.escape(input.value) %]</tt>
[% ELSE %]
<tt>[% HTML.escape(input.uri) %][% IF input.revision %] (r[% HTML.escape(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="_blank" 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="_blank" href="[% HTML.escape(c.uri_for('/api/scmdiff', {
uri = url,
rev1 = bi1.revision,
rev2 = bi2.revision,
type = bi1.type,
branch = branch
})) %]">[% contents %]</a>
[% ELSE;
contents;
END;
END;
END;
BLOCK renderInputs; %]
<table class="table table-striped table-condensed">
<thead>
<tr><th>Name</th><th>Type</th><th>Value</th><th>Revision</th><th>Store path</th></tr>
</thead>
<tbody>
[% FOREACH input IN inputs %]
<tr>
<td><tt>[% input.name %]</tt></td>
<td>[% type = input.type; inputTypes.$type %]</td>
<td>
[% IF input.type == "build" || input.type == "sysbuild" %]
[% INCLUDE renderFullBuildLink build=input.dependency %]
[% ELSIF input.type == "string" %]
<tt>"[% HTML.escape(input.value) %]"</tt>
[% ELSIF input.type == "nix" || input.type == "boolean" %]
<tt>[% HTML.escape(input.value) %]</tt>
[% ELSE %]
<tt>[% HTML.escape(input.uri) %]</tt>
[% END %]
</td>
<td>[% IF input.revision %][% HTML.escape(input.revision) %][% END %]</td>
<td><tt>[% input.path %]</tt></td>
</tr>
[% END %]
</tbody>
</table>
[% 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 inputs1;
deletedInput = 1;
FOREACH bi2 IN inputs2;
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 inputs1=bi1.dependency.inputs inputs2=bi2.dependency.inputs 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 %]
<ul class="pager">
<li [% IF page == 1 %]class="disabled"[% END %]><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 [% IF page * resultsPerPage >= total %]class="disabled"[% END %]><a href="[% "$baseUri?page="; (total - 1) div resultsPerPage + 1 %]">Last »</a></li>
</ul>
[% 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 == "hg" %]
<tt>[% input.revision.substr(0, 12) %]</tt>
[% ELSIF input.type == "build" || input.type == "sysbuild" %]
<a href="[% c.uri_for('/build' input.get_column('dependency')) %]">[% input.get_column('dependency') %]</a>
[% ELSE %]
<tt>[% input.revision %]</tt>
[% END;
END;
BLOCK renderEvals %]
<table class="table table-condensed table-striped clickable-rows">
<thead>
<tr>
<th>#</th>
[% IF !jobset && !build %]
<th>Jobset</th>
[% END %]
<th style="width: 10em">Date</th>
<th>Input changes</th>
<th colspan='2' style="width: 25em">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>
<td><a class="row-link" href="[% link %]">[% eval.id %]</a></td>
[% IF !jobset && !build %]
<td>[% INCLUDE renderFullJobsetName project=eval.get_column('project') jobset=eval.get_column('jobset') %]</td>
[% END %]
<td class="nowrap">[% INCLUDE renderRelativeDate 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' class="nowrap">
<span class="label label-success">[% e.nrSucceeded %]</span>
[% IF e.nrFailed > 0 %]
<span class="label label-important">[% e.nrFailed %]</span>
[% END %]
[% IF e.nrScheduled > 0 %]
<span class="label">[% e.nrScheduled %]</span>
[% END %]
</td>
<td align='right' class="nowrap">
[% 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="5"><a href="[% linkToAll %]"><em>More...</em></a></td></tr>
[% END %]
</tbody>
</table>
[% END;
BLOCK renderLogLinks %]
(<a [% IF inRow %]class="row-link"[% END %] href="[% url %]">log</a>, <a href="[% "$url/raw" %]">raw</a>, <a href="[% "$url/tail-reload" %]">tail</a>)
[% END;
BLOCK makeLazyTab %]
<div id="[% tabName %]" class="tab-pane">
<center><img src="[% c.uri_for("/static/images/ajax-loader.gif") %]" alt="Loading..." /></center>
</div>
<script>
$(function() { makeLazyTab("[% tabName %]", "[% uri %]"); });
</script>
[% END;
BLOCK makePopover %]
<div class="btn hydra-popover [% classes %]" data-toggle="popover" data-html="true" [% HTML.attributes('data-content' => content, 'data-placement' => placement || 'bottom') %]>
[% title %]
</div>
[% END;
BLOCK menuItem %]
<li class="[% IF "${root}${curUri}" == uri %]active[% END %]" [% IF confirmmsg %]onclick="javascript:return confirm('[% confirmmsg %]')"[% END %]>
<a [% HTML.attributes(href => uri) %] [%+ IF modal %]data-toggle="modal"[% END %]>
[% IF icon %]<i class="[% icon %] icon-black"></i> [%+ END %]
[% title %]
</a>
</li>
[% END;
BLOCK makeStar %]
<span class="star" data-post="[% starUri %]">[% IF starred; "★"; ELSE; "☆"; END %]</span>
[% END;
BLOCK renderJobsetOverview %]
<table class="table table-striped table-condensed clickable-rows">
<thead>
<tr>
<th></th>
<th>Name</th>
<th>Description</th>
<th>Last evaluated</th>
<th colspan="2">Success</th>
</tr>
</thead>
<tbody>
[% FOREACH j IN jobsets %]
[% successrate = 0 %]
<tr>
<td>
[% IF j.get_column('nrscheduled') > 0 %]
<img src="[% c.uri_for("/static/images/help_16.png") %]" alt="Scheduled" />
[% ELSIF j.get_column('nrfailed') == 0 %]
<img src="[% c.uri_for("/static/images/checkmark_16.png") %]" alt="Succeeded" />
[% ELSIF j.get_column('nrfailed') > 0 && j.get_column('nrsucceeded') > 0 %]
<img src="[% c.uri_for("/static/images/error_some_16.png") %]" alt="Some Failed" />
[% ELSE %]
<img src="[% c.uri_for("/static/images/error_16.png") %]" alt="All Failed" />
[% END %]
</td>
<td><span class="[% IF !j.enabled %]disabled-jobset[% END %] [%+ IF j.hidden %]hidden-jobset[% END %]">[% IF showProject; INCLUDE renderFullJobsetName project=j.get_column('project') jobset=j.name inRow=1; ELSE; INCLUDE renderJobsetName project=j.get_column('project') jobset=j.name inRow=1; END %]</span></td>
<td>[% HTML.escape(j.description) %]</td>
<td>[% IF j.lastcheckedtime; INCLUDE renderDateTime timestamp = j.lastcheckedtime; ELSE; "-"; END %]</td>
[% IF j.get_column('nrtotal') > 0 %]
[% successrate = ( j.get_column('nrsucceeded') / j.get_column('nrtotal') )*100 %]
[% IF j.get_column('nrscheduled') > 0 %]
[% class = 'label' %]
[% ELSIF successrate < 25 %]
[% class = 'label label-important' %]
[% ELSIF successrate < 75 %]
[% class = 'label label-warning' %]
[% ELSIF successrate <= 100 %]
[% class = 'label label-success' %]
[% END %]
[% END %]
<td><span class="[% class %]">[% successrate FILTER format('%d') %]%</span></td>
<td>
[% IF j.get_column('nrsucceeded') > 0 %]
<span class="label label-success">[% j.get_column('nrsucceeded') %]</span>
[% END %]
[% IF j.get_column('nrfailed') > 0 %]
<span class="label label-important">[% j.get_column('nrfailed') %]</span>
[% END %]
[% IF j.get_column('nrscheduled') > 0 %]
<span class="label label">[% j.get_column('nrscheduled') %]</span>
[% END %]
</td>
</tr>
[% END %]
</tbody>
</table>
[% END;
BLOCK includeFlot %]
<script src="[% c.uri_for("/static/js/flot/jquery.flot.min.js") %]" type="text/javascript"></script>
<script src="[% c.uri_for("/static/js/flot/jquery.flot.time.min.js") %]" type="text/javascript"></script>
<script src="[% c.uri_for("/static/js/flot/jquery.flot.selection.min.js") %]" type="text/javascript"></script>
<div id="flot-tooltip" class="flot-tooltip"></div>
[% END;
BLOCK createChart %]
<div id="[%id%]-chart" style="width: 1000px; height: 400px;"></div>
<div id="[%id%]-overview" style="margin-top: 20px; margin-left: 50px; margin-right: 50px; width: 900px; height: 100px"></div>
<script type="text/javascript">
$(function() {
showChart("[%id%]", "[%dataUrl%]", "[%yaxis%]");
});
</script>
[% END;
BLOCK renderMachineName;
machine ? stripSSHUser(machine).match('^(([^\.]|\.[0-9])*)').0 : "localhost";
END;
%]