Skip to content

Conversation

@HeikoNeblung
Copy link

@HeikoNeblung HeikoNeblung commented Dec 13, 2025

Description

Fixes #5089

Exclude blocks defined in parent configuration files will be merged in the resulting config even when no exclude block is present in current configuration.

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)

fixed handling of included exclude blocks

Migration Guide

n/a

Summary by CodeRabbit

  • Bug Fixes
    • Fixed configuration merging to properly preserve exclude rules from included configurations when the parent configuration doesn't define its own exclude rules. This ensures exclude configurations are respected consistently across configuration hierarchies.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Dec 13, 2025

@HeikoNeblung is attempting to deploy a commit to the Gruntwork Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 13, 2025

📝 Walkthrough

Walkthrough

The change modifies the config parsing logic to conditionally preserve the Exclude block from an included configuration file. Previously, any Exclude block from an included config would be unconditionally merged into the current config; now it is only applied if the current config has not already defined an Exclude block.

Changes

Cohort / File(s) Summary
Config merge logic
config/config.go
Modified the ParseConfig function to conditionally merge Exclude blocks from included configs, preserving the included Exclude only when the current config does not define its own Exclude block

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Suggested reviewers

  • denis256
  • yhakbar
  • ThisGuyCodes

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR addresses issue #5059 by fixing Exclude block merging behavior. However, the linked issue concerns HCL validation with validation blocks in variables, which appears unrelated to the Exclude config merging change. Verify that the Exclude config fix actually resolves the HCL validation issue #5059, or confirm if this PR addresses a different aspect of the same issue than the validation block problem described.
Out of Scope Changes check ❓ Inconclusive The code change is narrowly focused on Exclude config merging in ParseConfig. However, this change may be out of scope relative to the linked issue about HCL validation with validation blocks in variables. Clarify the relationship between the Exclude config merging fix and the HCL validation failure reported in issue #5059 to confirm scope alignment.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main code change: preventing overwriting of Exclude config when not explicitly set in the current configuration.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description check ✅ Passed The PR description includes all required template sections: issue reference (#5089), clear description of changes, completed TODO checklist, and release notes. Minor detail: migration guide states 'n/a' rather than being omitted.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • 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

Comment @coderabbitai help to get the list of available commands and usage tips.

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: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 971e7f3 and 583ac4b.

📒 Files selected for processing (1)
  • config/config.go (1 hunks)
🧰 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:

  • config/config.go
🧬 Code graph analysis (1)
config/config.go (1)
cli/commands/find/cli.go (1)
  • Exclude (27-27)

Comment on lines +1353 to +1357

