diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c11117b32a..07636bde02 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,6 +65,7 @@ jobs: - name: Run installer test run: | cd installer + mix deps.get mix test if: ${{ matrix.installer }} diff --git a/installer/lib/mix/tasks/phx.new.ex b/installer/lib/mix/tasks/phx.new.ex index dc4807b652..991b3d1358 100644 --- a/installer/lib/mix/tasks/phx.new.ex +++ b/installer/lib/mix/tasks/phx.new.ex @@ -69,6 +69,8 @@ defmodule Mix.Tasks.Phx.New do * `-v`, `--version` - prints the Phoenix installer version + * `--no-version-check` - skip the version check for the latest phx_new version + When passing the `--no-ecto` flag, Phoenix generators such as `phx.gen.html`, `phx.gen.json`, `phx.gen.live`, and `phx.gen.context` may no longer work as expected as they generate context files that rely @@ -140,7 +142,8 @@ defmodule Mix.Tasks.Phx.New do install: :boolean, prefix: :string, mailer: :boolean, - adapter: :string + adapter: :string, + version_check: :boolean ] @impl true @@ -151,17 +154,40 @@ defmodule Mix.Tasks.Phx.New do def run(argv) do elixir_version_check!() - case OptionParser.parse!(argv, strict: @switches) do - {_opts, []} -> - Mix.Tasks.Help.run(["phx.new"]) + {opts, argv} = OptionParser.parse!(argv, strict: @switches) - {opts, [base_path | _]} -> - if opts[:umbrella] do - generate(base_path, Umbrella, :project_path, opts) - else - generate(base_path, Single, :base_path, opts) - end + version_task = + if Keyword.get(opts, :version_check, true) do + get_latest_version("phx_new") + end + + result = + case {opts, argv} do + {_opts, []} -> + Mix.Tasks.Help.run(["phx.new"]) + + {opts, [base_path | _]} -> + if opts[:umbrella] do + generate(base_path, Umbrella, :project_path, opts) + else + generate(base_path, Single, :base_path, opts) + end + end + + if version_task do + try do + # if we get anything else than a `Version`, we'll get a MatchError + # and fail silently + %Version{} = latest_version = Task.await(version_task, 3_000) + maybe_warn_outdated(latest_version) + rescue + _ -> :ok + catch + :exit, _ -> :ok + end end + + result end @doc false @@ -385,4 +411,55 @@ defmodule Mix.Tasks.Phx.New do ) end end + + defp maybe_warn_outdated(latest_version) do + current_version = + Application.spec(:phx_new)[:vsn] + |> to_string() + |> Version.parse!() + + if Version.compare(current_version, latest_version) == :lt do + Mix.shell().info([ + :yellow, + "A new version of phx.new is available:", + :green, + " v#{latest_version}", + :reset, + ".", + "\n", + "You are currently running ", + :red, + "v#{current_version}", + :reset, + ".\n", + "To update, run:\n\n", + " $ mix local.phx\n" + ]) + end + end + + defp get_latest_version(package) do + Task.async(fn -> + # ignore any errors to not prevent the generators from running + # due to any issues while checking the version + try do + with {:ok, {200, _headers, package}} <- + :hex_repo.get_package(:hex_core.default_config(), package) do + versions = + for release <- package.releases, + version = Version.parse!(release.version), + # ignore pre-releases like release candidates, etc. + version.pre == [] do + version + end + + Enum.max(versions, Version) + end + rescue + e -> {:error, e} + catch + :exit, _ -> {:error, :exit} + end + end) + end end diff --git a/installer/mix.exs b/installer/mix.exs index 518f3a2432..99d90dc9f8 100644 --- a/installer/mix.exs +++ b/installer/mix.exs @@ -58,6 +58,7 @@ defmodule Phx.New.MixProject do def deps do [ + {:hex_core, "~> 0.11.0"}, {:ex_doc, "~> 0.24", only: :docs} ] end diff --git a/installer/mix.lock b/installer/mix.lock index 394ffc7366..02fb04015c 100644 --- a/installer/mix.lock +++ b/installer/mix.lock @@ -2,6 +2,7 @@ "earmark": {:hex, :earmark, "1.4.10", "bddce5e8ea37712a5bfb01541be8ba57d3b171d3fa4f80a0be9bcf1db417bcaf", [:mix], [{:earmark_parser, ">= 1.4.10", [hex: :earmark_parser, repo: "hexpm", optional: false]}], "hexpm", "12dbfa80810478e521d3ffb941ad9fbfcbbd7debe94e1341b4c4a1b2411c1c27"}, "earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"}, "ex_doc": {:hex, :ex_doc, "0.34.0", "ab95e0775db3df71d30cf8d78728dd9261c355c81382bcd4cefdc74610bef13e", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "60734fb4c1353f270c3286df4a0d51e65a2c1d9fba66af3940847cc65a8066d7"}, + "hex_core": {:hex, :hex_core, "0.11.0", "d1c6bbf2a4ee6b5f002bec6fa52b5080c53c8b63b7caf6eb88b943687547bff4", [:rebar3], [], "hexpm", "707893677a425491962a2db522f1d2b1f85f97ea27418b06f7929f1d30cde0b0"}, "makeup": {:hex, :makeup, "1.1.2", "9ba8837913bdf757787e71c1581c21f9d2455f4dd04cfca785c70bbfff1a76a3", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cce1566b81fbcbd21eca8ffe808f33b221f9eee2cbc7a1706fc3da9ff18e6cac"}, "makeup_elixir": {:hex, :makeup_elixir, "0.16.2", "627e84b8e8bf22e60a2579dad15067c755531fea049ae26ef1020cad58fe9578", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "41193978704763f6bbe6cc2758b84909e62984c7752b3784bd3c218bb341706b"}, "makeup_erlang": {:hex, :makeup_erlang, "1.0.0", "6f0eff9c9c489f26b69b61440bf1b238d95badae49adac77973cbacae87e3c2e", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "ea7a9307de9d1548d2a72d299058d1fd2339e3d398560a0e46c27dab4891e4d2"}, diff --git a/integration_test/test.sh b/integration_test/test.sh index a2cdb03528..ccddbf89e6 100755 --- a/integration_test/test.sh +++ b/integration_test/test.sh @@ -14,6 +14,7 @@ socat TCP-LISTEN:1433,fork TCP-CONNECT:mssql:1433& # Run installer tests echo "Running installer tests" cd installer +mix deps.get mix test echo "Running integration tests"