jakesgordon
Recompiling mix.exs when external_resource changes
I would like to load my app version from an external VERSION file (so that other CI/CD tools have easy access to the value). I’ve updated my mix.exs to load the value at compile time (see below), which works great, however mix.exs doesn’t get recompiled when I modify my external VERSION file. I’ve added it as an @external_resource but maybe that module attribute has no effect in .exs files (I’m not entirely sure if a .exs script is considered a module) ?
@external_resource version_file = "VERSION"
@version File.read!(version_file) |> String.trim
def project do
[
version: @version,
# ...
]
end
I can workaround it by also doing a touch mix.exs whenever I bump the version number, but was looking to see if there’s anyway to get the @external_resource attribute to work inside mix.exs ?
Thanks!
Most Liked
axelson
Hmmm, I’m pretty sure that mix.exs is “compiled” every single time you run a mix command. But what doesn’t happen is that the rest of the project is not recompiled when you change your VERSION file. Judging from the docs on @external_resource:
Specifies an external resource for the current module.
Sometimes a module embeds information from an external file. This attribute allows the module to annotate which external resources have been used.
Tools like Mix may use this information to ensure the module is recompiled in case any of the external resources change.
I think that what is happening is that since mix.exs is an .exs file it always needs to be recompiled so adding @external_resource does not change which files need to be recompiled. And the behavior that you see after a touch mix.exs is (I think) special behavior specifically for mix.exs and configuration files. I could be wrong on some of these details, and if so I would be glad for someone to correct me.
Are there other specific files that you want to be recompiled when your VERSION file changes? One potential solution is to add the @extrernal_resource to those files directly. Or if you have some other goal then it would be helpful to know exactly what you’re trying to do. If it’s an issue in CI/CD environment maybe it’s best to not cache parts of the build. But it’s a little hard to say without more details.
It is considered a module if there is a defmodule contained within. But there are a few different behaviors of .exs file vs .ex files, for example the .beam files for .exs files are not persisted to disk (although they are loaded in memory when the beam is running).
kokolegorille
Hello and welcome,
exs files are for scripting, and are not compiled.
jakesgordon
Update: I just noticed that if I look at the value of Mix.Project.config[:version] (in IEx) then that value does reflect the latest correct value from the VERSION file. So assuming that iex -S mix runs the mix.exs file each time that would make sense…
So I guess that just leaves me a bit confused about the difference between Mix.Project.config[:version] and Application.spec(:my_app, :vsn). The former is updated whenever I touch the VERSION file but the latter is only updated if (something) gets recompiled.








