From 7465a5ffa6b015012d2425213f881f49ea387feb Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 24 Nov 2025 23:14:06 +0000 Subject: [PATCH 1/4] Fix: Auto-cleanup existing database containers before running prep When running `pushkin-dev prep` with existing database containers from a previous run, the command would fail with a misleading "password authentication failed" error. This happened because the existing containers were using different credentials than the current pushkin.yaml config. This commit implements Option 1 from the issue: automatic detection and cleanup of stale database containers. Changes: - Added `ensureCleanState()` function that checks for existing database containers before setup - If containers exist, displays a warning and removes them cleanly - Uses `docker ps -a` to detect both running and stopped containers - Follows the same pattern as `killLocal()` using compose.stop() and compose.rm() - Includes proper error handling to avoid failing the entire setup Benefits: - Makes `prep` command idempotent - safe to run multiple times - Eliminates confusing password authentication errors - Improves developer experience by avoiding manual cleanup steps - No waiting through 10 failed connection attempts (~2+ minutes) Fixes pushkin-dev prep fails cryptically when database containers already exist --- .../pushkin-cli/src/commands/setupdb/index.js | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/packages/pushkin-cli/src/commands/setupdb/index.js b/packages/pushkin-cli/src/commands/setupdb/index.js index acbd99fe..8433b8b6 100644 --- a/packages/pushkin-cli/src/commands/setupdb/index.js +++ b/packages/pushkin-cli/src/commands/setupdb/index.js @@ -336,10 +336,73 @@ export async function migrateTransactionsDB(coreDBs, verbose) { }); } +/** + * Ensures a clean state by detecting and removing existing database containers + * This prevents issues with stale containers that may have different credentials + * @param {boolean} verbose Output extra debugging info + * @returns {Promise} + */ +async function ensureCleanState(verbose) { + if (verbose) console.log("--verbose flag set inside ensureCleanState()"); + + try { + // Check if database containers are running or stopped + const { stdout } = await exec( + `docker ps -a --format "{{.Names}}" | grep -E "pushkin[-_](test_db|test_transaction_db)[-_]"` + ); + + if (stdout.trim()) { + // Found existing containers - clean them up + console.log('⚠️ Found existing database containers. Cleaning up...'); + + const dockerPath = path.join(process.cwd(), "pushkin"); + const dockerConfig = "docker-compose.dev.yml"; + + try { + // Stop containers if running + await compose.stop({ + cwd: dockerPath, + config: dockerConfig, + }); + } catch (err) { + // Containers might already be stopped, which is fine + if (verbose) console.log("Containers already stopped or error stopping:", err.message); + } + + try { + // Remove containers + await compose.rm({ + cwd: dockerPath, + config: dockerConfig, + commandOptions: ["-f", "-v"], // -f: force, -v: remove volumes + }); + } catch (err) { + if (verbose) console.warn("Warning removing containers:", err.message); + } + + console.log('✓ Cleanup complete. Starting fresh databases...'); + } else { + if (verbose) console.log("No existing database containers found. Proceeding with fresh setup."); + } + } catch (e) { + // If grep finds nothing, it returns exit code 1, which throws an error + // This is expected when no containers exist, so we can safely ignore it + if (e.code === 1 && e.stderr === '') { + if (verbose) console.log("No existing database containers found (grep returned no matches)."); + } else { + // Actual error - log it but don't fail the entire setup + if (verbose) console.warn("Warning: Could not check for existing containers:", e.message); + } + } +} + export async function setupdb(coreDBs, mainExpDir, verbose) { if (verbose) console.log("--verbose flag set inside setupdb()"); // load up all migrations for same dbs to be run at same time (knex requires this) + // Ensure clean state before starting databases + await ensureCleanState(verbose); + let dbPromise; if (verbose) console.log("Spooling up databases."); try { From b46d185f3f786ceea0d6a72b7e8e8f739f2f4eee Mon Sep 17 00:00:00 2001 From: Becky Gilbert Date: Fri, 20 Mar 2026 15:23:13 -0700 Subject: [PATCH 2/4] log the warning if this check fails for a reason other than grep finds nothing (not only for verbose) --- packages/pushkin-cli/src/commands/setupdb/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pushkin-cli/src/commands/setupdb/index.js b/packages/pushkin-cli/src/commands/setupdb/index.js index 8433b8b6..7d54ace9 100644 --- a/packages/pushkin-cli/src/commands/setupdb/index.js +++ b/packages/pushkin-cli/src/commands/setupdb/index.js @@ -391,7 +391,7 @@ async function ensureCleanState(verbose) { if (verbose) console.log("No existing database containers found (grep returned no matches)."); } else { // Actual error - log it but don't fail the entire setup - if (verbose) console.warn("Warning: Could not check for existing containers:", e.message); + console.warn("Warning: Could not check for existing containers:", e.message); } } } From 0bc9e5f95377ff9dd67b4e2e6f1ea57cabecdfe5 Mon Sep 17 00:00:00 2001 From: Becky Gilbert Date: Fri, 20 Mar 2026 15:24:57 -0700 Subject: [PATCH 3/4] fix undefined var e in catch block (pre-existing bug) --- packages/pushkin-cli/src/commands/setupdb/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pushkin-cli/src/commands/setupdb/index.js b/packages/pushkin-cli/src/commands/setupdb/index.js index 7d54ace9..f639c5c9 100644 --- a/packages/pushkin-cli/src/commands/setupdb/index.js +++ b/packages/pushkin-cli/src/commands/setupdb/index.js @@ -410,7 +410,7 @@ export async function setupdb(coreDBs, mainExpDir, verbose) { cwd: path.join(process.cwd(), "pushkin"), config: "docker-compose.dev.yml", }); - } catch { + } catch (e) { console.error("something went wrong starting database containers."); throw e; } From 55c4cb3cf699c778914b3c6d4dbb8b8e175eee30 Mon Sep 17 00:00:00 2001 From: Becky Gilbert Date: Fri, 20 Mar 2026 16:14:13 -0700 Subject: [PATCH 4/4] switch from compose stop/rm to down - same thing but also removes named volumes --- .../pushkin-cli/src/commands/setupdb/index.js | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/packages/pushkin-cli/src/commands/setupdb/index.js b/packages/pushkin-cli/src/commands/setupdb/index.js index f639c5c9..d755c388 100644 --- a/packages/pushkin-cli/src/commands/setupdb/index.js +++ b/packages/pushkin-cli/src/commands/setupdb/index.js @@ -359,22 +359,11 @@ async function ensureCleanState(verbose) { const dockerConfig = "docker-compose.dev.yml"; try { - // Stop containers if running - await compose.stop({ + // Remove containers and named volumes so new containers start with fresh credentials + await compose.down({ cwd: dockerPath, config: dockerConfig, - }); - } catch (err) { - // Containers might already be stopped, which is fine - if (verbose) console.log("Containers already stopped or error stopping:", err.message); - } - - try { - // Remove containers - await compose.rm({ - cwd: dockerPath, - config: dockerConfig, - commandOptions: ["-f", "-v"], // -f: force, -v: remove volumes + commandOptions: ["--volumes"], // removes named volumes (e.g. test_transaction_db_volume) }); } catch (err) { if (verbose) console.warn("Warning removing containers:", err.message);