Proposal can also be read on gist. 
<https://gist.github.com/benstepp/35d35e09315ca11adad3c7777b516bc0>

---

*Motivation:*

We were using System.otp_release() as a part of a cache-key in our build 
system, and a patch version of an OTP release introduced an ssl handshake 
bug in a few of our applications. Once we pinned down the problem, and 
cleared our build cache, we realized we should have been using the full otp 
version as the cache key, instead of just the major release.


*Existing behaviour:*

   - System.version() returns the full elixir version (ie: "1.14.0").
   - System.otp_release() returns the major portion of the otp release (ie.
    "25").

Note that System.otp_release() just calls 
:erlang.system_info(:system_version) which only returns "25" because "The 
exact OTP version in the general case is difficult to determine" source 
<https://www.erlang.org/doc/man/erlang.html#system_info_otp_release>


*Current workarounds:*

The current OTP version can be found using the method here 
<https://www.erlang.org/doc/system_principles/versions.html#retrieving-current-otp-version>
.

And this workaround can already be found among the community:

   - hex 
   
<https://github.com/hexpm/hex/blob/b2f23089d6c609465c3b570b4fc40c469b57cc1b/lib/hex/utils.ex#L263-L276>
   - dialyzer 
   
<https://github.com/jeremyjh/dialyxir/blob/b78735f75b325238b7db20d9eed22f018cca5f26/lib/dialyxir/project.ex#L221-L238>
   - elsewhere (github code search) 
   
<https://github.com/search?q=Path.join%28%5B%3Acode.root_dir%28%29%2C+%22releases%22%2C+major%2C+%22OTP_VERSION%22%5D%29&type=code>


*Solution:*

The proposal is to add a better function that can return the full otp 
version, somewhere in the core library.

Here are a few example APIs that do not have any breaking changes, but the 
final result doesn't have to be one of these:

*Example api with options seen in the Version module:*
# Return major version (existing behaviour)
iex> System.otp_release()
"25"

# Return up to the major version (same as existing)
iex> System.otp_release(:major)
"25"

# Return up to the minor version
iex> System.otp_release(:minor)
"25.0"

# Return up to the patch version
iex> System.otp_release(:patch)
"25.0.4"

# Return up to the pre-release version
iex> System.otp_release(:pre)
"25.0-rc3"

*Example api with options seen in Date, DateTime, modules:*
# Return major version (existing behaviour)
iex> System.otp_release()
"25"

# Return the full version
iex> System.otp_release(:extended)
"25.0.4"

*Example api returning a %Version{} struct instead of a string:*

Version implements String.Chars so it's pretty easy to get the string this 
way. This one is probably my favorite, but it means System.version() and 
System.otp_version() would have different call signatures, which may not be 
very ergonomic.
# Return major version (existing behaviour)
iex> System.otp_release()
"25"

# Returns the full version
iex> v = System.otp_version()
%Version{major: 25, minor: 0, patch: 4}
iex> to_string(v)
"25.0.4"

---

I haven't thought too much about how to handle file read/version parsing 
failures, but falling back to the current behaviour of returning the major 
version might be acceptable. Also, it may be considered too dangerous to 
have a file reading and version parsing function like this in the core 
library, without :ok/:error tuples which I totally understand (There's an 
existing workaround that works for all of our use cases).

Thank you for your time and consideration, and sorry if something similar 
has been requested before; I tried searching, but "version" "otp" and 
"release" show up in pretty much every discussion on this mailing list.

-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elixir-lang-core+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/fd52d094-cbcc-4b2a-9939-41774274c159n%40googlegroups.com.

Reply via email to