Skip to content

Conversation

@pseudomorph
Copy link
Contributor

@pseudomorph pseudomorph commented Jul 31, 2025

Description

This allows for unit values files to be written as either terragrunt.values.hcl or terragrunt.values.json. Default is current behavior (writing terragrunt.values.hcl).

TODOs

Read the Gruntwork contribution guidelines.

  • I authored this code entirely myself
  • I am submitting code based on open source software (e.g. MIT, MPL-2.0, Apache)]
  • I am adding or upgrading a dependency or adapted code and confirm it has a compatible open source license
  • Update the docs.
  • Run the relevant tests successfully, including pre-commit checks.
  • Include release notes. If this PR is backward incompatible, include a migration guide.

Release Notes (draft)

Added support for generating values files in JSON format using the --json-values flag with terragrunt stack generate.

Migration Guide

N/A

Summary by CodeRabbit

  • New Features

    • Added support for generating stack values files in JSON format using a new --json-values flag with stack commands. Both HCL and JSON formats are now supported and functionally equivalent.
    • JSON values files are generated with sorted keys for deterministic output and include a comment field for context.
    • When both HCL and JSON values files exist, the JSON file takes precedence during stack operations.
  • Documentation

    • Updated documentation to describe the new --json-values flag, explain values file formats, and provide usage examples for both HCL and JSON output options.
  • Tests

    • Added comprehensive unit and integration tests to verify JSON values file generation, reading, precedence, and backward compatibility with HCL files.

@vercel
Copy link

vercel bot commented Jul 31, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
terragrunt-docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 31, 2025 7:07pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 31, 2025

📝 Walkthrough

Walkthrough

Support for generating and consuming stack values files in JSON format has been added alongside the existing HCL format. This is controlled by a new --json-values CLI flag and an associated option. Code, tests, and documentation have been updated to reflect the new format, its precedence, and usage.

Changes

Cohort / File(s) Change Summary
CLI Flag & Option Wiring
cli/commands/stack/cli.go, options/options.go
Adds --json-values CLI flag and corresponding StackValuesJSON field in options to control output format for stack values files.
Stack Values Read/Write Logic
config/stack.go, config/config_helpers.go
Updates stack values logic to support both HCL and JSON formats; adds helpers for rendering and reading JSON, updates file precedence, and modifies write/read signatures.
Unit Tests for Stack Values
config/stack_test.go
Refactors and extends tests to cover both HCL and JSON formats, adds tests for format precedence and correct parsing of JSON files.
Integration Tests for Stack Values
test/integration_stacks_test.go
Adds integration tests to verify JSON values generation, precedence, backward compatibility, and correct behavior in stack commands.
Documentation Updates
docs/_docs/02_features/02-stacks.md, docs/_docs/04_reference/01-configuration.md, docs/_docs/04_reference/02-cli-options.md, docs/_docs/04_reference/04-config-blocks-and-attributes.md, docs-starlight/src/content/docs/02-features/02-stacks.mdx
Updates documentation to describe the new --json-values flag, JSON format support, usage examples, and clarifies values file precedence and format equivalence.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI
    participant StackLogic
    participant FileSystem

    User->>CLI: terragrunt stack generate [--json-values]
    CLI->>StackLogic: Generate stack values (opts.StackValuesJSON)
    alt opts.StackValuesJSON == true
        StackLogic->>FileSystem: Write terragrunt.values.json
    else opts.StackValuesJSON == false
        StackLogic->>FileSystem: Write terragrunt.values.hcl
    end

    User->>CLI: terragrunt stack plan/apply
    CLI->>StackLogic: Read stack values
    alt terragrunt.values.json exists
        StackLogic->>FileSystem: Read terragrunt.values.json
    else
        StackLogic->>FileSystem: Read terragrunt.values.hcl
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • denis256
  • yhakbar

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (9)
options/options.go (1)

308-310: Consider adding explicit struct-tags / comment for consistency

The new field is fine functionally (zero-value false keeps existing behaviour), but every other boolean CLI flag exposed on TerragruntOptions carries at least a json / mapstructure tag or an explanatory doc-comment describing the default.
Recommend adding something similar so downstream reflection (e.g. when serialising options or binding env vars) behaves consistently.

