-
Notifications
You must be signed in to change notification settings - Fork 3.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement :env_vars option for %Mix.Dep{} #6933
Conversation
lib/mix/lib/mix/dep/loader.ex
Outdated
@@ -36,6 +36,15 @@ defmodule Mix.Dep.Loader do | |||
only != nil and env not in List.wrap(only) | |||
end | |||
|
|||
def with_env_vars(%Mix.Dep{env_vars: env_vars}, callback) do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's have a fast path clause that checks if env_vars is an empty list and then we just invoke the callback.
lib/mix/lib/mix/dep/loader.ex
Outdated
@@ -36,6 +36,15 @@ defmodule Mix.Dep.Loader do | |||
only != nil and env not in List.wrap(only) | |||
end | |||
|
|||
def with_env_vars(%Mix.Dep{env_vars: env_vars}, callback) do | |||
env = System.get_env() | |||
System.put_env(env_vars) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use try/after here.
@@ -261,9 +261,15 @@ defmodule Mix.Tasks.Deps.Compile do | |||
end | |||
end | |||
|
|||
defp do_command(%Mix.Dep{app: app, opts: opts}, config, command, print_app?, env \\ []) do | |||
defp do_command( | |||
%Mix.Dep{app: app, env_vars: env_vars, opts: opts}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please move %Mix.Dep{app: app, opts: opts}
out of the function head and into the function body.
lib/mix/test/mix/dep_test.exs
Outdated
|
||
with_deps( | ||
[ | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please look at the other tests. You should define the deps as a variable before calling with_deps
.
/cc @mobileoverlord could this be useful to you? |
My only concern is regarding the name since "env" is a bit overloaded. I wonder if |
If I had to choose between |
lib/mix/lib/mix/dep.ex
Outdated
@@ -31,6 +31,8 @@ defmodule Mix.Dep do | |||
the information on this field is private to the manager and should not be | |||
relied on | |||
|
|||
* `env_vars` - an enumerable of tuples containing environment key-value as binary |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be elaborated on. It doesn't say what the option does and when it's used. For example it is only used during loading and not during compilation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I copied the text of the :env
option of System.cmd/3 which is of the same type. You're absolutely right that it needs better doc there, I'll update it.
Should I also add an entry in the changelog about this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We try to avoid updating the changelog in PRs because it easily leads to conflicts. An entry will be added before we do a new release of course.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reworded it to:
an enumerable of key-value tuples of binaries to be set as environment variables when loading or compiling the dependency
I tried to keep keep it short to match the terseness of the rest of the options. Let me know what you think.
Keep in mind that this option won't be honored for hex package dependencies so we will have to reject publishing to hex when the option is used. |
@ericmj do you have any preference regarding the name? |
I prefer |
@zorbash let's go with |
c2519a6
to
730bafb
Compare
I've made changes reflecting suggestions in the comments and renamed @ericmj about #6933 (comment) Would it be desirable to submit a PR to hex to not publish when |
Please do. |
lib/mix/lib/mix/dep/loader.ex
Outdated
@@ -161,7 +174,8 @@ defmodule Mix.Dep.Loader do | |||
app: app, | |||
requirement: req, | |||
status: scm_status(scm, opts), | |||
opts: Keyword.put_new(opts, :env, :prod) | |||
opts: Keyword.put_new(opts, :env, :prod), | |||
system_env: Keyword.get(opts, :system_env, []) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we have to separate this from opts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It makes it easier to pattern match on it later and I don't think this needs to be available to the SCM, does it?
In any case, if we have a dedicated field for it, we should probably pop
it from opts
by calling Keyword.pop(opts, :system_env, [])
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With system_env
as a dedicated field, we can pattern match to reject a package from being published by adding:
%Mix.Dep{app: app, system_env: _} ->
Mix.raise "Can't build package when :system_env is set for dependency #{app}, remove `system_env: ...`"
to https://github.com/hexpm/hex/blob/v0.17.1/lib/mix/tasks/hex.build.ex#L157
But I don't see how hex, containing such a change would keep being compatible with all the Elixir versions (other than master) defined in its .travis.yml
, unless if we pattern match on it as a Map.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hex wouldn't be able to pattern match on it, we would have to pull it out with Map.get/3
. We don't seem to use it for pattern matching in this PR either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ericmj we pattern match on it both times we use it. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ericmj if you're OK with something like:
Enum.each(include, fn %Mix.Dep{app: app, opts: opts} = dep ->
if Map.get(dep, :system_env) do
Mix.raise "Can't build package when :system_env is set for dependency #{app}, remove `system_env: ...`"
end
end)
we can keep the dedicated field and also use keyword.pop/3 as @josevalim suggested, so not to have it in the opts as it's not an SCM option.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@josevalim I meant pattern match in a conditional way, right now the pattern matches could be replaced with dep.system_env or opts[:system_env]. But it’s not a strong opinion so let’s go ahead with th dedicated field.
@zorbash yeah, something like that would work.
Thank you! |
This PR is the implementation of this proposal, which allows defining per dependency env variables to be used when loading or compiling it.
Example:
Will set the
EXOMETER_PACKAGES
env variable to "(amqp)" which will include the amqp dependencies in themix.lock
(see: exometer-dependency-management). This is a Rebar specific example, but the PR sets the env vars to all types of supported packages.All the files have been formatted using the new
mix format
task.I'll be really happy to get feedback to improve this PR and make all the required changes to have it merged.