feat: add confirmed Take down stack action with optional volume removal (#1599)

* feat: add confirmed Take down stack action with optional volume removal

Expose Take down in the stack header and sidebar with a confirmation dialog
that runs compose down while keeping the stack definition on disk. Optional
volume removal is gated by node capability and stack:deploy permission, with
remote gateway preflight before proxying removeVolumes requests.

Closes #1582

* fix: reset take-down volume checkbox when dialog closes

* test: align getStackMenuVisibility assertions with showTakeDown key

getStackMenuVisibility now returns a fifth lifecycle flag, showTakeDown,
but three exhaustive toEqual assertions still listed only the prior four
keys and failed. Add the expected showTakeDown value to each: true for
the partial and exited running-stack cases, false for the self stack.

* test: cover Take down visibility for running non-self stacks

The getStackMenuVisibility assertions exercised the partial and exited
branches and the self-stack guard, but not the raw === 'running' literal
that drives showTakeDown for a normal running stack. Add a case so a
regression dropping 'running' from that check is caught.

* fix: drop Take down from header overflow and wire activity shortcut

Remove duplicate Take down from More actions.

Keep inline button when running, sidebar menu, and Cmd+ArrowDown.

Record stack_taken_down in activity on successful POST /down.
This commit is contained in:
Anso
2026-07-09 12:20:13 -04:00
committed by GitHub
parent 296ddff2a0
commit d113004359
48 changed files with 952 additions and 110 deletions
+1 -1
View File
@@ -150,7 +150,7 @@ Authorises every `GET`, plus exactly six `POST` patterns that operate on a stack
| Method | Path pattern | Action |
|--------|--------------|--------|
| `POST` | `/api/stacks/:name/deploy` | Create or update and bring up. |
| `POST` | `/api/stacks/:name/down` | Tear down. |
| `POST` | `/api/stacks/:name/down` | Tear down containers and compose-created networks. Add `?removeVolumes=true` to also remove compose volumes when the node supports it. |
| `POST` | `/api/stacks/:name/restart` | Restart in place. |
| `POST` | `/api/stacks/:name/stop` | Stop without removing. |
| `POST` | `/api/stacks/:name/start` | Start a stopped stack. |
+1 -1
View File
@@ -160,7 +160,7 @@ Of those, **Deploy**, **Update**, **Install**, and Git **Apply** route through `
The [health gate](#health-gate) activates only after **Deploy** and **Update**; it does not fire for Restart, Stop, Install, Git Apply, or Scanning.
The HTTP API also exposes a `down` action (compose-level teardown) that streams its output the same way Deploy and Update do, but no UI control currently triggers it; the `down` endpoint is reachable from automation and from Sencho's own internal cleanup paths.
The HTTP API exposes **Take down** as `POST /api/stacks/:name/down`. The stack header, sidebar context menu, and confirmation dialog call this endpoint. Compose output streams through the same progress modal as Deploy and Update. Optional `?removeVolumes=true` removes compose volumes when the node advertises support.
## Troubleshooting
+2 -1
View File
@@ -25,12 +25,13 @@ The top card on the left holds the stack's identity and primary controls.
### Stack action bar
The action bar runs every state transition for the whole stack. The primary buttons (**Start**, **Restart**, **Stop**, **Update**) require the `stack:deploy` permission; the **Delete** entry in the kebab dropdown requires the `stack:delete` permission. The bar still appears when only **Delete** is authorised so the operator has a way to remove the stack.
The action bar runs every state transition for the whole stack. The primary buttons (**Start**, **Restart**, **Stop**, **Take down** when running, **Update**) require the `stack:deploy` permission; the **Delete** entry in the kebab dropdown requires the `stack:delete` permission. The bar still appears when only **Delete** is authorised so the operator has a way to remove the stack.
| Button | Behavior |
|--------|----------|
| **Start** / **Restart** | A single button that becomes **Restart** when at least one container is running and **Start** otherwise. |
| **Stop** | Stops every container in the stack. Hidden when nothing is running. |
| **Take down** | Shown when at least one container is running. Opens a confirmation dialog, then runs `docker compose down`. Removes containers and compose-created networks while keeping the stack directory. Optional volume removal is offered when the active node supports it. On stopped stacks, use the sidebar context menu or `⌘↓` / `Ctrl+↓`. |
| **Update** | Pulls fresh images and reapplies the compose file. |
| **More actions** (`⋮`) | Opens a dropdown with secondary actions. |
+1 -1
View File
@@ -30,7 +30,7 @@ Each row is one of the permission keys the backend checks. The matrix below is t
| Permission | Admin | Node Admin | Deployer | Auditor | Viewer |
|------------|:-----:|:----------:|:--------:|:-------:|:------:|
| View stacks, logs, stats (`stack:read`) | Yes | Yes | Yes | Yes | Yes |
| Deploy, restart, stop, start (`stack:deploy`) | Yes | Yes | Yes | No | No |
| Deploy, restart, stop, start, take down (`stack:deploy`) | Yes | Yes | Yes | No | No |
| Edit compose and `.env` files (`stack:edit`) | Yes | Yes | No | No | No |
| Create stacks (`stack:create`) | Yes | Yes | No | No | No |
| Delete stacks (`stack:delete`) | Yes | Yes | No | No | No |
+1
View File
@@ -119,6 +119,7 @@ Shortcuts fire on the currently selected stack. They are blocked while a text in
| <kbd>Ctrl</kbd>+<kbd>.</kbd> | Stop | Stack is running |
| <kbd>Ctrl</kbd>+<kbd>R</kbd> | Restart | Stack is running |
| <kbd>Ctrl</kbd>+<kbd>↑</kbd> | Update images | Stack is running |
| <kbd>Ctrl</kbd>+<kbd>↓</kbd> | Take down | Stack has been deployed (opens confirmation) |
| <kbd>Ctrl</kbd>+<kbd>Backspace</kbd> | Delete | Stack exists |
On macOS, use <kbd>Cmd</kbd> in place of <kbd>Ctrl</kbd>.
+6
View File
@@ -347,6 +347,7 @@ The stack header groups actions by frequency of use. The most common action is t
|-----------|--------|---------|--------------|
| Primary | **Restart** | `docker compose restart` | Restarts all containers in the stack. |
| Secondary | **Stop** | `docker compose stop` | Stops containers without removing them. State is preserved. |
| Secondary | **Take down** | `docker compose down` | Removes containers and compose-created networks. The stack definition stays on disk so you can deploy again later. Optional volume removal is available in the confirmation dialog. |
| Secondary | **Update** | `docker compose pull` + `up -d` (or build-aware rebuild when services declare `build:`) | Pulls registry images and recreates containers. When one or more services use `build:`, Update rebuilds those images from source (`compose build --pull`), pulls any remaining registry images, then recreates containers. |
| Overflow | **Rollback** | Restores backup | Reverts compose and env files to the pre-deploy snapshot and redeploys. Only shown when a backup exists. |
| Overflow | **Scan config** | Trivy config scan | Scans the compose file for misconfigurations (admin role). |
@@ -360,8 +361,12 @@ The stack header groups actions by frequency of use. The most common action is t
| Secondary | **Update** | `docker compose pull` + `up -d` (or build-aware rebuild when services declare `build:`) | Pulls registry images and recreates containers. When one or more services use `build:`, Update rebuilds those images from source (`compose build --pull`), pulls any remaining registry images, then recreates containers. |
| Overflow | **Delete** | Removes files | Deletes the stack directory. |
Use the sidebar context menu or `⌘↓` / `Ctrl+↓` for **Take down** on a stopped stack.
<Warning>
**Delete** is irreversible. It removes the stack directory, including `compose.yaml`, `.env`, and any bind-mounted files stored there. Back up important files before deleting.
**Take down** keeps your compose files on disk. It removes running containers and compose-created networks. When you opt in to volume removal, named and anonymous compose volumes are removed as well. Use **Stop** when you want containers to stay in place for a quick resume.
</Warning>
<Note>
@@ -426,6 +431,7 @@ Click the kebab on a stack row in the sidebar to open its context menu. The menu
**lifecycle**
- **Stop** (`⌘.`): shown when running.
- **Take down** (`⌘↓`): shown when the stack has been deployed (running, partial, or exited). Opens a confirmation dialog; optional volume removal is offered when the active node supports it.
- **Restart** (`⌘R`): shown when running.
- **Update** (`⌘↑`): pulls the latest image tags and redeploys.
- **Schedule task**: open the scheduler pre-filled for this stack; pick **Auto-update Stack** to set up unattended image updates on your own cadence. See [Scheduled Operations](/features/scheduled-operations) and [Auto-Update Policies](/features/auto-update-policies).