OXYGENHUB
# 3d1e74cdac76 oxygenhub / templates / flow_run.html
3.9 KiB · HTML · last changed OxygenFlow runs: pushes start pipeline runs, a runner API with job tokens, jobs as checks, and a Flow tab with the job graph and live logs 1 month ago source blame history raw
1
{% extends "base.html" %}
2
{% import "repo_tabs.html" as m %}
3
{% block title %}Run #{{ run.id }} · Flow · {{ repo.owner }}/{{ repo.name }}{% endblock %}
4
{% block bodyattrs %} data-repo="{{ repo.url }}"{% if run.live() %} data-flow-live="{{ repo.url }}/flow/{{ run.id }}/live"{% endif %}{% endblock %}
5
{% block tabs %}{% call m::tabs(repo, "flow") %}{% endblock %}
6
{% block mainclass %} class="wide"{% endblock %}
7
{% block content %}
8
<div class="head">
9
  <h1><span class="flow-glyph st-{{ run.status }}" data-run-glyph>{{ crate::web::flow::glyph(run.status) }}</span> Run #{{ run.id }} <small data-run-status>{{ run.status }}</small></h1>
10
  <p class="small mute"><span class="lbl lbl-bm">{{ run.bookmark }}</span> at <a class="px" href="{{ repo.url }}/tree/{{ run.heads }}" title="{{ run.state }}">{{ run.state|short }}</a> · pushed by {{ run.actor }} <time title="{{ run.created_ms|when_i }}">{{ run.created_ms|ago_i }}</time> · {{ duration }}{% if !run.pipeline_hash.is_empty() %} · pipeline <code title="{{ run.pipeline_hash }}">{{ run.pipeline_hash|short }}</code>{% endif %} · <a href="{{ repo.url }}/file/{{ run.heads }}/.flow/pipeline.kdl">.flow/pipeline.kdl</a> · <a href="{{ repo.url }}/flow">all runs</a></p>
11
</div>
12
{% if run.status == "error" %}
13
<section class="panel"><div class="strip bad">The pipeline is not valid, so nothing ran.</div><pre class="snippet">{{ run.error }}</pre><p class="small mute">Run <code>flow check</code> locally to see the same problems.</p></section>
14
{% else %}
15
<section class="panel flow-graph-box">
16
  <svg class="flow-graph" viewBox="0 0 {{ graph.width }} {{ graph.height }}" width="{{ graph.width }}" height="{{ graph.height }}" role="img" aria-label="Job graph of run {{ run.id }}">
17
    {% for e in graph.edges %}<path class="edge st-{{ e.status }}" d="{{ e.d }}"/>{% endfor %}
18
    {% for n in graph.nodes %}
19
    <a href="#job-{{ n.j.id }}" data-job-node="{{ n.j.id }}" class="node st-{{ n.j.status }}">
20
      <rect x="{{ n.x }}" y="{{ n.y }}" width="{{ crate::web::flow::NODE_W }}" height="{{ crate::web::flow::NODE_H }}" rx="6"/>
21
      <text class="g" x="{{ n.x + 18 }}" y="{{ n.y + 30 }}" text-anchor="middle" data-glyph>{{ crate::web::flow::glyph(n.j.status) }}</text>
22
      <text class="name" x="{{ n.x + 34 }}" y="{{ n.y + 21 }}">{{ n.j.name }}</text>
23
      <text class="meta" x="{{ n.x + 34 }}" y="{{ n.y + 37 }}" data-meta>{{ n.j.status }} · {{ n.duration }}</text>
24
    </a>
25
    {% endfor %}
26
  </svg>
27
</section>
28
{% for l in logs %}
29
<details class="panel flow-job st-{{ l.j.status }}" id="job-{{ l.j.id }}" data-job="{{ l.j.id }}"{% if l.j.status == "failed" || l.j.status == "error" || l.j.status == "running" %} open{% endif %}>
30
  <summary><span class="flow-glyph st-{{ l.j.status }}" data-glyph>{{ crate::web::flow::glyph(l.j.status) }}</span> <strong>{{ l.j.name }}</strong> <span class="small mute" data-meta>{{ l.j.status }}{% if let Some(c) = l.j.exit_code %} · exit {{ c }}{% endif %} · {{ l.duration }}{% if !l.j.runner.is_empty() %} · on {{ l.j.runner }}{% endif %}</span>{% if !l.j.receipt_hash.is_empty() %} <span class="small mute">· receipt <code title="{{ l.j.receipt_hash }}">{{ l.j.receipt_hash|short }}</code></span>{% endif %}</summary>
31
  {% if !l.j.error.is_empty() %}<div class="strip bad">{{ l.j.error }}</div>{% endif %}
32
  <pre class="flow-log" data-log data-seq="{{ l.last_seq }}">{% for line in l.lines %}<span class="ln s-{{ line.stream }}"><span class="t">{{ line.t / 1000 }}.{{ "{:01}"|format(line.t % 1000 / 100) }}s</span>{{ line.text }}</span>
33
{% endfor %}</pre>
34
  {% if l.lines.is_empty() && l.j.status == "queued" %}<p class="small mute pad">Waiting for a runner{% if !l.j.depends_on().is_empty() %} and for {{ l.j.depends_on().join(", ") }}{% endif %}.</p>{% endif %}
35
  {% if l.lines.is_empty() && l.j.status == "skipped" %}<p class="small mute pad">Skipped: a job it depends on did not pass.</p>{% endif %}
36
</details>
37
{% endfor %}
38
{% endif %}
39
{% endblock %}