Build custom container images / build (map[base_image:php:8-fpm-alpine build_args:PHP_VERSION=8
context:php8-pgsql fingerprint_command:{ apk info -v | LC_ALL=C sort; find /usr/local/lib/php/extensions /usr/local/etc/php/conf.d -type f -exec sha256sum {} + | LC_ALL=C sort; }
name:ph… (push) Successful in 39s
Build custom container images / build (map[base_image:postgres:18 build_args:PG_VERSION=18
POSTGIS_VERSION=3
VCHORD_VERSION=0.5.3
context:postgres fingerprint_command:{ dpkg-query -W -f='${binary:Package}=${Version}\n' | LC_ALL=C sort; find /usr/lib/postgresql -type f -exec sha256su… (push) Successful in 53s
Build custom container images / build (map[base_image:python:3 build_args:PYTHON_VERSION=3
context:python-tools fingerprint_command:{ dpkg-query -W -f='${binary:Package}=${Version}\n' | LC_ALL=C sort; pip freeze | LC_ALL=C sort; }
name:python-tools oci_labels:org.opencontainers.ima… (push) Successful in 1m17s
131 lines
7.2 KiB
HTML
131 lines
7.2 KiB
HTML
{% extends "base.html" %}
|
|
{% block content %}
|
|
<h1>Tasks</h1>
|
|
{% if not groups %}
|
|
<p>No task groups found.</p>
|
|
{% endif %}
|
|
{% for group in groups %}
|
|
{% set group_run = latest[("group", group.id)] %}
|
|
<section class="group">
|
|
<div class="group-heading">
|
|
<h2>{{ group.display_name }}</h2>
|
|
{% if group.can_run_as_group %}
|
|
<form method="post" action="{{ url_for('run_group', group_id=group.id) }}">
|
|
<button type="submit">Run group</button>
|
|
</form>
|
|
{% endif %}
|
|
</div>
|
|
{% if group_run %}
|
|
<p class="run-summary">
|
|
Group: <a href="{{ url_for('run_detail', run_id=group_run.id) }}">{{ group_run.status }}</a>
|
|
· {{ group_run.finished_at|timestamp if group_run.finished_at else "in progress" }}
|
|
</p>
|
|
{% endif %}
|
|
<ul class="tasks">
|
|
{% for task in group.tasks %}
|
|
{% set task_run = latest[("task", task.id)] %}
|
|
<li class="task">
|
|
<div class="task-details">
|
|
<h3>{{ task.display_name }}</h3>
|
|
{% if task.description %}<p>{{ task.description }}</p>{% endif %}
|
|
{% if task_run %}
|
|
<p class="run-summary">
|
|
Last run:
|
|
<a href="{{ url_for('run_detail', run_id=task_run.id) }}">{{ task_run.status }}</a>
|
|
· {{ task_run.finished_at|timestamp if task_run.finished_at else "in progress" }}
|
|
· <a href="{{ url_for('history', target_kind='task', target_path=task.id) }}">history</a>
|
|
</p>
|
|
{% endif %}
|
|
</div>
|
|
<form class="task-form" method="post" action="{{ url_for('run_task', task_id=task.id) }}" enctype="multipart/form-data"{% if task.wait_for_result %} data-wait-for-result{% endif %}{% if task.download_artifacts %} data-download-artifacts{% endif %}>
|
|
{% set values = form_values.get(task.id, {}) %}
|
|
{% set errors = input_errors.get(task.id, {}) %}
|
|
<div class="task-options">
|
|
{% for field in task.inputs %}
|
|
{% if not task.execution or field.name != task.execution.field.name %}
|
|
<div class="task-input">
|
|
{% if field.type == "file" %}
|
|
<label>{{ field.label }}{% if field.required %} (required){% endif %}
|
|
<input type="file" name="{{ field.name }}" {% if field.required %}required{% endif %}{% if field.accept %} accept="{{ field.accept|join(',') }}"{% endif %}>
|
|
</label>
|
|
{% elif field.type == "multi_choice" %}
|
|
<fieldset>
|
|
<legend>{{ field.label }}{% if field.required %} (required){% endif %}</legend>
|
|
{% set selected = values.get(field.name, field.default or ()) %}
|
|
{% for option in field.options %}
|
|
<label>
|
|
<input type="checkbox" name="{{ field.name }}" value="{{ option.value }}" {% if option.value in selected %}checked{% endif %}>
|
|
{{ option.label }}
|
|
</label>
|
|
{% endfor %}
|
|
</fieldset>
|
|
{% elif field.type == "choice" %}
|
|
<label>{{ field.label }}
|
|
<select name="{{ field.name }}" {% if field.required %}required{% endif %}>
|
|
{% if not field.required %}<option value="">No selection</option>{% endif %}
|
|
{% set selected = values.get(field.name, field.default or "") %}
|
|
{% for option in field.options %}
|
|
<option value="{{ option.value }}" {% if option.value == selected %}selected{% endif %}>{{ option.label }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</label>
|
|
{% else %}
|
|
{% set html_type = "password" if field.sensitive else "number" if field.type == "integer" else "datetime-local" if field.type == "datetime" else field.type %}
|
|
<label>{{ field.label }}{% if field.required %} (required){% endif %}
|
|
<input
|
|
type="{{ html_type }}"
|
|
name="{{ field.name }}"
|
|
value="{{ "" if field.sensitive else values.get(field.name, field.default if field.default is not none else "") }}"
|
|
{% if field.sensitive %}autocomplete="off"{% endif %}
|
|
{% if field.required %}required{% endif %}
|
|
{% if field.minimum is not none %}min="{{ field.minimum }}"{% endif %}
|
|
{% if field.maximum is not none %}max="{{ field.maximum }}"{% endif %}
|
|
{% if field.step is not none %}step="{{ field.step }}"{% endif %}
|
|
{% if field.pattern %}pattern="{{ field.pattern }}"{% endif %}
|
|
>
|
|
</label>
|
|
{% endif %}
|
|
{% if errors.get(field.name) %}<p class="input-error">{{ errors[field.name] }}</p>{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
{% endfor %}
|
|
</div>
|
|
<div class="task-action">
|
|
{% if task.execution %}
|
|
<div class="split-button">
|
|
{% set execution = task.execution.field %}
|
|
{% set submitted = values.get(execution.name) %}
|
|
{% set selected = submitted[0] if submitted else execution.default %}
|
|
{% set selected_option = execution.options|selectattr("value", "equalto", selected)|first %}
|
|
<input type="hidden" name="{{ execution.name }}" value="{{ selected }}" data-execution-value>
|
|
<button class="split-primary" type="submit">
|
|
<span class="button-label">{{ selected_option.label if selected_option else execution.options[0].label }}</span>
|
|
{% if task.wait_for_result %}<span class="spinner" aria-hidden="true"></span>{% endif %}
|
|
</button>
|
|
<details class="split-menu">
|
|
<summary aria-label="Choose run mode" title="Choose run mode">▾</summary>
|
|
<div class="split-menu-options">
|
|
{% for option in execution.options %}
|
|
<button type="button" data-execution-choice data-value="{{ option.value }}" data-label="{{ option.label }}"{% if option.value == selected %} aria-pressed="true"{% endif %}>{{ option.label }}</button>
|
|
{% endfor %}
|
|
</div>
|
|
</details>
|
|
</div>
|
|
{% else %}
|
|
<button type="submit">
|
|
<span class="button-label">Run</span>
|
|
{% if task.wait_for_result %}<span class="spinner" aria-hidden="true"></span>{% endif %}
|
|
</button>
|
|
{% endif %}
|
|
</div>
|
|
{% if task.wait_for_result %}<p class="task-result" aria-live="polite"></p>{% endif %}
|
|
</form>
|
|
</li>
|
|
{% else %}
|
|
<li>No exposed tasks in this group.</li>
|
|
{% endfor %}
|
|
</ul>
|
|
</section>
|
|
{% endfor %}
|
|
{% endblock %}
|