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
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:
@@ -119,12 +119,12 @@ def test_manifest_orders_listed_tasks_and_allows_empty_declarations(tmp_path: Pa
|
||||
assert [task.filename for task in tasks.tasks] == ["review.py", "apply.py", "status.py"]
|
||||
|
||||
|
||||
def test_manifest_can_override_the_group_display_name(tmp_path: Path) -> None:
|
||||
def test_manifest_can_override_the_group_title(tmp_path: Path) -> None:
|
||||
root = tmp_path / "tasks"
|
||||
group = root / "service"
|
||||
write_task(root, "service", "status.py", '"""Shows status."""\n')
|
||||
(group / "task-inputs.json").write_text(
|
||||
'''{"version":1,"label":"Service UI","tasks":{}}''',
|
||||
'''{"version":1,"title":"Service UI","tasks":{}}''',
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
@@ -144,6 +144,30 @@ def test_display_names_keep_common_acronyms_capitalized(tmp_path: Path) -> None:
|
||||
assert task.display_name == "Replace API URLs"
|
||||
|
||||
|
||||
def test_manifest_can_override_task_title_and_description(tmp_path: Path) -> None:
|
||||
root = tmp_path / "tasks"
|
||||
group = root / "examples"
|
||||
write_task(root, "examples", "inspect.py", '"""Inspects the default thing."""\n')
|
||||
(group / "task-inputs.json").write_text(
|
||||
'''{
|
||||
"version": 1,
|
||||
"tasks": {
|
||||
"inspect.py": {
|
||||
"title": "Inspect saved item",
|
||||
"description": "Checks one saved item without changing it."
|
||||
}
|
||||
}
|
||||
}''',
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
task = TaskCatalog(root).task("examples/inspect.py")
|
||||
|
||||
assert task is not None
|
||||
assert task.display_name == "Inspect saved item"
|
||||
assert task.description == "Checks one saved item without changing it."
|
||||
|
||||
|
||||
def test_rejects_manifest_for_unknown_task(tmp_path: Path) -> None:
|
||||
root = tmp_path / "tasks"
|
||||
group = root / "examples"
|
||||
@@ -219,7 +243,6 @@ def test_execution_declaration_generates_an_action_choice(tmp_path: Path) -> Non
|
||||
"migrate.py": {
|
||||
"execution": {
|
||||
"field": "mode",
|
||||
"label": "Action",
|
||||
"dry_run_value": "report",
|
||||
"dry_run_label": "Report only",
|
||||
"execute_value": "apply",
|
||||
|
||||
@@ -213,7 +213,6 @@ print(Path(os.environ["SERVER_MAINTENANCE_INPUT"]).read_text())
|
||||
"migrate.py": {
|
||||
"execution": {
|
||||
"field": "mode",
|
||||
"label": "Action",
|
||||
"dry_run_value": "report",
|
||||
"dry_run_label": "Report only",
|
||||
"execute_value": "apply",
|
||||
@@ -230,7 +229,8 @@ print(Path(os.environ["SERVER_MAINTENANCE_INPUT"]).read_text())
|
||||
page = client.get("/")
|
||||
assert b"Report only" in page.data
|
||||
assert b"Apply changes" in page.data
|
||||
assert b"data-execution-mode" in page.data
|
||||
assert b"data-execution-value" in page.data
|
||||
assert b"data-execution-choice" in page.data
|
||||
assert b'class="split-button"' in page.data
|
||||
response = client.post("/tasks/examples/migrate.py/run")
|
||||
run_id = int(response.headers["Location"].rsplit("/", 1)[1])
|
||||
@@ -294,6 +294,47 @@ print("archive created")
|
||||
assert app.extensions["run_manager"].artifact_path(run_id, "review.zip") is None
|
||||
|
||||
|
||||
def test_json_artifact_can_be_opened_without_deleting_it(settings) -> None:
|
||||
write_task(
|
||||
settings.task_root,
|
||||
"exports",
|
||||
"report.py",
|
||||
'''"""Creates a report."""
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
artifact = Path(os.environ["SERVER_MAINTENANCE_ARTIFACTS"]) / "report.json"
|
||||
artifact.write_text('{"status":"ok"}', encoding="utf-8")
|
||||
''',
|
||||
)
|
||||
app = create_app(settings)
|
||||
client = app.test_client()
|
||||
|
||||
response = client.post("/tasks/exports/report.py/run")
|
||||
run_id = int(response.headers["Location"].rsplit("/", 1)[1])
|
||||
deadline = time.monotonic() + 3
|
||||
while time.monotonic() < deadline:
|
||||
run = app.extensions["run_store"].get(run_id)
|
||||
assert run is not None
|
||||
if run.status == "succeeded":
|
||||
break
|
||||
time.sleep(0.01)
|
||||
else:
|
||||
raise AssertionError("JSON artifact task did not finish")
|
||||
|
||||
listed = client.get(f"/runs/{run_id}/artifacts").get_json()
|
||||
artifact = listed["artifacts"][0]
|
||||
assert artifact == {
|
||||
"name": "report.json",
|
||||
"url": f"/runs/{run_id}/artifacts/report.json",
|
||||
"view_url": f"/runs/{run_id}/artifacts/report.json/view",
|
||||
}
|
||||
opened = client.get(artifact["view_url"])
|
||||
assert opened.mimetype == "application/json"
|
||||
assert opened.get_json() == {"status": "ok"}
|
||||
assert app.extensions["run_manager"].artifact_path(run_id, "report.json") is not None
|
||||
|
||||
|
||||
def test_file_input_rejects_the_wrong_extension(settings) -> None:
|
||||
task = write_task(settings.task_root, "imports", "apply.py", '"""Applies a CSV."""\n')
|
||||
(task.parent / "task-inputs.json").write_text(
|
||||
|
||||
Reference in New Issue
Block a user