-	// StackValuesJSON writes stack values files in JSON format instead of HCL.
-	StackValuesJSON bool
+	// StackValuesJSON determines whether stack values files are written as JSON (`terragrunt.values.json`)
+	// instead of the default HCL (`terragrunt.values.hcl`). Defaults to false.
+	StackValuesJSON bool `mapstructure:"stack_values_json" json:"stack_values_json,omitempty"`
docs/_docs/04_reference/02-cli-options.md (1)

214-221: Add precedence note & mirror change in docs-starlight.

  1. Users may wonder which file wins when both terragrunt.values.hcl and terragrunt.values.json are present. A short sentence clarifying the precedence (JSON vs HCL) will remove ambiguity.
  2. Per the migration notice, every addition under docs/** must be duplicated in the new docs-starlight/** tree. Please verify that an equivalent --json-values section exists there.
docs-starlight/src/content/docs/02-features/02-stacks.mdx (2)

181-185: Separate the two possible filenames for better readability

Collapsing the two alternatives onto one line with Markdown underscores renders as italic text and makes the file tree harder to scan. Listing each variant on its own line—even if one is “optional”—keeps the tree visually aligned and avoids Markdown side-effects.

-    - terragrunt.values.hcl _or terragrunt.values.json with --json-values_
+    - terragrunt.values.hcl           # default
+    - terragrunt.values.json          # generated with `--json-values`

Apply the same change to the database entry below for consistency.


188-201: Minor wording & heading-style tweaks

  1. In headings we usually use title-case (“Values File Formats” → “Values file formats”) to match the surrounding docs.
  2. “contain the same values data” reads awkwardly—“contain the same data” is simpler.
-#### Values File Formats
+#### Values file formats
@@
-Both formats are functionally equivalent and contain the same values data.
+Both formats are functionally equivalent and contain the same data.

Optional: add an inline link to the CLI reference for --json-values to aid discoverability.

docs/_docs/04_reference/04-config-blocks-and-attributes.md (5)

1742-1744: Cross-link the new flag and clarify default behaviour

Nice addition. To make this self-contained, please:

  1. Add an inline link to the --json-values option in the CLI-options reference (02-cli-options.md) so that readers can jump straight to the flag description.
  2. State explicitly that, when the flag is omitted, Terragrunt always falls back to terragrunt.values.hcl even if a .json file already exists (current wording leaves the precedence ambiguous).

1752-1759: Minor grammar / flow

Consider “The generated values file contains…” (present tense) instead of “will contain”, which reads better in reference docs.


1762-1770: Use jsonc fence or drop the leading // comment

The leading // .terragrunt-stack/... line is invalid JSON and causes red highlighting when rendered with a json fence. Either:

-```json
-// .terragrunt-stack/vpc/terragrunt.values.json
+```jsonc
+// .terragrunt-stack/vpc/terragrunt.values.json

or move the path comment outside the fenced block.


1772-1781: Tiny wording fix

“leverage those values via values variables regardless of format” →
“leverage those values via the values variables regardless of the file format”


1895-1896: Duplication with unit section

This bullet is nearly identical to the one in the unit section. Consider extracting to a reusable snippet or ensure any future edits touch both places to avoid drift.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b094bc4 and 1f3b5a7.

📒 Files selected for processing (11)
  • cli/commands/stack/cli.go (2 hunks)
  • config/config_helpers.go (1 hunks)
  • config/stack.go (6 hunks)
  • config/stack_test.go (3 hunks)
  • docs-starlight/src/content/docs/02-features/02-stacks.mdx (1 hunks)
  • docs/_docs/02_features/02-stacks.md (1 hunks)
  • docs/_docs/04_reference/01-configuration.md (1 hunks)
  • docs/_docs/04_reference/02-cli-options.md (1 hunks)
  • docs/_docs/04_reference/04-config-blocks-and-attributes.md (5 hunks)
  • options/options.go (1 hunks)
  • test/integration_stacks_test.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.go

⚙️ CodeRabbit Configuration File

Review the Go code for quality and correctness. Make sure that the Go code follows best practices, is performant, and is easy to understand and maintain.

Files:

  • options/options.go
  • config/config_helpers.go
  • cli/commands/stack/cli.go
  • test/integration_stacks_test.go
  • config/stack.go
  • config/stack_test.go
docs/**/*.md

⚙️ CodeRabbit Configuration File

