Skip to content

chore(deps): update dependency gruntwork-io/terragrunt to v1 (terragrunt)#837

Open
renovate[bot] wants to merge 1 commit into
mainfrom
renovate/terragrunt-gruntwork-io-terragrunt-1.x
Open

chore(deps): update dependency gruntwork-io/terragrunt to v1 (terragrunt)#837
renovate[bot] wants to merge 1 commit into
mainfrom
renovate/terragrunt-gruntwork-io-terragrunt-1.x

Conversation

@renovate
Copy link
Copy Markdown
Contributor

@renovate renovate Bot commented Mar 31, 2026

ℹ️ Note

This PR body was truncated due to platform limits.

This PR contains the following updates:

Package Update Change
gruntwork-io/terragrunt major v0.83.0v1.0.7

Release Notes

gruntwork-io/terragrunt (gruntwork-io/terragrunt)

v1.0.7

Compare Source

✨ New Features

tfr:// source URLs accept an optional version

The version query parameter on tfr:// source URLs is now optional. When omitted, Terragrunt queries the registry's list-versions endpoint and downloads the latest stable version, matching how OpenTofu and Terraform resolve a module reference that has no version constraint.

terraform {
  source = "tfr:///terraform-aws-modules/vpc/aws"
}

Prereleases are excluded from resolution, so a registry that only publishes 4.0.0-rc1 alongside 3.3.0 will pin to 3.3.0. Pin a version explicitly with ?version= when you need reproducible builds or want to opt into a prerelease.

Thanks to @​raman1236 for contributing this feature!

🐛 Bug Fixes

update_source_with_cas: preserve //subdir on a unit's terraform.source

When a unit's terraform.source used the // subdir convention (for example, source = "../..//modules/foo") and opted into update_source_with_cas, the rewritten source dropped the //subdir tail and the synthetic tree contained only the leaf module's files. A module that referenced a sibling via a relative path (source = "../bar") could not resolve that reference after materialization.

Rewrites now preserve the original //subdir (for example, cas::sha1:<hash>//modules/foo), and the synthetic tree is rooted at the path before //, so sibling files reachable via relative paths land in the materialized working directory.

Sources without // are unchanged: the tree stays scoped to the leaf module, and the rewritten reference has no //subdir tail.

--filter now detects affected units on Windows

On Windows, terragrunt find --filter '[origin/main...HEAD]' (and its variants) returned no affected units even when git diff reported changed files. The source= and reading= filters were affected by the same problem.

Filter glob patterns are always written with forward slashes, but the affected-unit comparison was being made with Windows backslash separators, so nothing matched. Terragrunt now compares paths consistently with forward slashes on every platform, and the filter detects changed units on Windows as it already did on Linux and macOS.

Reported in #​6214.

startswith, endswith, strcontains, and run_cmd no longer panic on malformed calls

Calling startswith, endswith, or strcontains with the wrong number of arguments (for example a single argument instead of two) crashed Terragrunt instead of reporting a configuration error. Calling run_cmd with only option flags and no command (for example run_cmd("--terragrunt-quiet")) crashed the same way.

These calls now return a clear error: a wrong-number-of-parameters error for the string functions, and an empty-command error for run_cmd.

The --parallelism flag no longer accepts non-positive numbers

Previously, terragrunt commands that accept the --parallelism flag (or equivalently the $TG_PARALLELISM environment variable) used to hang indefinitely when invoked with --parallelism=0.

Terragrunt now validates that the value is positive and exits with an error otherwise.

Reported in #​6211

🧪 Experiments Updated

cas — content-addressing for non-git sources

CAS now covers module sources beyond git: http(s), Amazon S3, Google Cloud Storage, and Mercurial. Repeat runs against an unchanged remote reuse the cached tree instead of downloading the bytes again.

Before fetching, CAS issues a cheap remote probe (an HTTP HEAD, an S3 object-attributes lookup, a GCS metadata read, or hg identify) to derive a cache key without pulling the source. On a hit, the cached tree is linked directly; on a miss, or when the remote exposes no usable signal, CAS downloads the source, ingests it, and keys the resulting tree by its content hash. A remote that publishes a new version under the same address pins to a new entry, so a stale cache cannot serve outdated bytes.

cas — OpenTofu/Terraform registry sources

Module sources of the form tfr://... are now content-addressed in CAS. Repeat runs against the same pinned registry version reuse the cached module instead of re-downloading the archive from the registry.

CAS resolves a tfr:// source by asking the registry where the underlying archive lives and uses that resolved URL as the cache key. Two runs that pin the same version share one entry; a republish under the same version pins to a new entry, so a stale cache cannot serve outdated bytes.

stack-dependencies: unit.<name>.path and stack.<name>.path resolve in values

The stack-dependencies experiment now exposes unit.<name>.path and stack.<name>.path when evaluating the values attribute of a unit or stack block, not only inside autoinclude blocks. A parent stack can pass the generated path of a sibling component down into a child stack, so a unit nested in that child stack can depend on a unit that lives at a different level of the hierarchy.

unit "vpc" {
  source = "../catalog/units/vpc"
  path   = "vpc"
}

stack "app" {
  source = "../catalog/stacks/app"
  path   = "app"

  values = {
    vpc_path = unit.vpc.path
  }
}

A unit inside the app stack reads values.vpc_path and uses it as the config_path of an autoinclude dependency, wiring the cross-level relationship at generation time. Paths follow the same layout the generator produces, including no_dot_terragrunt_stack on the referenced block.

stack-dependencies: simplified unit.* / stack.* ref shape

The stack-dependencies experiment no longer resolves stack.<name>.<unit_name>.path or stack.<name>.<nested_stack>.path. Only the top-level stack.<name>.path and unit.<name>.path forms remain. stack.<name>.name and unit.<name>.name are gone too; both only ever echoed the label that the reference already had to spell out.

Nested references required parsing every nested catalog up front and conflicted with the reserved name and path attributes on each ref: a nested unit named name or path could not be addressed.

To depend on a generated unit inside a stack, compute the path as ${stack.<name>.path}/<unit-relative-path> directly. The layout under a stack's generated directory follows no_dot_terragrunt_stack on the parent stack and on each unit, so hand-computed paths must mirror that resolution.

