0

Having:

  defp deps do
    [
      {:poison, "~> 3.0"},
      {:credo, "~> 0.10.0", only: [:dev, :test], runtime: false}
    ]
  end

I am doing something like this to ensure all dependencies are started:

MixProject.project()
|> Keyword.get(:deps)
|> Keyword.keys()
|> Enum.each(fn dep ->
  Application.ensure_all_started(dep)
end

But is crashing with :dev dependencies like credo.

Can I retreive :prod only dependencies? since filtering out only: [:dev, :test], runtime: false is a bit tricky

lapinkoira
  • 8,320
  • 9
  • 51
  • 94
  • 1
    Does passing your app's name to `Application.ensure_all_started` not work? Starting your app will start all your dependencies if they're not started. – Dogbert Aug 07 '18 at 13:44
  • this is intended for mix tasks where my app is not running – lapinkoira Aug 07 '18 at 13:55
  • Something like this https://stackoverflow.com/questions/35706320/starting-mix-task-process-dependencies but I added all the dependencies because I have a lot of mandatory dependencies – lapinkoira Aug 07 '18 at 13:56

1 Answers1

3

First, about the reason you're getting an error. In your example this invocation

MixProject.project()
|> Keyword.get(:deps)

returns a List and not a Keyword List which is what the next line expects

|> Keyword.keys()

That's why it crashes with what can be assumed to be

** (FunctionClauseError) no function clause matching in anonymous fn/1 in Keyword.keys/1

As you pointed out it crashes specifically on those dependencies that are not described by a two-item tuple and therefore do not represent elements of a Keyword List.


Now to the core of your question. As you pointed out you could filter the deps manually but scenarios like these make it rather tedious to do:

{:dep_one, "~> 1.0"},
{:dep_two, "~> 1.0", only: [:prod]},
{:dep_three, "~> 1.0", except: [:dev, :test]}

An alternative is to build your deps list dynamically depending on the environment, e.g.:

defp deps do
  [
    # universal deps go here
  ] ++ deps(Mix.env)
end

defp deps(env) when env == :dev do
  [
    # dev-only deps
  ]
end
defp deps(env) when env == :test do
  [
    # test-only deps
  ]
end
defp deps(env) when env == :prod do
  [
    # prod-only deps
  ]
end

This simplistic implementation would require duplicate definitions of the deps defined for multiple environments, such as only: [:dev, :test], but it could be reworked to avoid that.

Nic Nilov
  • 5,056
  • 2
  • 22
  • 37