Skip to content

feat(update): show download speed, percent and time left during the panel update - #52

Merged
agentHits merged 5 commits into
AgentHits-Devfrom
feat/update-download-progress
Oct 9, 2026
Merged

agentHits merged 5 commits into
AgentHits-Devfrom
feat/update-download-progress

Conversation

@agentHits

Copy link
Copy Markdown
Owner

Summary

The "Server update in progress" dialog now shows download progress as a bar with a percentage, the current download speed in MB/s, and an estimate of the time left. The existing layer summary and elapsed time stay.

How it works

  • Before the existing update command runs, the panel pulls the image through the Docker Engine API. The engine sends JSON progress events with the bytes of each layer, which give the percentage, speed and time left.
  • The update command itself is unchanged. After the API pull, its own docker pull finds the image present.
  • If the API pull fails, the update does not fail. The dialog shows the layer share as before, and the update command pulls as it does today.
  • Until enough data exists, speed and time left show as unknown. They are never negative or infinite.

Limits

  • Pulls are anonymous. A private registry takes the fallback path and shows the layer share only.
  • Not yet run against a live daemon. The event shapes come from the Engine API and recorded samples. Please check the dialog during the first real update.

Test plan

  • biome check passes on each changed file; tsc --noEmit passes in packages/server and apps/dokploy.
  • bun run test __test__/settings __test__/server: 33 files, 376 tests pass. The new tests use recorded event sequences, including a layer with no total yet, a complete layer, and a failed pull that falls back.

🤖 Generated with Claude Code

agentHits and others added 5 commits October 8, 2026 18:53
Parse the per-layer byte counts from docker pull progress lines (current
and total, in docker's decimal units) and keep them in the update status.

The overall share uses bytes only once every unfinished layer has a known
size. Until then it uses the layer share, because a layer that has not
started has no size yet and would make the byte share read too high.

Download rate is measured over the last five seconds from the byte
samples. Time left is (total - done) / rate. Both stay null until there
is enough data, and the time left is never negative or infinite.

The update command and its flow are unchanged. The update script's output
is piped rather than sent to a terminal, so byte counts may not appear
there; the layer share is the fallback in that case.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
While the image downloads, the downloading step shows a progress bar with
the percentage, the download speed in MB/s and the estimated time left.
Speed and time left read unknown until there is enough data.

The detail lines are now block elements so the bar can sit between them,
and the step content fills the dialog width.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The update script's output is piped, so docker prints no byte counts
there. Pull the image through the local Docker client before the script
runs, and read the JSON progress events, which carry each layer's bytes
and total. The script's own docker pull then finds the image present.

If the engine pull fails, the error is logged, the partial layer progress
is dropped, and the script pulls the image as before. Error events inside
the stream are checked explicitly, since docker-modem reports only stream
failures.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The router passes the image of the chosen update source, so the engine
pull can run before the update script. The script's command is unchanged;
the official image reference moves into a helper that the command reuses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The displayed percent no longer goes backwards when a large layer gets its
  size after smaller ones finished.
- The progress bar exposes its value to assistive technology.
- An engine pull with no event for 90 seconds is cancelled and the update falls
  back to the script pull. The timer is cleared on every exit.
- The engine pull is skipped when a Docker host is set in the environment,
  because the script's docker CLI may then use a different daemon.
- At 100% the panel shows "Finishing" instead of a decaying speed.

Tests cover the monotonic percent, the rendered aria value, the idle timeout
with fake timers, and the remote host skip.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@agentHits agentHits closed this Oct 9, 2026
@agentHits agentHits reopened this Oct 9, 2026
@agentHits
agentHits merged commit 2b312c4 into AgentHits-Dev Oct 9, 2026
8 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