stack-dependencies: .terragrunt-stack-origin no longer written

Terragrunt no longer writes the .terragrunt-stack-origin file when generating nested stacks. Set update_source_with_cas = true on your unit and stack blocks if you would like relative paths in your catalog to resolve correctly instead.

Pull Requests

✨ Features
🐛 Bug Fixes
📖 Documentation
🧹 Chores

v1.0.6

Compare Source

🐛 Bug Fixes

terragrunt no longer hangs when download_dir is a non-hidden subdirectory of the unit

Setting download_dir (via the attribute, --download-dir, or TG_DOWNLOAD_DIR) to a subdirectory of the unit's working directory whose name did not start with a dot caused commands that prepare the OpenTofu or Terraform source (apply, plan, run, and similar) to hang.

For example:

# /infra/web/terragrunt.hcl
download_dir = "cache"

terraform {
  source = "./mod"
}

Here terragrunt apply would copy ./mod into cache/, see the new cache/ directory on the next read of the unit, and recurse into it. The default .terragrunt-cache was unaffected because Terragrunt's source-copy step skips any directory whose name starts with a dot.

These configurations now produce an immediate error identifying the source and destination paths.

mark-many-as-read experiment now triggers during discovery

With the mark-many-as-read experiment enabled, a unit whose terraform { source = ... } pointed at a local module did not show up under --filter 'reading=' filters that referenced files inside that module. Discovery would parse the unit, but the module files were never recorded as read, so the reading filter attribute could not match and the queue came back empty.

The module walk now runs on the discovery code path as well, so changes to files in a local module source flow through to the units that depend on them.

terragrunt render no longer crashes on exclude or catalog blocks with certain attributes

Rendering a config crashed with a value has no attribute of that name panic before any output could be produced when:

  • the exclude block set no_run, or
  • the catalog block set default_template, no_shell, or no_hooks.

These attributes are now carried through the render pipeline alongside the other fields on their respective blocks, so both blocks round-trip cleanly.

terragrunt render no longer crashes on multiple errors.ignore blocks with mismatched signals

Rendering a config that defined more than one errors.ignore block crashed with an inconsistent list element types panic when the signals map was populated on one block and absent (or differently typed) on another. The same crash showed up in dependency-output evaluation, since both paths build the same rendered representation of the config.

Each ignore block is now rendered with a uniform shape. Indexed access (errors.ignore[0]), length, and iteration still work, and the signals map on each block is preserved as written.

Suppress spurious Unknown variable: dependency errors during dependency resolution

terragrunt plan and apply no longer print ERROR Error: Unknown variable "dependency" lines when a unit pulls in a shared include (e.g. via find_in_parent_folders) that references dependency.* outputs. The plans completed correctly, but the error lines cluttered CI logs.

Resolves #​6036.

terragrunt stack commands no longer crash on stacks with multiple units

Running terragrunt stack output (or any command that resolves concurrently parsing multiple configuration files) against a stack with several units could intermittently crash while the units were being parsed in parallel due to a race on internal bookkeeping of files read (used in the reading filter attribute).

Parallel unit parsing now coordinates safely when recording which source files were read, preventing crashes.

terraform_binary properly respected when both tofu and terraform are on PATH

A regression in command execution caching resulted in over-caching the STDOUT result of tofu --version when both tofu and terraform were available on PATH and terraform_binary was set. Early on in the execution flow, Terragrunt checks if OpenTofu is installed what its version is to determine if it supports setting of the automatic provider cache directory. This resulted in the value of terraform_binary being ignored for later version checks to assess compliance with terraform_version_constraint.

The version-detection cache used per run is now scoped to the binary that produced each entry, so the version recorded against an early default-binary resolution no longer leaks into the later resolution that honors terraform_binary.

🧪 Experiments Added

deep-merge experiment adds a deep_merge HCL function

Enable the new deep-merge experiment to use the deep_merge(map1, map2, ...) HCL function.

deep_merge recursively merges map and object values. Later arguments override earlier arguments for overlapping keys, nested maps are merged recursively, lists are appended, and null arguments are ignored.

This is useful when composing inputs from multiple decoded JSON, YAML, or HCL-derived maps:

locals {
  config_json_files = sort(fileset(get_terragrunt_dir(), "*.json"))
  config = deep_merge([
    for file in local.config_json_files :
    jsondecode(file("${get_terragrunt_dir()}/${file}"))
  ]...)
}

inputs = local.config

Calling deep_merge without enabling the deep-merge experiment returns an error.

opt-out-auth — Opt out of --auth-provider-cmd during discovery

Enable the new opt-out-auth experiment to use --no-discovery-auth-provider-cmd (env: TG_NO_DISCOVERY_AUTH_PROVIDER_CMD), which disables the auth provider command during the discovery phase.

Without the flag, Terragrunt assumes that --auth-provider-cmd must be run per parsed component during the discovery phase so that it can reliably resolve HCL functions such as get_aws_account_id and run_cmd. On large repositories with run --all --filter='reading=', this dominates wall-clock time because the auth command runs for every discovered unit rather than only the subset that will run.

The --no-discovery-auth-provider-cmd flag turns off auth invocations during discovery. The auth provider command still runs normally when running units.

Units whose discovery-relevant blocks depend on credentials produced by --auth-provider-cmd will fail to parse with the flag set. Use it when you know that parsing will resolve successfully without any authentication done beforehand by Terragrunt.

While this flag is experimental, you must also opt-in to the opt-out-auth experiment by setting the TG_EXPERIMENT environment variable to opt-out-auth or by passing the --experiment=opt-out-auth flag to terragrunt run. This flag might experience breaking changes based on community feedback for the duration of the experiment.

e.g.

terragrunt run --all \
  --experiment=opt-out-auth \
  --no-discovery-auth-provider-cmd \
  --queue-include-units-reading=./changed-file.txt \
  plan

🧪 Experiments Updated

catalog-redesign — Interactive scaffold form on s

Pressing s from the catalog list or detail view now opens an in-TUI form that prompts for every variable/value the selected component exposes. The form is modal: in navigate mode j and k (or the arrow keys) move between fields and enter interacts with the focused one. Required entries are flagged, and optional entries show their default in a muted style until the user opts in.

