b6b7e4cf Andy McCall 1 month ago ↶
1
{% extends "base.html" %}
737de0fa Andy McCall 15 days ago ↶
2
{% import "admin_nav.html" as an %}
b6b7e4cf Andy McCall 1 month ago ↶
3
{% block title %}{{ r.name }} · Runners{% endblock %}
4
{% block mainclass %} class="wide"{% endblock %}
5
{% block content %}
6
< 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 >
737de0fa Andy McCall 15 days ago ↶
7
< div class = " settings-layout " >
8
{% call an::nav(crate::web::admin::AdminSection::Runners) %}
9
< div class = " sections settings-body " >
b6b7e4cf Andy McCall 1 month ago ↶
10
< section class = " panel " >
11
< dl class = " facts " >
12
< 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 >
13
< 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 >
7f5f6c05 Andy McCall 1 month ago ↶
14
< 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 >
15
< 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 >
4d2e44d7 Andy McCall 1 month ago ↶
16
< 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 >
b6b7e4cf Andy McCall 1 month ago ↶
17
< 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 >
18
< dt > Running now</ dt > < dd > {{ running|plural("job", "jobs") }}</ dd >
19
< dt > Ran</ dt > < dd > {{ jobs|plural("job", "jobs") }}, {{ passed }} passed{% if jobs > 0 %} ({{ passed * 100 / jobs }}%){% endif %}, busy {{ self.busy() }}</ dd >
20
< 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 >
21
< 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 >
22
</ dl >
23
</ section >
24
< section class = " panel " >
7f5f6c05 Andy McCall 1 month ago ↶
25
< h2 > Settings</ h2 >
26
< form class = " card " method = " post" action = " /admin/runners/{{ r.id }}/limits" >
27
< input type = " hidden" name = " _csrf" value = " {{ shell.csrf }}" >
28
< label > Labels given here, beside those it reports{% if !r.reported_label_list().is_empty() %} ({{ r.reported_label_list().join(", ") }}){% endif %}</ label >
29
< input type = " text" name = " labels" value = " {{ r.admin_labels }}" placeholder = " gpu, plex" >
30
< label > Job time limit in minutes (empty: the site's)</ label >
31
< input type = " number" name = " timeout_minutes" min = " 1" max = " 1440" value = " {% if let Some(m) = r.timeout_minutes %}{{ m }}{% endif %}" >
32
< button type = " submit" > SAVE</ button >
33
</ form >
34
</ section >
4d2e44d7 Andy McCall 1 month ago ↶
35
{% if !declines.is_empty() %}< section class = " panel " >
36
< h2 > Declined</ h2 >
37
< p class = " small mute " > Jobs this runner handed back before running them, and why (OxygenFlow spec §11.5).</ p >
38
< div class = " table " > < table >
39
< tr > < th > Repository</ th > < th > Run</ th > < th > Job</ th > < th > Reason</ th > < th > When</ th > </ tr >
40
{% for d in declines %}< tr >
41
< td > < a href = " /{{ d.owner }}/{{ d.name }}" > {{ d.owner }}/{{ d.name }}</ a > </ td >
42
< td > < a href = " /{{ d.owner }}/{{ d.name }}/flow/{{ d.run_number }}" > #{{ d.run_number }}</ a > </ td >
43
< td > {{ d.job }}</ td >
44
< td > {{ d.reason }}</ td >
45
< td class = " small " > < time title = " {{ d.ms|when_i }}" > {{ d.ms|ago_i }}</ time > </ td >
46
</ tr > {% endfor %}
47
</ table > </ div >
48
</ section > {% endif %}
7f5f6c05 Andy McCall 1 month ago ↶
49
< section class = " panel " >
b6b7e4cf Andy McCall 1 month ago ↶
50
< h2 > Jobs</ h2 >
51
{% if history.is_empty() %}< p class = " mute " > No jobs yet.</ p > {% else %}
52
< div class = " table " > < table >
53
< tr > < th > Repository</ th > < th > Run</ th > < th > Job</ th > < th > Status</ th > < th > Duration</ th > < th > Started</ th > < th > Receipt</ th > </ tr >
54
{% for j in history %}< tr >
55
< td > < a href = " /{{ j.owner }}/{{ j.repo }}" > {{ j.owner }}/{{ j.repo }}</ a > </ td >
56
< td > < a href = " /{{ j.owner }}/{{ j.repo }}/flow/{{ j.run_number }}" > #{{ j.run_number }}</ a > </ td >
57
< td > {{ j.job }}</ td >
58
< td > < span class = " flow-glyph st-{{ j.status }} " > {{ crate::web::flow::glyph(j.status) }}</ span > {{ j.status }}</ td >
59
< td > {{ crate::web::runners::duration(j) }}</ td >
60
< td class = " small " > {% if let Some(t) = j.started_ms %}< time title = " {{ t|when_i }}" > {{ t|ago_i }}</ time > {% endif %}</ td >
61
< td class = " small " > {% if !j.receipt_attest.is_empty() %}< a href = " /{{ j.owner }}/{{ j.repo }}/receipts/{{ j.receipt_attest }}" > signed</ a > {% endif %}</ td >
62
</ tr > {% endfor %}
63
</ table > </ div >
64
{% if let Some(b) = older %}< p > < a href = " ?before={{ b }}" > Older jobs</ a > </ p > {% endif %}
65
{% endif %}
66
</ section >
737de0fa Andy McCall 15 days ago ↶
67
</ div >
68
</ div >
b6b7e4cf Andy McCall 1 month ago ↶
69
{% endblock %}