For some time I had big problem with Mix that it didn’t supported fetching project version from Git, like Rebar3 does with {version, git} in .app.src. So finally I have crafted the snippet that works and does exactly that:
defp version do
case :file.consult('hex_metadata.config') do
{:ok, data} ->
{"version", version} = List.keyfind(data, "version", 0)
version
_ ->
version =
case System.cmd("git", ~w[describe --dirty=+dirty]) do
{version, 0} ->
String.trim(version)
{_, code} ->
Mix.shell().error("Git exited with code #{code}, falling back to 0.0.0")
"0.0.0"
end
case Version.parse(version) do
{:ok, %Version{pre: ["pre" <> _ | _]} = version} ->
to_string(version)
{:ok, %Version{pre: []} = version} ->
to_string(version)
{:ok, %Version{patch: patch, pre: pre} = version} ->
to_string(%{version | patch: patch + 1, pre: ["dev" | pre]})
:error ->
Mix.shell().error("Failed to parse #{version}, falling back to 0.0.0")
"0.0.0"
end
end
end
And now use [version: version()] and it will automatically use version from Hex when available, Git version when project is fetched via Git, if everything fails then it will fall back to 0.0.0.
Unfortunately as Mix do not have a way to have per-project extensions preloaded it need to be distributed as such snippet and I cannot make it into library that would make it clearer.
I have used above in Watermelon and I have tested that it works as expected.






















