moon v0.23 - Scoped task inheritance, and project config updates
With this release, we're launching the next iteration of our task inheritance model, as well as quality of life improvements for project configuration.
Developer survey
Before we dive into this new release, we have a quick survey for everyone. We know how everyone feels about surveys, but this one is real quick, only a few minutes, and is mostly multiple choice questions.
We're looking for feedback on moon itself, what features you're looking for, what you currently do not like, how you're currently using monorepos, your development workflows, so on and so forth. We'd very much appreciate it if you could engage with this survey!
Improved task inheritance model
One of the guiding principles behind moon is to simplify repository maintenance, with task
management being top of list. We weren't happy with the current state of things, as every build
system and task runner that exists always opted for per-project task management, which is a massive
amount of overhead and tech debt in the long run. To combat this, moon was designed from the
ground-up using a task inheritance model, where "global" tasks were defined in
.moon/project.yml
, with per-project tasks still being an option with
moon.yml
.
While inheritance worked great, it did have some shortcomings, such as:
- With the addition of new programming languages, there's no way to easily define tasks for specific languages, that should only be inherited by specific projects.
- There's no way to differentiate tasks between applications or libraries, as they typically have different build/compilation systems.
- All of the problems above can be "solved" with
workspace.inheritedTasks
in all projects, but it's a maintenance headache.
We've been documenting a solution to these problems for many months now, and we're very excited to finally release our new and improved task inheritance model that solves all of the problems above, and opens the doors for future enhancements! Keep reading for more information.
New .moon/tasks.yml
(breaking)
To start, we renamed .moon/project.yml
to .moon/tasks.yml
as we want to emphasize that this
configuration file is for task inheritance functionality only. However, the semantics of this file
has not changed, and is still "tasks to be inherited by all projects".
$schema: 'https://moonrepo.dev/schemas/tasks.json'
tasks:
# ...
We'll automatically rename this file for you when running a
moon
command!
New scoped tasks with .moon/tasks/*.yml
The biggest change to task inheritance is that tasks can now be scoped by a project's
language
or type
using the new
.moon/tasks/<language>.yml
or .moon/tasks/<language>-<type>.yml
configuration files! Jump to the
official documentation on task inheritance for more information
on how scoping works, the lookup order of files, and much more.
As a demonstration, you can scope tasks to Node.js projects with .moon/tasks/node.yml
, Rust
applications with .moon/tasks/rust-application.yml
, Go libraries with
.moon/tasks/go-library.yml
, Ruby scripts with .moon/tasks/ruby-tool.yml
, so on and so forth!
We're very excited for this feature, as it's something we personally needed, and we're sure you all do as well. It also future proofs moon for new programming languages, additional implicit scenarios to handle, and yet to be discovered functionality.
- Node
- Go
- PHP
- Python
- Ruby
- Rust
tasks:
format:
command: 'prettier --write .'
tasks:
format:
command: 'go fmt'
tasks:
format:
command: 'phpcbf .'
tasks:
format:
command: 'pylint .'
tasks:
format:
command: 'rubocop -l'
tasks:
format:
command: 'cargo fmt --all --check'
Moved implicitDeps
and implicitInputs
(breaking)
To standardize inheritance and expansion related functionality, we've moved the
runner.implicitDeps
and runner.implicitInputs
settings from .moon/workspace.yml
to
.moon/tasks.yml
and
.moon/tasks/*.yml
and removed the runner
prefix.
This allows for implicits to also be scoped accordingly and granularly. For example, projects can now inherit dependency manager related files as implicit inputs on a per-language basis:
- Node
- Go
- PHP
- Python
- Ruby
- Rust
implicitInputs:
- 'package.json'
implicitInputs:
- 'go.mod'
implicitInputs:
- 'composer.json'
implicitInputs:
- 'pyproject.toml'
implicitInputs:
- 'Gemfile'
implicitInputs:
- 'Cargo.toml'
Project-level environment variables
Since moon's inception, tasks can be configured with pre-defined environment variables using the
env
setting. These variables would then be passed to the command
during execution. This works perfectly for encapsulation, but becomes tedious when the same
variables are repeated for multiple tasks.
To remedy this, environment variables can now be defined at the top of
moon.yml
using the top-level env
setting.
Variables defined at the top-level will be inherited by all tasks in the current project, but will
not override task-level variables of the same name.
To demonstrate this, the following config:
tasks:
dev:
# ...
env:
TARGET_ENV: 'development'
build:
# ...
env:
TARGET_ENV: 'development'
serve:
# ...
env:
TARGET_ENV: 'development'
Can be rewritten as:
env:
TARGET_ENV: 'development'
tasks:
dev:
# ...
build:
# ...
serve:
# ...
Globs in task outputs
Another feature that's been around since moon's inception is task
outputs
, which only supported relative files and folders. For
historical reasons, it was the easiest solution at the time, but in practice, supporting more
granular control is better.
As such, task outputs
now support glob patterns as well! This is perfect for restricting and
filtering down which files are cached in the artifact. However, be aware that during hydration (a
cache hit), all files not matching the glob will be deleted, so ensure that critical files do
match.
To demonstrate this, if building a JavaScript project, you may want to include .js
and .css
files, but exclude everything else (.map
, etc).
tasks:
build:
command: 'webpack'
outputs:
- 'build/**/*.{js,css}'
Other changes
View the official release for a full list of changes.
- Updated
moon migrate from-turborepo
to preserve globs in outputs. - Updated project graph to no longer cache when there's no VCS root.
- Updated pnpm to use the new
pnpm dedupe
command when the version is >= 7.26.0.
What's next?
Expect the following in the v0.24 release!
- New
moon query tasks
command. - New per-project
platform
setting. - Token support in task
outputs
. - TypeScript v5 support.