Today I’m trying for the first time to run mix release
on my project… just as a sanity check: I’m failing.
I’ve run into a bit of a roadblock and I’m not precisely sure how to troubleshoot it. I am going to simplify a bit here so it is possible I’m leaving something important out, but with luck I’m including the essentials. Finally, I should note that everything in my application works as expected when I run it in my development environment, when I run the test suites, or let GitHub Actions take a crack. These issues are only seen using mix release
. This will cover things I’ve tried up to the present time.
The Scenario
I am using a third party library in my application (GitHub - ExHammer/hammer: An Elixir rate-limiter with pluggable backends). Out of box, the library wants to start an an application with a supervisor and to put some services under it… however I don’t want that. I’ve actually included this library in my own little private library (wrapper library from here out) and I want to be responsible for starting the services, including Hammer’s, in the correct part of the supervision tree and at the right time.
First Effort
Initially to achieve this, in the wrapper library mix.exs
I had the Hammer library as dependencies in deps like so:
{:hammer, "~> 6.0", runtime: false},
This achieved what I wanted for my development environment, but didn’t work for mix release
; I got errors about Hammer.Supervisor
not being found and also warnings along the lines of:
…is used by the current application but the current application does not depend on…
I’ve since read:
So that approach was bound to fail for releases. Lets try something different.
Second Effort
I went back to the mix docs and found this:
:included_applications
- specifies a list of applications that will be included in the application. It is the responsibility of the primary application to start the supervision tree of all included applications, as only the primary application will be started. A process in an included application considers itself belonging to the primary application.
Great! As described, this is almost exactly what I want. I’m a bit dubious about the primary application
discussion since the wrapper library isn’t the final application which will ultimately be released but lets try this in my wrapper library mix.exs
application/0
function:
included_applications: [
:hammer
]
The “used by/doesn’t depend on” warnings all disappeared… but now mix release
gives me this:
** (Mix) :hammer is listed both as a regular application and as an included application
Hmmm… OK.
I know that if no :applications
key is given, that the applications will be inferred from the dependencies so maybe it’s inferring it from the fact that Hammer is a dependency… so try and silence that by making the mix.exs
application/0
function include this:
applications: [],
included_applications: [
:hammer
]
Mix release still gives me:
** (Mix) :hammer is listed both as a regular application and as an included application
Current Time
I know why it thinks its in included applications (I put it there), but I’m unsure why it thinks it is configured as a regular application as well. My little wrapper library is the only place bringing in Hammer. In the Hammer mix.exs
it shows up as:
def application do
# Specify extra applications you'll use from Erlang/Elixir
[mod: {Hammer.Application, []}, extra_applications: [:logger, :runtime_tools]]
end
Which is exactly what I’m trying to suppress so that I can start things in my code, but I don’t know if this would cause that error. Naturally, I don’t want to futz with a third party library and create a one-off solution applicable to just me either.
I’m not sure how to troubleshoot further (aside from diving into the source code of mix processing/compiling). Perhaps what I’m trying to do isn’t possible… but it sounds like it should be… at least the documentation implies that it should be. I do see compiler warnings during the mix release
process, but they’re all coming from unrelated third party libraries that are also part of the application.
Thanks in advance for any help/pointers on how I might proceed from here.