Skip to content

feat(stacks): pick GPU services from the stack's own services, not free text - #72

Merged
swimmesberger merged 1 commit into
mainfrom
feat/gpu-service-picker
Aug 29, 2026
Merged

feat(stacks): pick GPU services from the stack's own services, not free text#72
swimmesberger merged 1 commit into
mainfrom
feat/gpu-service-picker

Conversation

@swimmesberger

Copy link
Copy Markdown
Owner

What

Follow-up to ADR-0031 (merged in #71) from testing it on real hardware. The GPU control asked for a service name in a free-text field that sat under a "GPU passthrough" heading, directly above a line listing the detected GPUs — so it read as "type a GPU here". Even read correctly, it asked an operator to recall a compose service name from memory.

Watchtower already knows the stack's services, so the control is now a toggle per service — the checkbox originally asked for.

  • stacks.services — the stack's compose service names from its containers' com.docker.compose.service labels (one cheap Docker call, all states, so a stopped stack still lists them). Deliberately the deployed services rather than the repository's compose file: the file would have to be cloned and resolved per keystroke. A Docker outage returns an empty list rather than an error — this is an input aid, and failing it would take the whole Settings tab down with it.
  • GpuServiceEditor is a toggle per known service. A selected service the engine no longer reports still gets a row, marked "not deployed" — silently dropping it would erase a stored setting the operator cannot see (profile-gated services, or a stack not currently up).
  • An "another service…" row keeps every case configurable, including a stack that has never been deployed, where no services are known yet.
  • The literal device editor's Service column offers the same names as a datalist, and both sub-sections gained a line saying what they take.

Why not select the GPUs themselves

Unchanged by design (ADR-0031 decision 5): the stored intent is "map the host's GPUs", resolved by probing on each deploy, which is what makes one setting portable to a host whose render node has a different number. Per-GPU selection only becomes meaningful on a multi-GPU host, and doing it properly needs the stable /dev/dri/by-path/pci-…-render alias rather than renderD128, since probe order can shuffle across reboots. Still deferred until a real multi-GPU need appears.

Reviewer notes

  • No schema/migration changes — storage is unchanged; this is the read path plus UI.
  • rpc-schema.json regenerated (156 methods).

Testing

Verified live against the dev instance: created two containers labelled into the stack's compose project so it reported real services, confirmed the picker listed api and transcoder, toggled one on, saved through the actual Save button, and read the stored row back; then deleted that container and confirmed the row returned checked and marked "not deployed". Test containers and the row were cleaned up afterwards.

Both backend suites green (1910 Application + 339 Api), frontend tsc and lint clean.

…ee text

The GPU control asked for a service name in a free-text field sitting
under a "GPU passthrough" heading, so it read as "type a GPU here" — and
even read correctly, it asked an operator to recall a compose service
name. Watchtower knows the stack's services from its containers' labels,
so the control becomes a toggle per service.

- stacks.services: the stack's compose service names from
  com.docker.compose.service labels of its project's containers (one
  cheap Docker call, all states); a Docker outage is an empty list, not
  an error, because this is an input aid
- GpuServiceEditor is a toggle per known service; a selected service the
  engine no longer reports still gets a row marked "not deployed", so a
  stored setting is never silently dropped
- an "another service…" row keeps every case configurable, including a
  stack that has never been deployed (no containers, no known services)
- the literal device editor's service column gets the same names as a
  datalist, and both sub-sections gained a line saying what they take
@swimmesberger
swimmesberger merged commit 4644500 into main Aug 29, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant