-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
allow input validation with variable in source or version #5041
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughReplaced tfconfig-based module parsing with explicit HCL/JSON parsing to detect module variables (required vs optional) even when variables appear in module source/version. Added fixtures and an integration test covering variable-in-source/version, circular refs, invalid locals, and required-input cases; updated docs and pre-commit config. Changes
Sequence Diagram(s)sequenceDiagram
participant Caller as terragrunt hcl validate
participant Parser as tf/tf.go (new HCL/JSON)
participant Files as Module files (.tf/.tofu/.json)
participant Vars as Variable extraction
rect rgb(240,255,240)
Caller->>Parser: Request ModuleVariables(modulePath)
Parser->>Files: Read directory, filter target files
Files-->>Parser: File contents
Parser->>Parser: Parse .tf/.tofu with HCL parser\nParse .json with JSON parser
Parser->>Parser: Aggregate diagnostics, merge HCL bodies
end
rect rgb(255,250,240)
Parser->>Vars: PartialContent(variable block schema)
Vars-->>Parser: variable blocks
Parser->>Parser: For each variable: if default -> optional else -> required
Parser-->>Caller: (requiredVars, optionalVars, error/diagnostics)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related issues
Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
739b926 to
9d7f9b1
Compare
| --- | ||
|
|
||
| When enabled, Terragrunt will validate that all variables are set by the module a unit provisions. | ||
| When enabled, Terragrunt will validate that all variables a module (provisioned by a unit) requires are set. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Open to input on this, or even removing it. But I definitely don't think the current wording is correct (since we're checking that the unit sets variables consumed by the module, the module doesn't set them).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would better wording be: "When enabled, Terragrunt will validate that all inputs set by Terragrunt units are valid OpenTofu/Terraform variables consumed by their respective modules"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel that only is accurate when using --strict, without --strict you can set inputs that are not consumed / don't exist as variables
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was able to make an even more minimal example than the one in #4986
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know empty files seem silly, but in the spirit of "minimal reproduction" I don't think you can get more minimal than empty!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing wrong with it! If you want to be explicit about this, you can leave a one-line comment in the file that it's intentionally empty.
| t.Run("using --all", func(t *testing.T) { | ||
| t.Parallel() | ||
| helpers.CleanupTerraformFolder(t, testFixtureHclvalidate) | ||
| tmpEnvPath := helpers.CopyEnvironment(t, testFixtureHclvalidate) | ||
| rootPath := util.JoinPath(tmpEnvPath, testFixtureHclvalidate) | ||
|
|
||
| _, _, err := helpers.RunTerragruntCommandWithOutput(t, "terragrunt hcl validate --all --strict --inputs --working-dir "+path.Join(rootPath, "valid")) | ||
| require.NoError(t, err) | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added this test, but actually it was already passing! Is --all not supposed to return non-zero?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's entirely possible there's a bug in the error handling. I think it should be returning an error if anything fails during an --all run.
tf/tf.go
Outdated
| ignorableErrors := []tfconfig.Diagnostic{ | ||
| // These two occur when a module block uses a variable in the `version` or `source` fields. | ||
| // Terraform doesn't support this, but OpenTofu does. Either way our ability to extract variables is unaffected. | ||
| // | ||
| // What we really need is an OpenTofu version of terraform-config-inspect. This may work for now but as / if | ||
| // syntax continues to diverge we may run into other issues. | ||
| {Summary: "Variables not allowed", Detail: "Variables may not be used here."}, | ||
| {Summary: "Unsuitable value type", Detail: "Unsuitable value: value must be known"}, | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to keep this scoped to this function, plus putting it outside the function would require a more descriptive name.
I'm 90% sure the compiler notices it's never changed and pre-allocates it, but am happy to be proven wrong (and will move it if so).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it's a big deal either way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
docs-starlight/src/data/flags/hcl-validate-inputs.mdx(1 hunks)test/fixtures/hclvalidate/valid/var-in-source/main.tf(1 hunks)test/fixtures/hclvalidate/valid/var-in-version/main.tf(1 hunks)test/integration_test.go(1 hunks)tf/tf.go(2 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
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
docsto the Starlight + Astro based documentation indocs-starlight. Make sure that thedocs-starlightdocumentation is accurate and up-to-date with thedocsdocumentation, and that any difference between them results in an improvement in thedocs-starlightdocumentation.
Files:
docs-starlight/src/data/flags/hcl-validate-inputs.mdx
**/*.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:
tf/tf.gotest/integration_test.go
🧠 Learnings (2)
📚 Learning: 2025-08-19T16:05:54.723Z
Learnt from: Resonance1584
Repo: gruntwork-io/terragrunt PR: 4683
File: go.mod:86-90
Timestamp: 2025-08-19T16:05:54.723Z
Learning: When analyzing Go module dependencies for removal, always check for both direct imports and API usage across all Go files in the repository, not just a quick search. The github.com/mattn/go-zglob library is used for filesystem walking and glob expansion in multiple Terragrunt files including util/file.go, format commands, and AWS provider patch functionality.
Applied to files:
tf/tf.go
📚 Learning: 2025-02-10T13:36:19.542Z
Learnt from: levkohimins
Repo: gruntwork-io/terragrunt PR: 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:
tf/tf.go
🧬 Code graph analysis (2)
tf/tf.go (1)
internal/view/diagnostic/diagnostic.go (1)
Diagnostic(21-27)
test/integration_test.go (2)
test/helpers/package.go (3)
CleanupTerraformFolder(879-886)CopyEnvironment(89-102)RunTerragruntCommandWithOutput(1004-1008)util/file.go (1)
JoinPath(626-628)
🪛 Checkov (3.2.334)
test/fixtures/hclvalidate/valid/var-in-source/main.tf
[medium] 5-8: Ensure Terraform module sources use a commit hash
(CKV_TF_1)
[high] 5-8: Ensure Terraform module sources use a tag with a version number
(CKV_TF_2)
test/fixtures/hclvalidate/valid/var-in-version/main.tf
[medium] 5-8: Ensure Terraform module sources use a commit hash
(CKV_TF_1)
[high] 5-8: Ensure Terraform module sources use a tag with a version number
(CKV_TF_2)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Pull Request has non-contributor approval
- GitHub Check: base_tests / Test (macos)
- GitHub Check: base_tests / Test (ubuntu)
- GitHub Check: Pull Request has non-contributor approval
tf/tf.go
Outdated
| return true | ||
| } | ||
|
|
||
| i := slices.IndexFunc(ignorableErrors, func(ie tfconfig.Diagnostic) bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking that this can be simplified to
return slices.ContainsFunc(ignorableErrors, func(ie tfconfig.Diagnostic) bool {
return ie.Summary == d.Summary && ie.Detail == d.Detail
})
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes way more sense. I already know about contains so I don't know what I was thinking when I wrote this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this does the job, so I'll approve it. It's not how I thought you'd tackle this.
I was assuming you'd do something like this untested code:
type Variable struct {
Name string `hcl:"name,label"`
Default string `hcl:"default,optional"`
Remainder hcl.Body `hcl:",remain"`
}
type ModuleVars struct {
Variables []Variable `hcl:"variable,block"`
}
// ModuleVariables will return all the variables defined in the downloaded terraform modules, taking into
// account all the generated sources. This function will return the required and optional variables separately.
func ModuleVariables(modulePath string) ([]string, []string, error) {
parser := hclparse.NewParser()
files, err := os.ReadDir(modulePath)
if err != nil {
return nil, nil, err
}
hclFiles := []*hcl.File{}
errs := []error{}
for _, file := range files {
if file.IsDir() {
continue
}
// This would only solve the issue for HCL files. We'd need to also check JSON files.
if !strings.HasSuffix(file.Name(), ".tf") && !strings.HasSuffix(file.Name(), ".tofu") {
continue
}
hclFile, err := parser.ParseFromFile(file.Name())
if err != nil {
errs = append(errs, err)
}
hclFiles = append(hclFiles, hclFile.File)
}
if len(errs) > 0 {
return nil, nil, errors.New(errs)
}
body := hcl.MergeFiles(hclFiles)
moduleVars := ModuleVars{}
if err := gohcl.DecodeBody(body, nil, &moduleVars); err != nil {
return nil, nil, err
}
required := []string{}
optional := []string{}
for _, variable := range moduleVars.Variables {
if variable.Default != "" {
optional = append(optional, variable.Name)
}
}
return required, optional, nil
}To fully drop the dependency on github.com/hashicorp/terraform-config-inspect/tfconfig.
It's a bigger change than what you're doing here, so I'll accept that you might prefer your current solution. Please confirm that you've evaluated this, and don't want to make this or the changes that @denis256 recommended before merging if you're happy with the solution.
| --- | ||
|
|
||
| When enabled, Terragrunt will validate that all variables are set by the module a unit provisions. | ||
| When enabled, Terragrunt will validate that all variables a module (provisioned by a unit) requires are set. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would better wording be: "When enabled, Terragrunt will validate that all inputs set by Terragrunt units are valid OpenTofu/Terraform variables consumed by their respective modules"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing wrong with it! If you want to be explicit about this, you can leave a one-line comment in the file that it's intentionally empty.
| t.Run("using --all", func(t *testing.T) { | ||
| t.Parallel() | ||
| helpers.CleanupTerraformFolder(t, testFixtureHclvalidate) | ||
| tmpEnvPath := helpers.CopyEnvironment(t, testFixtureHclvalidate) | ||
| rootPath := util.JoinPath(tmpEnvPath, testFixtureHclvalidate) | ||
|
|
||
| _, _, err := helpers.RunTerragruntCommandWithOutput(t, "terragrunt hcl validate --all --strict --inputs --working-dir "+path.Join(rootPath, "valid")) | ||
| require.NoError(t, err) | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's entirely possible there's a bug in the error handling. I think it should be returning an error if anything fails during an --all run.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love the names on these fixtures. Reading the name of the fixture should tell you what the fixture is for.
tf/tf.go
Outdated
| ignorableErrors := []tfconfig.Diagnostic{ | ||
| // These two occur when a module block uses a variable in the `version` or `source` fields. | ||
| // Terraform doesn't support this, but OpenTofu does. Either way our ability to extract variables is unaffected. | ||
| // | ||
| // What we really need is an OpenTofu version of terraform-config-inspect. This may work for now but as / if | ||
| // syntax continues to diverge we may run into other issues. | ||
| {Summary: "Variables not allowed", Detail: "Variables may not be used here."}, | ||
| {Summary: "Unsuitable value type", Detail: "Unsuitable value: value must be known"}, | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it's a big deal either way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (2)
tf/tf.go (2)
162-164: Avoid allocating slice on every iteration.The slice
[]string{"tf", "tofu", "json"}is allocated on every loop iteration. Define it once outside the loop or use a switch statement for better performance.Apply this diff:
+ validExtensions := []string{"tf", "tofu", "json"} + for _, file := range files { if file.IsDir() { continue } + parseFunc := parser.ParseHCLFile - suffix := "" - for s := range strings.SplitSeq(file.Name(), ".") { - suffix = s - } - if suffix == "json" { + ext := path.Ext(file.Name()) + if len(ext) > 0 { + ext = ext[1:] // Remove leading dot + } + + if ext == "json" { parseFunc = parser.ParseJSONFile } - if !(slices.Contains([]string{"tf", "tofu", "json"}, suffix)) { + if !slices.Contains(validExtensions, ext) { continue } + - file, parseDiags := parseFunc(path.Join(modulePath, file.Name())) + parsedFile, parseDiags := parseFunc(path.Join(modulePath, file.Name())) - hclFiles = append(hclFiles, file) + hclFiles = append(hclFiles, parsedFile) allDiags = append(allDiags, parseDiags...) }
196-198: Consider adding context to error messages.When diagnostics contain errors, it would be helpful to include information about which files caused the issues to aid debugging.
Consider enhancing the error message:
if allDiags.HasErrors() { - return nil, nil, errors.New(allDiags) + return nil, nil, errors.Errorf("failed to parse module at %s: %w", modulePath, errors.New(allDiags)) }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
docs-starlight/src/data/flags/hcl-validate-inputs.mdx(1 hunks)test/fixtures/hclvalidate/valid/circular-reference/main.tf(1 hunks)test/fixtures/hclvalidate/valid/circular-reference/terragrunt.hcl(1 hunks)test/fixtures/hclvalidate/valid/duplicate-attributes-in-required-providers/main.tf(1 hunks)test/fixtures/hclvalidate/valid/duplicate-attributes-in-required-providers/terragrunt.hcl(1 hunks)test/fixtures/hclvalidate/valid/invalid-local/main.tf(1 hunks)test/fixtures/hclvalidate/valid/invalid-local/terragrunt.hcl(1 hunks)test/fixtures/hclvalidate/valid/single-required-input/main.tf(1 hunks)test/fixtures/hclvalidate/valid/single-required-input/terragrunt.hcl(1 hunks)test/fixtures/hclvalidate/valid/var-in-source/terragrunt.hcl(1 hunks)test/fixtures/hclvalidate/valid/var-in-version/terragrunt.hcl(1 hunks)test/integration_test.go(1 hunks)tf/tf.go(2 hunks)
✅ Files skipped from review due to trivial changes (6)
- test/fixtures/hclvalidate/valid/var-in-source/terragrunt.hcl
- test/fixtures/hclvalidate/valid/circular-reference/terragrunt.hcl
- test/fixtures/hclvalidate/valid/var-in-version/terragrunt.hcl
- test/fixtures/hclvalidate/valid/invalid-local/terragrunt.hcl
- test/fixtures/hclvalidate/valid/duplicate-attributes-in-required-providers/main.tf
- test/fixtures/hclvalidate/valid/duplicate-attributes-in-required-providers/terragrunt.hcl
🚧 Files skipped from review as they are similar to previous changes (1)
- test/integration_test.go
🧰 Additional context used
📓 Path-based instructions (2)
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
docsto the Starlight + Astro based documentation indocs-starlight. Make sure that thedocs-starlightdocumentation is accurate and up-to-date with thedocsdocumentation, and that any difference between them results in an improvement in thedocs-starlightdocumentation.
Files:
docs-starlight/src/data/flags/hcl-validate-inputs.mdx
**/*.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:
tf/tf.go
🧠 Learnings (3)
📚 Learning: 2025-08-19T16:05:54.723Z
Learnt from: Resonance1584
Repo: gruntwork-io/terragrunt PR: 4683
File: go.mod:86-90
Timestamp: 2025-08-19T16:05:54.723Z
Learning: When analyzing Go module dependencies for removal, always check for both direct imports and API usage across all Go files in the repository, not just a quick search. The github.com/mattn/go-zglob library is used for filesystem walking and glob expansion in multiple Terragrunt files including util/file.go, format commands, and AWS provider patch functionality.
Applied to files:
tf/tf.go
📚 Learning: 2025-02-10T13:36:19.542Z
Learnt from: levkohimins
Repo: gruntwork-io/terragrunt PR: 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:
tf/tf.go
📚 Learning: 2025-02-10T23:20:04.295Z
Learnt from: yhakbar
Repo: gruntwork-io/terragrunt PR: 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:
test/fixtures/hclvalidate/valid/single-required-input/terragrunt.hcl
🪛 GitHub Actions: CI
tf/tf.go
[error] 153-153: wsl_v5: missing whitespace above this line (invalid statement above assign)
[error] 154-154: wsl_v5: missing whitespace above this line (too many statements above range)
[error] 158-158: wsl_v5: missing whitespace above this line (invalid statement above if)
[error] 165-165: wsl_v5: missing whitespace above this line (invalid statement above assign)
[error] 185-185: wsl_v5: missing whitespace above this line (no shared variables above range)
[error] 188-188: wsl_v5: missing whitespace above this line (too many statements above if)
[error] 199-199: wsl_v5: missing whitespace above this line (too many lines above return)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Pull Request has non-contributor approval
- GitHub Check: Pull Request has non-contributor approval
🔇 Additional comments (5)
test/fixtures/hclvalidate/valid/circular-reference/main.tf (1)
1-4: LGTM! Appropriate edge case test fixture.This fixture correctly tests that the HCL parser can handle circular local references without crashing during validation. While this would fail at runtime, it's valid syntax and an appropriate edge case for the validation logic.
test/fixtures/hclvalidate/valid/invalid-local/main.tf (1)
1-3: LGTM! Valid test for undefined reference handling.This fixture appropriately tests that the validation logic can handle references to undefined locals without crashing. The syntax is valid HCL, making it a good test case for semantic validation.
test/fixtures/hclvalidate/valid/single-required-input/terragrunt.hcl (1)
1-3: LGTM! Clean test fixture.This fixture correctly provides an input value for the required variable defined in the corresponding main.tf, making it suitable for testing input validation.
test/fixtures/hclvalidate/valid/single-required-input/main.tf (1)
1-2: LGTM! Correct required variable definition.This fixture correctly defines a required variable (no default value) that pairs with the terragrunt.hcl input, making it suitable for testing required input validation.
docs-starlight/src/data/flags/hcl-validate-inputs.mdx (1)
3-3: LGTM! Clearer and more accurate documentation.The updated wording correctly reflects that validation ensures units provide values for variables that modules require, rather than the previous confusing "set by the module" phrasing. This aligns well with the actual validation behavior.
Also applies to: 9-9
tf/tf.go
Outdated
| parseFunc := parser.ParseHCLFile | ||
| suffix := "" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix whitespace linting errors.
The pipeline reports multiple wsl_v5 linting failures for missing whitespace. Add blank lines as indicated by the linter to improve code readability and comply with project standards.
Based on the linting errors, add blank lines:
- After line 152 (before line 153)
- After line 153 (before line 154)
- After line 157 (before line 158)
- After line 164 (before line 165)
- After line 184 (before line 185)
- After line 187 (before line 188)
- After line 198 (before line 199)
Also applies to: 158-158, 165-165, 185-185, 188-188, 199-199
🧰 Tools
🪛 GitHub Actions: CI
[error] 153-153: wsl_v5: missing whitespace above this line (invalid statement above assign)
[error] 154-154: wsl_v5: missing whitespace above this line (too many statements above range)
🤖 Prompt for AI Agents
In tf/tf.go around the region covering lines 152–199, the linter flagged missing
blank lines; add single blank lines after lines 152, 153, 157, 164, 184, 187,
and 198 (which also covers the specific spots 158, 165, 185, 188, 199 mentioned)
so each indicated line is followed by an empty line to satisfy wsl_v5 whitespace
rules and restore readability.
tf/tf.go
Outdated
| file, parseDiags := parseFunc(path.Join(modulePath, file.Name())) | ||
|
|
||
| hclFiles = append(hclFiles, file) | ||
| allDiags = append(allDiags, parseDiags...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Variable shadowing detected.
The variable file on line 165 shadows the loop variable file from line 149, making the code confusing and error-prone.
Apply this diff:
- file, parseDiags := parseFunc(path.Join(modulePath, file.Name()))
+ parsedFile, parseDiags := parseFunc(path.Join(modulePath, file.Name()))
- hclFiles = append(hclFiles, file)
+ hclFiles = append(hclFiles, parsedFile)
allDiags = append(allDiags, parseDiags...)🧰 Tools
🪛 GitHub Actions: CI
[error] 165-165: wsl_v5: missing whitespace above this line (invalid statement above assign)
🤖 Prompt for AI Agents
In tf/tf.go around lines 165 to 168, the local variable `file` returned from
parseFunc is shadowing the loop variable `file`; rename the value returned by
parseFunc (for example to `parsedFile` or `parsed`) and use that renamed
variable when appending to hclFiles and collecting diagnostics so the loop
variable remains unshadowed and the code is clear.
97170ba to
6c52da2
Compare
6c52da2 to
e9a8894
Compare
|
@yhakbar I had considered it, and really would prefer it, but I had two thoughts:
However text in the terraform-config-inspect readme made a really good point about the compatibility promise (alleviating the first point), and the presence of your suggestion mostly alleviates my concern for the second point (since it implies you're not concerned about this sort of implicit validation), so I went ahead and did it. I also added more test cases, some I just thought of when thinking about this "implicit validation" thing; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
tf/tf.go (1)
5-5: Consider usingpath/filepathinstead ofpathfor file system operations.The
pathpackage is designed for slash-separated paths (canonical/URL-style), whilepath/filepathhandles OS-specific path separators (e.g., backslash on Windows). Since this function works with file system paths fromos.ReadDirand joins them on line 169, usingfilepath.Joinwould ensure better cross-platform compatibility.Apply this diff:
import ( "os" - "path" + "path/filepath" "slices"Then update line 169:
- file, parseDiags := parseFunc(path.Join(modulePath, file.Name())) + file, parseDiags := parseFunc(filepath.Join(modulePath, file.Name()))
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
test/fixtures/hclvalidate/valid/duplicate-attributes-in-required-providers/main.tf(1 hunks)test/fixtures/hclvalidate/valid/duplicate-attributes-in-required-providers/terragrunt.hcl(1 hunks)tf/tf.go(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- test/fixtures/hclvalidate/valid/duplicate-attributes-in-required-providers/terragrunt.hcl
🧰 Additional context used
📓 Path-based instructions (1)
**/*.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:
tf/tf.go
🧠 Learnings (3)
📚 Learning: 2025-08-19T16:05:54.723Z
Learnt from: Resonance1584
Repo: gruntwork-io/terragrunt PR: 4683
File: go.mod:86-90
Timestamp: 2025-08-19T16:05:54.723Z
Learning: When analyzing Go module dependencies for removal, always check for both direct imports and API usage across all Go files in the repository, not just a quick search. The github.com/mattn/go-zglob library is used for filesystem walking and glob expansion in multiple Terragrunt files including util/file.go, format commands, and AWS provider patch functionality.
Applied to files:
tf/tf.go
📚 Learning: 2025-04-17T13:02:28.098Z
Learnt from: yhakbar
Repo: gruntwork-io/terragrunt PR: 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:
tf/tf.go
📚 Learning: 2025-02-10T13:36:19.542Z
Learnt from: levkohimins
Repo: gruntwork-io/terragrunt PR: 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:
tf/tf.go
🪛 GitHub Actions: CI
test/fixtures/hclvalidate/valid/duplicate-attributes-in-required-providers/main.tf
[error] 4-4: Attribute redefined. The argument 'attr' was already set at 3,5-9. Each argument may be set only once.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Pull Request has non-contributor approval
test/fixtures/hclvalidate/valid/duplicate-attributes-in-required-providers/main.tf
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this test case fails using the tfconfig package, but passes doing our own parsing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I stand corrected! I swear I saw this pass locally, but apparently I was imagining things.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! Great job!
|
Awesome, thank you very much. I was really not expecting this problem to be resolved quickly or by somebody else. |
Description
Terragrunt does not support using variables in the
sourceorversionfields ofmoduleblocks, but OpenTofu does.This becomes a problem because when validating inputs via
terragrunt hcl validate --inputswe use github.com/hashicorp/terraform-config-inspect to read the variables defined by the target module; since this is a Go module designed for Terraform it returns error diagnostics when variables are used as defined above.Thus a valid OpenTofu module will fail a run of
terragrunt hcl validate -inputs.Fixes #4986
Despite these error diagnostics, as long as the syntax is valid we don't actually care (we just want to know what variables are defined, and if they have defaults defined).
This PR totally removes this use of github.com/hashicorp/terraform-config-inspect , instead parsing the Terraform / Tofu code just for variable definitions, ignoring everything else (our goal is validating the Terragrunt code anyway, validating the Tofu / Terraform code should be left to the respective tools).
Also reworded the docs on
--inputs, as I found it a bit confusing.TODOs
Release Notes (draft)
Allow variables in module source / version
Summary by CodeRabbit
Bug Fixes
Tests
Documentation
Chores