enter on a text or HCL field switches the form into edit mode. Typing edits the value in place; esc returns to navigate. Only fields the user actually changes get written to the generated file, and optional defaults stay implicit, so the result is leaner than the placeholder flow.

enter on a boolean field toggles between [x] true and [ ] false directly, without a separate edit mode.

x on an optional field marks it "use default" again, removing any in-progress value and leaving the source's default to apply.

Complex types (lists, maps, objects) accept raw HCL and are validated before the file is written, so a typo surfaces inline rather than producing a broken terragrunt.hcl or terragrunt.values.hcl file.

ctrl+d finishes the form. Required fields the user never set still write as # TODO: fill in value so the rest of the file is usable.

S (capital) keeps the previous placeholder-only flow, generating the same TODO-laden file as before for users who prefer to populate values by editing the generated file.

stack-dependencies: parser tolerates HCL expressions throughout terragrunt.stack.hcl

The stack-dependencies experiment now defers evaluation of source, path, values, and include.path until each unit or stack block is parsed on its own. As a result, autoinclude resolution during stack generation and run --all discovery no longer fall over when other parts of a stack file use Terragrunt functions, local.*, or values.*. A few adjacent behaviors are tightened up at the same time.

Autoinclude resolves even when sibling units use expressions.

Before 1.0.6, if any unit in a stack file used a function call or a local.* / values.* reference in source, path, or values, generating an autoinclude on a different unit in the same file could fail. The parser now leaves those expressions alone until they're needed, so an unrelated unit can carry an autoinclude block without being blocked by its neighbors:

locals {
  shared_region = "us-east-1"
}

unit "account" {
  source = "${get_terragrunt_dir()}/../catalog/units/account"
  path   = "account"
  values = {
    account = values.account
    region  = local.shared_region
  }
}

unit "roles" {
  source = "${get_terragrunt_dir()}/../catalog/units/roles"
  path   = "roles"

  autoinclude {
    dependency "account" {
      config_path = unit.account.path
    }
  }
}

include blocks in terragrunt.stack.hcl accept computed paths.

The path attribute on an include block can be an HCL expression, not just a string literal. An autoinclude block in the included file is resolved normally after the include merges in:

include "shared" {
  path = find_in_parent_folders("shared.stack.hcl")
}

What's Changed

New Contributors

Full Changelog: gruntwork-io/terragrunt@v1.0.5...v1.0.6

v1.0.5

Compare Source

✨ New Features

Full .terraform.lock.hcl files from the provider cache server

When the provider cache server is used against the OpenTofu provider registry, Terragrunt now writes .terraform.lock.hcl files containing h1: hashes for every platform the registry supports. A single terragrunt init produces a lock file that works on every platform, removing the need to run tofu providers lock -platform=... separately for each target architecture.

provider "registry.opentofu.org/hashicorp/null" {
  version     = "3.2.2"
  constraints = "3.2.2"
  hashes = [
    "h1:+1mRmfyz6oA00IhrrSkHK3h/Mdh032x2p0F6OMdMo5s=",
    "h1:FjLTqvaaYo+vHN8pHZB1cOwEGiNzOj+I9kQyHmr9/7o=",
    # ... one entry per supported platform ...
    "zh:00e5877d19fb1c1d8c4b3536334a46a5c86f57146fd115c7b7b4b5d2bf2de86d",
    # ... one entry per supported platform ...
  ]
}

The hashes come from the registry's per-platform download response. When the registry does not supply them (for example, a third-party registry that has not adopted the field), Terragrunt falls back to its previous behavior of writing an h1: hash for the current platform plus zh: hashes for every platform listed in the shasums document.

[!TIP]
Thanks to the OpenTofu team

This feature builds on work done by the OpenTofu team to expose per-platform hashes directly from the OpenTofu provider registry. Starting with OpenTofu 1.12, tofu init populates .terraform.lock.hcl with hashes for every supported platform out of the box, with no tofu providers lock invocation required. Users on older OpenTofu versions still get the same lock files when running through Terragrunt's provider cache server, but upgrading to 1.12 is the easiest way to get the same behavior everywhere, including when using the automatic provider cache dir.

🏎️ Performance Improvements

stack output fetches unit outputs in parallel

terragrunt stack output now fetches outputs from multiple units at the same time, which is noticeably faster on larger stacks. Use the existing --parallelism flag (or TG_PARALLELISM) to lower concurrency if you need to.

terragrunt stack output --parallelism 4

💡 Tips Added

Stack-target hint when --filter is missing | type=stack

run and stack generate now emit a tip when a --filter path resolves to a directory containing terragrunt.stack.hcl but the filter is not restricted to stacks. Without | type=stack, stack generate ignores the filter and run does not generate that stack.

The tip prints the offending filter, the suggested rewrite, and a link to the filter docs. Suppress it with --no-tip stack-target-missing-type-stack or --no-tips.

🐛 Bug Fixes

Auth provider command returning null no longer crashes Terragrunt

If the command configured via --auth-provider-cmd wrote the JSON value null to stdout, Terragrunt crashed with a nil pointer dereference before it could obtain credentials.

A null response is now treated as an empty response: no environment variables and no credentials are applied, and the run continues.

Auto-init now re-runs after a source change when modules are already cached

terragrunt plan/apply could fail with Error: Required plugins are not installed after a source-version change in any unit with a module "" block. The .terragrunt-init-required marker written on source change was being ignored because modulesNeedInit short-circuited as soon as .terraform/modules/ existed.

The marker check now lives at the top of needsInitRunCfg and is honored regardless of cached .terraform/modules/ contents.

Thanks to @​arnaud-dezandee for contributing this fix!

--download-dir is now respected through dependency blocks and read_terragrunt_config

A custom download directory set via --download-dir (or TG_DOWNLOAD_DIR) was honored for the unit being run, but lost as soon as parsing crossed into another config. dependency blocks and read_terragrunt_config() would fall back to the dependency's local .terragrunt-cache next to its terragrunt.hcl, ignoring the user-set path.

TG_DOWNLOAD_DIR=/tmp/tg-cache terragrunt run --all plan