Review the documentation for clarity, grammar, and spelling. Make sure that the documentation is easy to understand and follow. There is currently a migration underway from the Jekyll based documentation in docs to the Starlight + Astro based documentation in docs-starlight. Whenever changes are made to the docs directory, ensure that an equivalent change is made in the docs-starlight directory to keep the docs-starlight documentation accurate.

Files:

  • docs/_docs/04_reference/01-configuration.md
  • docs/_docs/02_features/02-stacks.md
  • docs/_docs/04_reference/04-config-blocks-and-attributes.md
  • docs/_docs/04_reference/02-cli-options.md
docs-starlight/**/*.md*

⚙️ CodeRabbit Configuration File

Review the documentation for clarity, grammar, and spelling. Make sure that the documentation is easy to understand and follow. There is currently a migration underway from the Jekyll based documentation in docs to the Starlight + Astro based documentation in docs-starlight. Make sure that the docs-starlight documentation is accurate and up-to-date with the docs documentation, and that any difference between them results in an improvement in the docs-starlight documentation.

Files:

  • docs-starlight/src/content/docs/02-features/02-stacks.mdx
🧠 Learnings (5)
📚 Learning: in terragrunt projects, all `.hcl` files can be assumed to be terragrunt configurations by default, ...
Learnt from: yhakbar
PR: gruntwork-io/terragrunt#3868
File: docs-starlight/patches/@astrojs%[email protected]:33-33
Timestamp: 2025-02-10T23:20:04.295Z
Learning: In Terragrunt projects, all `.hcl` files can be assumed to be Terragrunt configurations by default, with specific exceptions like `.terraform.lock.hcl` that need explicit handling.

Applied to files:

  • docs/_docs/04_reference/01-configuration.md
  • config/config_helpers.go
  • docs/_docs/02_features/02-stacks.md
  • docs-starlight/src/content/docs/02-features/02-stacks.mdx
  • docs/_docs/04_reference/04-config-blocks-and-attributes.md
  • docs/_docs/04_reference/02-cli-options.md
  • config/stack.go
📚 Learning: the project uses a custom error package `github.com/gruntwork-io/terragrunt/internal/errors` which p...
Learnt from: levkohimins
PR: gruntwork-io/terragrunt#3723
File: cli/commands/stack/action.go:160-160
Timestamp: 2025-02-10T13:36:19.542Z
Learning: The project uses a custom error package `github.com/gruntwork-io/terragrunt/internal/errors` which provides similar functionality to `fmt.Errorf` but includes stack traces. Prefer using this package's error functions (e.g., `errors.Errorf`, `errors.New`) over the standard library's error handling.

Applied to files:

  • docs/_docs/04_reference/01-configuration.md
  • docs/_docs/02_features/02-stacks.md
  • docs-starlight/src/content/docs/02-features/02-stacks.mdx
  • docs/_docs/04_reference/04-config-blocks-and-attributes.md
  • docs/_docs/04_reference/02-cli-options.md
  • test/integration_stacks_test.go
  • config/stack.go
