Files
sencho/docs/features/stack-labels.mdx
T
Anso a695251f38 fix(labels): harden stack labels with nodeId filtering, concurrency guard, and test coverage (#552)
* fix(labels): add nodeId filter, existence check, stale cleanup, concurrency guard, and body validation

- Fix getStacksForLabel to filter by node_id (prevents cross-node data leak)
- Add getLabel(id, nodeId) for single-label existence check
- Add getLabelCount(nodeId) for enforcing per-node label limit (50)
- Add cleanupStaleAssignments to remove orphaned assignments for deleted stacks
- Add label/assignment cleanup to deleteNode transaction
- Add label existence check on bulk action endpoint (returns 404 for missing labels)
- Add concurrency guard on bulk actions (returns 429 if already in-flight)
- Add requireBody guard on all mutation endpoints
- Extract isSqliteUniqueViolation helper to deduplicate constraint checks
- Add MAX_LABELS_PER_NODE constant (50) with limit enforcement on create
- Add diagnostic logging on all label endpoints (gated behind developer_mode)
- Add operational log line for bulk action results

* fix(labels): use ScrollArea, show failure details, add loading feedback, deduplicate constants

- Replace overflow-y-auto div with ScrollArea in LabelAssignPopover (design system)
- Show failed stack names in bulk action error toast
- Add loading toast for context menu label toggle
- Disable bulk action menu items while a bulk action is running
- Disable "New Label" button at 50-label limit with "Limit reached" text
- Export LABEL_COLORS and MAX_LABELS_PER_NODE from LabelPill (single source of truth)
- Import shared constants in LabelAssignPopover and LabelsSection (remove duplicates)
- Add BulkActionResult interface to replace inline type assertion

* test(labels): add comprehensive coverage for label CRUD, assignments, and bulk edge cases

42 tests covering:
- getLabels: empty, ordered, node isolation
- getLabel: found, wrong node, nonexistent
- createLabel: returns with ID, duplicate name constraint
- getLabelCount: correct count, zero for empty node
- updateLabel: name, color, both, not found, wrong node
- deleteLabel: removes label, cascades assignments, wrong node no-op
- setStackLabels: assign, replace, clear, invalid ID throws
- getLabelsForStacks: correct mapping, empty result
- getStacksForLabel: correct results, node filter, empty for nonexistent
- cleanupStaleAssignments: removes stale, preserves valid, handles empty
- deleteNode: cascades labels and assignments
- Edge cases: atomicity, cascade across stacks, multi-label assignment

* docs(labels): document 50-label limit and bulk action failure details

* fix(labels): add missing LabelColor type imports and explicit parameter types

* refactor(labels): extract label types and constants to label-types.ts

Moves LabelColor, Label, LABEL_COLORS, and MAX_LABELS_PER_NODE out of
LabelPill.tsx into a dedicated non-component file. This fixes the
react-refresh/only-export-components lint error caused by mixing
constant exports with component exports.
2026-04-13 12:49:03 -04:00

101 lines
4.2 KiB
Plaintext

---
title: Stack Labels
description: Organize your stacks with colored labels for quick filtering, grouping, and bulk actions.
---
<Note>
Stack Labels require a Sencho **Skipper** or **Admiral** license.
</Note>
Stack Labels let you tag your Docker Compose stacks with custom colored labels like `production`, `staging`, or `media-server`. Once labeled, you can filter your stack list, identify stacks at a glance, and run bulk actions on entire groups.
<Frame>
<img src="/images/stack-labels/sidebar-with-labels.png" alt="Sidebar showing stacks with colored label dots and a label filter pill" />
</Frame>
## Creating labels
### From Settings
1. Open **Settings > Labels**
2. Click **+ New Label**
3. Enter a name and pick a color from the 10 available swatches
4. Click **Create**
<Frame>
<img src="/images/stack-labels/settings-labels.png" alt="Settings Labels section showing existing labels with assignment counts" />
</Frame>
The label list shows each label's color, name, and how many stacks are currently assigned to it. Hover over a label row to reveal **Edit** and **Delete** buttons.
<Frame>
<img src="/images/stack-labels/create-label-dialog.png" alt="Create Label dialog with name input and color picker" />
</Frame>
### From the stack context menu
You can also create labels without leaving the sidebar:
1. Right-click any stack in the sidebar
2. Hover over **Labels** to open the submenu
3. Click **Manage labels...** at the bottom to open the Labels section in Settings
### From the three-dot menu
1. Click the three-dot menu on any stack row in the sidebar
2. Click **Labels** to open the label assignment popover
3. Click **Create new label** at the bottom of the popover to create and assign in one step
## Assigning labels to stacks
There are two ways to assign labels:
**Right-click context menu:** Right-click a stack in the sidebar, hover over **Labels**, and click a label to toggle it on or off. A checkmark indicates the label is currently assigned.
<Frame>
<img src="/images/stack-labels/context-menu-labels.png" alt="Right-click context menu with Labels submenu showing assigned label with checkmark" />
</Frame>
**Three-dot menu popover:** Click the three-dot menu on a stack row, then click **Labels**. The popover shows all labels with checkmarks for assigned ones. Click any label to toggle it.
A stack can have multiple labels. Changes save immediately.
## Filtering by label
### Sidebar
When at least one label exists, a pill bar appears between the search box and the stack list. Click a label pill to filter: only stacks with that label are shown. Click multiple pills to see stacks matching **any** of the selected labels. Click an active pill again to deselect it.
<Frame>
<img src="/images/stack-labels/sidebar-filtered.png" alt="Sidebar filtered by the prod label showing only matching stacks" />
</Frame>
### Fleet View
The **Tags** filter in the [Fleet View](/features/fleet-view) toolbar lets you filter nodes by stack labels. Selecting a label filters to nodes that contain stacks with that label.
## Bulk actions
Right-click a label pill in the sidebar to access bulk actions:
| Action | Effect |
|--------|--------|
| **Deploy all** | Runs deploy on every stack with that label |
| **Stop all** | Stops every stack with that label |
| **Restart all** | Restarts every stack with that label |
<Frame>
<img src="/images/stack-labels/bulk-actions-menu.png" alt="Right-click context menu on a label pill showing Deploy all, Stop all, and Restart all options" />
</Frame>
A confirmation dialog shows which stacks will be affected before executing. If any stacks fail during a bulk action, the error toast lists the specific stack names that failed. Only one bulk action can run at a time per node.
## Managing labels
Open **Settings > Labels** to view, edit, and delete your labels.
- **Edit**: Click the pencil icon on a label row to change its name or color
- **Delete**: Click the trash icon to remove the label. A confirmation dialog explains that the label will be removed from all stacks. This cannot be undone.
Label names must be unique per node. You can create up to 50 labels per node. There are 10 color options: teal, blue, purple, rose, amber, green, orange, pink, cyan, and slate.