# Root unit: outputs landed in /tmp/tg-cache ✓
# Dependency outputs: written next to each dependency's terragrunt.hcl ✗

When the parsing context switches to a new config path, the download directory is now updated only if it still points at the previous module's default location. A user-supplied path never matches any module's default and is carried through every dependency hop unchanged.

Thanks to @​maonat for contributing this fix!

remote_state — apply tags during DynamoDB lock table creation

Terragrunt previously applied dynamodb_table_tags to DynamoDB lock tables after table creation rather than during the initial CreateTable API request.

This caused failures in environments enforcing required AWS resource tags through SCPs or tag policies, where tags must be present at resource creation time.

Terragrunt now includes dynamodb_table_tags in the initial DynamoDB table creation request during remote state bootstrap.

remote_state {
  backend = "s3"

  config = {
    bucket         = "my-state-bucket"
    dynamodb_table = "terraform-locks"

    dynamodb_table_tags = {
      Environment = "prod"
      Team        = "platform"
    }
  }
}

Thanks to @​Rahul-Kumar-prog for contributing this fix!

Engine archive extraction rejects path-traversal entries

When Terragrunt extracted an engine archive while the engine experiment was active, entries whose target path resolved outside the extraction directory were not rejected correctly. Such an entry could overwrite files anywhere the Terragrunt process could write.

These entries are now rejected early with a descriptive error before any bytes are written. Engine archives produced by Gruntwork were never affected; the gap only mattered for a tampered or untrusted archive.

Thanks to @​jackiesre721 for reporting this!

--filter combined with a negation no longer parses excluded units

When a positive path filter was combined with a negated one, Terragrunt classified any unit that matched neither expression as requiring defensive parsing before exclusion instead of being excluded early.

e.g.

$ terragrunt run --all --filter './foo' --filter '!./baz'

# If `./bar` existed on disk, it would be parsed before being excluded. This is no longer the case.

Any positive filepath filter now consistently results in units that cannot be discovered during Terragrunt discovery being excluded from parsing for evaluating candidacy of inclusion. When a sufficiently complex filter is present, like the following:

$ terragrunt run --all --filter './foo' --filter '!./baz' --filter 'reading=root.hcl'

# If `./bar` existed on disk, it will still be parsed before being excluded to determine if it reads `root.hcl`.

macOS and Windows binaries report the correct release version

The v1.0.4 macOS and Windows release binaries reported terragrunt version main and parsed as 0.0.0, breaking any terragrunt_version_constraint configured against them.

sign-macos.yml and sign-windows.yml included build jobs for standalone workflow_dispatch runs. During the release workflow, those jobs still saw the original workflow_dispatch event from release.yml, so the old condition evaluated to true. The redundant build used BUILD_VERSION=${{ github.ref_name }} and replaced the correctly versioned artifact uploaded by build.yml.

The signing workflows now skip their internal build job when invoked via workflow_call and only build when dispatched directly, so release binaries keep the version stamped by build.yml.

Fixed 403 Forbidden on nested private modules when using the provider cache server

With TG_PROVIDER_CACHE enabled, OpenTofu/Terraform sent nested module-registry lookups to the upstream registry with the cache server's API key as the bearer token, instead of the credentials configured for that host. Private registries rejected those requests:

Error: Error accessing remote module registry

Failed to retrieve available versions for module "<name>" from
<registry>: error looking up module versions: 403 Forbidden.

Terragrunt sets TF_TOKEN_<host> to the cache server's API key so the cache can front provider downloads. Module-registry requests bypassed the cache and went straight to the upstream, so the registry saw the cache key instead of the user's token.

The cache server now also fronts the modules.v1 endpoint for each configured registry. It drops the inbound cache-server bearer, looks up the user's credentials for the upstream host from the loaded CLI config (TF_TOKEN_<host>, ~/.terraform.d/credentials.tfrc.json, etc.), and forwards the request with that token.

Run report file generation no longer stalls or deadlocks with many runs

Generating a run report via --report-file could stall or deadlock when a queue contained many runs and some were still recording their final status as the report was written.

Reports now serialize each run independently, so writing a report no longer blocks status updates from runs that are still finishing.

Thanks to @​jackiesre721 for contributing this fix!

Declining a run --all or --graph confirmation no longer skips cleanup

When terragrunt run --all destroy (or --all state, --all apply, or the equivalent --graph variants) prompted for confirmation and the user answered "no", Terragrunt terminated the process directly, skipping cleanup the run had registered.

Cleanup now runs before Terragrunt exits.

s3:: and gcs:: stack sources now download

Stack file source URLs starting with s3::https:// or gcs::https:// previously failed with a credentials error even when valid credentials were available. They now download. Existing stack files need no change.

Plain https://www.googleapis.com/storage/... URLs are now intended to download anonymously without GCP credentials, but Terragrunt continues to use GCS credentials to download them for backward compatibility, emitting a deprecation warning the first time it does so. To opt into the new behavior, enable the legacy-gcs-public-prefix strict control. To pull from a private GCS bucket explicitly, prefix the URL with gcs:: yourself.

Fixed nested key order in terragrunt stack output

When a unit lived inside more than one nested stack, terragrunt stack output rendered its key with the stack names reversed, so a unit inside root_stack_3 > stack_v3 > stack_v2 appeared under stack_v2.stack_v3.root_stack_3 instead of root_stack_3.stack_v3.stack_v2. Deeply nested units also leaked to the top level of the output.

The output now joins stack names from outermost to innermost, matching the declared hierarchy in both the HCL and JSON formats.

Thanks to @​anuragrao04 for contributing this fix!

Fixed failed to create directory ...: file exists from the provider cache server

If a previous run had cached a provider by symlinking ~/.terraform.d/plugins/<provider> into Terragrunt's own provider cache, and that user plugin directory was later moved or deleted, the symlink was left dangling. The next run failed with failed to create directory ...: file exists and refused to cache the provider.

Terragrunt now removes a dangling symlink at the cache path on the next run and proceeds to download the provider. A non-symlink at that path is left in place and surfaced as an error.

🧪 Experiments Added

azure-backend — Native Azure Storage (azurerm) remote-state support

