ojinari

ojinari

When deploying a release via “mix compile / release”, Mix may not exist on a server, right? Therefore, if Mix.env() == 'abc' won’t work.

What is it then a way to detect the current environment? A one which would work everywhere, whether it be in dev or production or any other custom environment that I may create. And a one which won’t require copy-paste, and which will update itself automatically. Namely, merely using an environmental variable won’t work because what if I launched a project in prod. enviroment but locally? And then in dev. env again locally too. Or in dev. environment on a server? An env. variable would hold the wrong value half of the time - unreliable solution.

Also note that on a server I may use systemd or rc.d service, therefore simply using .env file although would work locally in dev env, wouldn’t on a server because it’d require copy-pasting the env. data into systemd or rc.d services and I want to avoid copy-paste.

Showing Posts 1 to 10

jwarlander

jwarlander

I’m not 100% sure what you’re after, but neither Elixir / Phoenix nor any other programming platform can automagically know if you intend to run the program in “production” or not when you start it.

You have to figure out how to make it work for you.

In our case, we deploy to AWS, with different accounts for test & prod. The app picks up configuration from Secrets Manager, in the form of secrets for eg. database access (hostname + user + password). The secret is always called the same name, but has different contents in the test vs prod accounts.

If we run locally in Mix dev mode, it will just pick up environment variables. If running locally in Mix prod, it’ll pick up the relevant secrets depending on which account the AWS_PROFILE env var points to.

josevalim

josevalim

Creator of Elixir

The thing is that hardcoding Mix.env() checks in your application is confusing and error prone. Instead, try using the application configuration and setting the proper values in your dev/test/prod. This way an operator of the system can see all behaviour that is different between dev/test/prod without having to grep for Mix.env() checks in the codebase.

ojinari

ojinari OP

Do you suggest that I hard-code “current_env: :dev” in config/dev.exs and “current_env: :prod” in config/prod.exs? This doesn’t make sense because how does the appropriate enviroment config file get loaded in the first place? Where does Phoenix itself get information about the current environment from and therefore which env. config file to load?


And it’s not about setting values in dev/prod/test. It’s about checking the current environment itself. It’s because in some places in my project I need to check whether or not, for instance, the current environment is dev, in others – if it’s prod, in others – if it’s staging, in others – if it’s my_custom_env.

soup

soup

Application.get_env?

Can you provide a stricter example of need? It sounds like a code smell.

I am assuming that say, in Prod you want to hit a real remote service, but in dev you want to hit something else or not hit anything at all.

IMO you should keep your code the same no matter the env and swap in/out a stub service to act as the API where required.

E.g:

Dev -> CreateTicketMock() # does nothing
Staging -> CreateTicketAsFile() # write to local file
Prod -> CreateTicketInHugeInfrastructuerWithExternalService() # actually do something

And your config/dev|prod|staging sets an appropriate value for the application to load the right service, so your code is just TicketCreator.create_ticket(...) no matter the environment.

ojinari

ojinari OP

if current_env == a do
  # something
end
if current_env == b do
  # something 2
end
soup

soup

Yes, but why.

josevalim

josevalim

Creator of Elixir

No, instead have a config for each specific behavior. For example, imagine there is an external service which provides both dev and prod URLs, make that a configuration instead of checking for the environment inside the code.

ojinari

ojinari OP

And it’s not about setting values in dev/prod/test. It’s about checking the current environment itself. It’s because in some places in my project I need to check whether or not, for instance, the current environment is dev, in others – if it’s prod, in others – if it’s staging, in others – if it’s my_custom_env.

The behaviour of some parts of my project would differ depending on the current env. That is, I may do something in case the env. is “dev”, and don’t do it if it’s “my_custom_env”, and do something different if it’s “prod”.

soup

soup

Why do you have to have the if in code and not just inject the correct delegate when the service boots though?

Anyway, I believe Jose is saying set whatever you want to check in the appropriate config file, you can then get that with Application.get_env or you can use System.get_env if you want to get an regular system environment variables. You could probably do config :my_app, :execution_env, Mix.env() in config/config.exs I guess then Application.get_env(:my_app, :execution_env).

I think Jose is also implying that instead of checking against the env en todo, it’s better design to check against specific configurations, which is more readable and maintainable:

if Application.get_env(:my_app, :do_use_service) ...
if Applcation.get_env(:my_app,  :logging_is_enabled) ...

vs

if Application.get_env(:my_app, :mode) ==  :dev then do_use_service()

See h Application.get_env and h System.get_env in iex.

jwarlander

jwarlander

I guess you could define a module attribute?

@current_env Mix.env()

defmodule MyModule do
  def current_env, do: @current_env
end

..and then use it wherever you need. If I’m not mistaken, it should be evaluated at compile time, so if compiled for Mix env = dev, will always be “dev”, etc.

Where Next? Top

Trending in Discussions Top

AstonJ
As the title says, please share what you’ve been up to with Elixir. Whether that’s been learning it, looking into it, making stuff with i...
2977 94592 917
New
cblavier
Hey there, It’s been more than a year since we started using LiveView as our main UI library and building a whole library of UI componen...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
heathen
Quite interesting article Google brought me. Didn’t find any mentions about it here. What do you think in general? Would you use togethe...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
AstonJ
Since we have deprecated our Erlang sections (as we have dedicated Erlang Forums now) let’s add this thread for those who’d like to post ...
New
Null-logic-0
What IDE or editor are you using for Elixir development? Personally, I use Zed, and I really like it, but sometimes I wish there were a ...
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews