From 202f4843909d90f16155b65f23a3a46f89add7b3 Mon Sep 17 00:00:00 2001 From: timujeen Date: Sat, 22 Nov 2025 15:15:05 +0000 Subject: [PATCH 1/3] Fix phoenix_kit.status database connection check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed issue where mix phoenix_kit.status was showing "Connection failed" even when the database was properly configured and accessible. Problem: - The task attempted to minimize app startup to avoid conflicts - Complex conditional logic in ensure_app_started/0 failed to properly initialize the Ecto repository - Repository process was not available during status checks Solution: - Simplified run/1 to use standard Mix.Task.run("app.start") - Removed unnecessary ensure_app_started/0 function - Now properly starts the application with all dependencies including repo Result: - Database connection check now works correctly in all installations - Status command shows accurate "Connected ✅" when database is available - Will work consistently across all PhoenixKit installations --- lib/mix/tasks/phoenix_kit.status.ex | 50 ++++++----------------------- 1 file changed, 9 insertions(+), 41 deletions(-) diff --git a/lib/mix/tasks/phoenix_kit.status.ex b/lib/mix/tasks/phoenix_kit.status.ex index f3aee7abd..6189f4ee9 100644 --- a/lib/mix/tasks/phoenix_kit.status.ex +++ b/lib/mix/tasks/phoenix_kit.status.ex @@ -60,24 +60,15 @@ defmodule Mix.Tasks.PhoenixKit.Status do ] def run(argv) do - # Conditionally start the application if repositories aren't available - app_started_by_us = ensure_app_started() - - try do - {opts, _argv, _errors} = OptionParser.parse(argv, switches: @switches, aliases: @aliases) - - prefix = opts[:prefix] || "public" - verbose = opts[:verbose] || false - - show_comprehensive_status(prefix, verbose) - after - # Stop the application if we started it - if app_started_by_us do - # Note: Mix doesn't have app.stop task, and typically apps stay running - # This is normal behavior for Mix tasks - :ok - end - end + # Start the application to ensure repo is available + Mix.Task.run("app.start") + + {opts, _argv, _errors} = OptionParser.parse(argv, switches: @switches, aliases: @aliases) + + prefix = opts[:prefix] || "public" + verbose = opts[:verbose] || false + + show_comprehensive_status(prefix, verbose) end # Main status display function @@ -526,29 +517,6 @@ defmodule Mix.Tasks.PhoenixKit.Status do _ -> false end - # Ensure application is started only if needed - # Returns true if we started the app, false if it was already running - defp ensure_app_started do - # Check if we can get repo configuration - case get_repo_with_fallback() do - nil -> - # No repo found, start app and try again - Mix.Task.run("app.start") - true - - repo -> - # Repo found, check if it's actually available - if repo_available?(repo) do - # Repo is available, no need to start app - false - else - # Repo not available, start app - Mix.Task.run("app.start") - true - end - end - end - # Pad version number for consistent display defp pad_version(version) when version < 10, do: "0#{version}" defp pad_version(version), do: to_string(version) From 5a262dbd21111c59d68d1fedf7e7407e06812c83 Mon Sep 17 00:00:00 2001 From: timujeen Date: Sat, 22 Nov 2025 17:03:17 +0000 Subject: [PATCH 2/3] Fix show_missing_config_message to include Oban The message shown to users when configuration is missing did not mention Oban (background jobs for file processing), although the code already checks for Oban configuration and adds it when missing. This created confusion as: - The code checks 3 configurations (Ueberauth, Hammer, Oban) - The message only mentioned 2 (Ueberauth, Hammer) - install.ex already had the correct message with Oban - update.ex was missing this line Now both install.ex and update.ex show consistent messages to users about all required configurations. --- lib/mix/tasks/phoenix_kit.update.ex | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/mix/tasks/phoenix_kit.update.ex b/lib/mix/tasks/phoenix_kit.update.ex index 0fdeec72a..1429dd62d 100644 --- a/lib/mix/tasks/phoenix_kit.update.ex +++ b/lib/mix/tasks/phoenix_kit.update.ex @@ -201,6 +201,7 @@ if Code.ensure_loaded?(Igniter.Mix.Task) do PhoenixKit requires configuration for: - Ueberauth (OAuth authentication) - Hammer (rate limiting) + - Oban (background jobs for file processing) This configuration will be added now. From ad87f7a41bed48a01b95cf51c523687f6ec49094 Mon Sep 17 00:00:00 2001 From: timujeen Date: Sat, 22 Nov 2025 22:03:27 +0000 Subject: [PATCH 3/3] Fix Oban config detection and add automatic restart This commit fixes the infinite loop issue where mix phoenix_kit.update would get stuck checking for Oban configuration and never execute migrations. Problems fixed: 1. has_active_oban_config? was checking for hardcoded app name - BEFORE: Searched for "config :phoenix_kit, Oban" - AFTER: Searches for ", Oban" to match any app name - This fix applied to both install.ex and update.ex 2. No automatic restart after adding configuration - Commands now automatically restart instead of asking user - Uses is_retry flag and recursive run(argv) call - Prevents infinite loops with {:missing, true} safety check 3. Removed unused code that caused compilation warnings - Removed unused 'result' variable in both files - Removed show_config_added_message/1 function (no longer needed) Technical implementation: - Pattern match on {config_status, is_retry} tuple - First pass {:missing, false}: Add config + automatic restart - Second pass {:ok, _}: Execute migrations normally - Safety check {:missing, true}: Prevent infinite loops Results: - mix phoenix_kit.update now completes in one command - Automatically detects missing Oban config (any app name) - Automatically adds config and reruns - Executes migrations without manual intervention - No more "run again" messages - fully automatic Also includes: - Comment explaining igniter usage in mix.exs --- lib/mix/tasks/phoenix_kit.install.ex | 69 ++++++++++++++++++++-------- lib/mix/tasks/phoenix_kit.update.ex | 64 ++++++++++++++++++-------- mix.exs | 2 + 3 files changed, 96 insertions(+), 39 deletions(-) diff --git a/lib/mix/tasks/phoenix_kit.install.ex b/lib/mix/tasks/phoenix_kit.install.ex index 23c43a078..4ad875c35 100644 --- a/lib/mix/tasks/phoenix_kit.install.ex +++ b/lib/mix/tasks/phoenix_kit.install.ex @@ -135,18 +135,40 @@ if Code.ensure_loaded?(Igniter.Mix.Task) do # CRITICAL: Check if required configuration exists BEFORE starting app # This prevents configuration timing issues where config is added via Igniter # but the app has already started with cached (missing) configuration + + # Check if this is a retry pass (automatic restart after adding config) + is_retry = Process.get(:phoenix_kit_retry_pass, false) config_status = check_required_configuration() - case config_status do - :missing -> + case {config_status, is_retry} do + {:missing, false} -> # First pass: Add configuration via Igniter without starting app + # Store status in Process dictionary for tracking + Process.put(:phoenix_kit_config_status, :missing) + show_missing_config_message(argv) - result = super(argv) - show_config_added_message(argv) - result + super(argv) + + # AUTOMATIC RESTART instead of asking user to run again manually + Mix.shell().info(""" + + ✅ Configuration added successfully! + 🔄 Automatically restarting to complete the installation... + """) - :ok -> + # Clean Process dictionary to ensure fresh state for retry + Process.delete(:phoenix_kit_config_status) + + # Mark this as a retry pass to prevent infinite loops + Process.put(:phoenix_kit_retry_pass, true) + + # Recursive call with same arguments - automatic restart + run(argv) + + {:ok, _} -> # Second pass: Configuration exists, safe to start app and complete installation + Process.put(:phoenix_kit_config_status, :ok) + # Run standard igniter process result = super(argv) @@ -158,7 +180,27 @@ if Code.ensure_loaded?(Igniter.Mix.Task) do AssetRebuild.check_and_rebuild(verbose: true) end + # Clean up retry flag on successful completion + Process.delete(:phoenix_kit_retry_pass) result + + {:missing, true} -> + # Safety check: Configuration still missing after automatic retry + # This prevents infinite loops if configuration addition fails + Mix.shell().error(""" + + ❌ Configuration was not added successfully after automatic retry. + + Please check config/config.exs manually and ensure it contains: + - config :ueberauth, Ueberauth (with providers: %{}) + - config :hammer (with backend and expiry_ms) + - config :phoenix_kit, Oban (with queues configuration) + + Then run: mix phoenix_kit.install #{Enum.join(argv, " ")} + """) + + Process.delete(:phoenix_kit_retry_pass) + :error end end end @@ -286,17 +328,6 @@ if Code.ensure_loaded?(Igniter.Mix.Task) do """) end - # Display message after configuration is added - defp show_config_added_message(argv) do - Mix.shell().info(""" - - ✅ Configuration added successfully! - - Next step: Run the install command again to complete the installation: - mix phoenix_kit.install #{Enum.join(argv, " ")} - """) - end - # Check if all required configuration exists # Returns :ok if all config present, :missing if any config is missing defp check_required_configuration do @@ -361,9 +392,9 @@ if Code.ensure_loaded?(Igniter.Mix.Task) do has_oban_config = Enum.any?(lines, fn line -> trimmed = String.trim(line) - # Not a comment and contains config :phoenix_kit, Oban + # Not a comment and contains config :any_app, Oban !String.starts_with?(trimmed, "#") and - String.contains?(line, "config :phoenix_kit, Oban") + String.contains?(line, ", Oban") end) has_queues = diff --git a/lib/mix/tasks/phoenix_kit.update.ex b/lib/mix/tasks/phoenix_kit.update.ex index 1429dd62d..c5fee6650 100644 --- a/lib/mix/tasks/phoenix_kit.update.ex +++ b/lib/mix/tasks/phoenix_kit.update.ex @@ -167,26 +167,60 @@ if Code.ensure_loaded?(Igniter.Mix.Task) do # CRITICAL: Check if required configuration exists BEFORE starting app # This prevents configuration timing issues where config is added via Igniter # but the app has already started with cached (missing) configuration + + # Check if this is a retry pass (automatic restart after adding config) + is_retry = Process.get(:phoenix_kit_retry_pass, false) config_status = check_required_configuration() - case config_status do - :missing -> + case {config_status, is_retry} do + {:missing, false} -> # First pass: Add configuration via Igniter without starting app # Store config status in Process dictionary for igniter/1 to read Process.put(:phoenix_kit_config_status, :missing) show_missing_config_message(argv) - result = super(argv) - show_config_added_message(argv) - result + super(argv) + + # Automatic restart instead of manual prompt + Mix.shell().info(""" + + ✅ Configuration added successfully! + 🔄 Automatically restarting to complete the update... + """) - :ok -> - # Second pass: Configuration exists, safe to start app and update + # Clean Process dictionary for fresh state + Process.delete(:phoenix_kit_config_status) + Process.put(:phoenix_kit_retry_pass, true) + + # Recursive call with same arguments + run(argv) + + {:ok, _} -> + # Second pass (automatic or manual): Configuration exists, safe to start app # Store config status in Process dictionary for igniter/1 to read Process.put(:phoenix_kit_config_status, :ok) Mix.Task.run("app.start") result = super(argv) post_igniter_tasks(elem(opts, 0)) + + # Clean retry flag + Process.delete(:phoenix_kit_retry_pass) result + + {:missing, true} -> + # Safety: Configuration still missing after retry + Mix.shell().error(""" + + ❌ Configuration was not added successfully after automatic retry. + + This may indicate a problem with your config/config.exs file. + Please check the file manually and ensure it's writable. + + Then run manually: + mix phoenix_kit.update #{Enum.join(argv, " ")} + """) + + Process.delete(:phoenix_kit_retry_pass) + :error end end end @@ -210,17 +244,6 @@ if Code.ensure_loaded?(Igniter.Mix.Task) do """) end - # Display message after configuration is added - defp show_config_added_message(argv) do - Mix.shell().info(""" - - ✅ Configuration added successfully! - - Next step: Run the update command again to complete the upgrade: - mix phoenix_kit.update #{Enum.join(argv, " ")} - """) - end - # Check if all required configuration exists # Returns :ok if all config present, :missing if any config is missing defp check_required_configuration do @@ -285,9 +308,10 @@ if Code.ensure_loaded?(Igniter.Mix.Task) do has_oban_config = Enum.any?(lines, fn line -> trimmed = String.trim(line) - # Not a comment and contains config :phoenix_kit, Oban + # Not a comment and contains config for any app with Oban + # Matches: "config :any_app, Oban" or "config :any_app, Oban," !String.starts_with?(trimmed, "#") and - String.contains?(line, "config :phoenix_kit, Oban") + String.contains?(line, ", Oban") end) has_queues = diff --git a/mix.exs b/mix.exs index 66a80709f..03d8a52fa 100644 --- a/mix.exs +++ b/mix.exs @@ -128,6 +128,8 @@ defmodule PhoenixKit.MixProject do {:finch, "~> 0.18"}, # Code generation and project patching + # Note: Available in all environments for library code, but typically + # only needed in :dev when used as a dependency in parent projects {:igniter, "~> 0.7"} ] end