Where / How does the Mix environment variable get set?

I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set?

Thanks.

2 Likes

https://github.com/elixir-lang/elixir/blob/50293b46f13a86328f0ffabdcbb8592e29ac24c6/lib/mix/lib/mix/state.ex#L11

it gets set here. It’s a compile-time variable, gets fetched fron shell environment, and default value is “dev”.

5 Likes

And for anyone who isn’t already aware (like me until relatively recently), this means you can set the environment on each mix command.

Unix-like:

MIX_ENV=prod mix {task}

Windows:

set "MIX_ENV=prod" && mix {task}
8 Likes

At least for UNIXoid systems, that is not possible on windows.

2 Likes

As it happens I was at the mix intro doc tonight so I came across the Windows equivalent and edited my reply.

1 Like

It is not 100% equivalent and one needs to know the differences when using the windows version:

$ echo %MIX_ENV%
%MIX_ENV%

$ set MIX_ENV=test && mix deps.get
Running dependency resolution...
All dependencies up to date

$ echo %MIX_ENV%
test

Linux:

$ echo $MIX_ENV

$ MIX_ENV=test mix deps.get
Running dependency resolution...
All dependencies up to date

$ echo $MIX_ENV

As you can see, in linux the value of MIX_ENV is only overwritten for that single command and recovered afterwards, while the windows version changes the value permanently.

3 Likes

I just use a bash/cygwin shell on Windows, much more uniform. ^.^

3 Likes

aside from inlining them with command calls in Linux these can be set on a user level by adding them to .profile or .bashrc or for all users in /etc/environment or /etc/profile, this might be useful when provisioning servers

1 Like

A related concept: you may have noticed that when you run mix test, it assumes MIX_ENV=test, but most tasks assume MIX_ENV=dev unless otherwise specified.

To set the default environment for a Miix task (eg, a task to run JS tests) or task alias, you can use :preferred_cli_env. For example:

defmodule MyProject.Mixfile do
  use Mix.Project

  def project do
    [
      # ...
      aliases: aliases(),
      preferred_cli_env: [
        # note that all task names are atoms
        test: :test,
        jstest: :test,
        "test.all": :test
      ]
    ]
  end

  # ...

  defp aliases do
    [
      "test.all": ["test", "jstest"]
    ]
  end
end
4 Likes

See also this answer https://stackoverflow.com/a/35888676/119790