DEV Community

Cover image for ASDF: Automatic Management of Multiple Versions
Ludal ๐Ÿš€
Ludal ๐Ÿš€

Posted on • Updated on • Originally published at iamludal.fr

ASDF: Automatic Management of Multiple Versions

Have you ever been in this situation where you are working on multiple projects and have to deal with multiple versions of Java, NodeJS or Postgres? In this article, weโ€™ll discover how to switch between different runtime versions automatically depending on the current folder, and therefore the project. ๐Ÿ“

Setting the Scene

As a freelance developer working on different projects for different clients, you have probably already found yourself in this situation: project A runs with Java 8, project B runs with Java 11, and project C runs with Java 17. To easily switch between these versions, you might have used the update-alternatives command.

sudo update-alternatives --config java
Enter fullscreen mode Exit fullscreen mode

This works pretty fine, but there is a drawback to this approach: you have to manually run this command every time you have to switch to another version, which can quickly get cumbersome. Also, this command does not work with all tools, such as node or postgres.

One way to solve this problem is to use Docker. Indeed, the purpose of Docker is to create an image that contains all the correct versions for the current project. However, not everyone knows Docker, and not every project has a Dockerfile to build this setup. Also, not all teams have the time to build a Dockerfile: depending on the project size, it can easily get complicated to create one quickly.

Another solution would be to have something like a magic wand that automatically switches between Java 8 in the project-A folder and Java 11 in the project-B folder, and so on.

Actually, this magic wand exists, and is called asdf. ๐Ÿช„

ASDF: Our Magic Wand

So what really is asdf? It is a CLI tool that automatically switches between your runtime versions (Java, NPM, Node, Postgres, PHP, and even more) depending on your current folder. To do so, it relies on a file named .tool-versions (located in the folders where you need to use it) to know which version to use for each tool. This file simply contains a mapping list of each tool with the correct version to use.

java openjdk-17
nodejs 17.3.0
postgres 13.5
Enter fullscreen mode Exit fullscreen mode

When your current folder does not contain a .tool-versions, asdf will just look in the parent folders to find the first one containing such a file. As a result, you need to define a default version for each tool, so that asdf can use this default version if no .tool-versions file was found in the parent folders. The default versions are stored in your home directory: ~/.tool-versions.

Something really interesting is that you can commit this .tool-versions file to your git repository so that your colleagues can also have the correct versions of the different tools, as long as they are using asdf. ๐Ÿ’ช๐Ÿผ

An Example

Letโ€™s say your default node version is 17.3.0, but one of the projects you are working on is a bit old and uses version 12.13.0. If you start a terminal and run the command to get the node version, it will display your current one.

$ node --version
v17.3.0
Enter fullscreen mode Exit fullscreen mode

This command will produce the same output if you are in the project-A folder. However, if you tell asdf that it should use the version 12.13.0 of node in this project, the output will change.

$ asdf local nodejs 12.13.0
$ node --version
v12.13.0
Enter fullscreen mode Exit fullscreen mode

And if you change to another directory, the node version will magically change back to your default one.

$ cd ..
$ node --version
v17.3.0
Enter fullscreen mode Exit fullscreen mode

Totally crazy, right? ๐Ÿคฏ Letโ€™s now see how to set-up asdf (spoiler alert: it is ridiculously easy).

Setting Up ASDF

In the first place, you will need to download asdf (available on Linux and MacOS, but unfortunately
not on Windows). To do so, just clone the git repository to your home folder.

git clone https://github.com/asdf-vm/asdf.git ~/.asdf
Enter fullscreen mode Exit fullscreen mode

If you are on MacOS, you can simply use brew.

brew install asdf

Once done, you will need to add these two lines to your .bashrc (or .zshrc).

. $HOME/.asdf/asdf.sh
. $HOME/.asdf/completions/asdf.bash
Enter fullscreen mode Exit fullscreen mode

And thatโ€™s it, youโ€™ve successfully installed asdf! ๐ŸŽ‰

Usage

To use asdf, you will first need to add the plugins you need. A plugin corresponds to a tool: for instance, you will need to add the java plugin to switch between java versions, the nodejs plugin to switch between NodeJS versions, and so on. To add a plugin, simply run the following command:

asdf plugin add [plugin]
Enter fullscreen mode Exit fullscreen mode

In this example, we will continue with nodejs, so we will install this plugin.

asdf plugin add nodejs
Enter fullscreen mode Exit fullscreen mode

๐Ÿ’ก You can list all the available plugins with the asdf plugin list all command. As this will produce a pretty big list, you can filter the results with grep.

asdf plugin list all | grep node

Now that weโ€™ve added the nodejs plugin, we will need to download the versions we want to use. In our case, we want both 12.13.0 and 17.3.0 versions.

asdf install nodejs 12.13.0
asdf install nodejs 17.3.0
Enter fullscreen mode Exit fullscreen mode

After installing these versions, the last step is to specify which one to use depending on the project. To do so, head over to the folder of the project that uses 12.13.0 (letโ€™s say project-A) and select the correct nodejs version.

asdf local nodejs 12.13.0
Enter fullscreen mode Exit fullscreen mode

And thatโ€™s it! The 12.13.0 version of Node will be used in the project-A directory and sub-directories. ๐Ÿฅณ

If you now run ls -al in the project folder to list all the files, you will notice the .tool-versions file that contains the correct Node version. You can commit it to your version control system.

nodejs 12.13.0
Enter fullscreen mode Exit fullscreen mode

๐Ÿ’ก When cloning the project containing this file, your colleagues donโ€™t even have to manually install the listed versions: they can simply run asdf install, and the magic wand will take care of downloading all required versions.

Lastly, as weโ€™ve seen earlier, we need to define a default version to use when we are in another folder which has no .tool-versions file in it or in its parent folders. In our case, we want the default version of Node to be 17.3.0.

asdf global nodejs 17.3.0
Enter fullscreen mode Exit fullscreen mode

๐Ÿ’ก You can also specify a version for the current shell.

asdf shell nodejs 17.3.0

And thatโ€™s it, weโ€™ve successfully got rid of the pain of having to manually switch between our runtime versions, thanks to our new magic wand. ๐Ÿช„

Wrapping Up

Thanks to asdf, our runtime versions are now managed automatically. When you need to use a new plugin, the steps will always be the same:

  1. Install the corresponding plugin: asdf plugin add [plugin]
  2. Install all the versions you need: asdf install [plugin] [version]
  3. Select the local version for each concerned project: asdf local [plugin] [version]
  4. Select the default version for this plugin: asdf global [plugin] [version]

For more information, or if you need help on this awesome tool, donโ€™t hesitate to head over to asdf-vm.com. Also, feel free to star the GitHub Repository of asdf to support the team behind this project. ๐Ÿ˜‰

I hope this article was useful to you, and Iโ€™ll see you in the next ones. ๐Ÿค˜๐Ÿผ

More Articles From Me

Discussion (0)