// preserve included Exclude config when no Exclude config is present in current config
if config.Exclude != nil {
mergedConfig.Exclude = config.Exclude
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, let's examine the code around lines 1353-1357 to understand the full context
cat -n config/config.go | sed -n '1340,1365p'

Repository: gruntwork-io/terragrunt

Length of output: 1391


🏁 Script executed:

# Run the verification script to examine handleInclude and FieldsMetadata behavior
#!/bin/bash
set -euo pipefail

echo "=== Locate handleInclude implementation ==="
rg -n 'func\s+handleInclude' config/ -A 15 || true

echo
echo "=== Find where Exclude is merged/overridden ==="
rg -n 'Exclude\s*=' config/config.go | head -20

echo
echo "=== Find FieldsMetadata operations ==="
rg -n 'FieldsMetadata|SetFieldMetadata' config/config.go | head -30

echo
echo "=== Look for tests with include/exclude ==="
find . -name '*test.go' -type f | head -10

Repository: gruntwork-io/terragrunt

Length of output: 5715


🏁 Script executed:

# Check if SetFieldMetadata method exists
rg -n 'func.*SetFieldMetadata' . --type go

Repository: gruntwork-io/terragrunt

Length of output: 436


🏁 Script executed:

# Get the full handleInclude implementation
cat -n config/include.go | sed -n '116,183p'

Repository: gruntwork-io/terragrunt

Length of output: 3241


🏁 Script executed:

# Check the merge strategy implementation
rg -n 'GetMergeStrategy|mergeStrategy' config/include.go -A 5 -B 2 | head -60

Repository: gruntwork-io/terragrunt

Length of output: 2033


🏁 Script executed:

# Search for exclude-related tests
find . -name '*test.go' -type f | xargs rg -l 'exclude' -i | head -10

Repository: gruntwork-io/terragrunt

Length of output: 389


🏁 Script executed:

# Look at the actual merge function to see how metadata is handled
rg -n 'func.*merge|mergeWith' config/include.go -A 10 | head -80

Repository: gruntwork-io/terragrunt

Length of output: 3336


🏁 Script executed:

# Find Merge and DeepMerge implementations
rg -n 'func.*\(.*TerragruntConfig\).*Merge' config/ -A 20 | head -120

Repository: gruntwork-io/terragrunt

Length of output: 2357


🏁 Script executed:

# Look specifically for how Exclude is handled in merge operations
rg -n 'Exclude' config/config.go -B 2 -A 2

Repository: gruntwork-io/terragrunt

Length of output: 2275


🏁 Script executed:

# Check if FieldsMetadata is copied during merge
rg -n 'FieldsMetadata' config/config.go -B 1 -A 1 | head -60

Repository: gruntwork-io/terragrunt

Length of output: 826


🏁 Script executed:

# Get complete Merge implementation
sed -n '242,363p' config/include.go | cat -n

Repository: gruntwork-io/terragrunt

Length of output: 5193


🏁 Script executed:

# Get complete DeepMerge implementation
sed -n '364,500p' config/include.go | cat -n

Repository: gruntwork-io/terragrunt

Length of output: 5204


🏁 Script executed:

# Check if Exclude is handled in Merge or DeepMerge
rg -n 'Exclude' config/include.go

Repository: gruntwork-io/terragrunt

Length of output: 740


🏁 Script executed:

# Get the end of DeepMerge function
sed -n '364,600p' config/include.go | tail -100

Repository: gruntwork-io/terragrunt

Length of output: 3084


🏁 Script executed:

# Find CopyFieldsMetadata implementation
rg -n 'func.*CopyFieldsMetadata' config/ -A 30

Repository: gruntwork-io/terragrunt

Length of output: 3260


🏁 Script executed:

# Check if there are tests for exclude + include scenarios
find . -name '*test.go' -type f -exec rg -l 'exclude.*include|include.*exclude' {} \; | head -5

Repository: gruntwork-io/terragrunt

Length of output: 258


🏁 Script executed:

# Search for tests related to exclude and include
rg -n 'exclude.*include|Exclude.*Include' test/ config/ -i | grep -i test

Repository: gruntwork-io/terragrunt

Length of output: 1125


🏁 Script executed:

# Look for integration tests that might test this scenario
rg -n 'func.*Test.*Exclude|func.*Test.*Include' test/ -A 5 | head -100

Repository: gruntwork-io/terragrunt

Length of output: 6732


🏁 Script executed:

# Check integration_regressions_test.go which was found
rg -n 'exclude|Exclude' test/integration_regressions_test.go -B 2 -A 5 | head -80

Repository: gruntwork-io/terragrunt

Length of output: 3563


🏁 Script executed:

# Search for uses of FieldsMetadata and GetFieldMetadata related to exclude
rg -n 'GetFieldMetadata|FieldsMetadata\[.*exclude' config/ -i -C 3

Repository: gruntwork-io/terragrunt

Length of output: 804


🏁 Script executed:

# Check if metadata is used for validation or error reporting
rg -n 'FoundInFile|FieldsMetadata' config/ -B 2 -A 2 | grep -A 10 -B 10 'exclude\|Exclude' | head -80

Repository: gruntwork-io/terragrunt

Length of output: 49


🏁 Script executed:

# Look for any code that validates or uses metadata for exclude specifically
rg -n 'exclude' config/config.go | grep -i metadata

Repository: gruntwork-io/terragrunt

Length of output: 118


🏁 Script executed:

# Find where defaultMetadata is created/defined
rg -n 'defaultMetadata\s*:=' config/ -B 5 -A 2

Repository: gruntwork-io/terragrunt

Length of output: 488


🏁 Script executed:

# Look for FoundInFile constant/usage
rg -n 'FoundInFile' config/

Repository: gruntwork-io/terragrunt

Length of output: 282


🏁 Script executed:

# Check the full context of lines around 1713 to see how defaultMetadata is built
sed -n '1700,1720p' config/config.go | cat -n

Repository: gruntwork-io/terragrunt

Length of output: 986


Ensure exclude field metadata is updated when child config overrides the included value.

The override at lines 1355–1356 correctly preserves the included exclude when the child omits it. However, the FieldsMetadata[exclude] is not updated, leaving it pointing to the included file instead of the current config file. This causes metadata to be inconsistent with the value's origin, which can lead to confusing error messages and incorrect file attribution in logs.

Add a SetFieldMetadata call after the override to keep metadata in sync:

 // preserve included Exclude config when no Exclude config is present in current config
 if config.Exclude != nil {
     mergedConfig.Exclude = config.Exclude
+    mergedConfig.SetFieldMetadata(MetadataExclude, map[string]any{FoundInFile: config.ConfigPath})
 }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In config/config.go around lines 1353 to 1357, when preserving the included
Exclude value for a child that omits it the code assigns mergedConfig.Exclude =
config.Exclude but does not update FieldsMetadata; update metadata immediately
after the assignment by calling mergedConfig.SetFieldMetadata for the "exclude"
field using the current child config's metadata (e.g., the child's file path or
its FieldsMetadata entry for "exclude") so the merged metadata reflects the
child config as the origin.

@HeikoNeblung
Copy link
Author

Hi @yhakbar i had to rebase my branch to fix the tests on macos. Unfortunately the original PR was closed by this. Can you please run the CI again on your site. The base-test was sucessful in my forked repo.

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.

Imported exclude block not working on single unit commands

1 participant