Skip to content

Commit 2ae1b46

Browse files
aboucaudclaude
andcommitted
feat(launcher): use rich spinners for build/install/pull progress messages
Replaces plain stderr prints with Console.status() spinners that disappear on completion. Install subprocess output is now captured so it doesn't interfere with the spinner; stderr is surfaced on failure. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent e885ce5 commit 2ae1b46

1 file changed

Lines changed: 34 additions & 26 deletions

File tree

src/lightcone/engine/launcher.py

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@
1414
import os
1515
import re
1616
import subprocess
17-
import sys
1817
from dataclasses import dataclass, field
1918
from pathlib import Path
2019
from uuid import uuid4
2120

21+
from rich.console import Console
22+
2223
from lightcone.engine.container import (
2324
_DAEMONLESS_RUNTIMES,
2425
ContainerBuildError,
@@ -36,6 +37,8 @@
3637
# Registry where pre-built release images are published.
3738
_GHCR_PREFIX = "ghcr.io/lightconeresearch"
3839

40+
_console = Console(stderr=True)
41+
3942
# Local image name for the shared sandbox base image.
4043
_SANDBOX_IMAGE_NAME = "lightcone-sandbox"
4144

@@ -394,16 +397,16 @@ def _try_pull_and_cache(
394397
if runtime in _DAEMONLESS_RUNTIMES:
395398
return False
396399
try:
397-
_print(f"Pulling {registry_ref} from registry…")
398-
pull_image(registry_ref, runtime=runtime)
399-
# Retag to the content-addressed local tag so the rest of the launch
400-
# pipeline (image_exists_locally, _exec_interactive) works unchanged.
401-
subprocess.run(
402-
[runtime, "tag", registry_ref, tag],
403-
check=True,
404-
capture_output=True,
405-
)
406-
save_image_as_tarball(tag, tarball, runtime=runtime)
400+
with _console.status(f"Pulling [bold]{registry_ref}[/] from registry…"):
401+
pull_image(registry_ref, runtime=runtime)
402+
# Retag to the content-addressed local tag so the rest of the launch
403+
# pipeline (image_exists_locally, _exec_interactive) works unchanged.
404+
subprocess.run(
405+
[runtime, "tag", registry_ref, tag],
406+
check=True,
407+
capture_output=True,
408+
)
409+
save_image_as_tarball(tag, tarball, runtime=runtime)
407410
return True
408411
except (ContainerBuildError, subprocess.CalledProcessError, OSError):
409412
_print("Registry pull failed — falling back to local build.")
@@ -449,18 +452,23 @@ def _ensure_harness_image(
449452

450453
tmp_name = f"lc-install-{target.name}-{uuid4().hex[:8]}"
451454
install_cmd = " && ".join(target.install_cmds)
452-
_print(f"Installing {target.name} harness (first run — this may take a few minutes)…")
453455
try:
454-
subprocess.run(
455-
[runtime, "run", "--entrypoint", "sh", "--name", tmp_name,
456-
base_image, "-c", install_cmd],
457-
check=True,
458-
)
459-
subprocess.run(
460-
[runtime, "commit", tmp_name, committed_tag],
461-
check=True,
462-
capture_output=True,
463-
)
456+
with _console.status(f"Installing [bold]{target.name}[/] harness…"):
457+
result = subprocess.run(
458+
[runtime, "run", "--entrypoint", "sh", "--name", tmp_name,
459+
base_image, "-c", install_cmd],
460+
capture_output=True,
461+
text=True,
462+
)
463+
if result.returncode != 0:
464+
if result.stderr:
465+
_console.print(result.stderr.strip(), style="red")
466+
raise subprocess.CalledProcessError(result.returncode, result.args)
467+
subprocess.run(
468+
[runtime, "commit", tmp_name, committed_tag],
469+
check=True,
470+
capture_output=True,
471+
)
464472
except subprocess.CalledProcessError as exc:
465473
raise ContainerBuildError(f"Harness install failed for {target.name}: {exc}") from exc
466474
finally:
@@ -495,9 +503,9 @@ def launch_target(
495503
registry_ref = _registry_image_ref(target.registry_name or target.name, version)
496504
pulled = _try_pull_and_cache(tag, registry_ref, tarball, runtime=choice.runtime)
497505
if not pulled:
498-
_print(f"Building {name} container (first run — this may take a few minutes)…")
499-
build_image(tag, rendered_cf, rendered_cf.parent, runtime=choice.runtime)
500-
save_image_as_tarball(tag, tarball, runtime=choice.runtime)
506+
with _console.status(f"Building [bold]{name}[/] container…"):
507+
build_image(tag, rendered_cf, rendered_cf.parent, runtime=choice.runtime)
508+
save_image_as_tarball(tag, tarball, runtime=choice.runtime)
501509

502510
if not image_exists_locally(tag, runtime=choice.runtime, project_path=project_root):
503511
load_image_from_tarball(tarball, runtime=choice.runtime)
@@ -611,4 +619,4 @@ def _exec_interactive(
611619

612620

613621
def _print(msg: str) -> None:
614-
print(msg, file=sys.stderr)
622+
_console.print(msg)

0 commit comments

Comments
 (0)