Skip to main content
warning

Documentation is currently for moon v2. If you are using v1, some of the examples and settings may differ in syntax and functionality.

Task inheritance

Unlike other task runners that require the same tasks to be repeatedly defined for every project, moon uses an inheritance model where tasks can be defined once at the workspace-level, and are then inherited by many or all projects.

Workspace-level tasks (also known as global tasks) are defined in .moon/tasks/**/*.yml, and are inherited by based on conditions. However, projects are able to include, exclude, or rename inherited tasks using the workspace.inheritedTasks in moon.yml.

Conditional inheritance

Task inheritance is powered by the inheritedBy setting in global task configurations (those in .moon/tasks/**/*). This setting defines conditions that a project must meet in order for inheritance to occur. If the setting is not defined, or no conditions are defined, the configuration is inherited by all projects.

The following conditions are supported:

  • file, files - Inherit for projects that contain specific files.
  • language, languages - Inherit for projects that belong to specific languages.
  • layer, layers - Inherit for projects that belong to specific layers.
  • stack, stacks - Inherit for projects that belong to specific stacks.
  • tag, tags - Inherit for projects that have specific tags.
  • toolchain, toolchains - Inherit for projects that belong to specific toolchains.

One or many conditions can be defined, and all conditions must be met for inheritance to occur. For example, the following configuration will only be inherited by Node.js frontend libraries.

.moon/tasks/node-frontend-library.yml
inheritedBy:
toolchain: 'node'
stack: 'frontend'
layer: 'library'

Each condition supports a single value or an array of values. For example, the previous example could be rewritten to inherit for both Node.js or Deno frontend libraries.

.moon/tasks/js-frontend-library.yml
inheritedBy:
toolchains: ['node', 'deno']
stack: 'frontend'
layer: 'library'

Clauses

The tags and toolchains conditions support special clauses and, or (the default), and not for matching more complex scenarios.

inheritedBy:
toolchains:
or: ['javascript', 'typescript']
not: ['ruby']
layer: 'library'

Merge strategies

When a global task and local task of the same name exist, they are merged into a single task. To accomplish this, one of many merge strategies can be used.

Merging is applied to the parameters args, deps, env, inputs, outputs, and toolchains, using the merge, mergeArgs, mergeDeps, mergeEnv, mergeInputs, mergeOutputs and mergeToolchains options respectively. Each of these options support one of the following strategy values.

  • append (default) - Values found in the local task are merged after the values found in the global task. For example, this strategy is useful for toggling flag arguments.
  • prepend - Values found in the local task are merged before the values found in the global task. For example, this strategy is useful for applying option arguments that must come before positional arguments.
  • preserve - Preserve the original global task values. This should rarely be used, but exists for situations where an inheritance chain is super long and complex, but we simply want to the base values. v1.29.0
  • replace - Values found in the local task entirely replaces the values in the global task. This strategy is useful when you need full control.

All 3 of these strategies are demonstrated below, with a somewhat contrived example, but you get the point.

# Global
tasks:
build:
command:
- 'webpack'
- '--mode'
- 'production'
- '--color'
deps:
- 'designSystem:build'
inputs:
- '/webpack.config.js'
outputs:
- 'build/'

# Local
tasks:
build:
args: '--no-color --no-stats'
deps:
- 'reactHooks:build'
inputs:
- 'webpack.config.js'
options:
mergeArgs: 'append'
mergeDeps: 'prepend'
mergeInputs: 'replace'

# Merged result
tasks:
build:
command:
- 'webpack'
- '--mode'
- 'production'
- '--color'
- '--no-color'
- '--no-stats'
deps:
- 'reactHooks:build'
- 'designSystem:build'
inputs:
- 'webpack.config.js'
outputs:
- 'build/'
options:
mergeArgs: 'append'
mergeDeps: 'prepend'
mergeInputs: 'replace'