Retrieve the used version of a development dependency at runtime

So I want to display the versions of certain dependencies that were used to the user, these dependencies might be development dependencies.

I tried to use Application.spec(:lib, :vsn) which works in library development, but inside a project that uses it, it will come up empty. Presumably it’s (correctly) not declared under applications as it’s not needed to run in production/shouldn’t be packaged up in a release.

After starting the associated application it works though:

iex(3)> Application.spec(:benchee, :vsn) 
nil
iex(4)> Application.spec(:credo, :vsn)   
nil
iex(5)> Application.spec(:phoenix, :vsn) 
'1.2.5'
iex(6)> Application.ensure_all_started(:benchee)
{:ok, [:deep_merge, :benchee]}
iex(7)> Application.spec(:benchee, :vsn)        
'0.12.0'

Is there any other way to get the version of a (potentially) development version dependency or do I just need to make sure that all my applications are started if I want to get the version information?

Thanks for the help!

From the documentation of Application.spec/2:

Returns nil if the application is not loaded.

So you do not need to start the application, Application.load/1 should be enough.

But you will not able to start or load development dependencies in a :prod built application, as they are not referenced/included.

I’m not sure how you can access :dev or :test deps when in :prod at all.

1 Like

I should have found this myself :see_no_evil:

Thanks for the help and sorry for not getting that myself :slight_smile:
Also I might have miscommunicated, I don’t wanna access them from the prod environment - just normal local running and be sure to get them.

Thanks a bunch!

Any reason why you don’t want to start the application?

I assume it’s about benchee - I think it would be perfectly fine for the Benchee.run/2 function to call Application.ensure_all_started(:benchee) first, to make sure it all runs correctly outside of releases.

The reason most likely my general lacking experience with OTP, applications and friends. That and minimizing side-effects :slight_smile:

ensure_all_started(:benchee) seems fine to run on Benchee.init/1 (which .run/2 calls), however I also want to get the spec of benchee_html (the footer of the HTML report is supposed to display both the used benchee and benchee_html versions) - with the current interface of formatters I’d have to then call ensure_all_started(:benchee_html) in HTML.format/1 to get the correct version numbers. As I want format/1 to be pure it felt wrong. While Application.load/1 also changes some state it didn’t seem as intrusive.

Maybe I’m wrong. Maybe formatters should get an init callback. I’m not sure.

Teach me :smiley:

1 Like