Dependency Management in Elixir with Mix

Image of Author
April 1, 2022 (last updated September 21, 2022)

Helping yourself with mix

Run mix help to see all possible mix commands, and a breif description of what they each do. For any given mix command, you can read more detailed documentation by running mix help [command]. E.g., mix help hex.outdated, mix help deps.update, etc.

Finding outdated dependencies

mix hex.outdated will let you to see at a glance which of your top level mix.exs file dependencies have newer versions released, and whether or not you can upgrade to them. If you are interested in only a single package, run mix hex.outdated [package-name].

When an upgrade is possible, you can run mix deps.upgrade [dep], which is the effective equivalent of mix deps.unlock [dep] && mix deps.get [dep]. This allows you to install that latest package version this still satisfies your specified SemVer restrictions in your mix.exs file.

Manually bumping your SemVer

If you want to bump the version of you mix.exs file semver, that is a manual action, since you are in a sense violating your previous semver restrictions. You have to go out of your way to tell mix that you have new restrictions, etc.

If mix hex.outdated [dep] says "Update not possible", it is because there is a shared dependency between your mix app and the newer version of the dependency. Let's call the dependency we want to version bump "depA", and the other dependency blocking the version bump "depB". If your mix app did not otherwise depend on depB, you would be able to update, because mix would notice that only depA dependend on it, and would update it along with depA. But, the problem comes when you are telling mix to lock down the version of depB as well.

The solution is first version bumping depB and then version bumping depA. You might have to repeat this action a few times depending on how many shared dependencies exist.

The way I do it is by manually editing the semver of depA in my mix.exs file and then running mix deps.get. It should fail because of the depB conflict. I will then update whatever dependencies I am told to via the conflict error log, also in mix.exs. I then run mix deps.get and continue through the version-bumping loop until I have depA where I want it. Since this process is liable to introduce breaking changes, make sure to run your test suite and all the other safety checks you go through.

Also, it's worth noting that you could very well not be able to bump versions without major issues. A recent example in my own history was trying to do a minor version bump to depA that required a minor version bump of depB that required a minor version bump of phoenix_liveview to version 0.17.0. But, that version of liveview made the ~H sigil the only viable sigil for liveview components. I had pragmatic issues disallowing me from spending the time fixing the breaking sigils. But, I also had a bug that the bump to depA was going to fix. This is the rock and the hard place of versions management. (I'm not blaming anything or anyone here, it's just a regular example of how version management [in any system] can cause problems.)

Other Notes

  • Mix is the build and dependency management tool in Elixir.

  • Hex is the Erlang package manager that mix leverages when managing dependencies.

  • Elixir follows semantic versioning, SemVer. Details can be found in the Version module of Elixir.