Releases: gruntwork-io/terragrunt
v1.0.4
🏎️ Performance Improvements
run_cmd and Git repo-root results memoized without the Provider Cache Server
Within a single command, repeated run_cmd(...) calls and repeated Git repo-root lookups across units used to share their cached results only when the Provider Cache Server was running. Commands invoked without --provider-cache (the common case for find, list, and run --all against estates that do not need provider caching) re-evaluated each run_cmd and re-shelled to git rev-parse --show-toplevel for every unit.
Both caches are now active for every command, so identical run_cmd arguments and repeated repo-root lookups are reused across units regardless of whether the Provider Cache Server is enabled.
fast-copy strict control
With the new fast-copy strict control enabled, Terragrunt compiles each include_in_copy and exclude_from_copy pattern once and evaluates it inline during a single copy walk. This avoids re-walking subdirectories for every pattern, which should result in noticeable speed improvements for large source modules.
terragrunt run plan --strict-control fast-copyThe new matcher does not collapse ** to zero path segments when a neighbor is a wildcard, so a/**/*.tf matches a/sub/main.tf but not a/main.tf. Patterns that relied on the old collapsing behavior should use brace alternation like {*.tf,**/*.tf} to cover both depths.
Fewer git rev-parse invocations on large estates
The get_repo_root() HCL function, the runner, and the find and list discovery commands all ask Git for the enclosing repository root. Previously, two units in the same repository each triggered their own git rev-parse --show-toplevel, even when the answer was identical. On large estates this added up to one fork per unit (and sometimes more) for a value that never changed.
A repository discovered for one working directory is now reused for any other working directory inside it, for the duration of the command. Nested repositories (a checkout vendored inside another) still resolve to their own root.
🐛 Bug Fixes
--auth-provider-cmd no longer runs once per dependency cache directory
Resolving dependency outputs ran the configured --auth-provider-cmd again from inside each .terragrunt-cache working directory, on top of the call already made for the unit.
Terragrunt now reuses the credentials already obtained for the dependency when reading outputs from a cached working directory, so --auth-provider-cmd is invoked once per dependency instead of twice.
Fixed exclude block being dropped when defined only in an included parent
A unit that pulled in an exclude block from an include that did not declare its own exclude block saw the include's exclude configurations ignored.
Included exclude blocks now get properly merged into unit configurations.
Reported in #5089. Thanks to @HeikoNeblung for contributing this fix!
Fixed terragrunt find --include failing on relative include paths
Running terragrunt find --include against units whose include blocks reference parent configs with relative paths (../root.hcl, ./common.hcl, bare filenames, etc.) emitted errors like Rel: can't make ../root.hcl relative to /abs/working-dir and dropped those entries from the output.
Relative include paths are now resolved against the unit's directory before being made relative to the working directory, matching how the rest of Terragrunt interprets the path attribute on an include block.
find and list no longer hard-fail when a path cannot be made relative to its base. The condition is logged as a warning and the path is emitted as-is, so output stays complete and the command exits zero.
Tolerate non-JSON warnings in tofu/terraform output -json
Resolving dependency outputs no longer fails when the underlying tofu/terraform output -json invocation prints a deprecation warning to stdout alongside the JSON payload. Terraform 1.15.0 introduced a backend deprecation warning for the S3 dynamodb_table parameter that is emitted on stdout after the JSON object, which broke parsing with errors like invalid character 'W' after top-level value and the misleading downstream message There is no variable named "dependency".
Terragrunt now isolates the first JSON object in the captured stdout, so leading log lines (for example, the long-standing AWS Client Side Monitoring Enabling CSM line) and trailing warning blocks are both ignored when reading dependency outputs.
Resolves #6001. Thanks to @jpke for contributing this fix!
get_repo_root() returns OS-native separators on Windows
git rev-parse --show-toplevel always emits forward-slash paths, even on Windows. Terragrunt returned that string unchanged from get_repo_root(), so configurations that compared the result against path/filepath-style paths or fed it back into helpers expecting OS-native separators saw spurious mismatches and broken joins on Windows.
The output is now normalized to OS-native separators before being returned, so get_repo_root() produces C:\repo\path on Windows and /repo/path on Linux and macOS.
Reported in #5976.
Hardened module manifest handling
Terragrunt now bounds .terragrunt-module-manifest cleanup to the manifest's own folder, skips paths with symlinked parents, and removes invalid manifests after reading any valid entries. Existing manifests keep the same gob format.
Provider Cache Server now supports custom host blocks
Running terragrunt with the Provider Cache Server enabled against a private registry declared via a host block in .terraformrc (or a file referenced by TF_CLI_CONFIG_FILE) failed with errors such as provider registry.opentofu.org/<org>/<provider> was not found, because the cache server proxy did not recognize the custom registry and rewrote requests to registry.opentofu.org.
Terragrunt now registers each custom host block with the cache server, seeds its service discovery from the services map so registries that do not serve .well-known/terraform.json still work, and forwards OPENTOFU_NETRC_* / TF_TOKEN_* credentials so authenticated registries continue to authenticate through the proxy.
# .terraformrc
host "registry.example.com" {
services = {
"providers.v1" = "https://registry.example.com/repository/terraform-hosted/v1/providers/"
}
}Resolves #5916. Thanks to @elkh510 for contributing this fix!
🧪 Experiments Updated
stack-dependencies — Stricter validation and clearer parse errors for autoinclude
Malformed configuration inside an autoinclude block previously produced misleading messages or, in some cases, was silently ignored during stack discovery.
Two changes tighten this up:
- A
dependencyblock insideautoincludemust declare exactly one label. Zero labels (dependency {}) and multiple labels (dependency "a" "b" {}) are now rejected at parse time with a diagnostic that points at the offending block. - Parse failures encountered while expanding
autoincludefiles duringstack generate,find, andlistare surfaced with the underlying HCL diagnostic instead of being swallowed or remapped to a generic discovery error.
Reported in #5980.
cas — Local paths supported as stack component sources
CAS-backed stack generation now accepts a local filesystem path as the source of a consumer stack or unit block, in addition to a remote Git URL. Terragrunt copies the referenced directory into a temporary directory, computes a content-addressed root hash over the copy, and applies the same update_source_with_cas rewriting as the remote flow. The original directory is left untouched.
# live/terragrunt.stack.hcl
stack "service" {
source = "../catalog//stacks/service"
path = "service"
}This makes a catalog usable against a local checkout under the same update_source_with_cas = true attributes that already work for Git URLs, which is helpful when iterating on a catalog before tagging a release.
See the CAS documentation and Explicit Stacks: Local catalog sources for details.
catalog-redesign — Units and stacks, scaffolded values, and key-binding cleanup
The redesigned terragrunt catalog TUI gains two new component kinds, a guided scaffolding flow for placing them, and a small key-binding cleanup.
Units and stacks join modules and templates
Catalog discovery now classifies units (directories containing a terragrunt.hcl) and stacks (directories containing a terragrunt.stack.hcl) as first-class component kinds, alongside OpenTofu/Terraform modules and boilerplate templates. The list view picks them up automatically and they appear under their own tabs; press tab and shift+tab to cycle.
When more than one classification could apply to the same directory (for example, a stack directory that also contains a unit), Terragrunt resolves it to a single kind under a fixed precedence: template, stack, unit, module.
Copy and scaffolded values
Selecting a unit or stack from the catalog now offers a copy action that materializes the component into your working directory. Terragrunt walks the copied component for values.<name> references and, if it finds any, writes a ...
v1.0.3
✨ New Features
--no-cas flag for disabling CAS per command
The new --no-cas flag disables the CAS for a single invocation, even when the cas experiment is enabled. It is available on run, stack generate, and stack run.
terragrunt stack generate --experiment cas --no-casThis is useful when you want to fall back to the standard getter path without unwinding experiment configuration.
Generation and runs error when --no-cas is combined with update_source_with_cas = true on any reachable unit, stack, or terraform block, since relative sources in catalog repositories cannot be resolved without the CAS.
🐛 Bug Fixes
hcl fmt --diff no longer requires the diff binary
Previously, terragrunt hcl fmt --diff spawned a diff process discovered in $PATH to render its output. This made it incompatible with minimal container images and Windows installations where that binary was unavailable.
The flag now produces unified diff output without depending on any external binary.
Note that the output is not byte-identical to GNU diff -u. Each file diff is now preceded by a diff old/<path> new/<path> header line, and the ---/+++ lines no longer include a trailing timestamp. Scripts that parsed the previous output may need small adjustments.
Fixed crash when include and locals with read_terragrunt_config coexist
A unit that combined an include block with a locals block calling read_terragrunt_config(...) could crash during discovery, surfacing as a misleading Call to function "read_terragrunt_config" failed error pointed at the locals expression.
Discovery now reports the underlying error instead of crashing.
Reported in #5949.
Fixed crash when a root.hcl declares no remote_state block
A root.hcl that only declared locals (or otherwise omitted a remote_state block) could trigger a nil pointer dereference inside Terragrunt's remote-state initialization. Downstream tools that embed the Terragrunt config parser, such as terragrunt-ls, crashed on every such file.
A missing remote_state block now initializes an empty remote-state value instead of panicking, so parsing proceeds normally when no backend is configured.
Reported in terragrunt-ls#134.
Thanks to @SAY-5 for contributing this fix!
Fixed a race condition in terragrunt stack generate
Fixed a race condition in terragrunt stack generate that could produce non-deterministic file errors on nested stack hierarchies. The same stack file could reach the worker pool twice through different path forms and cause the duplicate writes to conflict with each other. Paths are now normalized before dispatch so each stack file is generated exactly once per invocation.
When a stack file is legitimately claimed by more than one parent during generation, Terragrunt now logs a warning that names the contending parents and records the latest claimant, so the configuration can be corrected before it causes silent overwrites.
Fixed data race in --version flag parsing under concurrent CLI invocations
When multiple Terragrunt CLI invocations ran concurrently in the same process, urfave/cli/v2's package-level VersionFlag singleton was mutated concurrently by each invocation's flag-parsing path, producing a WARNING: DATA RACE on shared flag state.
Terragrunt now sets cli.App.HideVersion = true at construction, which prevents urfave from auto-appending its shared VersionFlag into each App's flag set. The --version / -v flag is unchanged from the user's perspective — it is handled by Terragrunt's own flag registered in internal/cli/flags/global.NewHelpVersionFlags.
🧪 Experiments Added
mark-many-as-read — Mark many files as read in one step
Enable the new mark-many-as-read experiment to turn on two behaviors that each mark many files as read in a single call: automatic marking of files inside a local terraform { source = "..." } block, and the new mark_glob_as_read HCL function.
With the experiment on, a unit like this:
# live/unit/terragrunt.hcl
terraform {
source = "../../modules/service"
}records every *.tf, *.tf.json, *.hcl, *.tofu, and *.tofu.json file found under ../../modules/service (recursively) as read for the unit. Non-source files such as README.md are skipped. A reading-based filter expression such as --filter 'reading=../../modules/service/**' then matches every unit that points at the module, so a change to any file in the module cascades to its consumers.
The same experiment also enables a new HCL function, mark_glob_as_read(pattern), which expands a glob using the same gobwas/glob syntax as filter expressions and marks every matching file as read. It returns the list of absolute paths that matched, so it composes with other expressions:
locals {
configs = mark_glob_as_read("${get_terragrunt_dir()}/config/{*.yaml,**/*.yaml}")
}** only collapses the surrounding separators when the adjacent segments are literals, so match-at-any-depth with a wildcard trailing segment is written as {*.yaml,**/*.yaml}. See the HCL reference for full pattern syntax.
This is useful when a unit reads a collection of files indirectly (for example, via run_cmd or templatefile) and you want changes to any of them to trigger the unit through reading-based filters. Calling mark_glob_as_read without the experiment enabled returns an error.
🧪 Experiments Updated
cas — Stack integration via update_source_with_cas
The cas experiment now integrates with stacks. Units and terraform blocks can set update_source_with_cas = true to use relative source paths in catalog repositories, removing the need to plumb remote Git URLs through values expressions.
# stacks/my-stack/terragrunt.stack.hcl (in your catalog repository)
unit "service" {
source = "../..//units/my-service"
update_source_with_cas = true
path = "service"
}During stack generation, Terragrunt rewrites these relative sources to cas:: references that resolve against content stored in the CAS. The repository is cloned once, and subsequent stack generations resolve content from the local store without network access. Generated .terragrunt-stack files contain deterministic CAS references, so regeneration does not produce spurious diffs.
CAS also supports SHA-256 repositories now, detected automatically via git rev-parse --show-object-format. The on-disk store layout was reorganized into blobs/ and trees/ namespaces under ~/.cache/terragrunt/cas/store/.
To learn more, see the CAS documentation and Explicit Stacks: CAS Integration.
catalog-redesign — Templates and .terragrunt-catalog-ignore
The catalog-redesign experiment picked up user-visible improvements to discovery and filtering.
Discovery walks the entire repository instead of only a modules/ directory, so modules and templates can live anywhere in the tree. Boilerplate templates (directories containing a .boilerplate/ subdirectory or a top-level boilerplate.yml) are discovered as a distinct component kind alongside OpenTofu/Terraform modules and labeled as templates in the UI. When a directory qualifies as both, it is classified as a template.
Catalog authors can commit a .terragrunt-catalog-ignore file at the repo root to keep directories such as examples/ or test/ out of discovery. The file uses .gitignore-style semantics: one pattern per line, # for comments, ! for negation, and last match wins. Matching is anchored at the repo root; a lone * does not cross /, and ** does.
# .terragrunt-catalog-ignore
examples
examples/**
test/**
!test/keep
An --ignore-file flag (also available via TG_IGNORE_FILE) points at an additional ignore file that is layered on top of the repo's .terragrunt-catalog-ignore. The extra rules are appended under last-match-wins semantics, so the flag can either add new exclusions or re-include paths that the repo file excluded.
To learn more, see Excluding paths from discovery.
The list view is split into All, Modules, and Templates tabs, with All selected on launch so every discovered component is visible without switching views. Press tab and shift+tab to cycle between them; each tab keeps its own cursor and search filter.
stack-dependencies — Multi-level nested stack.<name>.<nested_stack>.path references
The stack-dependencies experiment already supported stack.<name>.path (a whole stack) and stack.<name>.<unit_name>.path (a unit inside a stack). It now also resolves references where the second segment is itself a nested stack, so an autoinclude block in a parent stack can target a stack that lives inside another stack:
# live/terragrunt.stack.hcl
stack "infra" {
source = "../catalog/stacks/infra"
path = "infr...v1.0.2
🐛 Bug Fixes
shared_credentials_files and other list/map backend config values were serialized incorrectly
Setting shared_credentials_files (or any other list-valued key) in the remote_state.config block produced a broken -backend-config argument:
-backend-config=shared_credentials_files=[/a/creds /b/creds]
OpenTofu and Terraform both failed to parse this. The same problem affected map-valued keys. Lists and maps are now written as single-line HCL (["/a/creds","/b/creds"] and {key="value"}), and strings inside them are quoted so embedded quotes, newlines, and tabs survive the round trip.
Thanks to @Rahul-Kumar-prog for contributing this fix!
Panic in get_repo_root() when OpenTelemetry tracing is enabled with TRACEPARENT
Running terragrunt stack generate (or any command that invoked shell commands like git rev-parse) with OpenTelemetry trace exporting enabled (TG_TELEMETRY_TRACE_EXPORTER=http) caused a nil pointer panic:
Call to function "get_repo_root" failed: panic in function implementation:
runtime error: invalid memory address or nil pointer dereference
The root cause of the panic was fixed, and telemetry codepaths have been hardened against future panics.
stack output now respects the exclude block
terragrunt stack output previously ignored the exclude block on units, attempting to fetch outputs (including directly from S3 state when using --dependency-fetch-output-from-state) for units that should have been excluded.
The fix uses Terragrunt discovery to identify excluded units before reading outputs. Excluded units are now omitted from the stack output entirely, consistent with how they are handled during stack run.
To exclude a unit from stack output, add "output" to the actions list in the exclude block:
exclude {
if = true
actions = ["plan", "apply", "destroy", "output"]
}Special action values "all" and "all_except_output" are also supported.
🧪 Experiments Added
catalog-redesign — Reworked terragrunt catalog TUI
A new catalog-redesign experiment reworks the design of the terragrunt catalog TUI.
terragrunt catalog now launches the TUI right away and runs discovery in the background instead of waiting for discovery to complete before launching the TUI. As a consequence, terragrunt catalog users with large catalogs should see significant speed improvements as they launch the terragrunt catalog TUI.
Modules now stream into the list view of the catalog as they are discovered, so you'll be able to select and use a module even if your entire catalog hasn't been discovered yet.
If catalog.urls is not configured in root.hcl, terragrunt catalog no longer errors. A welcome screen explains how to populate the catalog and can open the catalog documentation on a keypress. In addition, terraform.source values from existing units are automatically included in the set of URLs used for discovery, so users with existing units get a populated catalog pointing to other modules that can be pulled from the same module source without any additional configuration.
This experiment is subject to change, and core elements of the design are being iterated on rapidly.
To try it out, run:
terragrunt catalog --experiment catalog-redesignTo learn more, see the experiment documentation.
🧪 Experiments Updated
stack-dependencies — Cross-stack dependency support and autoinclude improvements
The stack-dependencies experiment now supports cross-stack and nested-stack dependency patterns, expanding the autoinclude block capabilities in terragrunt.stack.hcl files.
New features:
stack.<name>.pathreferences for depending on an entire stack. The DAG expands the stack into its constituent units so that all units in the stack complete before the dependent unit runsstack.<name>.<unit_name>.pathreferences for depending on a specific unit within a nested stack (fine-grained cross-stack dependencies)dependencyblocks targeting stack directories — aggregated outputs from all units in the stack are accessible asdependency.stack_name.outputs.unit_name.output_key- Partial evaluation of
local.*in autoinclude — expressions mixinglocal.*anddependency.*are partially evaluated during stack generation: locals resolve to literals while dependency references are preserved for evaluation when the unit is applied
Dependency on an entire stack:
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
}
}
}Dependency on a unit within a nested stack:
stack "networking" {
source = "../catalog/stacks/networking"
path = "networking"
}
unit "app" {
source = "../catalog/units/app"
path = "app"
autoinclude {
dependency "vpc" {
config_path = stack.networking.vpc.path
}
inputs = {
vpc_id = dependency.vpc.outputs.vpc_id
}
}
}terragrunt run --all --experiment stack-dependencies -- planTo learn more, see the experiment documentation.
⚙️ Process Updates
Install script now supports tip and test builds
The install script can now install tip builds and on-demand test builds. Three new flags are available:
--tipinstalls the latest tip build frommain--testinstalls an on-demand test build--commit <sha>installs a build for a specific commit
Downloads are verified against GPG/Cosign signatures and SHA256 checksums before installation.
Tip build notifications on referenced issues
When a tip build is produced on main for a merged PR, Terragrunt now posts a comment on any issues that PR references, linking to the build and including instructions for installing and testing it.
What's Changed
- feat: add new hclparse package in internal by @denis256 in #5816
- feat: Adding
catalog-redesignexperiment by @yhakbar in #5894 - feat: Adding types, sources and versions to catalog by @yhakbar in #5922
- feat: handling of stacks dependencies in run queue / runner pool by @denis256 in #5909
- feat: Supporting catalog with no config by @yhakbar in #5902
- feat: Supporting streaming components to the catalog by @yhakbar in #5914
- fix: Addressing #5895 review comments by @yhakbar in #5897
- fix: correct cloud-nuke config YAML keys and bump to v0.49.0 by @james00012 in #5920
- fix: Fixing panic in telemetry by @yhakbar in #5915
- fix: handling of exclusions when reading outputs by @denis256 in #5900
- fix: Use
httptestin./internal/tfto avoid issues from integration in unit tests by @yhakbar in #5925 - fix(s3): fix shared_credentials_files HCL serialization for backend config by @Rahul-Kumar-prog in #5886
- docs: Avoid indexing changelog in search by @yhakbar in #5928
- docs: Fix bash commands in "Terralith to Terragrunt" guide by @chorrell in #5904
- docs: Fix missing newline in remote_state examples by @thoreinstein in #5921
- docs: Splitting up changelog by @yhakbar in #5930
- docs: updated stack-dependencies implementation roadmap by @denis256 in #5910
- docs: Updating
v1.0.2changelog entries by @yhakbar in #5927 - docs: Updating install docs by @yhakbar in #5923
- chore: add 7-day cooldown to dependabot updates by @diofeher in #5889
- chore: Adding
vexecby @yhakbar in #5931 - chore: Adding catalog redesign fork by @yhakbar in #5896
- chore: Adding support for
vfsincasby @yhakbar in #5908 - chore: Adding tests and docs missing from #5886 by @yhakbar in #5926
- chore: Adding tip notification system by @yhakbar in #5895
- chore: bump cloud-nuke to v0.49.0 by @james00012 in #5893
- chore: coverage scripts collection simplifications by @denis256 in #5724
- chore: Dropping CAS test by @yhakbar in #5936
- chore: Expanding
lllcoverage toconfigbridgeby @yhakbar in #5834 - chore: Expanding
lllcoverage toerrorsby @yhakbar in #5833 - chore: Expanding
lllcoverage togcphelperby @yhakbar in https://githu...
v1.0.1
🧪 Experiments Added
dag-queue-display — DAG tree visualization for the run queue
A new dag-queue-display experiment renders the run queue as a dependency tree instead of a flat list, making it easier to understand execution order and dependency relationships at a glance.
$ terragrunt run --all --experiment dag-queue-display -- plan
19:06:59.108 INFO The following units will be run, starting with dependencies and then their dependents:
.
├── monitoring
╰── vpc
╰── database
╰── backend-app
╰── frontend-appTo learn more, see the experiment documentation.
slow-task-reporting — Progress reporting for long-running operations
A new slow-task-reporting experiment displays animated progress spinners for operations that take longer than 1 second, such as source downloads, Git worktree creation, and catalog repository cloning. In non-interactive environments (CI/CD, piped output), spinners are replaced with periodic INFO log lines every 30 seconds to prevent CI systems from killing jobs due to output inactivity.
$ terragrunt run --all --experiment slow-task-reporting -- plan
INFO Downloading source from git::https://github.com/example/module.git...
INFO Downloaded source from git::https://github.com/example/module.git (3.2s)To learn more, see the experiment documentation.
stack-dependencies — Dependency wiring between units in stacks
A new stack-dependencies experiment enables the autoinclude block in terragrunt.stack.hcl files, allowing units and stacks to define dependency relationships and arbitrary configuration overrides during stack generation. This implements RFC #5663.
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 run --all --experiment stack-dependencies -- planTo learn more, see the experiment documentation.
💡 Tip Added
Windows symlink warning for provider cache users
Terragrunt now warns Windows users when symlink creation fails and provider caching is enabled. OpenTofu and Terraform may silently fall back to copying provider plugins instead of symlinking, which can increase disk usage and slow down operations. For OpenTofu >= 1.12.0, the tip includes guidance on using TF_LOG=warn to detect the fallback.
Thank you to the OpenTofu team for introducing this warning to ensure that Windows users are aware of the fallback behavior.
🐛 Bug Fixes
hcl validate no longer fails on dependency.outputs references
terragrunt hcl validate previously failed with "Unsupported attribute" when a configuration referenced dependency.<name>.outputs.<key> without mock_outputs.
During validation, output resolution is skipped, but the outputs attribute was never added to the dependency evaluation context, causing any output reference to error. The fix provides a dynamic placeholder for dependency outputs (and inputs) during validation so that attribute access evaluates to unknown rather than failing. Additionally, the dependency resolution pipeline is now more resilient during validation. Dependencies with unresolvable config_path values or nonexistent targets no longer cause the entire dependency namespace to disappear from the evaluation context.
Destroy queue now displays units in correct order
Previously, the run queue display showed units in apply order even for destroy commands. The queue now correctly shows dependents before their dependencies when running destroy, matching the actual execution order.
Dependent discovery fixed in worktrees
Dependents are now correctly discovered when units are discovered in worktrees. Previously, dependent discovery could fail to find related units when operating within a git worktree.
Filter exclusions now respected in worktree sub-discoveries
Negated filters (e.g., !./catalog/** from .terragrunt-filters or --filter) are now propagated to worktree sub-discoveries used by git-based filtering (--filter-affected, --filter '[ref...ref]').
Previously, excluded source catalog units in worktrees were still discovered and parsed, causing errors when they referenced values.* or dependency.* variables without the stack generation context.
read_terragrunt_config() behavior in implicit stacks fixed
A regression introduced in v0.99.4 caused read_terragrunt_config() to fail to parse dependency blocks in external configurations during stack execution. This is fixed by resetting parsing context fields that prevented proper evaluation of dependencies in configurations read by read_terragrunt_config().
get_original_terragrunt_dir() now resolves correctly during dependency parsing
A regression introduced in v1.0.0-rc3 caused get_original_terragrunt_dir() to return the dependent directory instead of the dependency's directory when parsing dependency configurations from a unit.
This broke configurations where a dependency's read_terragrunt_config() chain relied on get_original_terragrunt_dir() to locate sibling files. The fix introduces a dedicated WithDependencyConfigPath method that correctly resets the original config path when parsing a dependency as an independent unit.
Chained dependency with exposed include conversion fixed
Chaining dependencies with exposed includes no longer produces a spurious "Could not convert include to the execution ctx to evaluate additional locals" error during partial parsing.
Provider cache fixed on Windows for remote URLs
The provider cache failed on Windows with CreateFile https://...: The filename, directory name, or volume label syntax is incorrect because remote download URLs were passed to os.Stat, and the colon in https: is invalid Windows path syntax. The fix skips the filesystem existence check when the download URL is a remote URL (://), going directly to the download path.
Additional transient network errors now retried automatically
Added retry patterns for provider resolution and registry connection failures commonly seen in CI environments, including TLS handshake timeouts, TCP connection resets, context deadline exceeded errors, and failed discovery document requests. These cover both Terraform and OpenTofu provider workflows.
File copy performance improved
Terragrunt now streams data from source files to target files more often by replacing some instances where files were read into memory in their entirety and written to a target file. This results in improved performance when copying files and reduced memory footprint.
⚙️ Process Updates
Tip builds now available from main
Every successful CI run on the main branch now automatically produces tip build binaries with signed checksums for all supported platforms (Windows and macOS binaries are not codesigned in tip builds). These builds are accessible via the builds API at https://builds.terragrunt.com — see the releases process documentation for API endpoints and usage examples. Maintainers can also trigger on-demand test builds from any branch using the test-build.yml workflow.
Concurrency limits now respect GOMAXPROCS
All internal concurrency limits now use runtime.GOMAXPROCS(0) instead of runtime.NumCPU(). This means Terragrunt correctly honors the GOMAXPROCS environment variable and container CPU quotas (e.g., cgroups), resulting in better behavior in resource-constrained environments like Kubernetes pods and CI runners with CPU limits.
AWS SDK updated to v1.41.5
The aws-sdk-go-v2 dependency has been updated to v1.41.5.
Terragrunt Scale documentation added
A new Terragrunt Scale section has been added to the docs, covering Pipelines, Drift Detection, and Patcher with brief overviews and links to the full Gruntwork documentation.
What's Changed
- feat: experiment for reporting long running tasks by @denis256 in #5730
- feat: add stack dependencies experiment by @denis256 in #5809
- fix: Fixing #5624 by @yhakbar in #5766
- fix: Fixing #4153 by @yhakbar in #5746
- fix: Fixing macOS linting by @yhakbar in #5775
- fix: Refactoring unit display in runs for better communication by @yhakbar in #5752
- fix: Discover dependents in worktrees if units are discovered there by @yhakbar in #5763
- fix: provider cache path handling in Windows by @denis256 in #5788
- fix: Adding Windows symlink tip by @yhakbar in #5778
- fix: Addressing test flakes for
TestReadTerragruntConfigDependencyInStackby @yhakbar in #5781 - fix: Fixing generation in stacks that read files by @yhakbar in h...
alpha-2026040801
⚠️ Alpha Release
Prototype implementation of stack dependencies
RFC: #5663
What's Changed
- chore: Adding tests to confirm #4395 is resolved by @yhakbar in #5761
- fix: Fixing #5624 by @yhakbar in #5766
- docs: Adding
v1.0.0callout by @yhakbar in #5768 - fix: Fixing #4153 by @yhakbar in #5746
- docs: Updating GTM tag by @yhakbar in #5769
- fix: Fixing macOS linting by @yhakbar in #5775
- docs: Fixing search by @yhakbar in #5776
- fix: Refactoring unit display in runs for better communication by @yhakbar in #5752
- chore: updated aws-sdk-go-v2 to 1.41.5 by @denis256 in #5771
- fix: Discover dependents in worktrees if units are discovered there by @yhakbar in #5763
- docs: Fixing strict controls by @yhakbar in #5782
- docs: Fixing up changelog implementation by @yhakbar in #5784
- chore: disabled tmpfs usage in GHA by @denis256 in #5787
- Disable vercel skew protection by @karlcarstensen in #5789
- fix: provider cache path handling in Windows by @denis256 in #5788
Full Changelog: v1.0.0...alpha-2026040801
v1.0.0
🎉 v1.0.0 Release
Terragrunt is now v1!
This means that Terragrunt will no longer have any breaking changes in minor releases, with all future breaking changes taking place in (infrequent) future major releases.
For a list of guarantees that will be observed by maintainers for the duration of Terragrunt 1.0, see the Terragrunt 1.0 Guarantees page in the docs.
🛠️ Breaking Changes
Consistent .terragrunt-cache directory generation
Terragrunt now creates a .terragrunt-cache directory for every run, regardless of whether the terragrunt.hcl file defines a terraform block with a source attribute.
This change improves consistency across all Terragrunt executions, as OpenTofu/Terraform will now always run within the .terragrunt-cache directory. This standardized behavior simplifies troubleshooting and makes the execution model more predictable.
Note
If you currently depend on hidden files located in units to be available in your cache directory, use the include_in_copy attribute of the terraform block.
Removal of tflint
Terragrunt has been shipping with a version of tflint compiled into the binary to allow for more convenient usage without installing tflint directly. However due to the adoption of a BUSL license in tflint, the version included in Terragrunt was frozen.
The dependency on tflint is now fully removed from Terragrunt. If you want to call tflint using a before_hook using Terragrunt, you will have to have tflint installed locally to do so.
To reduce the burden of this breaking change, Terragrunt will continue to provide conveniences like automatically running tflint init on behalf of users, although it no longer ships with a compiled version of tflint in the terragrunt binary.
To learn more, read the documentation on the integration with tflint.
Discovery commands discover hidden configurations by default
The find and list commands now discover units/stacks in hidden directories by default (this previously required usage of the --hidden flag), notably this now discovers .terragrunt-stack directories by default. The commands also now support an opt-in --no-hidden flag to avoid discovery in hidden directories.
The --hidden flag has been deprecated, and will not be removed in 1.0. Using the flag no longer does anything.
render --format=json no longer discovers dependents by default
Prior to this release, the render --format=json command would automatically start to perform dependent discovery on other units related to the unit being rendered. Avoiding this required usage of the --disable-dependent-modules flag. That behavior has been removed. HCL and JSON rendering of unit configurations will now proceed without the additional overhead of dependent discovery by default.
This functionality is better served by a combination of find and graph-based filters.
e.g. If you want to detect all the dependents of a given unit foo, expecting to find the dependent unit bar you can run the following:
$ terragrunt find --filter '...^foo'
barIf you aren't familiar with filters, this reads as "find all dependents of foo, not foo itself"
Windows compatibility in file paths improved
All HCL functions now return operating system native file paths without forward slash normalization.
get_terragrunt_dir()get_original_terragrunt_dir()get_parent_terragrunt_dir()get_path_from_repo_root()get_path_to_repo_root()find_in_parent_folders()path_relative_to_include()path_relative_from_include()
If you and your team do not work in Windows environments, you are unlikely to see any change as a consequence of this. If you do use Terragrunt in a Windows environment, Terragrunt will now return appropriate Windows file paths, with backslashes as file path separators instead of Unix-like forward slashes.
If you need to normalize paths, you can use the replace function to achieve this.
# root.hcl
remote_state {
backend = "s3"
generate = {
path = "backend.tf"
if_exists = "overwrite_terragrunt"
}
config = {
bucket = "my-tofu-state"
key = "${replace(path_relative_to_include(), "\\", "/")}/tofu.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "my-lock-table"
}
}Ambiguous unit/stack components now throw errors
Previously, Terragrunt would silently engage in undefined behavior when both a terragrunt.hcl and terragrunt.stack.hcl file existed in the same directory.
With this release, Terragrunt will start to throw warnings and prevent such usage. Users will have to ensure that only one of a unit (terragrunt.hcl) or stack configuration (terragrunt.stack.hcl) exist in a unit or stack directory, respectively.
✨ New Features
Tips added
Terragrunt will now provide helpful tips when it detects usage patterns that might benefit from some additional guidance.
You can disable the display of tips at any time using --no-tips or disable individual tips with --no-tip, (e.g. --no-tip=debugging-docs).
--report-file support for single runs
The --report-file will now generate reports even when runs are performed without the --all flag.
Improved error messages for undefined flags
Detection has been added for scenarios when a user is using a flag that might be meant to be passed to OpenTofu/Terraform in the run command, and suggests using the -- argument to pass it through.
As an example:
$ terragrunt run providers lock -platform linux_amd64 -platform darwin_arm64
14:52:19.496 ERROR flag `-platform` is not a Terragrunt flag. If this is an OpenTofu/Terraform flag, use `--` to forward it (e.g., `terragrunt run -- <command> -platform`).🏎️ Performance Improvements
Discovery performance improved
The way in which Terragrunt discovers and filters units and stacks for runs has improved significantly.
Terragrunt is now better at avoiding parsing units/stacks unnecessarily, based on the filter you use. Previously, the logic used was more coarse, and could result in a requirement to parse some configurations (e.g. presence of a dependency graph expression) to result in parsing all configurations. Discovery has been refactored to allow for much more careful opt-in parsing based on the need to support the filter used by users (or lack thereof).
This will also result in improvements to Terragrunt's ability to ignore broken parts of infrastructure estates when Terragrunt can predictably determine that it won't impact a run.
EncodeSourceVersion execution sped up
The performance of EncodeSourceVersion has been improved by utilizing SkipDir to optimize directory traversals.
Special thanks to @healthy-pod for contributing this improvement!
Provider Cache Server used for fetching outputs from dependencies
The Provider Cache Server is now used when fetching outputs from dependencies, improving performance of output resolution for users using the provider cache server.
🐛 Bug Fixes
Improved filter parsing errors
Parsing errors returned when invalid filter queries are used with --filter have been improved to provide more detailed error messages and actionable recommendations.
Retries added for registry timeouts in provider cache server
The Provider Cache Server will now perform automatic retries on timeouts to OpenTofu/Terraform provider registries.
Discoverability of init-from-module documentation improved
The special internal init-from-module command referenced in hooks has had its documentation improved to make it easier to discover. It was difficult to find in the terraform HCL block documentation, and that resulted in confusion for users.
Over-warning on strict controls prevented
Using --strict-mode resulted in over-warning on completed controls. Those warnings will no longer appear when using strict mode.
Stdout/stderr from run_cmd emitted when included
A bug prevented the run_cmd HCL function from emitting to stdout/stderr when included by a unit. That bug has been fixed.
Provider Cache Server integration with custom registries fixed
The Provider Cache Server now properly integrates with custom registries. You will still need to use the --provider-cache-registry-names flag to ensure that the Provider Cache Server properly handles proxying requests to the custom provider registry.
The no_run attribute of exclude is fixed
A bug prevented the no_run attribute of the exclude block from being respected when being explicitly set to false (as opposed to not being defined at all). This bug has been fixed.
The --report-file is now respected for single runs
The --report-file will now generate reports even when runs are performed without the --all flag.
Path manipulation removed from log messages
Log messages no longer have paths updated automatically. This caused confusion for users when seeing OpenTofu/Terraform stdout and hook stdout emitted through logs, as paths were unconditionally updated to be relative to the unit path. This logic has been m...
v0.99.5
🐛 Bug Fixes
--working-dir interaction with exit codes fixed
A bug in the logic for tracking exit codes for plan -detailed-exitcode when users supply the --working-dir flag has been fixed.
Authentication during queue construction fixed
A bug in the logic for parsing configurations during discovery for use-cases like --filter 'reading=*' where configurations need to be parsed to determine whether or not they end up in the final run queue has been fixed. Configurations will now properly call any configured --auth-provider-cmd authenticator before parsing configurations, preventing errors for HCL functions like sops_decrypt_file that require authentication.
What's Changed
Full Changelog: v0.99.4...v0.99.5
alpha-2026032001
⚠️ Alpha Release
Alpha release including WIP work to fix the combination of sops_decrypt_file + --auth-provider-cmd + --filter 'reading=' from the following PR:
#5722
What's Changed
- docs: Fix 'move' to 'moved' block in documentation by @hashlash in #5661
- Fix theme light/dark by @karlcarstensen in #5669
- Hide switcher in hamburger menu by @karlcarstensen in #5668
- Fixing button by @karlcarstensen in #5667
- bug: handling of tofu extensions by @denis256 in #5675
- chore: cosign v4 upgrade by @denis256 in #5676
- chore: dead code removal by @denis256 in #5683
- docs: Fix typo in overview documentation by @BenjaminHerbert in #5666
- chore(deps): bump jdx/mise-action from 3.6.2 to 3.6.3 by @dependabot[bot] in #5678
- docs: Updating docs dependencies by @yhakbar in #5686
- chore: Multiple dependencies bump by @denis256 in #5673
- docs: Breaking down features by @yhakbar in #5684
- chore: go-getter upgrade 1.8.5 by @denis256 in #5691
- chore: Removing explicit mise cache by @yhakbar in #5694
- bug: fixed bootstrap and use_lockfile by @denis256 in #5665
- chore: addressing PR #5665 feedback by @denis256 in #5696
- chore(deps): bump mikepenz/action-junit-report from 6.1.0 to 6.3.1 by @dependabot[bot] in #5697
- chore(deps): bump actions/download-artifact from 8.0.0 to 8.0.1 by @dependabot[bot] in #5698
- fix: Fixing provider cache lock file corruption by @yhakbar in #5692
- chore(deps): bump jdx/mise-action from 3.6.3 to 4.0.0 by @dependabot[bot] in #5699
- chore: Adding
terragrunt-infrastructure-live-stacks-exampletest by @yhakbar in #5703 - bug: worktree fixes for read_terragrunt_config by @denis256 in #5682
- chore: Moving permissions down to job level when possible by @yhakbar in #5705
- chore: Pinning workflows further by @yhakbar in #5704
- chore(deps): bump google.golang.org/grpc from 1.79.2 to 1.79.3 by @dependabot[bot] in #5708
- chore: Adding some testing for
logsby @yhakbar in #5641 - fix: Moving tagging to bucket creation by @yhakbar in #5706
- chore: Cleaning up shell scripts by @yhakbar in #5707
- chore: Addressing #5707 feedback by @yhakbar in #5712
- bug: windows user input fixes by @denis256 in #5710
- chore: sops upgrade to 3.12.2 by @denis256 in #5718
New Contributors
- @BenjaminHerbert made their first contribution in #5666
Full Changelog: v1.0.0-rc3...alpha-2026032001
alpha-2026031901
⚠️ Alpha Release
- Release scripts testing
What's Changed
- docs: Fix 'move' to 'moved' block in documentation by @hashlash in #5661
- Fix theme light/dark by @karlcarstensen in #5669
- Hide switcher in hamburger menu by @karlcarstensen in #5668
- Fixing button by @karlcarstensen in #5667
- bug: handling of tofu extensions by @denis256 in #5675
- chore: cosign v4 upgrade by @denis256 in #5676
- chore: dead code removal by @denis256 in #5683
- docs: Fix typo in overview documentation by @BenjaminHerbert in #5666
- chore(deps): bump jdx/mise-action from 3.6.2 to 3.6.3 by @dependabot[bot] in #5678
- docs: Updating docs dependencies by @yhakbar in #5686
- chore: Multiple dependencies bump by @denis256 in #5673
- docs: Breaking down features by @yhakbar in #5684
- chore: go-getter upgrade 1.8.5 by @denis256 in #5691
- chore: Removing explicit mise cache by @yhakbar in #5694
- bug: fixed bootstrap and use_lockfile by @denis256 in #5665
- chore: addressing PR #5665 feedback by @denis256 in #5696
- chore(deps): bump mikepenz/action-junit-report from 6.1.0 to 6.3.1 by @dependabot[bot] in #5697
- chore(deps): bump actions/download-artifact from 8.0.0 to 8.0.1 by @dependabot[bot] in #5698
- fix: Fixing provider cache lock file corruption by @yhakbar in #5692
- chore(deps): bump jdx/mise-action from 3.6.3 to 4.0.0 by @dependabot[bot] in #5699
- chore: Adding
terragrunt-infrastructure-live-stacks-exampletest by @yhakbar in #5703 - bug: worktree fixes for read_terragrunt_config by @denis256 in #5682
New Contributors
- @BenjaminHerbert made their first contribution in #5666
Full Changelog: v1.0.0-rc3...alpha-2026031901
alpha-2026031001
⚠️ Alpha Release
- Cosign v4 signing test
What's Changed
- docs: Fix 'move' to 'moved' block in documentation by @hashlash in #5661
- Fix theme light/dark by @karlcarstensen in #5669
- Hide switcher in hamburger menu by @karlcarstensen in #5668
- Fixing button by @karlcarstensen in #5667
Full Changelog: v1.0.0-rc3...alpha-2026031001
