Refine Python tools task interface
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

This commit is contained in:
ajp_anton
2026-08-18 04:21:11 +00:00
parent b256147d28
commit 7e6dea8b24
11 changed files with 311 additions and 95 deletions
+75 -37
View File
@@ -28,51 +28,89 @@ first line of their module docstring. A task must not require stdin or command
line arguments, should write useful output, and must return a non-zero exit
code on failure.
## Task inputs
## Task definitions
An optional `task-inputs.json` beside a group's task files declares the fields
for its web forms and its task order. It is parsed as data only and uses version
`1`:
Each non-hidden directory directly below `/opt/tasks` is a task group. Its
direct `*.py` files are the exposed tasks. Use an optional
`task-inputs.json` beside those files to define the group's title, task titles
and descriptions, task order, and web form fields. It is parsed as data only
and currently uses version `1`:
```json
{
"version": 1,
"label": "Example Tasks",
"title": "Example Tasks",
"tasks": {
"task.py": {
"inspect.py": {
"title": "Inspect item",
"description": "Checks one item without changing it.",
"inputs": [
{"name": "identifier", "label": "Identifier", "type": "text", "required": true},
{"name": "attempts", "label": "Attempts", "type": "integer", "minimum": 1, "maximum": 5, "default": 2},
{"name": "mode", "label": "Mode", "type": "choice", "options": ["standard", "extended"]},
{"name": "alerts", "label": "Alerts", "type": "multi_choice", "options": ["email", "webhook"]}
]
{"name": "alerts", "label": "Alerts", "type": "multi_choice", "options": ["email", "webhook"]},
{"name": "review_csv", "label": "Review CSV", "type": "file", "accept": [".csv"], "maximum_bytes": 10485760}
],
"wait_for_result": true,
"execution": {
"field": "mode",
"dry_run_value": "review",
"dry_run_label": "Review",
"execute_value": "apply",
"execute_label": "Execute"
}
}
}
}
```
Supported field types are `text`, `integer`, `date`, `datetime`, `choice`,
`multi_choice`, and `file`. Text may also define a regular-expression
`pattern`; integer fields accept `minimum`, `maximum`, and `step`. Choices may
use strings or objects with `value` and `label`. File fields accept a list of
lowercase filename extensions in `accept` and a byte limit in `maximum_bytes`.
An input can define `required` and `default`.
Set `sensitive` to `true` for a value or upload that must not appear in run
history. The form masks sensitive text, the database records `[redacted]`, and
the original value is available only through a private execution input file.
Tasks listed in the manifest appear in JSON order. A listed task may use `{}`
when it only needs ordering; unlisted scripts appear afterward in alphabetical
order. `label` is optional and overrides the group name displayed in the UI.
Set `wait_for_result` to `true` for a short task whose form should wait for its
final success or failure status. This disables the form and warns before
leaving the page while the task is running; tasks without it keep the normal
queued-run behavior.
`title` is optional on a group and task. A group otherwise uses its directory
name; a task otherwise uses its filename without `.py`, with underscores made
readable. `description` is optional on a task and otherwise comes from the
first non-empty line of its module docstring. The order of keys in `tasks`
controls the listed tasks' display order. Include a task as `{}` when only
ordering is needed. Unlisted direct Python files follow alphabetically.
For a task with a review-first operation, declare `execution` with the input
field and its review and execution values. The control panel generates the
mode selector attached to the submit button. A successful review run offers a
button that repeats the same saved inputs using the execution value; it does not reuse a stale filesystem
snapshot, so the task must still validate its inputs before changing anything.
Each task declaration may contain `title`, `description`, `inputs`,
`wait_for_result`, `download_artifacts`, and `execution`. Set
`wait_for_result` for short tasks where the form should remain blocked until it
reports success or failure. The control panel disables its controls and warns
before page unload while such a task runs. `download_artifacts` additionally
starts the first non-JSON artifact download after a successful browser run;
reserve it for files such as archives that the browser should download
automatically.
Every input has `name`, `label`, and `type`; `required` defaults to `false`.
`default` is allowed for every type except `file`.
- `text`: optional `pattern`, a Python-compatible regular expression.
- `integer`: optional `minimum`, `maximum`, and positive `step`.
- `date` and `datetime`: ISO-formatted browser date controls.
- `choice`: `options` is required, as strings or `{ "value", "label" }` objects.
- `multi_choice`: the same required `options`; its `default` is an array.
- `file`: optional lowercase extension list in `accept` and positive byte cap
in `maximum_bytes`.
Set `sensitive` to `true` on text or file inputs that must not appear in run
history. Text is masked, the database records `[redacted]`, and the original
value is available only through a private execution-input file. Uploaded files
are likewise retained privately for the run and then removed.
For review-first tasks, use `execution`. It produces one split button: click
the main part to use its current mode, or use the arrow to select the other
mode. A successful review run can be repeated with its saved inputs in the
execution mode from the run-detail page. The task must still revalidate the
live filesystem before changing anything.
```json
{
"field": "mode",
"dry_run_value": "review",
"dry_run_label": "Review",
"execute_value": "apply",
"execute_label": "Execute"
}
```
The server validates every submitted value before a run is queued. It records
the validated object in the run database and writes it to a per-run file.
@@ -84,15 +122,15 @@ are stored in a private per-run directory; their absolute paths are provided in
the input JSON and the files are removed when the task finishes, fails, or is
cancelled.
## Downloads
## Artifacts
Tasks can write downloadable files to the directory named by
`SERVER_MAINTENANCE_ARTIFACTS`. Set `download_artifacts` to `true` alongside
`wait_for_result` to start the first artifact download after a successful web
run. Run-detail pages also show available downloads. The server deletes an
artifact after its HTTP transfer ends; any undownloaded artifact is removed
after 24 hours. A browser cannot confirm that a downloaded file was retained
on the client device.
Tasks can write files to the directory named by
`SERVER_MAINTENANCE_ARTIFACTS`. Run-detail pages show them when the task
finishes. JSON artifacts offer an **Open** link that renders the JSON in a new
tab and leaves the artifact available; other artifacts offer a download link.
The server deletes an artifact after its download transfer ends; any artifact
not downloaded is removed after 24 hours. A browser cannot confirm that a
downloaded file was retained on the client device.
## Background tasks