Node package updates: show pending apt upgrades (read-only) #26

Merged
Duckboot merged 1 commits from feat/package-updates-13 into main 2026-11-03 00:19:34 +01:00
Owner

What

  • Updates screen: U opens "Package updates". It lists the pending apt updates of every online node, with node, package, current and new version, origin and priority.
  • Failing nodes: a node that fails is shown as "<node>: unavailable", and the other nodes are still listed.
  • Freshness: a hint says the list is as of the node's last apt update. This call does not refresh it.
  • Count in the frame: the main frame's bottom border shows "· N package updates" after the backup count, with a singular for 1.
    • It is fetched on mount, after a context switch and whenever the updates screen loads, not on every guest reload, because it costs one CLI call per node.
    • It uses the same generation guard as the guest list, so a count from the old cluster is dropped after a switch.
  • Out of scope: running apt update or upgrade, since that is a write.

Verification

  • 441 tests pass.
  • ruff check and ruff format --check report no issues.
  • betterleaks found no secrets.
  • Read-only live check: the frame read "mainframe · 23 package updates", and the screen listed 23 rows.
  • The review found no substantive issues. The singular form was fixed afterwards.

This PR is stacked on #25 → #24 → #22. Merge them in that order.

Closes #13

Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com

## What - **Updates screen:** `U` opens "Package updates". It lists the pending apt updates of every online node, with node, package, current and new version, origin and priority. - **Failing nodes:** a node that fails is shown as "&lt;node&gt;: unavailable", and the other nodes are still listed. - **Freshness:** a hint says the list is as of the node's last apt update. This call does not refresh it. - **Count in the frame:** the main frame's bottom border shows "· N package updates" after the backup count, with a singular for 1. - It is fetched on mount, after a context switch and whenever the updates screen loads, not on every guest reload, because it costs one CLI call per node. - It uses the same generation guard as the guest list, so a count from the old cluster is dropped after a switch. - **Out of scope:** running apt update or upgrade, since that is a write. ## Verification - 441 tests pass. - `ruff check` and `ruff format --check` report no issues. - `betterleaks` found no secrets. - Read-only live check: the frame read "mainframe · 23 package updates", and the screen listed 23 rows. - The review found no substantive issues. The singular form was fixed afterwards. This PR is stacked on #25 → #24 → #22. Merge them in that order. Closes #13 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Duckboot added 4 commits 2026-11-03 00:14:16 +01:00
Add CI on Gitea Actions: pytest and ruff on every PR
CI / pytest and ruff (pull_request) Successful in 3m53s
CI / pytest and ruff (push) Has been cancelled
8c2b48a04c
.gitea/workflows/ci.yaml runs on PRs into main and on pushes to main.
It installs uv, runs `uv sync --locked` with Python 3.12 (the lowest
version requires-python allows), then pytest, `ruff check` and
`ruff format --check`.

ruff is pinned in the dev group (0.17.3). The repo has no ruff config,
so the rules are ruff's defaults for that version; pinning makes CI
and local runs check the same rules. The setup follows the workflow
that already runs green on this Gitea instance (ubuntu-latest, pinned
checkout SHA, uv via the official script). The README gets a CI badge
and the lint commands.

Closes #11

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Show live usage: CPU % and Mem % in the table, in-use on the info screen
CI / pytest and ruff (pull_request) Successful in 3m49s
CI / pytest and ruff (push) Has been cancelled
eec65e0585
The guest table gets two last columns, CPU % (cpu * 100) and Mem %
(mem / maxmem), each with one decimal. They show "-" for a guest that
is not running or lacks the field.

The info screen's Resources table gets a header and an "In use"
column: CPU %, memory MiB with %, swap for containers, and rootfs used
GiB with % for containers. VM disks show "-", because the API reports
0 without guest-agent disk info. The info screen reads status and
usage in one status/current call (new cli.current).

After an action, the acted guest's status and usage both come from
status/current, so a guest that has just started no longer shows the
lagging listing's 0.0 %.

One blind-written test expected a VM's CPU cell to read "4 cores". VMs
have always shown sockets ("4 cores × 1 socket", as the resources
spec and its tests define), so that expectation was corrected.

Closes #12

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add the task log: recent tasks with status, Enter shows the log
CI / pytest and ruff (pull_request) Successful in 4m10s
CI / pytest and ruff (push) Successful in 4m32s
1ed5e5069b
l on the main screen opens "Tasks", the recent cluster tasks newest
first. l on the info screen shows only that guest's tasks. Columns:
start, duration (or "running"), node, type, VMID ("-" for node
tasks), user and status. A failed task gets a "!" in the leading
column. Enter opens the task's log in a plain-text widget, so the
output is never parsed as markup.

`task list -o json` has no start or end times, so the list comes from
`/cluster/tasks`. The upid is validated (it must start with "UPID:")
before it goes in as a positional argument.

Review fixes:
- A finished task without a start time no longer crashes the app; its
  duration shows "-".
- "running" now means there is no endtime. A finished task with an
  empty status shows "unknown" and is flagged.

Read-only live check: 25 tasks listed, and the log of the newest
(vzdelsnapshot 104) ends with TASK OK.

Closes #10

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Show pending node package updates (read-only)
CI / pytest and ruff (pull_request) Successful in 4m47s
CI / pytest and ruff (push) Successful in 4m22s
364f8e2137
U opens "Package updates": the pending apt updates of every online
node, with node, package, current and new version, origin and
priority. A node that fails is shown as "<node>: unavailable", and the
other nodes are still listed. A hint says the list is as of the
node's last apt update; this call does not refresh it.

The main frame's bottom border shows "· N package updates" after the
backup count, with a singular for 1. The count is fetched on mount,
after a context switch and whenever the updates screen loads, not on
every guest reload, since it costs one CLI call per node. It uses the
same generation guard as the guest list, so a count from the old
cluster is dropped after a switch.

Running apt update or upgrade stays out of scope; it is a write.

Read-only live check: "mainframe · 23 package updates", and 23 rows
in the screen.

Closes #13

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Duckboot merged commit 364f8e2137 into main 2026-11-03 00:19:34 +01:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Duckboot/cv4pve-cli-tui#26