How to exclude a dependency's application from running but still Include it in the Release

I’m working on two Phoenix projects: A and B. Project B provides an HTTP API that is utilized by project A. Additionally, project B implements a Util module that project A uses. This is accomplished by adding project B as a dependency from GitHub to project A.

During development, I added the following dependency to project A:

  defp deps do
    [
      # ...
      {:a, app: false, github: "c/a", branch: "main"}
    ]
  end

I used app: false to prevent loading and running the application from project B, allowing project A to only use the Util module from project B.

However, when I create a release of project A with MIX_ENV="prod" mix release, I encounter an error when executing ./_build/prod/rel/a/bin/a start:

(CompileError) _build/prod/rel/a/releases/0.1.0/runtime.exs:100: module RuntimeConfig is not loaded and could not be found

Upon inspecting the _build/prod/rel/a/lib directory, I noticed that the b dependency is missing.

What is the correct way to add project B as a dependency to project A for this specific use case? I would appreciate any advice or suggestions.

1 Like

I think an included application does what you describe. Roughly, in project A’s mix.exs, you want to set runtime: false for the dependency to B, then update your application config:

  def application do
    [
      mod: {A.Application, []},
      included_applications: [:b],
      extra_applications: [:c, :d] # dependencies of :b that must be started for it to work
    ]
  end

The release will then include :b but not automatically start it. Note that if you have :b as a dependency elsewhere, that may cause it to start regardless - you need to add runtime: false there as well, in that case.
Hope that helps :slightly_smiling_face:

4 Likes

That worked brilliantly! :slight_smile:

I updated deps as follows:

  defp deps do
    [
      # ...
      {:a, github: "c/a", branch: "main", runtime: false}
    ]
  end

and application by:

  def application do
    [
      mod: {A.Application, []},
      included_applications: [:b],
      extra_applications: [:logger, :runtime_tools, :os_mon]
    ]
  end

In my case, I didn’t need to add anything to extra_applications because I was only using one simple module from B , which didn’t require any additional applications.

2 Likes