Keeping your dependencies up-to-date is essential to ensure that your applications stay healthy, secure, and performant. Thankfully, the BEAM ecosystem has its own package manager, Hex, which is fast, mature, and simple to use.
This article explores the available tools and commands to manage Hex dependencies and some tips to make the process more enjoyable.
Let's dive in!
List Updatable Dependencies in Your Elixir App
You can use the commands below to understand the relationships between dependencies before you attempt to update any of them.
List all your application's dependencies with:
Or you can choose to print them in a tree format with:
This produces output like the following:
To produce an image output, run:
Note: This option requires Graphviz
. Read these Graphviz instructions to install it on your system.
Then open the created deps_tree.png
file with a viewer of
your choice. Being able to quickly visualize dependencies can help you
decide whether a package is worth keeping in your mix.lock. A package could be
pulling too many sub-dependencies or might not even be used in your app. Remember,
the fewer dependencies, the easier it is to keep things up-to-date.
When you remove a dependency from mix.exs, it will remain in mix.lock. To remove unused dependencies, run:
Check for Outdated Dependencies with Hex
After making sense of your dependencies tree and performing any necessary cleanups, check for outdated packages with:
The output will resemble:
Note: The --all
flag shows all outdated packages, including the children of packages defined in mix.exs.
Notice the link in the output above. Hex prepares a nice page for us to inspect the diffs:
Pro-Tip
Use the --within-requirements
flag in your CI to notify you of
available updates.
The output of Elixir's package management tasks tends to be concise, well-documented and precisely guides you towards actions.
Inspecting Changes with Hex
To see changes between two package versions in the terminal, run:
You can view the diff in the browser by navigating to:
https://diff.hex.pm/diff/<package_name>/<version1>..<version2>
For example: https://diff.hex.pm/diff/opus/0.7.0..0.8.1
Hex Diff generates a highlighted git diff which you can view in the browser. You can share the link or even highlight a specific row.
Third-party dependencies are essentially somebody's code downloaded from the internet, which ends up in your application. There is no shortage of examples where packages have been hijacked and malicious versions uploaded.
Ideally, you should inspect the diff of every update. Hex seems to be the only package manager with this built-in feature at the moment.
Browsing Changelogs
Ultimately, an update might be available, but is it safe to apply it? Are there any code or configuration changes required for the update to work without issues? The diff between two package versions may contain thousands of lines of templates, tests, and docs that might not seem relevant to you.
Furthermore, a package might not even follow Semver (semver indicates whether the update is safe in compatibility terms).
Commonly, package maintainers keep a changelog to communicate notable changes and upgrade paths concisely. Read more about the benefits of keeping a changelog.
Now the bad news: not all packages have a changelog. So let's go changelog hunting!
The following task will fetch information for the credo
package:
As you can see, the maintainer has added a link to the changelog, so that's nice of them.
There is even a link to the changelog in the HexDocs, which some developers may find really handy:
Tips:
- Ensure there's a link to your changelog in
mix.exs
- Include the changelog in the hexdocs
Automated Changelog Fetching
Hunting for changelogs can get tedious after a while, especially if you want to update many packages. Thankfully, there is now an experimental package for that.
You can add it in your dependencies with:
Ensure it is fetched:
Invoke it for all updatable packages:
Or for a number of packages:
Note: This will only print the version to update to, a link to the diff, and the changelog when there is a more recent version.
I wrote this open-source task. It uses some heuristics to locate the changelog by retrieving the Hex package metadata from the API, falling back to common locations in the repo.
My wish is that Hex will standardize including a link to a changelog in mix.exs and
mix hex.info
, and that Hex Diff will be enhanced to include changelog
information.
Updating Dependencies in Elixir
To update all dependencies, run:
In the output, you will see version updates in the following format:
This is the same as running:
Keep in mind that this task will try to upgrade to versions that match the specifications in your mix.exs.
For example:
Even if there is a more recent 1.0 version for some_package
, it does
not match the specification above, and it won't be upgraded.
You will have to change your mix.exs and try again.
As we saw in the first section of this article, there is a task you can run to check if an update is possible for a package.
There might be a conflict in some cases where the package resolution cannot find a version to satisfy the dependencies in mix.exs.
A workaround (that you should use with caution) is override
.
In this case, the dependency will override any other definitions by other dependencies.
Further Reading: Keep Your Package Updates Safe in Elixir
Elixir comes with a whole arsenal of tools to manage dependencies. Try to master them and stir your mix.exs often. Read changelogs and diffs to ensure your updates are safe.
Here are some resources that can help you dive deeper into this topic:
- HexDocs:mix deps
- HexDocs:usage
- HexDocs:mix hex.outdated
- Hex
- Graphviz-install
- Keepachangelog
- Semver
- Changelog-repo
Happy coding!
P.S. If you'd like to read Elixir Alchemy posts as soon as they get off the press, subscribe to our Elixir Alchemy newsletter and never miss a single post!