📚 Learning: avoid shadowing imported packages with local variables in go code, such as using a variable named `f...
Learnt from: yhakbar
PR: gruntwork-io/terragrunt#4169
File: cli/commands/hcl/validate/cli.go:29-60
Timestamp: 2025-04-17T13:02:28.098Z
Learning: Avoid shadowing imported packages with local variables in Go code, such as using a variable named `flags` when the `github.com/gruntwork-io/terragrunt/cli/flags` package is imported. Use more specific variable names like `flagSet` instead.

Applied to files:

  • config/config_helpers.go
  • cli/commands/stack/cli.go
  • test/integration_stacks_test.go
  • config/stack.go
📚 Learning: the terragruntconfig struct in config/config.go does contain an engine field that's used to store en...
Learnt from: partcyborg
PR: gruntwork-io/terragrunt#3974
File: config/config_partial.go:448-456
Timestamp: 2025-03-06T23:44:09.413Z
Learning: The TerragruntConfig struct in config/config.go does contain an Engine field that's used to store engine configuration data.

Applied to files:

  • config/config_helpers.go
📚 Learning: constants defined in one go file are accessible from other files in the same package without explici...
Learnt from: wakeful
PR: gruntwork-io/terragrunt#4491
File: test/integration_test.go:4265-4265
Timestamp: 2025-07-03T22:05:07.356Z
Learning: Constants defined in one Go file are accessible from other files in the same package without explicit imports. When reviewing Go code, consider the package-level scope rather than just the individual file scope.

Applied to files:

  • config/stack.go
🔇 Additional comments (25)
docs/_docs/04_reference/01-configuration.md (1)

182-186: Mirror the doc update in docs-starlight

Per the repo-wide guideline, any change in the legacy docs/ tree must be duplicated in docs-starlight/.
Please replicate the “# or terragrunt.values.json with --json-values” comment in the equivalent MDX file so both doc sets stay in sync.

config/config_helpers.go (1)

738-738: LGTM! Clean extension to support JSON values files.

The addition of || strings.HasSuffix(targetConfig, valuesFileJSON) correctly extends the existing condition to recognize JSON values files alongside HCL values files. This change aligns perfectly with the PR objective of supporting both formats and maintains backward compatibility.

cli/commands/stack/cli.go (2)

19-19: LGTM! Constant follows existing naming conventions.

The JSONValuesFlagName constant is properly defined and follows the existing naming pattern used for other flag constants in this file.


87-92: LGTM! Well-implemented CLI flag addition.

The --json-values flag implementation correctly follows the established patterns in this file:

  • Uses proper flag creation with flags.NewFlag
  • Includes environment variable support via tgPrefix.EnvVars()
  • Correctly binds to &opts.StackValuesJSON
  • Provides clear usage description
  • Maintains consistency with other boolean flags

The integration is clean and maintains backward compatibility.

docs/_docs/02_features/02-stacks.md (2)

180-184: LGTM! Clear documentation of format options.

The updates to the directory tree examples properly illustrate that values files can be generated in either HCL or JSON format using the --json-values flag. The inline comments effectively communicate this option without cluttering the examples.


186-199: LGTM! Excellent documentation of the new feature.

The "Values File Formats" section provides comprehensive and clear documentation:

  • Clearly explains HCL as the default format
  • Shows practical command examples for both formats
  • Explains the functional equivalence of both formats
  • Provides good guidance on when JSON might be preferred
  • Mentions the deterministic alphabetical sorting behavior

The documentation is well-structured and will help users understand when and how to use the new JSON values feature.

docs/_docs/04_reference/04-config-blocks-and-attributes.md (3)

1748-1749: Update parallel docs-starlight tree snippet

The same tree comment (# or terragrunt.values.json with --json-values) must appear in the matching file under docs-starlight/... to keep both doc sets in sync, per the migration guideline.


1814-1818: Mirror change in docs-starlight

Replicate the updated comment in the directory tree example inside the docs-starlight reference to keep both doc paths aligned.


1828-1829: Bullet reads well – just ensure consistency

Good call-out about pre-created files. Confirm the same note is present in the stack/CLI docs so users don’t miss the nuance.

test/integration_stacks_test.go (4)

1318-1376: LGTM! Comprehensive test for JSON values generation.

The test properly validates JSON values file generation with the --json-values flag, including:

  • File existence/non-existence checks
  • Valid JSON structure validation
  • Expected content verification including the auto-generated comment
  • Both dev and prod environment coverage

1378-1409: LGTM! Good end-to-end test for JSON values usage.

This test validates the complete workflow of running stack commands with JSON values, ensuring the values are properly consumed and JSON files are generated as expected.


1411-1432: LGTM! Essential test for JSON values readability.

This focused test ensures that once JSON values files are generated, Terragrunt can properly read and use them in subsequent operations. The plan command validation confirms the feature works end-to-end.


1434-1468: LGTM! Critical test for backward compatibility and precedence.

This test validates the most important aspect of the JSON values feature - that JSON files take precedence over HCL files when both exist. This ensures smooth migration paths and prevents breaking existing workflows.

config/stack_test.go (5)

173-235: LGTM! Excellent refactoring to support both HCL and JSON formats.

The table-driven approach cleanly tests both formats while maintaining the deterministic sorting verification. The separation of test cases and verification logic improves maintainability.


238-292: LGTM! Clean helper function update.

The addition of the fileExt parameter is minimal and focused, enabling support for both HCL and JSON file extensions without breaking existing functionality.


354-400: LGTM! Comprehensive JSON values reading test.

The test thoroughly validates JSON parsing with multiple data types (strings, numbers, booleans, objects) and includes proper comment field handling. Good coverage of the core JSON reading functionality.


402-442: LGTM! Essential precedence test.

This test is crucial for validating that JSON values take precedence over HCL values when both files exist. The conflicting values approach clearly demonstrates the precedence behavior, and the assertions are explicit about expected behavior.


444-483: LGTM! Good comment handling test.

This test ensures that JSON comment fields are properly handled and accessible while not interfering with other values. Important for validating the auto-generated comment feature.

config/stack.go (7)

5-5: LGTM! Clean constants and imports addition.

The JSON import and valuesFileJSON constant follow existing patterns and are minimal additions that support the new functionality without affecting existing code.

Also applies to: 37-37


776-823: LGTM! Well-structured writeValues function update.

The function cleanly handles both HCL and JSON formats with proper conditional logic, error handling, and informative logging. The separation into helper functions maintains good code organization.


825-835: LGTM! Clean generic utility function.

The getSortedKeys function is well-implemented using Go generics, providing reusable key sorting functionality for deterministic output in both HCL and JSON formats.


837-865: LGTM! Good extraction with deterministic improvement.

The HCL rendering function maintains existing functionality while adding deterministic key sorting. The separation of concerns improves maintainability.


867-893: LGTM! Well-implemented JSON rendering function.

The function properly converts cty values to JSON with deterministic key sorting, auto-generated comments, and proper formatting. Good error handling and consistent behavior with the HCL equivalent.


895-939: LGTM! Solid precedence implementation in ReadValues.

The function correctly implements JSON-first precedence while maintaining backward compatibility with HCL files. The existing parsing logic is properly reused, and the updated documentation clearly describes the behavior.


586-586: LGTM! Necessary parameter addition.

The addition of the opts parameter to the writeValues call enables the function to access the StackValuesJSON flag, completing the integration chain from CLI to file generation.

@yhakbar
Copy link
Collaborator

yhakbar commented Aug 1, 2025

@pseudomorph could you explain why you need this feature? The Terragrunt CLI has a lot of flags, and adding another one should be justified with functionality that is valuable and hard to achieve otherwise.

@pseudomorph
Copy link
Contributor Author

@yhakbar - Sure!

We're currently working on a framework which leverages scaffold and stacks to replace our current homegrown set up to manage a large monorepo (3000+ deployments) which is deployed with Atlantis.

At first I was looking at a soft adoption of stacks around our current setup, but the proliferation of repetitive files in Git feel less than ideal. Foregoing the soft adoption would be nice from a DRY perspective, but here is still some necessity of visibility (for the end-user) and change tracking in Git (for Atlantis). The idea I have is render out metadata files for each of the generated stack units, which information about the rendered units (file hashes), along with unit-specific values. That way users can understand what values a specific deployment is getting (and why), and Atlantis can target the appropriate point changes.

We're planning to use stack operations for wholesale standup and teardown of infra, but do point operations on the day-to-day management... Lots of individual teams managing their specific slice of infra.

Having the values file rendered out as json as part of stack generation allows for more efficient processing (no secondary operations or tooling). It is possible to use terragrunt render along with a purpose built hcl file, but this is clunky and add extra time to CI operations. We can use external tooling like hcl2json, but that's still extra compute cycles, and it would be preferable if we could keep everything within one tool.

@pseudomorph
Copy link
Contributor Author

Actually, taking a step back, would it make more sense to place this functionality into a stack command?

Something like: terragrunt stack info, where information about stacks/units could be rendered from config. Output could contain source paths, values, etc..

This information could be used within workflows to help with the orphan units/state matter raised in #4504 .

Apologies, I should have started this off as an issue.

@yhakbar
Copy link
Collaborator

yhakbar commented Aug 1, 2025

@pseudomorph it's all good! Sometimes seeing a prototype helps shape better understanding of the problem and potential solutions. I would recommend creating an RFC, and then soliciting feedback from the community on the design. We want to think through all reasonable alternatives, and approaches (Discord is a good place to do that. Please tag me if you ask for feedback there).

@pseudomorph pseudomorph marked this pull request as draft August 1, 2025 17:53
@pseudomorph pseudomorph mentioned this pull request Aug 1, 2025
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants