website/docs/guides/exec-plan.mdx
import VersionLabel from '@site/src/components/Docs/VersionLabel';
<VersionLabel version="2.1.0" header />An execution plan is a JSON file that declaratively configures how moon exec
(and derived commands) runs tasks. Instead of passing many command line options, you can define your
execution settings in a file and pass it with a single flag — keeping your commands short and your
configuration version-controlled.
Pass an execution plan to moon exec with the --plan (or -p) flag:
$ moon exec --plan plan.json
Or set the MOON_EXEC_PLAN environment variable:
MOON_EXEC_PLAN=plan.json moon exec
The path can be relative (resolved against the working directory) or absolute. The file must be valid JSON.
When both a plan and CLI options are provided, plan values take priority. If targets are defined in both the plan and the command line, the plan's targets are used and a warning is logged.
A plan is a JSON object with four top-level blocks. All blocks are optional and default to safe values when omitted. Unknown fields are rejected.
{
"affected": {},
"graph": {},
"pipeline": {},
"targets": []
}
targetsDefines which tasks to run. Accepts the same target syntax as the moon exec command line
(project:task, :task, ~:task, #tag:task, globs, etc).
In its simplest form, targets is an array of target strings:
{
"targets": ["app:build", "lib:build"]
}
For advanced use cases, targets can be an object with one of two strategies:
include list (excluding coming soon):{
"targets": {
"include": ["app:build", "#frontend:test"]
}
}
{
"targets": {
"jobs": [
["app:build", "app:test"],
["lib:build", "lib:test"]
]
}
}
Use in combination with pipeline.job to select which partition to run.
pipelineControls how the pipeline executes tasks.
ci (boolean) - Force enable CI mode. Same as --ci.concurrency (number) - Maximum number of tasks to run in parallel.ignoreCiChecks (boolean) - Ignore "run in CI" task checks. Same as --ignore-ci-checks.noActions (boolean) - Skip sync and setup actions. Same as --no-actions.onFailure ("bail" | "continue") - When a task fails, either bail the pipeline immediately or
continue running other tasks. Same as --on-failure.job (number) - Index of the current job (0-based). Used with partitioned targets; errors if
targets are not partitioned. Same as --job.jobTotal (number) - Total number of jobs. Used with partitioned targets. Same as
--job-total.graphControls how deeply the dependency graph is traversed when building the task graph.
downstream (none | direct | deep) - Depth of downstream dependents to include. Defaults to
none. Same as --downstream.upstream (none | direct | deep) - Depth of upstream dependencies to include. Defaults to
none. Same as --upstream.affectedRestricts execution to tasks affected by changed files. When this block is omitted, affected filtering is disabled and all matched targets run.
base (string) - Base branch, commit, or revision to compare against. Same as --base.head (string) - Current branch, commit, or revision to compare with. Defaults to HEAD. Same
as --head.includeRelations (boolean) - Include graph relations for affected checks, instead of just
changed files. Same as --include-relations.source (string) - Source of affected files. Determines which git commands are used to detect
changes. Accepts local or remote.status (string[]) - Filter changed files by status. Same as --status.stdin (boolean) - Accept changed files from stdin. Same as --stdin.The simplest plan — just list the targets to run:
{
"targets": ["app:build", "lib:build"]
}
Only run tests affected by changes between the base branch and HEAD:
{
"affected": {
"base": "main",
"source": "remote"
},
"pipeline": {
"ci": true
},
"targets": [":test"]
}
Split targets across 3 CI jobs. Each job runs with --plan plan.json and sets its own job index
via the CLI or an environment variable:
{
"pipeline": {
"ci": true,
"jobTotal": 3
},
"targets": {
"jobs": [["app:build", "app:test"], ["lib:build", "lib:test"], ["docs:build"]]
}
}
Then in CI, run each partition:
# Job 0
$ moon exec --plan plan.json --job 0
# Job 1
$ moon exec --plan plan.json --job 1
# Job 2
$ moon exec --plan plan.json --job 2
Run all lint tasks, continuing past failures so you get the full list of issues:
{
"pipeline": {
"concurrency": 4,
"onFailure": "continue"
},
"targets": [":lint"]
}
Build a target along with all of its upstream dependencies and downstream dependents:
{
"graph": {
"upstream": "deep",
"downstream": "deep"
},
"targets": ["core:build"]
}
Combine all blocks — run affected tests in CI across partitioned jobs, with full graph traversal:
{
"affected": {
"base": "main",
"head": "HEAD",
"includeRelations": true,
"source": "remote",
"status": ["modified", "added"]
},
"graph": {
"upstream": "deep",
"downstream": "direct"
},
"pipeline": {
"ci": true,
"concurrency": 8,
"jobTotal": 3,
"onFailure": "continue"
},
"targets": {
"jobs": [["app:test", "app:lint"], ["#frontend:test"], ["lib:test", "core:test"]]
}
}