@@ -16,15 +16,16 @@ import (
1616)
1717
1818const (
19- includeDeepFixturePath = "fixtures/include-deep/"
20- includeDeepFixtureChildPath = "child"
21- includeFixturePath = "fixtures/include/"
22- includeShallowFixturePath = "stage/my-app"
23- includeNoMergeFixturePath = "qa/my-app"
24- includeExposeFixturePath = "fixtures/include-expose/"
25- includeChildFixturePath = "child"
26- includeMultipleFixturePath = "fixtures/include-multiple/"
27- includeRunAllFixturePath = "fixtures/include-runall/"
19+ includeDeepFixturePath = "fixtures/include-deep/"
20+ includeDeepFixtureChildPath = "child"
21+ includeFixturePath = "fixtures/include/"
22+ includeShallowFixturePath = "stage/my-app"
23+ includeNoMergeFixturePath = "qa/my-app"
24+ includeExposeFixturePath = "fixtures/include-expose/"
25+ includeChildFixturePath = "child"
26+ includeMultipleFixturePath = "fixtures/include-multiple/"
27+ includeRunAllFixturePath = "fixtures/include-runall/"
28+ rootTerragruntHCLFixturePath = "fixtures/root-terragrunt-hcl-regression/"
2829)
2930
3031func TestTerragruntWorksWithIncludeLocals (t * testing.T ) {
@@ -268,6 +269,55 @@ func TestTerragruntWorksWithMultipleInclude(t *testing.T) {
268269 }
269270}
270271
272+ func TestTerragruntWorksWithRootTerragruntHCL (t * testing.T ) {
273+ t .Parallel ()
274+
275+ // This is a regression test to ensure that users can still have a root terragrunt.hcl at the project root,
276+ // and run Terragrunt from that root, as long as they exclude that directory from the queue.
277+ //
278+ // In this fixture, the child units include the root config via:
279+ // path = find_in_parent_folders("terragrunt.hcl")
280+ //
281+ // The key requirement is: excluding "." should prevent Terragrunt from trying to treat the root directory
282+ // itself as a unit, while still allowing the root terragrunt.hcl to be used for includes.
283+ tmpEnvPath := helpers .CopyEnvironment (t , rootTerragruntHCLFixturePath )
284+ rootPath := filepath .Join (tmpEnvPath , rootTerragruntHCLFixturePath )
285+ rootPath , err := filepath .EvalSymlinks (rootPath )
286+ require .NoError (t , err )
287+
288+ stdout , stderr , err := helpers .RunTerragruntCommandWithOutput (
289+ t ,
290+ "terragrunt run --all --non-interactive --log-level trace --working-dir " + rootPath + " --queue-exclude-dir=. -- plan" ,
291+ )
292+ require .NoError (t , err , "stdout:\n %s\n stderr:\n %s" , stdout , stderr )
293+
294+ // Excluding "." should skip parsing the root directory as a component.
295+ assert .Contains (t , stderr , "Skipping parse for excluded component: ." )
296+
297+ // Child configs should still be able to include the root `terragrunt.hcl` (deprecated, but supported).
298+ assert .Regexp (t , `Included config \./terragrunt\.hcl` , stderr )
299+
300+ // And the child units should still be discovered.
301+ assert .Contains (t , stderr , "=> Unit bar (excluded: false" )
302+ assert .Contains (t , stderr , "=> Unit baz (excluded: false" )
303+ assert .Contains (t , stderr , "=> Unit foo (excluded: false" )
304+
305+ // And they should be queued for execution.
306+ assert .Contains (t , stderr , "Unit queue will be processed for plan in this order:" )
307+ assert .Contains (t , stderr , "- Unit bar" )
308+ assert .Contains (t , stderr , "- Unit baz" )
309+ assert .Contains (t , stderr , "- Unit foo" )
310+
311+ // Root should not be treated as a runnable unit.
312+ assert .Contains (t , stderr , "=> Unit . (excluded: true" )
313+
314+ assert .NotContains (t , stderr , "=> Unit bar (excluded: true" )
315+ assert .NotContains (t , stderr , "=> Unit baz (excluded: true" )
316+ assert .NotContains (t , stderr , "=> Unit foo (excluded: true" )
317+
318+ assert .NotContains (t , stderr , "Runner Pool Controller: starting with 0 tasks" )
319+ }
320+
271321func validateMultipleIncludeTestOutput (t * testing.T , outputs map [string ]helpers.TerraformOutput ) {
272322 t .Helper ()
273323
0 commit comments