[Proposal] Ability to change the default environment

99 views
Skip to first unread message

Kevin Sjöberg

unread,
Oct 1, 2022, 4:05:18 AM10/1/22
to elixir-lang-core
I'm currently working with a client that have hard requirements on what the default environments should be across all their products. For instance, `local` is the default environment. `ci` is the default environment for running tests and `dev` is used as a development staging environment.

Mix supports the `preferred_cli_env` option, which I can declare on a project level. This is nice because it allows me to specify the preferred environment for the test task. Unfortunately, there's no way of specifying the default environment. It's currently hard-coded to `dev` unless `MIX_ENV` is set. The problem with having `MIX_ENV` set is that it simply makes `preferred_cli_env` void as the environment variable always takes precedence, so I'm left with having to specify `MIX_ENV` explicitly when running tests anyway.

I propose adding a new option, `default_env`, to the Mix project configuration. If set, it will be reported by `Mix.env` unless `MIX_ENV` is also present.

I'd love to hear some thoughts before I pursue this any further.

José Valim

unread,
Oct 1, 2022, 4:29:34 AM10/1/22
to elixir-l...@googlegroups.com
Perhaps a simpler fix is to add a "ci" Mix task to your projects that:

1. sets MIX_ENV to "ci" if not set
2. invokes "mix test"

Another option is to relax the check we have inside "mix test" and only raise if you are accidentally trying to run tests inside the "dev" environment. Then you could change the preferred_cli_env env for the test task directly in your mix.exs.

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/9029fb90-362d-4a1f-be30-6a8b3bd5f074n%40googlegroups.com.

Kevin Hovsäter

unread,
Oct 1, 2022, 4:45:38 AM10/1/22
to elixir-lang-core
Thanks for the quick reply.

Right, I think that would be a possibility. So I would have MIX_ENV set to "local" by default, and then explicitly set MIX_ENV to "ci" when invoking the test task? I assume that would be done through an alias?

> Another option is to relax the check we have inside "mix test" and only raise if you are accidentally trying to run tests inside the "dev" environment. Then you could change the preferred_cli_env env for the test task directly in your mix.exs.

I'm not sure that would help as we still need to set MIX_ENV to "local" to not accidentally invoke "dev" (dev means something different in our case). And since MIX_ENV is set, preferred_cli_env isn't respected when invoking mix test.

José Valim

unread,
Oct 1, 2022, 5:03:37 AM10/1/22
to elixir-l...@googlegroups.com
> Right, I think that would be a possibility. So I would have MIX_ENV set to "local" by default, and then explicitly set MIX_ENV to "ci" when invoking the test task? I assume that would be done through an alias?

Right. Either an alias or a custom task!

Kevin Hovsäter

unread,
Oct 1, 2022, 5:08:29 AM10/1/22
to elixir-lang-core
Got it! I just tried making an alias called "test" that points to "test.ci" and then I defined as task within lib/mix/tasks/test.ci.ex containing the following code:

defmodule Mix.Tasks.Test.Ci do
  use Mix.Task

  @preferred_cli_env :ci

  @impl Mix.Task
  def run(_args) do
    if Mix.env != @preferred_cli_env, do: Mix.env(@preferred_cli_env)
    Mix.Task.run("ecto.create", ["--quiet"])
    Mix.Task.run("ecto.migrate", ["--quiet"])
    Mix.Task.run("test")
  end
end

Unfortunately,  that didn't seem to help. The Mix.env() is correct from within the Test.Ci task, but I assume it's not propagated to the tasks I run. How would I go about solving that? I realize this have become more of an support issue than actual proposal so I'm fine with taking this somewhere else. :)

José Valim

unread,
Oct 1, 2022, 5:37:41 AM10/1/22
to elixir-l...@googlegroups.com
Can you upload a very small mix new repo to GitHub with what you tried pls? :)

Kevin Hovsäter

unread,
Oct 1, 2022, 6:50:18 AM10/1/22
to elixir-lang-core

Feel free to reach out if anything is unclear. What we're trying to achieve is basically change the default environment from `dev` to `local`. And the default test environment from `test` to `ci`.

Thanks,
Kevin

Kevin Hovsäter

unread,
Oct 1, 2022, 7:18:01 AM10/1/22
to elixir-lang-core
What's evident by the sample app above is that the config_env is still set to whatever MIX_ENV is set to, even though the test task itself is running in the appropriate environment. As I mentioned earlier, this could be solved by just running MIX_ENV=ci mix test. It would however be nice to configure a Mix application in such a way that you could specify what the default environments for dev and test should be, so you would not need to explicitly set MIX_ENV correctly whenever you interact with mix itself.

José Valim

unread,
Oct 7, 2022, 4:43:48 AM10/7/22
to elixir-l...@googlegroups.com
> What's evident by the sample app above is that the config_env is still set to whatever MIX_ENV is set to,

Right, that's because the alias still reads the environment from the task, since you are using "mix test" as the entry point. You could do this:

preferred_cli_env: [test: :ci]

And then also set System.put_env/2 in your test.custom task. But my suggestion would be to use a "mix ci" task instead (that matches your environment). "mix test" will still be around but running it will fail anyway if the env is missing.

Kevin Hovsäter

unread,
Oct 10, 2022, 3:37:06 AM10/10/22
to elixir-lang-core
Thanks for the reply, José. Appreciate it!

> Right, that's because the alias still reads the environment from the task, since you are using "mix test" as the entry point. You could do this:
>
>    preferred_cli_env: [test: :ci]

I don't think that will work as MIX_ENV is set to "local" by default. E.g., if I run "echo $MIX_ENV" in the shell it will print "local". Since MIX_ENV is persistently set, it takes precedence over the preferred_cli_env setting leaving us no other choice than explicitly setting MIX_ENV before running a task expecting a different environment. And, if I'm not mistaken, the configuration is being loaded before the Mix tasks run, so the "local" configuration file will be loaded (incorrectly) when invoking mix test.

> But my suggestion would be to use a "mix ci" task instead (that matches your environment). "mix test" will still be around but running it will fail anyway if the env is missing.

I like this idea! However, I still need to run the tests, and at that point I'll face the same issues I've described above. Right?

I think there's a couple of problems here. Since you can't override the default environment you must set MIX_ENV. If MIX_ENV is persistently set, it will interfere with Mix tasks as it  always load the configuration associated with the value of MIX_ENV. Furthermore, since MIX_ENV is set, it will make preferred_cli_env mute as it takes precedence. This leaves us with the following options:

1. Don't persistently set MIX_ENV and always specify it before running a mix task. This is cumbersome and error-prone.
2. Persistently set MIX_ENV to the default environment and then explicitly set it to something else when invoking specific tasks. Less cumbersome but still somewhat error-prone.
3. Leave MIX_ENV unset and explicitly set preferred_cli_env for every single mix task.

I'm still somewhat new to Elixir, so maybe I'm missing some key thing here. If so, feel free to point it out. :)

José Valim

unread,
Oct 10, 2022, 7:27:40 AM10/10/22
to elixir-l...@googlegroups.com
Yes, you are right, I forgot to export MIX_ENV=local. :)

I believe the only way is to have a configuration to specify the actual default_env. I started adding support for such but I decided to revamp the whole CLI configuration. Please see the following PR: https://github.com/elixir-lang/elixir/pull/12183

Kevin Hovsäter

unread,
Oct 10, 2022, 7:56:07 AM10/10/22
to elixir-lang-core
Thank you so much! Looks like it's exactly what we're after.
Reply all
Reply to author
Forward
0 new messages