Deploy console: real progress bar for image pulls (0.39.0)

Compose is now run with `--progress json` (probed once, falls back to the
plain text stream on older compose/agents). The console folds the event
stream into a weighted progress bar — download bytes per layer, then
container create/start — with a per-image bar and a byte/layer counter,
and renders the raw output one line per layer (updated in place) instead
of a wall of scrolling text.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
menzelj
2026-08-16 14:19:27 +00:00
co-authored by Claude Opus 5
parent 9119f94536
commit ecf780c5e6
6 changed files with 657 additions and 50 deletions
+31 -1
View File
@@ -361,13 +361,43 @@ async def stream_compose(
await proc.wait()
_json_progress: Optional[bool] = None
async def supports_json_progress() -> bool:
"""Whether this Docker Compose understands ``--progress json``.
The JSON progress stream carries per-layer ``current``/``total`` bytes, which
the deploy console turns into a real progress bar. Older compose releases
reject the value, so probe once (cheap, no side effects) and cache it; on a
negative result callers fall back to the plain text stream.
"""
global _json_progress
if _json_progress is None:
try:
proc = await asyncio.create_subprocess_exec(
"docker", "compose", "--progress", "json", "version",
stdout=asyncio.subprocess.DEVNULL,
stderr=asyncio.subprocess.DEVNULL,
)
rc = await asyncio.wait_for(proc.wait(), timeout=15.0)
_json_progress = rc == 0
except Exception: # noqa: BLE001 - probe failure just disables the feature
_json_progress = False
return _json_progress
async def stream_up(stack_id: str, override: Optional[str] = None):
"""Run `compose up -d` streaming combined output, so the deploy console can
show image-pull and container-create progress live.
Yields ``("log", line)`` for each output line, then ``("done", returncode)``.
"""
cmd = _compose_base_cmd(stack_id, override) + ["up", "-d", "--remove-orphans"]
cmd = _compose_base_cmd(stack_id, override)
if await supports_json_progress():
# Global flag, must precede the subcommand.
cmd += ["--progress", "json"]
cmd += ["up", "-d", "--remove-orphans"]
proc = await asyncio.create_subprocess_exec(
*cmd,
stdout=asyncio.subprocess.PIPE,
+1 -1
View File
@@ -1,3 +1,3 @@
"""Single source of truth for the StackPilot release version."""
APP_VERSION = "0.38.4"
APP_VERSION = "0.39.0"