Skip to content

Commit 4916453

Browse files
committed
merge: fix/dream-cli-compose-summary-wrapper as staging base
2 parents 57899ea + 431e83c commit 4916453

2 files changed

Lines changed: 74 additions & 23 deletions

File tree

dream-server/dream-cli

Lines changed: 62 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,60 @@ get_compose_flags() {
510510
fi
511511
}
512512

513+
# Run `docker compose <args...>` with a compact summary on success and a
514+
# surfaced error banner on failure.
515+
#
516+
# Usage: _compose_run_with_summary <verb> <compose_args...>
517+
# <verb> Human-readable gerund phrase, e.g. "Restarting all services"
518+
# <compose_args> Everything that goes after `docker compose`, including
519+
# any `-f` flags resolved by get_compose_flags.
520+
#
521+
# Behavior:
522+
# - Runs `docker compose --progress quiet <compose_args>`, capturing
523+
# stdout+stderr to a mktemp log file.
524+
# - On success: prints "<verb> — done" and removes the log file.
525+
# - On failure: prints an error banner, surfaces up to 20 lines matching
526+
# /error|unhealthy|failed|dependency/, preserves the full
527+
# log file for inspection, and returns the compose exit
528+
# code so the caller (under `set -e`) aborts with it.
529+
#
530+
# The summary grep pipeline can legitimately produce zero matches if the
531+
# failing compose output has no error-keyword hits. `upstream/main` today
532+
# runs under `set -e` only (no `pipefail`), so grep's exit 1 is absorbed
533+
# by the pipeline's final-stage exit and the function continues to the
534+
# log-path surface below. When pipefail is eventually adopted (sibling
535+
# nounset/exit-code audit change), grep's no-match or a SIGPIPE from
536+
# `head -20` on >20 matches would abort this function before the caller
537+
# sees the compose log path or the compose exit code. `|| warn "..."`
538+
# is the project-blessed form (per CLAUDE.md) for "tolerate this specific
539+
# non-match and log why the summary is empty" — it costs nothing today
540+
# and keeps the function correct under future pipefail.
541+
_compose_run_with_summary() {
542+
local _verb="$1"; shift
543+
log "${_verb}..."
544+
545+
local _compose_log
546+
_compose_log=$(mktemp)
547+
548+
local _rc=0
549+
docker compose --progress quiet "$@" >"$_compose_log" 2>&1 || _rc=$?
550+
551+
if (( _rc == 0 )); then
552+
success "${_verb} — done"
553+
rm -f "$_compose_log"
554+
return 0
555+
fi
556+
557+
log_error "${_verb} failed:"
558+
grep -iE 'error|unhealthy|failed|dependency' "$_compose_log" \
559+
| sed 's/^/ /' \
560+
| head -20 \
561+
|| warn "(no error keywords matched in compose log)"
562+
echo ""
563+
log "Full compose output: $_compose_log"
564+
return "$_rc"
565+
}
566+
513567
#=============================================================================
514568
# Commands
515569
#=============================================================================
@@ -778,14 +832,10 @@ cmd_restart() {
778832
read -ra flags <<< "$flags_str"
779833

780834
if [[ -z "$service" ]]; then
781-
log "Restarting all services..."
782-
docker compose "${flags[@]}" up -d
783-
success "All services restarted"
835+
_compose_run_with_summary "Restarting all services" "${flags[@]}" up -d
784836
else
785837
service=$(resolve_service "$service")
786-
log "Restarting $service..."
787-
docker compose "${flags[@]}" up -d "$service"
788-
success "$service restarted"
838+
_compose_run_with_summary "Restarting $service" "${flags[@]}" up -d "$service"
789839
fi
790840
}
791841

@@ -801,14 +851,10 @@ cmd_stop() {
801851
read -ra flags <<< "$flags_str"
802852

803853
if [[ -z "$service" ]]; then
804-
log "Stopping all services..."
805-
docker compose "${flags[@]}" down
806-
success "All services stopped"
854+
_compose_run_with_summary "Stopping all services" "${flags[@]}" down
807855
else
808856
service=$(resolve_service "$service")
809-
log "Stopping $service..."
810-
docker compose "${flags[@]}" stop "$service"
811-
success "$service stopped"
857+
_compose_run_with_summary "Stopping $service" "${flags[@]}" stop "$service"
812858
fi
813859
}
814860

@@ -826,15 +872,11 @@ cmd_start() {
826872
read -ra flags <<< "$flags_str"
827873

828874
if [[ -z "$service" ]]; then
829-
log "Starting all services..."
830-
docker compose "${flags[@]}" up -d
831-
success "All services started"
875+
_compose_run_with_summary "Starting all services" "${flags[@]}" up -d
832876
else
833877
service=$(resolve_service "$service")
834878
_run_hook "$service" "pre_start"
835-
log "Starting $service..."
836-
docker compose "${flags[@]}" up -d "$service"
837-
success "$service started"
879+
_compose_run_with_summary "Starting $service" "${flags[@]}" up -d "$service"
838880
_run_hook "$service" "post_start"
839881
fi
840882
}
@@ -1040,13 +1082,11 @@ cmd_update() {
10401082
warn "dream-update.sh and dream-backup.sh not found; skipping pre-update snapshot."
10411083
fi
10421084

1043-
log "Pulling latest images..."
1044-
if ! docker compose "${flags[@]}" pull; then
1085+
if ! _compose_run_with_summary "Pulling latest images" "${flags[@]}" pull; then
10451086
error "Failed to pull latest images"
10461087
fi
10471088

1048-
log "Recreating containers with new images..."
1049-
if ! docker compose "${flags[@]}" up -d --force-recreate; then
1089+
if ! _compose_run_with_summary "Recreating containers with new images" "${flags[@]}" up -d --force-recreate; then
10501090
error "Failed to recreate containers. Run 'dream rollback' to restore previous state."
10511091
fi
10521092

dream-server/lib/service-registry.sh

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,10 +228,21 @@ sr_resolve_ports() {
228228
fi
229229
}
230230

231-
# Resolve a user-provided name to a compose service ID
231+
# Resolve a user-provided name to a compose service ID.
232+
#
233+
# Users copy container names (e.g. `dream-token-spy`) from `docker ps` and
234+
# expect them to work as arguments to `dream restart|stop|start|update`. The
235+
# registry loader names every container `dream-<sid>` (or the manifest's
236+
# explicit `container_name`, which by convention follows the same pattern),
237+
# so stripping a leading `dream-` recovers the alias key when the literal
238+
# input doesn't match an alias.
232239
sr_resolve() {
233240
sr_load
234241
local input="$1"
242+
if [[ -z "${SERVICE_ALIASES[$input]:-}" && "$input" == dream-* ]]; then
243+
local _stripped="${input#dream-}"
244+
[[ -n "${SERVICE_ALIASES[$_stripped]:-}" ]] && input="$_stripped"
245+
fi
235246
echo "${SERVICE_ALIASES[$input]:-$input}"
236247
}
237248

0 commit comments

Comments
 (0)