Toolchain
The toolchain is an internal layer for downloading, installing, and managing tools (languages, dependency managers, libraries, and binaries) that are required at runtime. We embrace this approach over relying on these tools "existing" in the current environment, as it ensures the following across any environment or machine:
- The version and enabled features of a tool are identical.
- Tools are isolated and unaffected by external sources.
- Builds are consistent, reproducible, and hopefully deterministic.
Furthermore, this avoids a developer, pipeline, machine, etc, having to pre-install all the necessary tools, and to keep them in sync as time passes.
How it works
The toolchain is built around proto, our stand-alone multi-language version manager. moon
will piggyback of proto's toolchain found at ~/.proto
and reuse any tools available, or download
and install them if they're missing.
Force disabling
The MOON_TOOLCHAIN_FORCE_GLOBALS
environment variable can be set to true
to force moon to use
tool binaries available on PATH
, instead of downloading and installing them. This is useful for
pre-configured environments, like CI and Docker.
MOON_TOOLCHAIN_FORCE_GLOBALS=true
Additionally, the name of one or many tools can be passed to this variable to only force globals for those tools, and use the toolchain for the remaining tools.
MOON_TOOLCHAIN_FORCE_GLOBALS=node,yarn
Configuration
The tools that are managed by the toolchain are configured through the
.moon/toolchain.yml
file, but can be overridden in each project with
moon.yml
.
Version specification
As mentioned above, tools within the toolchain are managed by version for consistency across
machines. These versions are configured on a per-tool basis in
.moon/toolchain.yml
. So what kinds of versions are allowed?
- Full versions - A full version is a semantic version that is fully specified, such as
1.2.3
or2.0.0-rc.1
. This is the most common way to specify a version, and is preferred to avoid subtle deviations. - Partial versions - A partial version is a version that is either missing a patch number, minor
number, or both, such as
1.2
or1
. These can also be represented with requirement syntax, such as^1.2
or~1
. If using partials, we suggest having a major and minor number to reduce the deviation of versions across machines. - Aliases - An alias is a human-readable word that maps to a specific version. For example,
latest
orstable
maps to the latest version of a tool, orcanary
which maps to applicable canary release, or even a completely custom alias likeberry
. Aliases are language specific, are not managed by moon, and are not suggested for use since they can change at any time (or even daily!).
This sounds great, but how exactly does this work? For full versions and aliases, it's straight
forward, as the resolved version is used as-is (assuming it's a legitimate version), and can be
found at ~/.proto/tools/<tool>/<version>
.
For partial versions, we first check locally installed versions for a match, by scanning
~/.proto/tools/<tool>
. For example, if the requested version is 1.2
and we have 1.2.10
installed locally, we'll use that version instead of downloading the latest 1.2.*
version.
Otherwise, we'll download the latest version that matches the partial version, and install it
locally.
Supported tools
The following tools are currently managed by the toolchain.
Bun
- View the Bun handbook
- Configured with:
bun
- Installed to:
~/.proto/tools/bun/x.x.x
Deno
- View the Deno handbook
- Configured with:
deno
- Installed to:
~/.proto/tools/deno/x.x.x
Node.js
- View the Node.js handbook
- Configured with:
node
- Installed to:
~/.proto/tools/node/x.x.x
- Dependency managers:
npm
,pnpm
,yarn
,bun
Rust
- View the Rust handbook
- Configured with:
rust
- Installed to:
~/.rustup/toolchains/x.x.x