Should I include mix app in extra_applications?

272 Views Asked by At

I'm using distillery to package an elixir application, and I want to have access to the current environment in the runtime (is it :dev, :test or :prod).

The goal will be checking the env at the runtime, something like this:

if Mix.env() == :prod do
  # do this only in production
end

What are the drawbacks of including the mix app in the release?

def application do
    [mod: {EvercamMedia, []}, extra_applications: [:runtime_tools, :os_mon, :recon, :mix]]
end
3

There are 3 best solutions below

5
On BEST ANSWER

Using mix to detect the production environment is clearly an antipattern. Instead, one should probably start the release as

MY_APP_PROD=true release start

and use the system environment check as shown below

if System.get_env("MY_APP_PROD") == "true" do
  ...
end
0
On

You should not include mix in your release. You have various alternatives:

  • Use an environment variable, which is set at runtime, and then either:
    • Check it in code using e.g. System.fetch_env!.
    • Check it in config/runtime.exs (not config/prod.exs; this is also evaluated at compile-time).
  • Or compile the value of MIX_ENV into your code. @Daniel provides one way to do this. I offer another:
defmodule M do
  @build_env Mix.env()

  def env(), do: @build_env
end

The trick here is that the @build_env... statement is evaluated at compile-time (when Mix is available), setting the attribute. You can then just return it from your function.

0
On

Mix is disabled in production for a reason, it is a build tool, you can read more about it here.

If you need only the current environment, then you can do something like this:

defmacro env() do
    quote do
      unquote(Mix.env())
    end
  end

However you need to remember that this code is evaluated at compile-time and will not work with things like runtime configurations.