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
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.