moon v2.1 - Execution plans, target deps scopes, toolchain/task settings, and more
It's been about a month since our major v2.0 release, and we're back with a smaller, but still
impactful, v2.1 release! This release includes a new execution plan feature for moon exec, the
ability to target project dependencies by scope, new common toolchain settings for aliases and
dependency installation, new task options for affectedFiles,
and more.
Execution plans
The moon exec command is powerful, but complex invocations can mean long
CLI commands that are hard to read and easy to get wrong. In v2.1, you can now define an execution
plan — a JSON file that declaratively configures targets, affected filtering, graph traversal, and
pipeline behavior — and pass it with a single flag:
{
"pipeline": {
"jobTotal": 3
},
"targets": {
"jobs": [["app:build", "app:test"], ["lib:build", "lib:test"], ["docs:build"]]
}
}
# Runs docs:build only!
$ moon exec --plan plan.json --job 2
This is especially useful for CI pipelines where you need partitioned jobs, affected-only runs, or
specific failure handling. Instead of stitching together a dozen flags, drop a plan.json into your
repo and version-control your execution strategy.
Check out the execution plan guide for the full structure and examples.
Target project dependencies by scope
moon has always allowed you to reference dependencies of a project (external projects) within a task
using ^ syntax, for both inputs and
deps. However, it was quite restrictive in that it referenced all
project dependencies, regardless of scope (production, development, etc).
We felt it was time to change this, and in v2.1 we're introducing a new syntax that allows you to
target dependencies by scope. By default, the ^ syntax will still reference all dependencies, but
you can now specify a scope by suffixing the ^ with one of the following:
development/devproduction/prodbuildpeer
tasks:
build:
command: 'tsc'
deps:
# Depend on build tasks in production level project dependencies
- '^production:build'
inputs:
# Source files of all production level project dependencies
- 'project:^production'
New common toolchain settings
Going forward, we want to provide more customization for toolchains, enabling you to curate the experience you want. The first step in this process is introducing 2 new settings that are common across all toolchains.
inheritAliases
Aliases are a feature of projects that allow for alternate names to be used when referencing them.
Aliases cannot be configured manually and instead are inferred from toolchains, typically by
extracting the name field from a manifest file (package.json, Cargo.toml, pyproject.toml,
etc).
This happens automatically, but what if you don't want to use aliases? Or there are conflicting
aliases across projects? In v2.1, we're introducing a new common toolchain setting called
inheritAliases that allows you to disable this feature.
When set to false, no aliases will be inferred for any projects using that toolchain.
javascript:
inheritAliases: false
We've also updated duplicate aliases to no longer be a hard error, and instead will apply to the first encountered project.
installDependencies
When you run a task, all toolchains associated with the task will automatically install dependencies if they've determined that they need to (lockfile changes, dependency updates, etc). This is a great feature for ensuring that your environment is always up to date, especially when switching branches, but it can be a bit too much for some use cases.
In v2.1, we're introducing another common toolchain setting called
installDependencies that allows you to disable this
feature. When set to false, toolchains will not automatically install dependencies before running
a task.
python:
installDependencies: false
Not all toolchains support this tier 2 feature.
New task affectedFiles settings
In v2 we introduced an object form for the the task option
affectedFiles, allowing you to further customize this
feature. Based on feedback from the community, we're introducing 3 new settings to this object:
filter- A list of glob patterns to filter the affected files list before passing to the task.ignoreProjectBoundary- When matching affected files, ignore the project boundary and include workspace relative files. Otherwise, only files within the project are matched.passDotWhenNoResults- When there are no affected files after matching and filtering, use.instead of an empty value.
tasks:
lint:
command: 'eslint'
inputs:
- 'src/**/*.{ts,tsx}'
- '**/*.json'
- 'eslint.config.*'
options:
affectedFiles:
filter: ['**/*.tsx?']
ignoreProjectBoundary: true
passDotWhenNoResults: false
Other changes
View the official release for a full list of changes.
- Improved our local and remote detection logic. We now also check for common remote devboxes (GitHub Codespaces, Gitpod, etc) in addition to CI environments.
- Added a new task option,
runInSyncPhase, that will run the task duringmoon synccommands. - Go
- Will now run
go list --depsto determine project relationships while extending the project graph.
- Will now run
- Python
- Normalized package/dependency names to PEP 503 during graph extending.
- Fixed an issue where package manager toolchain settings were not being inherited correctly.
- TypeScript
- Added a
pruneProjectReferencessetting that prunes non-moon managed project references when syncing.
- Added a