The azure-backend experiment has been added as the gate for native Terragrunt support of the Azure Storage (azurerm) remote-state backend. Once it stabilizes, Terragrunt will bootstrap, delete, and migrate Azure storage accounts and blob containers the same way it already does for S3 and GCS, and read state directly from Azure blobs for --dependency-fetch-output-from-state.

In this release the flag is reserved only. Enabling it has no behavioral effect, and remote_state { backend = "azurerm" } continues to pass through to the OpenTofu and Terraform native azurerm backend.

Track progress and share feedback in #​4307. For setup steps, see the experiment documentation.

Thanks to @​omattsson for driving this experiment forward!

🧪 Experiments Updated

CAS keeps a central Git store for incremental fetches

CAS now keeps one bare Git repository per remote URL inside its store, under ~/.cache/terragrunt/cas/store/git/ on Linux by default. See Storage for where this lives on macOS and Windows. On a cache miss, Terragrunt fetches just the requested ref into that repository instead of running a fresh shallow clone into a temporary directory. Repeated misses against the same remote reuse the existing pack files, so fetching a second ref from the same repository transfers only the new objects.

Concurrent Terragrunt runs against the same remote URL share one fetch instead of cloning in parallel; later runs reuse what the first one transferred. If the shared fetch hangs or fails, Terragrunt logs a warning and falls back to a temporary clone so cloning still succeeds.

You can reclaim space at any time by deleting the git/ subdirectory:

rm -rf ~/.cache/terragrunt/cas/store/git

cas — Commit SHAs accepted in ref=

Source URLs of the form git::<url>?ref=<commit-sha> now resolve through CAS. Previously these clones failed because Terragrunt asked the remote to look up the SHA as a symbolic reference, which Git servers don't support.

Both full SHAs (SHA-1 and SHA-256) and abbreviated SHAs are accepted. Abbreviated SHAs must disambiguate inside the repository, the same rule Git itself applies.

terraform {
  source = "git::https://github.com/acme/infrastructure-modules.git//vpc?ref=a1b2c3d4e5f67890abcdef1234567890deadbeef"
}

The first cold clone of a repository pinned to a commit SHA fetches the full history of every branch. Shallow fetches require a ref name, and fetching a commit SHA at limited depth depends on a server option (uploadpack.allowAnySHA1InWant) that is not universally enabled, so CAS fetches all branches at full depth and resolves the SHA locally. Subsequent clones reuse the cached repository and never touch the network for the same commit. Branch and tag refs continue to use the existing shallow path.

casmutable attribute on terraform, unit, and stack blocks

A new mutable attribute opts a block out of CAS hardlinking when its source is fetched through CAS. With mutable = true, files materialized into .terragrunt-cache (for terraform) or .terragrunt-stack (for unit and stack) are copied from the CAS store and the working tree is editable.

The default is false. Files are materialized read-only so an accidental edit cannot reach back into the shared CAS store.

terraform {
  source  = "git::https://github.com/acme/infrastructure-modules.git//vpc?ref=v1.0.0"
  mutable = true
}

The flag is orthogonal to update_source_with_cas and has no effect when content is fetched through the standard download path, which already produces an independent copy.

casupdate_source_with_cas now idempotent across unit and stack blocks

A terragrunt.stack.hcl with two blocks pointing at the same template directory used to fail stack generate when each block had update_source_with_cas = true. The first block's pass rewrote the shared template's source to a cas::sha256:... reference, then the second block's pass re-read the rewritten file and treated the reference as a relative path.

CAS now skips re-processing a source once it already carries the cas:: prefix, so multiple unit or stack blocks can share a template and resolve to the same synthetic tree.

cas — symlinks in the source repository

Source repositories fetched through CAS used to materialize committed symlinks as regular files whose contents were the link target path. The destination tree no longer matched the upstream layout, and any tooling that followed the link saw plain text instead.

CAS now writes a real symbolic link at the destination. Symlink targets that resolve outside the destination tree are rejected so a hostile or stale source cannot escape the working directory.

catalog-redesign — component tags

The catalog-redesign experiment now reads a tags field from the component's README.md front-matter. Tags appear as colored pills next to the component in the list view and in the detail view above the rendered README.

<!-- Frontmatter
name: VPC App
description: A VPC for application workloads.
tags: [networking, aws, module]
-->

Either inline-array or dash-list YAML form is accepted. Tags render in gray by default. When a tag matches a known component-type name (module, template, unit, or stack, case-insensitive), the pill takes on that type's color.

A tag matching a component-type name also promotes the component into that type's tab. A template whose tags include module appears under both Templates (by its native kind) and Modules (by tag), without changing how it scaffolds.

To learn more, see Component tags.

What's Changed

Note

PR body was truncated to here.


Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@szksh-lab-2-app
Copy link
Copy Markdown
Contributor

Plan Result (foo)

CI link

Plan: 1 to add, 0 to change, 0 to destroy.
  • Create
    • github_repository.example
