Release Notes
💥 Breaking
- WASM API
- Reworked the
VirtualPath type from the ground up. Is no longer an enum, but instead a newtype
wrapper around PathBuf.
- This allows for better interoperability with the Rust ecosystem, and makes it easier to work
with virtual paths in general.
- Additionally, because of this change,
VirtualPath now has access to all PathBuf methods,
which was not possible before.
- Removed the
from_virtual_path and to_virtual_path extism host functions, into_real_path
and into_virtual_path wrapper functions, and real_path! and virtual_path! macros. Use the
conversion utils instead (below).
🚀 Updates
- Action graph
- Added a new mechanism where toolchains can specify requirements (other toolchains to be setup)
for the setup environment action.
- CLI
- Added OpenTelemetry (OTEL) support, for exporting traces, metrics, and logs over OTLP.
- Added a
--otel global option (MOON_OTEL), for exporting traces and metrics.
- Added a
--otel-logs global option (MOON_OTEL_LOGS), for exporting log events as OTLP logs.
- Added a
--otel-service-name global option (MOON_OTEL_SERVICE_NAME), for the reported
service name.
- The destination and transport are configured with the standard
OTEL_EXPORTER_OTLP_*
environment variables.
- Updated the
moon setup action to also setup the toolchain environment, if their dependency
root is the same as the workspace root. Nested dependency roots will not be setup, as they are
expected to be setup by their parent project.
- Updated the
moon exec (and related pipeline commands) to display action failures in the
summary at the bottom, instead of interleaved within all actions.
- Config
- Added an unstable
cache.unstable_sharedWorktreeCache setting to .moon/workspace.*, which
shares the CAS cache between all VCS worktrees on the same machine. Only blobs and manifests are
shared, as they are portable, while hashes, locks, and states remain worktree-specific. The
cache is stored in the base checkout's .moon/cache directory, or ~/.moon/cache/shared when
the repository root has no checkout (bare clones). Requires the casOutputsCache experiment.
- Added environment variable support for cache settings:
MOON_CACHE_CAS_MAX_SIZE,
MOON_CACHE_CAS_VERIFY_INTEGRITY, and MOON_CACHE_SHARED_WORKTREE_CACHE.
- Added an
env setting to .moon/tasks/**/* configs. These environment variables are inherited
by all matching projects, and are merged into each project's env setting, with project-level
variables taking precedence.
- Added a
workspace.mergeStrategies setting to moon.* config, which controls how project
settings are merged with inherited workspace-level settings. Currently supports env and
fileGroups, using the same merge strategies as task merging (append, prepend, preserve,
and replace).
- Project globs can now be configured with a trailing file, allowing more precise project
matching. For example, apps/*/package.json will only find Node.js projects, and
src/**/*.csproj will only find .NET projects. The path without file name will be used as the
project identifier (if not defined).
- This change does not apply to root-level projects. Use a
. glob or target a moon
configuration file.
- Daemon
- Added task output archiving and hydrating to the daemon. All of these heavy file system
operations will now be offloaded into the background via the daemon. Because of this, you'll
need to inspect the daemon server logs to understand when something fails during archiving or
hydrating, as the main process will no longer block on these operations.
- Docker
- Improved the scaffolding and pruning workflows, by better handling edge cases, and ensuring its
more reliable.
- Experiments
- The
asyncAffectedTracking, asyncGraphBuilding, and nativeFileHashing experiments are now
enabled by default. If you run into issues, please report it, and then disable the experiment to
continue.
- Project graph
- Reworked the project graph to validate cycles per dependency scope partition. Production scoped
dependencies (production, peer) and development scoped dependencies (development, build,
root) are now tracked as separate internal graphs, so relationships that cross the boundary no
longer fail with a cycle error, or silently drop dependency edges.
- WASM API
- Added a
RealPath type, which is a newtype wrapper around PathBuf that represents a real path
on the host file system. This is a sibling to the VirtualPath type, which represents a virtual
path in the guest WASM environment.
- Added
convert_to_virtual_path and convert_to_real_path helper functions for converting
between real and virtual paths, using a list of host-to-guest path mappings.
- Can also use
VirtualPathExt::to_real_path and RealPathExt::to_virtual_path extension
traits for the same functionality.
- Added
DefineRequirementsOutput.for_setup_environment and for_setup_toolchain fields, which
allow toolchains to specify requirements for the setup environment and setup toolchain actions,
respectively.
- Added
PruneDockerInput.project_dependencies field, which allows the toolchain to know about
other projects that the focused project(s) depends on, so it can prune their dependencies as
well.
- Updated
DefineRequirementsInput.toolchain_config to inherit the project-level settings when
applicable.
🧰 Toolchains
- Go
- The
force option for bins entries is now respected, and will always install the binary.
- Fixed configured
bins not being reinstalled when their binaries were uninstalled or deleted
outside of moon.
- Reworked relationship inference to match package import paths instead of module paths. Each
project now resolves a canonical import path (nearest go.mod module path plus the project's
relative directory), and go list -deps results are matched against those by longest prefix.
This makes relationships resolvable in repositories that share a single go.mod across all
projects.
- Sibling modules required by version without a
go.work no longer create project relationships,
since those builds consume the published module rather than the local source. When the go
binary is unavailable, projects with their own go.mod under a workspace go.work fall back to
resolving relationships from their direct requires.
replace directives keep their meaning in the new model: a require replaced by a local
directory always links to the project at that location (it consumes local source even without a
go.work), while a require replaced by another module never links.
- Imports within a project's own import path are treated as ownership rather than dependencies.
go list -deps ./... enumerates packages belonging to projects nested inside the scanned
project, which previously inferred an edge from the parent to every nested child — forming a
cycle whenever a child declared dependsOn on its parent.
- JavaScript
- Added unstable support for Nub as a package manager:
- Natively uses
nub.lock (pnpm lockfile format), but will locate dependency roots using other
package manager lockfiles that nub can operate on.
- Reads workspace members and catalogs from
pnpm-workspace.yaml when present, otherwise from
package.json.
- Does not require the Node.js toolchain, as nub is a standalone binary.
- Fixed
bun.lock parsing failing on Git/GitHub dependencies that include both package metadata
(dependencies, bin, etc) and an integrity hash.
- Node
- Deprecated the
syncVersionManagerConfig setting (it never worked correctly).
- Python
- Ensures that package manager toolchains are installed before setting up the environment.
- Added support to the Docker pruning workflow where we remove
.venv directories for non-focused
projects (those that were not explicitly scaffolded).
- Rust
- Fixed an issue where Docker scaffolding would leave behind empty
lib.rs or main.rs files.
- Fixed configured
bins not being reinstalled when their binaries were uninstalled or deleted
outside of moon. Only missing binaries are now installed.
🐞 Fixes
- Fixed an issue where the
--stack and --source options of moon query projects displayed each
other's help text. The filtering behavior itself was correct.
- Fixed an issue where toolchain executable paths were not properly applied to all child processes.
- Fixed an issue where project and task graph node lookups could resolve the wrong entry, or fail
entirely, after building a partial graph (a subset of projects), as internal node identifiers were
not re-synced when placeholder nodes were removed.
- Fixed an issue where the async graph builder would fail with "unknown target" when a task
dependency referenced a project by its alias.
- Fixed an issue where the async graph builder would produce differently ordered graphs across runs,
as projects were inserted in completion order instead of a stable order. This could cause unstable
hashes and --dot/--json output.
- Fixed an issue where a task with
runDepsInParallel: false would not be linked to all of its
dependencies when a serial ordering edge was skipped to avoid a cycle, allowing the task to run
before a dependency had finished.
- Fixed an issue where moon would abort on startup with "Failed to load Git submodules" in
repositories without a .gitmodules file, when the git object database was incomplete or
unreachable (e.g. partial clones, or --reference clones whose alternates are inaccessible).
Submodule detection is now skipped entirely when no .gitmodules file exists.
- Fixed an issue where the synchronous affected tracker (
experiments.asyncAffectedTracking
disabled) would silently skip transitive dependent tasks when running with --downstream and
--include-relations, and could even schedule fewer tasks when the change set grew, as affected
marks were accumulated lazily in target iteration order. Affected status is now tracked up front,
mirroring the asynchronous tracker.
- Fixed an issue on Windows where path variables (
$workspaceRoot, $workingDir, $projectRoot)
expanded using the Windows path format (C:\path) based on the shell moon was executed from,
instead of the shell the task runs in. When the windowsShell task option is bash, they now
expand using the Unix path format (/c/path) that bash expects.
- Fixed an issue where
--downstream deep would also expand the dependents of upstream
dependencies, running tasks that are not dependents of the requested targets (with a deep enough
graph, the entire connected component). Downstream expansion now only flows from the requested
targets through their dependent chains, matching how --downstream direct already behaved.
- Fixed an issue where a failed proto installation would not abort the pipeline nor surface its
error. Dependent toolchain actions would run in the broken environment and fail with misleading
errors (like a missing proto-shim binary) that masked the root cause. Setup proto and setup
environment failures now abort the pipeline immediately, and when multiple actions fail, the first
failure is reported instead of the last.
⚙️ Internal
- Renamed the
TaskMergeStrategy type to MergeStrategy in @moonrepo/types, as it's no longer
exclusive to tasks.
- Updated proto to v0.60.2 from 0.58.2.
- Updated Rust to v1.97.0.
- Updated dependencies.
Install moon_cli 2.5.0
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/moonrepo/moon/releases/download/v2.5.0/moon_cli-installer.sh | sh
Install prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/moonrepo/moon/releases/download/v2.5.0/moon_cli-installer.ps1 | iex"
Download moon_cli 2.5.0