This action sets up an Erlang/OTP environment for use in a GitHub Actions workflow by:
- installing Erlang/OTP
- optionally, installing Elixir
- optionally, installing Gleam
- optionally, installing
rebar3 - optionally, installing
local.hex - optionally, installing
local.rebar - optionally, opting for strict or loose version matching
- optionally, having problem matchers show warnings and errors on pull requests
- optionally, using a version file (as explained in "Version file", below), to identify versions
Usage
See action.yml for the action's specification.
Input versioning
Input (tools') versions are controlled via with: (check the examples below).
Strict versions
The Erlang/OTP release version specification, for example, is relatively
complex, so,
for best results, we recommend specifying exact
versions, and setting option version-type to strict.
Version ranges
However, values like 22.x, or even >22, are also accepted, and we attempt to resolve them
according to semantic versioning rules. This implicitly means version-type is loose,
which is also the default value for this option.
Specify versions as strings, not numbers
Additionally, it is recommended that one specifies versions
using YAML strings, as these examples do, so that numbers like 23.0 don't
end up being parsed as 23, which is not equivalent.
Pre-release versions
To use a pre-release version such as v1.11.0-rc.0, specify the exact version
(v1.11.0-rc.0) and set version-type to strict.
Note that pre-release versions are opt-in by default.
Patterns like 1.11.x do not include pre-release versions unless latest is specified.
"Latest" versions
To retrieve the most recent available version of a tool, set the version to latest.
This may include pre-release versions such as release candidates.
If you want to target only the latest stable release and exclude pre-releases, use a
version range like > 0 instead.
Note that the latest version is determined locally by the action based on the versions it
has retrieved. This may differ from how GitHub defines "latest",
and some repositories may present different interpretations.
If you're unsure, perform a test run and compare the resolved version against the version you expect to be considered the latest.
Compatibility between Operating System and Erlang/OTP
This list presents the known working version combos between the target operating system and Erlang/OTP.
| Operating system | Erlang/OTP | OTP Architecture | Status |
|---|---|---|---|
ubuntu-22.04 |
24.2 - 28 | x86_64, arm64 | ✅ |
ubuntu-24.04 |
24.3 - 28 | x86_64, arm64 | ✅ |
windows-2019 |
21* - 25 | x86_64, x86 | ✅ |
windows-2022 |
21* - 28 | x86_64, x86 | ✅ |
windows-2025 |
21* - 28 | x86_64, x86 | ✅ |
macOS-13 |
25.0 - 28 | x86_64, arm64 | ✅ |
macOS-14 |
25.0 - 28 | x86_64, arm64 | ✅ |
macOS-15 |
25.0 - 28 | x86_64, arm64 | ✅ |
macOS-26 |
25.0 - 28 | x86_64, arm64 | ✅ |
Note *: prior to 23, Windows builds are only available for minor versions, e.g. 21.0, 21.3, 22.0, etc.
Compatibility between Erlang/OTP and rebar3
Check version compatibility
in erlang/rebar3.
Self-hosted runners
Self-hosted runners need to set env. variable ImageOS to one of the following, since the action
uses that to download assets:
| ImageOS | Operating system |
|---|---|
ubuntu22 |
ubuntu-22.04 |
ubuntu24 |
ubuntu-24.04 |
win19 |
windows-2019 |
win22 |
windows-2022 |
win25 |
windows-2025 |
macos13 |
macOS-13 |
macos14 |
macOS-14 |
macos15 |
macOS-15 |
macos26 |
macOS-26 |
as per the following example:
... jobs: test: runs-on: self-hosted env: ImageOS: ubuntu24 # equivalent to runs-on ubuntu-24.04 steps: - uses: actions/checkout@v4 - uses: erlef/setup-beam@v1 ...
Outputs
The action provides the following outputs:
| Output | Content |
|---|---|
otp-version |
The Erlang version, e.g. OTP-26.0 |
elixir-version |
The Elixir version, e.g. v1.14-otp-26 |
gleam-version |
The Gleam version, e.g. v1.5.1 |
rebar3-version |
The rebar3 version, e.g. 3.18.0 |
setup-beam-version |
The commit unique id of the executed action version, e.g. a34c98f |
accessible as ${{steps.<setup-beam-step-id>.outputs.<Output>}},
e.g. ${{steps.setup-beam.outputs.erlang-version}}
Version file
A version file is specified via input version-file (e.g. .tool-versions or mise.toml).
The file type is inferred from the filename: files ending in .toml are parsed as
mise configuration, and all others
are parsed as .tool-versions (asdf format).
This allows not having to use YML input for versions, though the action does check (and
will exit with error) if both inputs are set.
Note: if you're using a version file, option version-type is checked to be strict,
and will make the action exit with error otherwise.
Supported version elements are the same as the ones defined for the YML portion of the action, with the following correspondence.
.tool-versions / mise.toml format
| YML | Version file key |
|---|---|
otp-version |
erlang |
elixir-version |
elixir |
gleam-version |
gleam |
rebar3-version |
rebar |
Alternative hex.pm mirrors
It is possible to use alternative hex.pm mirror(s), in their declared order, with
option hexpm-mirrors. By default, the action will use builds.hex.pm.
To use other alternative mirrors, add one per line, as shown below.
# create this in .github/workflows/ci.yml on: push jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: erlef/setup-beam@v1 with: otp-version: '26' # Use `cdn.jsdelivr.net/hex` as an alternative to `builds.hex.pm` hexpm-mirrors: https://cdn.jsdelivr.net/hex
Alternatively, you may try cdn.jsdelivr.net/hex if builds.hex.pm fails:
# create this in .github/workflows/ci.yml on: push jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: erlef/setup-beam@v1 with: otp-version: '26' hexpm-mirrors: | https://builds.hex.pm https://cdn.jsdelivr.net/hex
OTP Architecture
On Windows you can specify the OTP architecture to install.
# create this in .github/workflows/ci.yml on: push jobs: test: runs-on: windows-latest steps: - uses: erlef/setup-beam@v1 with: otp-version: '26' otp-architecture: '32'
Environment variables
Base installation folders (useful for e.g. fetching headers for NIFs) are available in the following environment variables:
INSTALL_DIR_FOR_OTP: base folder for Erlang/OTPINSTALL_DIR_FOR_ELIXIR: base folder for ElixirINSTALL_DIR_FOR_GLEAM: base folder for GleamINSTALL_DIR_FOR_REBAR3: base folder forrebar3
In each of these you'll find folder bin where the appropriate binaries, platform-dependant,
are found (i.e. erl, erl.exe, rebar3, rebar3.exe, ...).
Elixir Problem Matchers
The Elixir Problem Matchers in this repository are adapted from vscode-elixir/package.json. See MATCHER_NOTICE for license details.
Examples
Erlang/OTP + Elixir, on Ubuntu
# create this in .github/workflows/ci.yml on: push jobs: test: runs-on: ubuntu-24.04 name: OTP ${{matrix.otp}} / Elixir ${{matrix.elixir}} strategy: matrix: otp: ['25.3.2', '26.2.5', '27.3.3'] elixir: ['1.17.3', '1.18.3'] steps: - uses: actions/checkout@v4 - uses: erlef/setup-beam@v1 with: otp-version: ${{matrix.otp}} elixir-version: ${{matrix.elixir}} - run: mix deps.get - run: mix test
Erlang/OTP + rebar3, on Ubuntu
# create this in .github/workflows/ci.yml on: push jobs: test: runs-on: ubuntu-24.04 name: Erlang/OTP ${{matrix.otp}} / rebar3 ${{matrix.rebar3}} strategy: matrix: otp: ['25.3.2', '26.2.5', '27.3.3'] rebar3: ['3.23.0', '3.24.0'] steps: - uses: actions/checkout@v4 - uses: erlef/setup-beam@v1 with: otp-version: ${{matrix.otp}} rebar3-version: ${{matrix.rebar3}} - run: rebar3 ct
Compatibility
To execute matrix testing with specific dependency versions, configure the environment matrix to use pinned, compatible releases:
test: runs-on: ${{matrix.compat.os}} name: Erlang/OTP ${{matrix.compat.otp}} / rebar3 ${{matrix.compat.rebar3}} strategy: matrix: compat: - otp: "26.2.5.5" rebar3: "3.22.1" os: ubuntu-24.04 - otp: "27.1.2" rebar3: "3.22.1" os: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: erlef/setup-beam@v1 with: otp-version: ${{matrix.compat.otp}} rebar3-version: ${{matrix.compat.rebar3}} version-type: strict - run: rebar3 eunit
Erlang/OTP + rebar3, on Windows
# create this in .github/workflows/ci.yml on: push jobs: test: runs-on: windows-2025 steps: - uses: actions/checkout@v4 - uses: erlef/setup-beam@v1 with: otp-version: '24' rebar3-version: '3.16.1' - run: rebar3 ct
Erlang/OTP + rebar3, on macOS
# create this in .github/workflows/ci.yml on: push jobs: test: runs-on: macos-15 steps: - uses: actions/checkout@v4 - uses: erlef/setup-beam@v1 with: otp-version: '28' rebar3-version: '3.25' - run: rebar3 ct
Gleam on Ubuntu
# create this in .github/workflows/ci.yml on: push jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: erlef/setup-beam@v1 with: otp-version: '27' gleam-version: '1.9.0' - run: gleam test
Gleam on Ubuntu without OTP
# create this in .github/workflows/ci.yml on: push jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: erlef/setup-beam@v1 with: otp-version: false gleam-version: '1.9.0' - run: gleam check
Note: the otp-version: false input is only applicable when installing Gleam.
The project
Versioning
setup-beam has three version paths, described below, for example version 1.8.0:
@v1: the latest in the1.y.zseries (this tag is movable),@v1.8: the latest in the1.8.zseries (this tag is movable),@v1.8.0: release1.8.0(this tag is not movable).
We make a real effort to not introduce incompatibilities without changing the major
version number. To be extra safe against changes causing issues in your CI you should specify
an exact version with @vx.y.z.
License
The scripts and documentation in this project are released under the MIT license.
Contributing
Check out this doc.
Code of Conduct
This project's code of conduct is made explicit in CODE_OF_CONDUCT.md.
Security
This project's security policy is made explicit in SECURITY.md.