Architecture Design¶
Understand how Cultivator works under the hood.
Overview¶
Cultivator is a CLI-first tool that orchestrates Terragrunt stack discovery, filtering, and execution. It runs as a command in CI/CD systems (GitHub Actions, GitLab CI) or locally, and delegates state management entirely to Terraform/OpenTofu backends.
Unlike PR-based automation, Cultivator is job-triggered: you call it explicitly in your CI workflow, providing flags to control scope and behavior.
Core Components¶
1. Config Loader¶
- Loads built-in defaults, optional config file (
--config), environment variables, and CLI flags - Merges configuration with CLI flags and environment variables
- Validates required configuration fields (root path exists, parallelism is positive)
2. Stack Discovery¶
- Walks the root directory recursively
- Finds all
terragrunt.hclfiles - Builds list of available stacks
3. Scope Filter¶
- Filters stacks by
--env(environment) - Filters stacks by
--include/--exclude(path patterns) - Filters stacks by
--tags(recommended# cultivator:tags = a,b; legacycultivator_tags = [...]supported)
4. Git Integration (Magic Mode)¶
- Queries Git for changed files using
git diff - Maps file changes to specific Terragrunt modules
- Filters execution scope to only affected modules when
--changed-onlyis active
5. Dependency Graph (DAG)¶
- Parses
terragrunt.hclfiles to extractdependencyblocks - Builds a Directed Acyclic Graph (DAG) representing module relationships
- Performs topological sorting to determine the correct execution order
- Detects and prevents circular dependencies
6. Executor¶
- Runs Terragrunt commands (
plan,apply,destroy) - Manages parallel execution via worker pool
- Captures stdout and stderr in a single chronologically-ordered stream using
cmd.CombinedOutput() - Captures output on per-stack, per-command basis
7. Output Formatter¶
- Formats and displays results in human-readable text
- Reports exit codes and errors per module
8. Logging Boundary¶
- CLI owns user-facing logs and summary output.
- Discovery, runner, and git use injected logger instances for debug-level diagnostics only.
Data Flow¶
CLI Invocation (plan/apply/destroy)
|
Config Loader -> Parse defaults + optional --config file + env vars + flags
|
Stack Discovery + Scope Filter -> Find all terragrunt.hcl files, apply --env, --include, --exclude, --tags
|
Git Integration -> Filter by changed files (if --changed-only)
|
Dependency Graph -> Build execution order (DAG)
|
Executor (parallel worker pool) -> Run Terragrunt commands
|
Output Formatter -> Display results
|
Exit Code (0 = success, 1 = failure, 2 = usage error)
Key Design Principles¶
1. Stateless Operation¶
- Cultivator does not manage state, backends, or locks
- All state is owned by Terraform/OpenTofu
- Concurrency is controlled via a bounded channel semaphore and dependency signaling between goroutines; there are no filesystem locks
2. Explicit Control¶
- No automatic triggers or webhooks
- User (or CI job) explicitly calls
cultivator plan/apply/destroy - Flags control what runs and how
3. Filter-First¶
- Start with all stacks, then filter by environment/path/tags
- Filters are composable (combine multiple
--include,--exclude,--tags) - Results show exactly which stacks will be affected
4. Dependency-Aware¶
- Respects Terragrunt
dependencyblocks - Runs stacks in correct order (topological sort)
- Prevents applying stack A before its dependency B
5. Parallel by Default¶
- Configurable worker pool (default: number of CPUs)
- Runs independent stacks concurrently
- Respects dependency graph for safe parallelism
6. Human-Readable Output¶
- Structured text output with a clear per-module section header
- Compatible with GitHub Actions, GitLab CI, and local debugging
Configuration Reference¶
When using a config file, pass it explicitly with --config:
root: live # Root directory to scan for stacks
parallelism: 4 # Worker pool size (default: number of CPUs)
non_interactive: false # Equivalent to -input=false
plan:
destroy: false # Defaults for 'plan' subcommand
apply:
auto_approve: true # Defaults for 'apply' subcommand
destroy:
auto_approve: true # Defaults for 'destroy' subcommand
CLI flags and environment variables override the config file. Flags take highest precedence.
See Configuration for full reference.
Security Considerations¶
Secrets Redaction¶
- Cultivator does not implement secret redaction in its own output layer
- Use your CI platform's built-in secret masking (GitHub Actions masked secrets, GitLab CI variable masking)
- Mark sensitive Terraform outputs with
sensitive = trueso Terragrunt/OpenTofu suppress them in plan output
Access Control¶
- Cultivator respects IAM permissions of the CI runner
- If the CI job lacks permissions to modify a stack, Terraform will error
- No additional RBAC layer in Cultivator itself
State Backend Protection¶
- All state is stored in the backend (S3, Terraform Cloud, etc.)
- Cultivator does not access or modify state directly
- Backend authentication is handled by Terragrunt/Terraform