Actions
Unlike other task runners in the industry that represent each node in the graph as a task to run, moon represents each node in the graph as an action to perform. This allows for more flexibility and efficiency in task execution, and enables additional functionality and automation. The following actions compose the action graph:Sync workspace
A common action that always runs first, giving moon a chance to perform operations and health checks across the entire workspace. This includes:- Validating workspace configuration
- Checking for configuration changes
- Initializing workspace-level state
- Running workspace-level hooks
This action can be skipped by disabling the
pipeline.syncWorkspace setting.Setup proto
Runs before all toolchain-related actions and ensures that proto has been installed and is available for use. This is required for toolchains that will be downloaded and installed.Setup toolchain
The most important action in the graph, which downloads and installs a tier 3 language into the toolchain. For other tiers, this is essentially a no-operation.- When the tool has already been installed, this action will be skipped
- Actions are scoped by language and version (runtime). For example:
SetupToolchain(node:18.1.0)SetupToolchain(deno:1.31.0)
- Tools that require a global binary (found on
PATH) will display the version as “global”. For example:SetupToolchain(node:global)
This action can be skipped by setting the
MOON_SKIP_SETUP_TOOLCHAIN=true environment variable. The skip can be scoped per tool by setting the value to the tool name (node), and also by version (node:20.0.0). Supports a comma-separated list.Setup environment
Runs after the toolchain has been set up, but before dependencies are installed, allowing the development environment to be configured. This includes operations such as:- Modifying manifests (
package.json, etc.) - Updating configuration files
- Initializing virtual environments (Python venv’s)
- Running environment-specific setup scripts
Install dependencies
Before running a task, moon ensures that all language dependencies (node_modules for example) have been installed. Dependencies are automatically installed if changes are detected since the last run. This is achieved by:
- Comparing lockfile modified timestamps
- Parsing manifest files
- Hashing resolved dependency versions
- When dependencies do not need to be installed, this action will be skipped
- Depending on the language and configuration, dependencies may be installed:
- Per-project:
InstallProjectDeps(node:18.1.0, example) - Workspace-wide:
InstallWorkspaceDeps(node:18.1.0)
- Per-project:
- Actions are scoped by language and version (runtime)
This action can be skipped by disabling the
pipeline.installDependencies setting.Sync project
To ensure a consistently healthy project and repository, moon runs a process known as syncing every time a task is run. This action runs sync operations for all toolchains associated with the project, which may include:- Syncing configuration files
- Updating project manifests
- Running project-level health checks
- Applying project-specific toolchain configurations
This action can be skipped by disabling the
pipeline.syncProject setting.Run task
The primary action in the graph, which runs a project’s task as a child process, derived from a target. Tasks can depend on other tasks, and they are effectively orchestrated and executed by running in topological order using a thread pool. Key features:- Dependencies - Ensures all task dependencies complete before execution
- Caching - Skips tasks if outputs are cached and inputs haven’t changed
- Parallel execution - Runs independent tasks concurrently
- Task states - Tracks success, failure, cached, or skipped states
Run interactive task
Like the base run task, but runs the task interactively with stdin capabilities. This is used for tasks that require user input or terminal interaction.- All interactive tasks are run in isolation in the graph
- Only one interactive task runs at a time
- stdin/stdout/stderr are directly connected to the terminal
Run persistent task
Like the base run task, but runs the task in a persistent process that never exits. This is used for long-running services like development servers.- All persistent tasks are run in parallel as the last batch in the graph
- They continue running even after other tasks complete
- Examples:
devservers, watch modes, background services
Graph construction
The action graph is built through a multi-step process:1. Initialize builder
The action graph builder is initialized with:- App context - Global application state
- Workspace graph - The complete project graph
- Options - Configuration for which actions to include
2. Add targets
Targets (task identifiers) are added to the graph. For each target:- Resolve the target to a specific project and task
- Add the run task action node
- Recursively add dependency tasks based on
--upstreamsetting - Add dependent tasks if
--downstreamis specified
3. Add supporting actions
For each task added, the builder automatically adds supporting actions:- Setup toolchain (if needed for the task’s toolchain)
- Install dependencies (if needed for the project)
- Setup environment (if needed)
- Sync project (if enabled)
4. Apply query filters
If a--query is specified, the graph is filtered to include only tasks matching the query criteria. See Query language for details.
5. Apply affected filtering
If--affected is enabled, the graph is filtered to include only tasks affected by changed files:
- Determine changed files from VCS
- Mark tasks as affected based on:
- Changed input files
- Changed environment variables
- Affected dependencies (if
--include-relationsis set) - Affected dependents (if
--include-relationsis set)
- Remove non-affected tasks from the graph
6. Build and optimize
Final optimizations are applied:- Transitive reduction - Remove redundant edges
- Cycle detection - Ensure the graph is acyclic
- Priority grouping - Group actions by priority level
- Topological sorting - Determine execution order
Graph execution
Once built, the action graph is executed through the action pipeline:1. Topological sort
The graph is sorted topologically to determine a valid execution order. This ensures dependencies always run before their dependents.2. Priority grouping
Actions are grouped by priority level:- Priority 0 (Critical) - Workspace sync, proto setup
- Priority 1 (High) - Toolchain setup
- Priority 2 (Normal) - Dependency installation, environment setup
- Priority 3 (Low) - Task execution
3. Parallel execution
Within each priority group, independent actions are executed in parallel using a thread pool. The number of concurrent actions is controlled by:- Available CPU cores
- Configuration settings
- System resource limits
4. State tracking
As actions execute, their states are tracked:- Pending - Waiting for dependencies
- Running - Currently executing
- Passed - Completed successfully
- Failed - Failed with error
- Cached - Skipped due to cache hit
- Skipped - Skipped due to conditions
5. Failure handling
When an action fails:- Bail mode (
--on-failure=bail) - Immediately stop execution - Continue mode (
--on-failure=continue) - Continue executing independent actions
Visualization
You can visualize the action graph using:- All actions as nodes
- Dependencies as directed edges
- Action types with different visual styles
- Execution order and groupings
Benefits
The action graph provides several key benefits:Correctness
- Guarantees tasks run in the correct order
- Ensures all dependencies are satisfied
- Prevents race conditions and conflicts
Performance
- Maximizes parallelism where possible
- Minimizes redundant work through caching
- Optimizes resource utilization
Flexibility
- Supports various execution modes (interactive, persistent)
- Allows fine-grained control via options
- Enables advanced workflows like job partitioning
Observability
- Tracks detailed execution state
- Provides clear error messages
- Enables visualization and debugging
Related
moon exec- Execute tasks using the action graphmoon action-graph- Visualize the action graph- Query language - Filter tasks in the graph
- Affected - Understand affected detection