We’re in the process of upgrading from 1.13 to 1.14.
We had various calls to
compile_env to access env variables, and from what the warnings are telling me these should be
I’ve replaced these all, going from
@access_key Application.compile_env(:app, key)
defp access_key, do: Application.get_env(:app, :key)
This seems to have worked fine and cleared 99% of the errors, however there is one issue with Guardian that I can’t solve:
defmodule App.Auth.Bla do
secret_key: Application.compile_env(:app, __MODULE__)[:secret_key]
Because this call happens outside of a function, I cannot replace it with
get_env. But leaving it at
compile_env throws an error. I also can’t move it into a function as the function is not yet defined when the above code is invoked.
How can I access an environment variable and feed it into Guardian as the secret key without calling compile_env? Or is there another approach I’m missing?
Can you post the error you get? You should be using
compile_env for compile time set config.
compile_env you want to put the complete path into the function call:
Application.compile_env(:app, [__MODULE__, :secret_key])
That allows elixir to track dependencies better.
== Compilation error in file lib/app/auth/bla.ex ==
** (RuntimeError) Application.compile_env/3 cannot be called inside functions, only in the module body
(elixir 1.14.0) lib/application.ex:532: Application."MACRO-compile_env"/4
(elixir 1.14.0) expanding macro: Application.compile_env/2
(elixir 1.14.0) expanding macro: Kernel.|>/2
It mentions line 8 and line 12 of the file, which are
use Guardian and
secret_key: Application.compile_env(:app, __MODULE__)[:secret_key] respectively
guardian is putting the AST of the call in a function. I’d probably just put assign the secret to a module attribute and give that to
guardian, unless you actually need that to be runtime configurable.
Annoyingly I can’t do that
@secret_key Application.compile_env(:app, [__MODULE__, :secret_key])
Throws an error as this variable is different at compile time vs run time, and I can’t call
get_env here as it’s outside of a function.
I also can’t do
defp secret_key, do: Application.get_env(:app, [__MODULE__, :secret_key])
as this function isn’t defined when Guardian has its secret key assigned
I might be off here, but if guardian indeed puts the AST for fetching the secret in a function for runtime use and also tries to access it at compile time then I think that’s something to fix on guardian’s end. It should be doing either/or, but not both.
You can keep configuration to the minimum in implementation module of the Guardian - move the rest in config files.
defmodule App.Auth.Bla do
use Guardian, otp_app: :app
config :app, App.Auth.Bla,
You can read more in config section of Guardian docs
This will be regular configuration loading from environment, once the implementation module is kept minimal.
This actually works too thank you so much