Skip to content

feat(tui): service history pane with one-press rollback#1

Merged
oddur merged 1 commit intomainfrom
feat/tui-history-rollback
Apr 26, 2026
Merged

feat(tui): service history pane with one-press rollback#1
oddur merged 1 commit intomainfrom
feat/tui-history-rollback

Conversation

@oddur
Copy link
Copy Markdown
Owner

@oddur oddur commented Apr 26, 2026

Ships as v0.4.0 (tag already pushed). Closes #62.

What

New top-level TUI view: from any service detail, press H to open the deploy history for that service. Lists every yoink-managed container (running + exited) across every host, sorted newest-first, with when / version / state / host / container / deployed-by columns.

Press r on a stopped row to open the existing reconcile-confirm modal pinned to that row's version → y to roll back. Same path yoink up uses today, just with an explicit --tag override. Refuses to 'rollback' to a currently-running row.

Test

  • cargo test --lib — 140 passed (4 new in tui::history::tests)
  • cargo clippy --workspace --all-targets -- -D warnings — clean
  • Live data path verified via yoink history api against backtrack-eu-1 (same query the new pane uses)

Roadmap

This is v0.4.0 of a sequence:

  • v0.4.0 (this) — history + rollback
  • v0.4.1 — container actions (kill, restart) keybinds in TUI
  • v0.4.2 — networks pane
  • v0.4.3 — top pane (CPU/mem)

New top-level TUI view: from any service detail, press `H` to open
the deploy history for that service. Lists every yoink-managed
container (running + exited) across every host, sorted newest-first,
with `when / version / state / host / container / deployed-by`
columns — same data the `yoink history` CLI surfaces.

The selected row is a rollback target. Press `r` to open the
existing reconcile-confirm modal pinned to that row's version, then
`y` / Enter to fire — the rest of the flow (lock, snapshot, swap,
healthcheck, status table) is the same path `yoink up` uses today.
The history pane refuses to "rollback" to a currently-running row
(no-op surprise); operators can still press `U` from Services to
redeploy the current spec.

Implementation:
- New `tui/history.rs` module with the state struct + render.
- `View::ServiceHistory(name)` enum variant + breadcrumb +
  per-view help text.
- `Update::ServiceHistory { service, rows }` arrives via the
  existing background-update channel.
- `schedule_history_refresh` fans out per-host
  `list_containers_by_label("yoink.service=<name>")`, exactly
  mirroring `cmd_history`.
- Key handler in `View::ServiceHistory`: j/k navigate, `r`
  rollback (sets `reconcile_target`), `R` refresh, esc back.

Tests: 4 unit tests covering apply-sort, stale-result guard,
rollback-target skip-on-running, and selection wrapping.
@oddur oddur merged commit 608a2fe into main Apr 26, 2026
10 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