Swap in richer progress UI; fix fzf preview to use docker label filter
docker-update (Python): - Add compose_binary detection (docker compose v2 plugin or legacy docker-compose) - is_git_repo() now uses `git -C dir rev-parse` instead of .git dir check - Rich runner: Panel header showing project count / git / registry split, per-project sub-task with step labels (git pull, down, pull, up --build…), BarColumn(30) + TimeElapsedColumn, bold summary line - Plain runner: same header line, passes compose_cmd through - Summary uses bold green/yellow/red instead of plain colours - All update functions accept compose_cmd parameter docker-update-fzf (Bash): - project_status_by_name(): check running state via `docker ps --filter label=com.docker.compose.project=NAME` — works from any directory, no workdir required - Preview script rebuilt: shows container table + per-container logs via docker ps/logs --filter label=…, includes stopped containers fallback - show_action_menu() now uses project_status_by_name() for live dot / actions - Trap extended to INT/TERM for cleaner SSH exit https://claude.ai/code/session_01LtPxA1zDET2JQn6NYDDxKn
This commit is contained in:
+45
-25
@@ -15,7 +15,7 @@ _DU_TMPDIR=""
|
||||
|
||||
_setup_tmpdir() {
|
||||
_DU_TMPDIR=$(mktemp -d /tmp/du-fzf-XXXXXX)
|
||||
trap '_cleanup' EXIT
|
||||
trap '_cleanup' EXIT INT TERM
|
||||
}
|
||||
|
||||
_cleanup() {
|
||||
@@ -27,6 +27,19 @@ die() {
|
||||
exit 1
|
||||
}
|
||||
|
||||
# ── project status (by name, no workdir needed) ────────────────────────────
|
||||
|
||||
# Returns "running" or "stopped" for a compose project by name.
|
||||
# Uses docker ps --filter so it works from any directory.
|
||||
project_status_by_name() {
|
||||
local name="$1"
|
||||
local running
|
||||
running=$(docker ps -q \
|
||||
--filter "label=com.docker.compose.project=${name}" \
|
||||
2>/dev/null | wc -l)
|
||||
[[ "$running" -gt 0 ]] && echo "running" || echo "stopped"
|
||||
}
|
||||
|
||||
# ── build_log_list ────────────────────────────────────────────────────────
|
||||
# Outputs tab-delimited lines:
|
||||
# DISPLAY_TEXT \t FULL_LOG_PATH
|
||||
@@ -138,29 +151,44 @@ PYEOF
|
||||
}
|
||||
|
||||
# ── write_preview_script ──────────────────────────────────────────────────
|
||||
# Writes a small bash script to $_DU_TMPDIR/preview.sh that fzf can call.
|
||||
# The script receives the full tab-delimited line as $1 and streams docker logs.
|
||||
# Writes a bash script to $_DU_TMPDIR/preview.sh that fzf calls on hover.
|
||||
# Uses docker ps --filter label=... so it works from any directory.
|
||||
write_preview_script() {
|
||||
local script="$_DU_TMPDIR/preview.sh"
|
||||
cat > "$script" << 'PREVIEW_EOF'
|
||||
#!/bin/bash
|
||||
line="$1"
|
||||
name=$(printf '%s' "$line" | cut -f2)
|
||||
workdir=$(printf '%s' "$line" | cut -f3)
|
||||
name=$(printf '%s' "$line" | cut -f2)
|
||||
|
||||
if [[ "$name" == "HEADER" || -z "$workdir" ]]; then
|
||||
if [[ "$name" == "HEADER" || -z "$name" ]]; then
|
||||
printf '\n (hover over a project to see its live container logs)\n'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ ! -d "$workdir" ]]; then
|
||||
printf 'Workdir not found: %s\n' "$workdir"
|
||||
exit 1
|
||||
printf '\033[1m── containers: %s ──\033[0m\n' "$name"
|
||||
docker ps \
|
||||
--filter "label=com.docker.compose.project=${name}" \
|
||||
--format ' {{.Names}} {{.Status}}' 2>/dev/null
|
||||
printf '\n\033[1m── logs (last 40 lines) ──\033[0m\n'
|
||||
|
||||
# Grab up to 3 container IDs for this project and tail their logs
|
||||
containers=$(docker ps -q \
|
||||
--filter "label=com.docker.compose.project=${name}" \
|
||||
2>/dev/null | head -3)
|
||||
|
||||
if [[ -z "$containers" ]]; then
|
||||
# Also check stopped containers
|
||||
containers=$(docker ps -aq \
|
||||
--filter "label=com.docker.compose.project=${name}" \
|
||||
2>/dev/null | head -3)
|
||||
[[ -z "$containers" ]] && { printf ' (no containers found)\n'; exit 0; }
|
||||
fi
|
||||
|
||||
printf '\033[1m── live logs: %s ──\033[0m\n\n' "$name"
|
||||
cd "$workdir" && docker compose logs --tail=80 --no-color 2>&1 \
|
||||
|| printf 'No logs available\n'
|
||||
printf '%s\n' "$containers" | while IFS= read -r cid; do
|
||||
cname=$(docker inspect --format '{{.Name}}' "$cid" 2>/dev/null | sed 's|^/||')
|
||||
printf '\n\033[2m--- %s ---\033[0m\n' "$cname"
|
||||
docker logs --tail=40 --timestamps "$cid" 2>&1
|
||||
done
|
||||
PREVIEW_EOF
|
||||
chmod +x "$script"
|
||||
echo "$script"
|
||||
@@ -189,22 +217,14 @@ LOGPREVIEW_EOF
|
||||
show_action_menu() {
|
||||
local name="$1" workdir="$2" is_git="$3" is_debug="$4"
|
||||
|
||||
# Live status check
|
||||
local running_count stopped_count
|
||||
running_count=$(cd "$workdir" 2>/dev/null \
|
||||
&& docker compose ps -q --status running 2>/dev/null | wc -l \
|
||||
|| echo 0)
|
||||
stopped_count=$(cd "$workdir" 2>/dev/null \
|
||||
&& docker compose ps -q 2>/dev/null | wc -l \
|
||||
|| echo 0)
|
||||
|
||||
local dot="○"
|
||||
[[ "$running_count" -gt 0 ]] && dot="●"
|
||||
local status dot
|
||||
status=$(project_status_by_name "$name")
|
||||
[[ "$status" == "running" ]] && dot="●" || dot="○"
|
||||
|
||||
local actions=""
|
||||
[[ "$running_count" -eq 0 ]] && actions+=" ▶ Start\n"
|
||||
[[ "$status" != "running" ]] && actions+=" ▶ Start\n"
|
||||
actions+=" ↺ Update\n"
|
||||
[[ "$running_count" -gt 0 ]] && actions+=" ■ Stop\n"
|
||||
[[ "$status" == "running" ]] && actions+=" ■ Stop\n"
|
||||
|
||||
local debug_note=""
|
||||
[[ "$is_debug" == "true" ]] && debug_note=" \033[33m[DEBUG — no real changes]\033[0m"
|
||||
|
||||
Reference in New Issue
Block a user