docs/src/data/experiments/stack-dependencies.mdx
import Since from '@components/Since.astro'; import Before from '@components/Before.astro'; import { Aside } from '@astrojs/starlight/components';
Support for the autoinclude block in terragrunt.stack.hcl files, enabling dependency relationships and configuration overrides during stack generation.
stack-dependencies - What it doesWhen enabled, this experiment adds support for the autoinclude block nested inside unit and stack blocks in terragrunt.stack.hcl files. The autoinclude block allows users to define dependency blocks and arbitrary configuration that gets generated into an autoinclude file during stack generation. This file is automatically merged into the unit/stack configuration when parsed.
The generated filename depends on the component kind:
terragrunt.autoinclude.hcl next to the unit's terragrunt.hcl.terragrunt.autoinclude.stack.hcl next to the nested stack's terragrunt.stack.hcl. The .stack.hcl suffix mirrors terragrunt.stack.hcl so tooling (LSP, read_terragrunt_config(), indexers) can identify the file's purpose from its name alone.This experiment enables:
unit.<name>.path and stack.<name>.path variables in terragrunt.stack.hcl for referencing sibling component pathsstack.<name>.<unit_name>.path for referencing individual units within a nested stack (fine-grained dependency)dependency blocks targeting stack directories: aggregated outputs from all units in the stack (dependency.stack_name.outputs.unit_name.output_key)terragrunt.autoinclude.hcl into unit configurations (autoinclude wins)# terragrunt.stack.hcl
unit "vpc" {
source = "../catalog/units/vpc"
path = "vpc"
}
unit "app" {
source = "../catalog/units/app"
path = "app"
autoinclude {
dependency "vpc" {
config_path = unit.vpc.path
}
inputs = {
vpc_id = dependency.vpc.outputs.vpc_id
}
}
}
# terragrunt.stack.hcl
stack "stack_w_outputs" {
source = "../catalog/stacks/stack-w-outputs"
path = "stack-w-outputs"
}
unit "unit_w_inputs" {
source = "../catalog/units/unit-w-inputs"
path = "unit-w-inputs"
autoinclude {
dependency "unit_w_outputs" {
config_path = stack.stack_w_outputs.unit_w_outputs.path
mock_outputs_allowed_terraform_commands = ["plan"]
mock_outputs = {
val = "fake-val"
}
}
inputs = {
val = dependency.unit_w_outputs.outputs.val
}
}
}
# terragrunt.stack.hcl
stack "infra" {
source = "../catalog/stacks/infra"
path = "infra"
}
unit "app" {
source = "../catalog/units/app"
path = "app"
autoinclude {
dependency "infra" {
config_path = stack.infra.path
}
inputs = {
vpc_id = dependency.infra.outputs.vpc.vpc_id
}
}
}
terragrunt run --all --experiment stack-dependencies -- plan
stack-dependencies - How to provide feedbackProvide your feedback on the Stack Dependencies RFC GitHub Issue.
stack-dependencies - Implementation roadmapterragrunt.stack.hcl: parse the file body, evaluate locals and values, apply include merges, then decode unit/stack blocks and resolve autoinclude. This lets unit/stack blocks use local.*, values.*, and Terragrunt functions.terragrunt run --all discovery can scan generated nested stack files without evaluating the unit source.stack run apply and stack run destroy.terragrunt-stack/<name>/ get a .terragrunt-stack-origin marker file, so bare relative ../../units/... paths resolve against the original catalog, not the copy. Only applies to local stack sources; remote and CAS-fetched stacks are unchanged.PartialEval depth guard (maxPartialEvalDepth = 10000) and IsWhollyKnown / IsNull checks on the fast path and traversal/template/conditional/parens branches, preventing crashes on unknown values or pathological nesting.Unwrap() across the package (FileParseError, FileDecodeError, IncludeValidationError, LocalEvalError, MalformedDependencyError, AutoIncludeParserStageError) preserving hcl.Diagnostics for source positions.LocalsCycleError.Names (DFS dep iteration sorted).resolveStackFilePath returns (string, bool): callers branch on isStackCandidate instead of a sentinel empty string. Backed by a two-arg fuzz that exercises raw/target independently.stack "foo" { unit "foo" { ... } }) addressable via stack.foo.foo.path and end-to-end covered by integration test.internal/hclparse source files (ASCII-only); intentional Unicode test fixtures remain.autoinclude syntax and merge behavior