Access project version within elixir application
Asked Answered
V

6

29

I have an elixir project with a defined version. How can I access this from within the running application.

in mix.exs

  def project do
    [app: :my_app,
     version: "0.0.1"]
  end

I would like to be access this version number in the application so I can add it to the returned message. I looking for something in the env hash like the following

__ENV__.version
# => 0.0.1
Variola answered 6/10, 2015 at 10:57 Comment(0)
L
28

Here's a similar approach to retrieve the version string. It also relies on the :application module, but is maybe a bit more straightforward:

{:ok, vsn} = :application.get_key(:my_app, :vsn)
List.to_string(vsn)
Leipzig answered 6/10, 2015 at 20:10 Comment(3)
This is a better way. Personally, I'd still use the charlist |> string |> integer parsing pipeline, but this is definitely cleaner than using which_applications.Deodorize
Yes good point. Chris' solution is obviously longer because it does an extra step to convert the string into a tuple of integers. Just for printing, the plain string should however be enough. You could combine the two answers to get the tuple if you need it.Leipzig
If you're using escript or similar to build a cli app, this solution fits very well :)Thanet
S
40

Mix.Project itself provides access to all project keywords defined in mix.exs using its config/0 (api doc) function. For concise access it might be wrapped into a function:

@version Mix.Project.config[:version]
def version(), do: @version
Squirt answered 29/2, 2016 at 16:14 Comment(1)
Make sure this is evaluated at compile time like shown in the example. Otherwise it will not work in production because module Mix.Project is not available.Whose
L
28

Here's a similar approach to retrieve the version string. It also relies on the :application module, but is maybe a bit more straightforward:

{:ok, vsn} = :application.get_key(:my_app, :vsn)
List.to_string(vsn)
Leipzig answered 6/10, 2015 at 20:10 Comment(3)
This is a better way. Personally, I'd still use the charlist |> string |> integer parsing pipeline, but this is definitely cleaner than using which_applications.Deodorize
Yes good point. Chris' solution is obviously longer because it does an extra step to convert the string into a tuple of integers. Just for printing, the plain string should however be enough. You could combine the two answers to get the tuple if you need it.Leipzig
If you're using escript or similar to build a cli app, this solution fits very well :)Thanet
G
22

In recent versions of Elixir, the Application module now wraps this for you:

https://github.com/elixir-lang/elixir/blob/master/lib/elixir/lib/application.ex

Application.spec(:my_app, :vsn) |> to_string()

The Kernel.to_string() method is necessary as Application.spec/2 for the keys :vsn and :description return charlists. to_string() from the Kernel module converts them to a binary.

Gobi answered 15/2, 2018 at 15:43 Comment(0)
D
6

I found the version inside of :application.which_applications, but it requires some parsing:

defmodule AppHelper do
  @spec app_version(atom) :: {integer, integer, integer}
  def app_version(target_app) do
    :application.which_applications
    |> Enum.filter(fn({app, _, _}) ->
                    app == target_app
                   end)
    |> get_app_vsn
  end

  # I use a sensible fallback when we can't find the app,
  # you could omit the first signature and just crash when the app DNE.
  defp get_app_vsn([]), do: {0,0,0} 
  defp get_app_vsn([{_app, _desc, vsn}]) do
    [maj, min, rev] = vsn
                      |> List.to_string
                      |> String.split(".")
                      |> Enum.map(&String.to_integer/1)
    {maj, min, rev}
  end
end

And then for usage:

iex(1)> AppHelper.app_version(:logger)
{1, 0, 5}

As always, there's probably a better way.

Deodorize answered 6/10, 2015 at 11:21 Comment(2)
Good answer cheers. Though kinda a shame if that is the best way to get at it.Variola
That's the guidance that Jose Valim gave to someone just a few weeks ago. That is, use :application.which_application. groups.google.com/d/msg/elixir-lang-talk/qlX4hJKZvC8/…Absalom
A
3

You can simple use:

YourApp.Mixfile.project[:version]
Aschim answered 16/10, 2015 at 10:16 Comment(1)
Just FYI, that's a canned comment inserted automatically during review - it really doesn't reflect this case, which is unfortunate. My own take on it: An answer is a statement, ideally backed up with authoritative references, examples, and/or experiences. Although there is no question mark here, "What about..." is a question. If this is indeed an answer, I suggest you edit it to sound like one, and offer a brief explanation that would educate readers by connecting the proffered solution to the problem.Odrick
E
2

Application.spec(:my_app, :vsn) works when the application is started. If you're in a Mix task and you don't need to start the application, in Elixir 1.8 you can use:

MyApp.MixProject.project |> Keyword.fetch!(:version)
Effects answered 4/5, 2019 at 23:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.