feat: show live grouped stack states

This commit is contained in:
lingkai5wu committed 2026-10-10 17:13:25 +08:00
1 parent ae5a980cac
commit 3da799a526
1 file changed
+58 -40
+58 -40
View File
@@ -290,11 +290,12 @@ run_group() {
local action="$2"
local group_name="${GROUP_NAMES[group_index]}"
local limit="${GROUP_LIMITS[group_index]}"
local stack pid finished_pid status result result_color marker success_result details
local next=0 running=0 completed=0 failed=0 stack_width=0 interactive=0
local stack pid finished_pid status success_result working_result details
local index finished_index total
local next=0 running=0 completed=0 failed=0 stack_width=0 interactive=0 rendered=0
local success_color="" failure_color="" color_reset=""
local -a stacks=()
local -A pid_stacks=()
local -a stacks=() states=() markers=() state_colors=()
local -A pid_indexes=()
if [[ -t 1 ]]; then
interactive=1
@@ -306,81 +307,98 @@ run_group() {
fi
read -r -a stacks <<<"${GROUP_STACKS[group_index]}"
((${#stacks[@]} > 0)) || return 0
for stack in "${stacks[@]}"; do
total="${#stacks[@]}"
((total > 0)) || return 0
for ((index = 0; index < total; index++)); do
stack="${stacks[index]}"
((${#stack} > stack_width)) && stack_width="${#stack}"
states+=("Waiting")
markers+=(" ")
state_colors+=("")
done
if ((limit == 0 || limit > ${#stacks[@]})); then
limit="${#stacks[@]}"
if ((limit == 0 || limit > total)); then
limit="$total"
fi
if ((${#stacks[@]} == 1)); then
if ((total == 1)); then
details="1 stack"
elif ((limit == ${#stacks[@]})); then
details="${#stacks[@]} stacks in parallel"
elif ((limit == total)); then
details="$total stacks in parallel"
else
details="${#stacks[@]} stacks, max $limit in parallel"
details="$total stacks, max $limit in parallel"
fi
echo
if ((interactive)); then
printf '[+] %s: %s 0/%d\n' "$group_name" "$action" "${#stacks[@]}"
else
if ((!interactive)); then
echo "==> Group $group_name: $action ($details)"
fi
case "$action" in
up | start) success_result="Started" ;;
restart) success_result="Restarted" ;;
stop) success_result="Stopped" ;;
down) success_result="Removed" ;;
pull) success_result="Pulled" ;;
update) success_result="Updated" ;;
up | start) working_result="Starting"; success_result="Started" ;;
restart) working_result="Restarting"; success_result="Restarted" ;;
stop) working_result="Stopping"; success_result="Stopped" ;;
down) working_result="Removing"; success_result="Removed" ;;
pull) working_result="Pulling"; success_result="Pulled" ;;
update) working_result="Updating"; success_result="Updated" ;;
esac
while ((next < ${#stacks[@]} || running > 0)); do
while ((next < ${#stacks[@]} && running < limit)); do
while :; do
while ((next < total && running < limit)); do
stack="${stacks[next]}"
states[next]="$working_result"
STACKS_QUIET_PROGRESS=1 run_stack "$stack" "$action" 0 &
pid="$!"
pid_stacks["$pid"]="$stack"
pid_indexes["$pid"]="$next"
((next += 1, running += 1))
done
if ((interactive)); then
((rendered)) && printf '\033[%dA' "$((total + 1))"
printf '\r\033[2K[+] %s: %s %d/%d\n' \
"$group_name" "$action" "$completed" "$total"
for ((index = 0; index < total; index++)); do
printf '\r\033[2K %s%s%s Stack %-*s %s%s%s\n' \
"${state_colors[index]}" "${markers[index]}" "$color_reset" \
"$stack_width" "${stacks[index]}" \
"${state_colors[index]}" "${states[index]}" "$color_reset"
done
rendered=1
fi
((running > 0)) || break
finished_pid=""
status=0
wait -n -p finished_pid || status=$?
[[ -n "$finished_pid" ]] || die "cannot identify completed stack"
stack="${pid_stacks[$finished_pid]}"
unset 'pid_stacks[$finished_pid]'
finished_index="${pid_indexes[$finished_pid]}"
unset 'pid_indexes[$finished_pid]'
stack="${stacks[finished_index]}"
((running -= 1))
if ((status == 0)); then
marker="✔"
result="$success_result"
result_color="$success_color"
markers[finished_index]="✔"
states[finished_index]="$success_result"
state_colors[finished_index]="$success_color"
((RUN_SUCCESS += 1))
else
marker="✘"
result="Failed"
result_color="$failure_color"
markers[finished_index]="✘"
states[finished_index]="Failed"
state_colors[finished_index]="$failure_color"
((RUN_FAILED += 1))
RUN_FAILED_STACKS+=("$stack")
((failed += 1))
fi
((completed += 1))
if ((interactive)); then
printf '\033[%dA\r\033[2K[+] %s: %s %d/%d\n' \
"$completed" "$group_name" "$action" "$completed" "${#stacks[@]}"
((completed > 1)) && printf '\033[%dB\r' "$((completed - 1))"
fi
if ((!interactive)); then
printf ' %s%s%s Stack %-*s %s%s%s\n' \
"$result_color" "$marker" "$color_reset" "$stack_width" "$stack" \
"$result_color" "$result" "$color_reset"
"${state_colors[finished_index]}" "${markers[finished_index]}" "$color_reset" \
"$stack_width" "$stack" \
"${state_colors[finished_index]}" "${states[finished_index]}" "$color_reset"
fi
done
((failed == 0))