Chapter 9. Releases

Erlang.mk relies on Relx for generating releases. This chapter covers the Erlang.mk-specific bits. Consult the Relx website for more information.

9.1. Setup

First, relx must be added in the dependencies of your project. You can add it to REL_DEPS so that it is fetched whenever you need to build the release:

REL_DEPS = relx

Then, you need to create a relx.config file in the $(RELX_CONFIG) location. This defaults to $(CURDIR)/relx.config. You can override it by defining the variable before including Erlang.mk:

RELX_CONFIG = $(CURDIR)/webchat.config

It is also possible to have multiple relx.config files. For example you might have one for development and one for production. You can use conditionals to decide which one should be used:

ifdef PROD
RELX_CONFIG = $(CURDIR)/relx.prod.config
else
RELX_CONFIG = $(CURDIR)/relx.dev.config
endif

9.2. Configuration

You can specify additional Relx options using the RELX_OPTS variable. For example, to enable dev_mode:

RELX_OPTS = -d true

While you can specify the output directory for the release in the Relx options directly, Erlang.mk provides a specific variable for it: RELX_OUTPUT_DIR. It defaults to the _rel directory. You can also override it:

RELX_OUTPUT_DIR = /path/to/staging/directory

9.3. Generating the release

Now that you’re all set, all you need to do is generate the release. As mentioned before, Erlang.mk will automatically generate it when it detects the $(RELX_CONFIG) file. This means the following command will also build the release:

$ make

If you need to generate the release, and only the release, the rel target can be used:

$ make rel

Erlang.mk always generates a tarball alongside the release, which can be directly uploaded to a server. The tarball is located at $(RELX_OUTPUT_DIR)/<name>/<name>-<vsn>.tar.gz.

9.4. Running the release

Erlang.mk provides a convenience function for running the release with one simple command:

$ make run

This command will also build the project and generate the release if they weren’t already. It starts the release in console mode, meaning you will also have a shell ready to use to check things as needed.

9.5. Upgrading a release

Erlang.mk provides a relup target for generating release upgrades. Release upgrades allow updating the code and the state of a running release without restarting it.

Once your changes are done, you need to update the version of the application(s) that will be updated. You also need to update the version of the release.

For each application that needs to be updated, an appup file must be written. Refer to the Erlang/OTP documentation for more details.

For the purpose of this section, assume the initial release version was 1, and the new version is 2. The name of the release will be example.

Once all this is done, you can build the tarball for the release upgrade:

$ make relup

This will create an archive at the root directory of the release, $RELX_OUTPUT_DIR/example/example-2.tar.gz.

Move the archive to the correct location on the running node. From the release’s root directory:

$ mkdir releases/2/
$ mv path/to/example-2.tar.gz releases/2/

Finally, upgrade the release:

$ bin/example_release upgrade "2/example_release"

Or on Windows:

$ bin/example_release.cmd upgrade "2/example_release"

Your release was upgraded!

9.6. Getting Relx semver value

There is a workaround to get the semver value which is generated by Relx based on VCS history.

Create a file config/version with only one line inside:

{{ release_version }}

Add/Update the overlay section of your relx.config:

{overlay, [
    {template, "config/version", "version"}
]}.

When you run make rel it creates the file $(RELX_OUTPUT_DIR)/example/version which contains the version value generated by Relx.

$ cat _rel/app/release
1.0.0+build.11.ref5612aa0

In your Makefile you can use this simple snippet to get the version, but please keep in mind that this should depend on the rel target:

$(shell cat $(RELX_OUTPUT_DIR)/$(RELX_REL_NAME)/version)

For example:

include erlang.mk

APP_VERSION = $(shell cat $(RELX_OUTPUT_DIR)/$(RELX_REL_NAME)/version)
myrecipe: all
        echo APP_VERSION = $(APP_VERSION)

Would output:

$ make myrecipe
...
===> Starting relx build process ...
===> Resolving OTP Applications from directories:
          /home/username/example/apps
          /home/username/example/deps
          /usr/lib/erlang/lib
          /home/username/example/_rel
===> Resolved example-0.3.10+build.11.ref5612aa0
===> Including Erts from /usr/lib/erlang
===> release successfully created!
===> tarball /home/username/example/_rel/example/example-0.3.10+build.11.ref5612aa0.tar.gz successfully created!
echo APP_VERSION = 0.3.10+build.11.ref5612aa0
APP_VERSION = 0.3.10+build.11.ref5612aa0