| 1 |
{% extends "base.html" %} |
| 2 |
{% block title %}{{ r.name }} · Runners{% endblock %} |
| 3 |
{% block mainclass %} class="wide"{% endblock %} |
| 4 |
{% block content %} |
| 5 |
<div class="head"><h1>{{ r.name }} <small><span class="runner-status st-{{ r.status() }}">{{ r.status() }}</span> · <a href="/admin/runners">Runners</a></small></h1></div> |
| 6 |
<section class="panel"> |
| 7 |
<dl class="facts"> |
| 8 |
<dt>Signing key</dt><dd>{% if r.key.is_empty() %}<span class="mute">bound on its first signed receipt</span>{% else %}<code class="full">{{ r.key }}</code> {{ r.key_name }}{% endif %}</dd> |
| 9 |
<dt>Machine</dt><dd>{% if r.arch.is_empty() %}<span class="mute">not reported yet</span>{% else %}{{ r.arch }} · {{ r.os }} · flow {{ r.version }}{% endif %}</dd> |
| 10 |
<dt>Labels</dt><dd>{% for l in r.label_list() %}<span class="lbl">{{ l }}</span> {% endfor %}{% if r.label_list().is_empty() %}<span class="mute">none</span>{% endif %}{% if !r.admin_label_list().is_empty() %} <span class="mute small">({{ r.admin_label_list().len() }} set here)</span>{% endif %}</dd> |
| 11 |
<dt>Time limit</dt><dd>{% if let Some(m) = r.timeout_minutes %}{{ m }} min for its jobs, below the site's{% else %}<span class="mute">the site's</span>{% endif %}</dd> |
| 12 |
<dt>Tiers</dt><dd>{% if r.tier_list().is_empty() %}<span class="mute">not reported yet</span>{% else %}{{ r.tier_list().join(", ") }}{% endif %}{% if let Some(i) = r.image_list() %} · {{ i.len()|plural("image", "images") }} held{% endif %}</dd> |
| 13 |
<dt>Capacity</dt><dd>{{ r.max_jobs|plural("job", "jobs") }} at once{% if let Some(m) = r.memory_mib %}, {{ m }} MiB{% endif %}{% if let Some(c) = r.cpus %}, {{ c }} vCPU{% endif %}</dd> |
| 14 |
<dt>Running now</dt><dd>{{ running|plural("job", "jobs") }}</dd> |
| 15 |
<dt>Ran</dt><dd>{{ jobs|plural("job", "jobs") }}, {{ passed }} passed{% if jobs > 0 %} ({{ passed * 100 / jobs }}%){% endif %}, busy {{ self.busy() }}</dd> |
| 16 |
<dt>Registered</dt><dd>{% if r.source == "config" %}configured in hub.toml{% else %}by {{ r.created_by }}{% endif %}, <time title="{{ r.created_ms|when_i }}">{{ r.created_ms|ago_i }}</time></dd> |
| 17 |
<dt>Last seen</dt><dd>{% if let Some(t) = r.last_seen_ms %}<time title="{{ t|when_i }}">{{ t|ago_i }}</time>{% else %}never{% endif %}</dd> |
| 18 |
</dl> |
| 19 |
</section> |
| 20 |
<section class="panel"> |
| 21 |
<h2>Settings</h2> |
| 22 |
<form class="card" method="post" action="/admin/runners/{{ r.id }}/limits"> |
| 23 |
<input type="hidden" name="_csrf" value="{{ shell.csrf }}"> |
| 24 |
<label>Labels given here, beside those it reports{% if !r.reported_label_list().is_empty() %} ({{ r.reported_label_list().join(", ") }}){% endif %}</label> |
| 25 |
<input type="text" name="labels" value="{{ r.admin_labels }}" placeholder="gpu, plex"> |
| 26 |
<label>Job time limit in minutes (empty: the site's)</label> |
| 27 |
<input type="number" name="timeout_minutes" min="1" max="1440" value="{% if let Some(m) = r.timeout_minutes %}{{ m }}{% endif %}"> |
| 28 |
<button type="submit">SAVE</button> |
| 29 |
</form> |
| 30 |
</section> |
| 31 |
{% if !declines.is_empty() %}<section class="panel"> |
| 32 |
<h2>Declined</h2> |
| 33 |
<p class="small mute">Jobs this runner handed back before running them, and why (OxygenFlow spec §11.5).</p> |
| 34 |
<div class="table"><table> |
| 35 |
<tr><th>Repository</th><th>Run</th><th>Job</th><th>Reason</th><th>When</th></tr> |
| 36 |
{% for d in declines %}<tr> |
| 37 |
<td><a href="/{{ d.owner }}/{{ d.name }}">{{ d.owner }}/{{ d.name }}</a></td> |
| 38 |
<td><a href="/{{ d.owner }}/{{ d.name }}/flow/{{ d.run_number }}">#{{ d.run_number }}</a></td> |
| 39 |
<td>{{ d.job }}</td> |
| 40 |
<td>{{ d.reason }}</td> |
| 41 |
<td class="small"><time title="{{ d.ms|when_i }}">{{ d.ms|ago_i }}</time></td> |
| 42 |
</tr>{% endfor %} |
| 43 |
</table></div> |
| 44 |
</section>{% endif %} |
| 45 |
<section class="panel"> |
| 46 |
<h2>Jobs</h2> |
| 47 |
{% if history.is_empty() %}<p class="mute">No jobs yet.</p>{% else %} |
| 48 |
<div class="table"><table> |
| 49 |
<tr><th>Repository</th><th>Run</th><th>Job</th><th>Status</th><th>Duration</th><th>Started</th><th>Receipt</th></tr> |
| 50 |
{% for j in history %}<tr> |
| 51 |
<td><a href="/{{ j.owner }}/{{ j.repo }}">{{ j.owner }}/{{ j.repo }}</a></td> |
| 52 |
<td><a href="/{{ j.owner }}/{{ j.repo }}/flow/{{ j.run_number }}">#{{ j.run_number }}</a></td> |
| 53 |
<td>{{ j.job }}</td> |
| 54 |
<td><span class="flow-glyph st-{{ j.status }}">{{ crate::web::flow::glyph(j.status) }}</span> {{ j.status }}</td> |
| 55 |
<td>{{ crate::web::runners::duration(j) }}</td> |
| 56 |
<td class="small">{% if let Some(t) = j.started_ms %}<time title="{{ t|when_i }}">{{ t|ago_i }}</time>{% endif %}</td> |
| 57 |
<td class="small">{% if !j.receipt_attest.is_empty() %}<a href="/{{ j.owner }}/{{ j.repo }}/receipts/{{ j.receipt_attest }}">signed</a>{% endif %}</td> |
| 58 |
</tr>{% endfor %} |
| 59 |
</table></div> |
| 60 |
{% if let Some(b) = older %}<p><a href="?before={{ b }}">Older jobs</a></p>{% endif %} |
| 61 |
{% endif %} |
| 62 |
</section> |
| 63 |
{% endblock %} |