Change Result (Click me)
  # github_repository.example will be created
  + resource "github_repository" "example" {
      + allow_auto_merge            = false
      + allow_merge_commit          = true
      + allow_rebase_merge          = true
      + allow_squash_merge          = true
      + archived                    = false
      + default_branch              = (known after apply)
      + delete_branch_on_merge      = false
      + etag                        = (known after apply)
      + full_name                   = (known after apply)
      + git_clone_url               = (known after apply)
      + html_url                    = (known after apply)
      + http_clone_url              = (known after apply)
      + id                          = (known after apply)
      + merge_commit_message        = "PR_TITLE"
      + merge_commit_title          = "MERGE_MESSAGE"
      + name                        = "test-tfaction"
      + node_id                     = (known after apply)
      + primary_language            = (known after apply)
      + private                     = (known after apply)
      + repo_id                     = (known after apply)
      + squash_merge_commit_message = "COMMIT_MESSAGES"
      + squash_merge_commit_title   = "COMMIT_OR_PR_TITLE"
      + ssh_clone_url               = (known after apply)
      + svn_url                     = (known after apply)
      + topics                      = (known after apply)
      + visibility                  = "public"
      + vulnerability_alerts        = (known after apply)
      + web_commit_signoff_required = false

      + security_and_analysis (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

@renovate renovate Bot force-pushed the renovate/terragrunt-gruntwork-io-terragrunt-1.x branch from 858eefe to 44b720c Compare April 8, 2026 18:52
@szksh-lab-2-app
Copy link
Copy Markdown
Contributor

Plan Result (foo)

CI link

Plan: 1 to add, 0 to change, 0 to destroy.
  • Create
    • github_repository.example
Change Result (Click me)
  # github_repository.example will be created
  + resource "github_repository" "example" {
      + allow_auto_merge            = false
      + allow_merge_commit          = true
      + allow_rebase_merge          = true
      + allow_squash_merge          = true
      + archived                    = false
      + default_branch              = (known after apply)
      + delete_branch_on_merge      = false
      + etag                        = (known after apply)
      + full_name                   = (known after apply)
      + git_clone_url               = (known after apply)
      + html_url                    = (known after apply)
      + http_clone_url              = (known after apply)
      + id                          = (known after apply)
      + merge_commit_message        = "PR_TITLE"
      + merge_commit_title          = "MERGE_MESSAGE"
      + name                        = "test-tfaction"
      + node_id                     = (known after apply)
      + primary_language            = (known after apply)
      + private                     = (known after apply)
      + repo_id                     = (known after apply)
      + squash_merge_commit_message = "COMMIT_MESSAGES"
      + squash_merge_commit_title   = "COMMIT_OR_PR_TITLE"
      + ssh_clone_url               = (known after apply)
      + svn_url                     = (known after apply)
      + topics                      = (known after apply)
      + visibility                  = "public"
      + vulnerability_alerts        = (known after apply)
      + web_commit_signoff_required = false

      + security_and_analysis (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

@renovate renovate Bot force-pushed the renovate/terragrunt-gruntwork-io-terragrunt-1.x branch from 44b720c to bff66e9 Compare April 13, 2026 17:01
@szksh-lab-2-app
Copy link
Copy Markdown
Contributor

Plan Result (foo)

CI link

Plan: 1 to add, 0 to change, 0 to destroy.
  • Create
    • github_repository.example
Change Result (Click me)
  # github_repository.example will be created
  + resource "github_repository" "example" {
      + allow_auto_merge            = false
      + allow_merge_commit          = true
      + allow_rebase_merge          = true
      + allow_squash_merge          = true
      + archived                    = false
      + default_branch              = (known after apply)
      + delete_branch_on_merge      = false
      + etag                        = (known after apply)
      + full_name                   = (known after apply)
      + git_clone_url               = (known after apply)
      + html_url                    = (known after apply)
      + http_clone_url              = (known after apply)
      + id                          = (known after apply)
      + merge_commit_message        = "PR_TITLE"
      + merge_commit_title          = "MERGE_MESSAGE"
      + name                        = "test-tfaction"
      + node_id                     = (known after apply)
      + primary_language            = (known after apply)
      + private                     = (known after apply)
      + repo_id                     = (known after apply)
      + squash_merge_commit_message = "COMMIT_MESSAGES"
      + squash_merge_commit_title   = "COMMIT_OR_PR_TITLE"
      + ssh_clone_url               = (known after apply)
      + svn_url                     = (known after apply)
      + topics                      = (known after apply)
      + visibility                  = "public"
      + vulnerability_alerts        = (known after apply)
      + web_commit_signoff_required = false

      + security_and_analysis (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

@renovate renovate Bot force-pushed the renovate/terragrunt-gruntwork-io-terragrunt-1.x branch from bff66e9 to 7f5c04b Compare April 21, 2026 16:43
@szksh-lab-2-app
Copy link
Copy Markdown
Contributor

Plan Result (foo)

CI link

Plan: 1 to add, 0 to change, 0 to destroy.
  • Create
    • github_repository.example
Change Result (Click me)
  # github_repository.example will be created
  + resource "github_repository" "example" {
      + allow_auto_merge            = false
      + allow_merge_commit          = true
      + allow_rebase_merge          = true
      + allow_squash_merge          = true
      + archived                    = false
      + default_branch              = (known after apply)
      + delete_branch_on_merge      = false
      + etag                        = (known after apply)
      + full_name                   = (known after apply)
      + git_clone_url               = (known after apply)
      + html_url                    = (known after apply)
      + http_clone_url              = (known after apply)
      + id                          = (known after apply)
      + merge_commit_message        = "PR_TITLE"
      + merge_commit_title          = "MERGE_MESSAGE"
      + name                        = "test-tfaction"
      + node_id                     = (known after apply)
      + primary_language            = (known after apply)
      + private                     = (known after apply)
      + repo_id                     = (known after apply)
      + squash_merge_commit_message = "COMMIT_MESSAGES"
      + squash_merge_commit_title   = "COMMIT_OR_PR_TITLE"
      + ssh_clone_url               = (known after apply)
      + svn_url                     = (known after apply)
      + topics                      = (known after apply)
      + visibility                  = "public"
      + vulnerability_alerts        = (known after apply)
      + web_commit_signoff_required = false

      + security_and_analysis (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

@renovate renovate Bot force-pushed the renovate/terragrunt-gruntwork-io-terragrunt-1.x branch from 7f5c04b to 54fb8dc Compare April 27, 2026 14:49
@szksh-lab-2-app
Copy link
Copy Markdown
Contributor

Plan Result (foo)

CI link

Plan: 1 to add, 0 to change, 0 to destroy.
  • Create
    • github_repository.example
Change Result (Click me)
  # github_repository.example will be created
  + resource "github_repository" "example" {
      + allow_auto_merge            = false
      + allow_merge_commit          = true
      + allow_rebase_merge          = true
      + allow_squash_merge          = true
      + archived                    = false
      + default_branch              = (known after apply)
      + delete_branch_on_merge      = false
      + etag                        = (known after apply)
      + full_name                   = (known after apply)
      + git_clone_url               = (known after apply)
      + html_url                    = (known after apply)
      + http_clone_url              = (known after apply)
      + id                          = (known after apply)
      + merge_commit_message        = "PR_TITLE"
      + merge_commit_title          = "MERGE_MESSAGE"
      + name                        = "test-tfaction"
      + node_id                     = (known after apply)
      + primary_language            = (known after apply)
      + private                     = (known after apply)
      + repo_id                     = (known after apply)
      + squash_merge_commit_message = "COMMIT_MESSAGES"
      + squash_merge_commit_title   = "COMMIT_OR_PR_TITLE"
      + ssh_clone_url               = (known after apply)
      + svn_url                     = (known after apply)
      + topics                      = (known after apply)
      + visibility                  = "public"
      + vulnerability_alerts        = (known after apply)
      + web_commit_signoff_required = false

      + security_and_analysis (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

@renovate renovate Bot force-pushed the renovate/terragrunt-gruntwork-io-terragrunt-1.x branch from 54fb8dc to 279d3ca Compare May 7, 2026 15:10
@szksh-lab-2-app
Copy link
Copy Markdown
Contributor

Plan Result (foo)

CI link

Plan: 1 to add, 0 to change, 0 to destroy.
  • Create
    • github_repository.example
Change Result (Click me)
  # github_repository.example will be created
  + resource "github_repository" "example" {
      + allow_auto_merge            = false
      + allow_merge_commit          = true
      + allow_rebase_merge          = true
      + allow_squash_merge          = true
      + archived                    = false
      + default_branch              = (known after apply)
      + delete_branch_on_merge      = false
      + etag                        = (known after apply)
      + full_name                   = (known after apply)
      + git_clone_url               = (known after apply)
      + html_url                    = (known after apply)
      + http_clone_url              = (known after apply)
      + id                          = (known after apply)
      + merge_commit_message        = "PR_TITLE"
      + merge_commit_title          = "MERGE_MESSAGE"
      + name                        = "test-tfaction"
      + node_id                     = (known after apply)
      + primary_language            = (known after apply)
      + private                     = (known after apply)
      + repo_id                     = (known after apply)
      + squash_merge_commit_message = "COMMIT_MESSAGES"
      + squash_merge_commit_title   = "COMMIT_OR_PR_TITLE"
      + ssh_clone_url               = (known after apply)
      + svn_url                     = (known after apply)
      + topics                      = (known after apply)
      + visibility                  = "public"
      + vulnerability_alerts        = (known after apply)
      + web_commit_signoff_required = false

      + security_and_analysis (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

@renovate renovate Bot force-pushed the renovate/terragrunt-gruntwork-io-terragrunt-1.x branch from 279d3ca to 829f7c6 Compare May 11, 2026 18:14
@szksh-lab-2-app
Copy link
Copy Markdown
Contributor

Plan Result (foo)

CI link

Plan: 1 to add, 0 to change, 0 to destroy.
  • Create
    • github_repository.example
Change Result (Click me)
  # github_repository.example will be created
  + resource "github_repository" "example" {
      + allow_auto_merge            = false
      + allow_merge_commit          = true
      + allow_rebase_merge          = true
      + allow_squash_merge          = true
      + archived                    = false
      + default_branch              = (known after apply)
      + delete_branch_on_merge      = false
      + etag                        = (known after apply)
      + full_name                   = (known after apply)
      + git_clone_url               = (known after apply)
      + html_url                    = (known after apply)
      + http_clone_url              = (known after apply)
      + id                          = (known after apply)
      + merge_commit_message        = "PR_TITLE"
      + merge_commit_title          = "MERGE_MESSAGE"
      + name                        = "test-tfaction"
      + node_id                     = (known after apply)
      + primary_language            = (known after apply)
      + private                     = (known after apply)
      + repo_id                     = (known after apply)
      + squash_merge_commit_message = "COMMIT_MESSAGES"
      + squash_merge_commit_title   = "COMMIT_OR_PR_TITLE"
      + ssh_clone_url               = (known after apply)
      + svn_url                     = (known after apply)
      + topics                      = (known after apply)
      + visibility                  = "public"
      + vulnerability_alerts        = (known after apply)
      + web_commit_signoff_required = false

      + security_and_analysis (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

@renovate renovate Bot force-pushed the renovate/terragrunt-gruntwork-io-terragrunt-1.x branch from 829f7c6 to 6517b2b Compare May 14, 2026 18:02
@szksh-lab-2-app
Copy link
Copy Markdown
Contributor

Plan Result (foo)

CI link

Plan: 1 to add, 0 to change, 0 to destroy.
  • Create
    • github_repository.example
Change Result (Click me)
  # github_repository.example will be created
  + resource "github_repository" "example" {
      + allow_auto_merge            = false
      + allow_merge_commit          = true
      + allow_rebase_merge          = true
      + allow_squash_merge          = true
      + archived                    = false
      + default_branch              = (known after apply)
      + delete_branch_on_merge      = false
      + etag                        = (known after apply)
      + full_name                   = (known after apply)
      + git_clone_url               = (known after apply)
      + html_url                    = (known after apply)
      + http_clone_url              = (known after apply)
      + id                          = (known after apply)
      + merge_commit_message        = "PR_TITLE"
      + merge_commit_title          = "MERGE_MESSAGE"
      + name                        = "test-tfaction"
      + node_id                     = (known after apply)
      + primary_language            = (known after apply)
      + private                     = (known after apply)
      + repo_id                     = (known after apply)
      + squash_merge_commit_message = "COMMIT_MESSAGES"
      + squash_merge_commit_title   = "COMMIT_OR_PR_TITLE"
      + ssh_clone_url               = (known after apply)
      + svn_url                     = (known after apply)
      + topics                      = (known after apply)
      + visibility                  = "public"
      + vulnerability_alerts        = (known after apply)
      + web_commit_signoff_required = false

      + security_and_analysis (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

@renovate renovate Bot force-pushed the renovate/terragrunt-gruntwork-io-terragrunt-1.x branch from 6517b2b to 9708981 Compare May 18, 2026 21:36
@szksh-lab-2-app
Copy link
Copy Markdown
Contributor

Plan Result (foo)

CI link

Plan: 1 to add, 0 to change, 0 to destroy.
  • Create
    • github_repository.example
Change Result (Click me)
  # github_repository.example will be created
  + resource "github_repository" "example" {
      + allow_auto_merge            = false
      + allow_merge_commit          = true
      + allow_rebase_merge          = true
      + allow_squash_merge          = true
      + archived                    = false
      + default_branch              = (known after apply)
      + delete_branch_on_merge      = false
      + etag                        = (known after apply)
      + full_name                   = (known after apply)
      + git_clone_url               = (known after apply)
      + html_url                    = (known after apply)
      + http_clone_url              = (known after apply)
      + id                          = (known after apply)
      + merge_commit_message        = "PR_TITLE"
      + merge_commit_title          = "MERGE_MESSAGE"
      + name                        = "test-tfaction"
      + node_id                     = (known after apply)
      + primary_language            = (known after apply)
      + private                     = (known after apply)
      + repo_id                     = (known after apply)
      + squash_merge_commit_message = "COMMIT_MESSAGES"
      + squash_merge_commit_title   = "COMMIT_OR_PR_TITLE"
      + ssh_clone_url               = (known after apply)
      + svn_url                     = (known after apply)
      + topics                      = (known after apply)
      + visibility                  = "public"
      + vulnerability_alerts        = (known after apply)
      + web_commit_signoff_required = false

      + security_and_analysis (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

@renovate renovate Bot force-pushed the renovate/terragrunt-gruntwork-io-terragrunt-1.x branch from 9708981 to 6ca2258 Compare May 25, 2026 14:00
@szksh-lab-2-app
Copy link
Copy Markdown
Contributor

Plan Result (foo)

CI link

Plan: 1 to add, 0 to change, 0 to destroy.
  • Create
    • github_repository.example
Change Result (Click me)
  # github_repository.example will be created
  + resource "github_repository" "example" {
      + allow_auto_merge            = false
      + allow_merge_commit          = true
      + allow_rebase_merge          = true
      + allow_squash_merge          = true
      + archived                    = false
      + default_branch              = (known after apply)
      + delete_branch_on_merge      = false
      + etag                        = (known after apply)
      + full_name                   = (known after apply)
      + git_clone_url               = (known after apply)
      + html_url                    = (known after apply)
      + http_clone_url              = (known after apply)
      + id                          = (known after apply)
      + merge_commit_message        = "PR_TITLE"
      + merge_commit_title          = "MERGE_MESSAGE"
      + name                        = "test-tfaction"
      + node_id                     = (known after apply)
      + primary_language            = (known after apply)
      + private                     = (known after apply)
      + repo_id                     = (known after apply)
      + squash_merge_commit_message = "COMMIT_MESSAGES"
      + squash_merge_commit_title   = "COMMIT_OR_PR_TITLE"
      + ssh_clone_url               = (known after apply)
      + svn_url                     = (known after apply)
      + topics                      = (known after apply)
      + visibility                  = "public"
      + vulnerability_alerts        = (known after apply)
      + web_commit_signoff_required = false

      + security_and_analysis (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

@renovate renovate Bot force-pushed the renovate/terragrunt-gruntwork-io-terragrunt-1.x branch from 6ca2258 to 3e304bc Compare May 27, 2026 22:35
@szksh-lab-2-app
Copy link
Copy Markdown
Contributor

Plan Result (foo)

CI link

Plan: 1 to add, 0 to change, 0 to destroy.
  • Create
    • github_repository.example
Change Result (Click me)
  # github_repository.example will be created
  + resource "github_repository" "example" {
      + allow_auto_merge            = false
      + allow_merge_commit          = true
      + allow_rebase_merge          = true
      + allow_squash_merge          = true
      + archived                    = false
      + default_branch              = (known after apply)
      + delete_branch_on_merge      = false
      + etag                        = (known after apply)
      + full_name                   = (known after apply)
      + git_clone_url               = (known after apply)
      + html_url                    = (known after apply)
      + http_clone_url              = (known after apply)
      + id                          = (known after apply)
      + merge_commit_message        = "PR_TITLE"
      + merge_commit_title          = "MERGE_MESSAGE"
      + name                        = "test-tfaction"
      + node_id                     = (known after apply)
      + primary_language            = (known after apply)
      + private                     = (known after apply)
      + repo_id                     = (known after apply)
      + squash_merge_commit_message = "COMMIT_MESSAGES"
      + squash_merge_commit_title   = "COMMIT_OR_PR_TITLE"
      + ssh_clone_url               = (known after apply)
      + svn_url                     = (known after apply)
      + topics                      = (known after apply)
      + visibility                  = "public"
      + vulnerability_alerts        = (known after apply)
      + web_commit_signoff_required = false

      + security_and_analysis (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

@renovate renovate Bot force-pushed the renovate/terragrunt-gruntwork-io-terragrunt-1.x branch from 3e304bc to d2b9369 Compare June 1, 2026 22:44
@szksh-lab-2-app
Copy link
Copy Markdown
Contributor

Plan Result (foo)

CI link

Plan: 1 to add, 0 to change, 0 to destroy.
  • Create
    • github_repository.example
Change Result (Click me)
  # github_repository.example will be created
  + resource "github_repository" "example" {
      + allow_auto_merge            = false
      + allow_merge_commit          = true
      + allow_rebase_merge          = true
      + allow_squash_merge          = true
      + archived                    = false
      + default_branch              = (known after apply)
      + delete_branch_on_merge      = false
      + etag                        = (known after apply)
      + full_name                   = (known after apply)
      + git_clone_url               = (known after apply)
      + html_url                    = (known after apply)
      + http_clone_url              = (known after apply)
      + id                          = (known after apply)
      + merge_commit_message        = "PR_TITLE"
      + merge_commit_title          = "MERGE_MESSAGE"
      + name                        = "test-tfaction"
      + node_id                     = (known after apply)
      + primary_language            = (known after apply)
      + private                     = (known after apply)
      + repo_id                     = (known after apply)
      + squash_merge_commit_message = "COMMIT_MESSAGES"
      + squash_merge_commit_title   = "COMMIT_OR_PR_TITLE"
      + ssh_clone_url               = (known after apply)
      + svn_url                     = (known after apply)
      + topics                      = (known after apply)
      + visibility                  = "public"
      + vulnerability_alerts        = (known after apply)
      + web_commit_signoff_required = false

      + security_and_analysis (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants