Skip to content

Dashboard post-process restart issue #110

Description

@moodmosaic

Summary

It can happen that post-process run, the dashboard showed the
post-process container as exited. Pressing lowercase p still printed:

post-processing is already running -- press P for logs
Stop it first with s before starting a new run.

Pressing s stopped containers, but lowercase p still refused to restart.
The dashboard was checking whether the post-process container existed, not
whether Docker reported it as running. An exited container therefore stranded
the TUI restart path.

The same dashboard path also launched post-processing without preserving the
dashboard's active SWARM_CONFIG, which matters when the dashboard was opened
with a non-default config.

Commit Message

Fix dashboard post-process restart

Dashboard p treated any existing post container as running.
Exited post-process containers could not be restarted from the TUI.

- Gate restart blocking on Docker state running, not container existence.

- Tell operators when an exited post container will be replaced.

- Preserve the dashboard's active SWARM_CONFIG when invoking launch.sh.

Add dashboard shortcut coverage for the restart and config propagation paths.

Exact Patch

diff --git a/dashboard.sh b/dashboard.sh
index 69f106a..927cc94 100755
--- a/dashboard.sh
+++ b/dashboard.sh
@@ -350,6 +350,12 @@ post_process_container_exists() {
     [ "$_pp_state" != "not found" ] && [ "$_pp_state" != "none" ]
 }
 
+post_process_container_running() {
+    local _pp_state
+    _pp_state=$(container_state "${IMAGE_NAME}-post")
+    [ "$_pp_state" = "running" ]
+}
+
 interactive_container_names() {
     docker ps -a --format '{{.Names}}' 2>/dev/null \
         | grep -E "^${IMAGE_NAME}-interactive-" \
@@ -770,7 +776,7 @@ draw() {
     printf "  ${DIM}[h]${RESET} harvest"
     # shellcheck disable=SC2059
     printf "  ${DIM}[s]${RESET} stop all"
-    if post_process_configured && ! post_process_container_exists; then
+    if post_process_configured && ! post_process_container_running; then
         # shellcheck disable=SC2059
         printf "  ${DIM}[p]${RESET} post-process"
     fi
@@ -838,7 +844,7 @@ while true; do
                     continue
                 fi
                 _pp_name="${IMAGE_NAME}-post"
-                if post_process_container_exists; then
+                if post_process_container_running; then
                     echo "(post-processing is already running -- press P for logs)"
                     echo "Stop it first with s before starting a new run."
                     echo ""
@@ -846,6 +852,9 @@ while true; do
                     enter_alt_screen
                     continue
                 fi
+                if post_process_container_exists; then
+                    echo "(previous post-processing container will be replaced)"
+                fi
                 _pp_prompt="Start post-processing now? [y/N] "
                 read -r -p "$_pp_prompt" _pp_confirm || _pp_confirm=""
                 case "$_pp_confirm" in
@@ -863,7 +872,7 @@ while true; do
                     docker stop "${IMAGE_NAME}-${i}" 2>/dev/null || true
                 done
                 echo "--- Starting post-processing ---"
-                "$SWARM_DIR/launch.sh" post-process || \
+                SWARM_CONFIG="$CONFIG_FILE" "$SWARM_DIR/launch.sh" post-process || \
                     echo "(post-processing failed)"
                 echo ""
                 read -rp "Press Enter to return to dashboard..." _
diff --git a/tests/test_dashboard.sh b/tests/test_dashboard.sh
index af75a8b..f6768f2 100755
--- a/tests/test_dashboard.sh
+++ b/tests/test_dashboard.sh
@@ -686,7 +686,7 @@ assert_eq "leading blank inspect fallback becomes not found" "not found" \
     "$(normalize_docker_state $'\nnot found')"
 assert_eq "leading blank inspect state keeps real state" "running" \
     "$(normalize_docker_state $'\nrunning')"
-assert_eq "dashboard uses normalized container state" "4" \
+assert_eq "dashboard uses normalized container state" "5" \
     "$(grep -cF 'container_state "' "$DASHBOARD_FILE")"
 
 pp_lower_case=$(awk '
@@ -727,12 +727,22 @@ assert_eq "lowercase p asks for confirmation" "true" \
 assert_eq "lowercase p can launch post-process" "1" \
     "$(printf '%s\n' "$pp_lower_case" \
         | grep -cF '"$SWARM_DIR/launch.sh" post-process' || true)"
+assert_eq "lowercase p preserves dashboard config" "1" \
+    "$(printf '%s\n' "$pp_lower_case" \
+        | grep -cF 'SWARM_CONFIG="$CONFIG_FILE"' || true)"
 assert_eq "lowercase p has cancellation path" "1" \
     "$(printf '%s\n' "$pp_lower_case" \
         | grep -cF 'post-processing not started' || true)"
 assert_eq "lowercase p refuses to replace running post-process" "1" \
     "$(printf '%s\n' "$pp_lower_case" \
         | grep -cF 'post-processing is already running' || true)"
+assert_eq "lowercase p blocks only running post-process" "1" \
+    "$(printf '%s\n' "$pp_lower_case" \
+        | grep -cF 'if post_process_container_running; then' || true)"
+assert_eq "lowercase p allows exited post-process replacement" "1" \
+    "$(printf '%s\n' "$pp_lower_case" \
+        | grep -cF 'previous post-processing container will be replaced' \
+        || true)"
 assert_eq "lowercase p has no replacement prompt" "0" \
     "$(printf '%s\n' "$pp_lower_case" \
         | grep -cF 'Replace existing' || true)"
@@ -745,9 +755,9 @@ assert_eq "footer merges P into the logs hint" "1" \
 assert_eq "footer offers lowercase p to start post-process" "1" \
     "$(printf '%s\n' "$help_bar" \
         | grep -cF '[p]' || true)"
-assert_eq "footer guards start hint on missing container" "1" \
+assert_eq "footer guards start hint on running container" "1" \
     "$(printf '%s\n' "$help_bar" \
-        | grep -cF 'post_process_configured && ! post_process_container_exists' \
+        | grep -cF 'post_process_configured && ! post_process_container_running' \
         || true)"
 assert_eq "s stops post-process container" "1" \
     "$(printf '%s\n' "$s_case" \

Tests

The patch adds static dashboard shortcut coverage in
tests/test_dashboard.sh for:

  • checking post_process_container_running instead of mere existence
  • preserving SWARM_CONFIG="$CONFIG_FILE" when launching post-process
  • allowing an exited post-process container to be replaced
  • keeping the footer hint aligned with the new running-state guard

Steps to reproduce

No response

Expected vs actual behavior

No response

Version

0.22

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions