Repository: gruntwork-io/terragrunt (language: go)

Issue:
Built-in tflint hook doesn't find .tflint.hcl if it's in the current directory
Minimal example:

```bash
mkdir -p demo
cd demo
touch main.tf
cat > .tflint.hcl <<-END
  config { format = "compact" }
END
cat > terragrunt.hcl <<-END
  terraform {
    before_hook "lint" {
      commands = ["validate"]
      execute  = ["tflint"]
    }
  }
END
terragrunt validate
```

This script fails on the last line with the error "Could not find .tflint.hcl config file in the parent folders: Traversed all the day to the root". Running `tflint` directly works as expected (it reads the config file in the current directory and prints a warning in compact format).

terragrunt version v0.43.2


Discussion / hints:

Fix patch:
diff --git a/.circleci/config.yml b/.circleci/config.yml
index bc769bee85..9cc63bcc4e 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -22,6 +22,10 @@ jobs:
           name: Install Terraform
           shell: powershell.exe
           command: ./_ci/install-terraform.ps1
+      - run:
+          name: Install TFLint
+          shell: powershell.exe
+          command: ./_ci/install-tflint.ps1
       - run:
           name: Run go tests
           shell: powershell.exe
@@ -30,6 +34,7 @@ jobs:
             # We're running this test only on Windows currently to provide a convenient
             # means of reproducing Terragrunt issues that only occur on that platform
             go test -v ./... -run TestWindowsTerragruntSourceMapDebug -timeout 45m
+            go test -v ./... -run TestWindowsTflintIsInvoked -timeout 45m
   # We're running unit tests separately from integration tests - with no parallelization.
   # With heavy parallelization coupled with re-use of test fixtures we've witnessed slight
   # instability with the tests. The unit tests are fast to execute, so there is negligible
diff --git a/_ci/install-tflint.ps1 b/_ci/install-tflint.ps1
new file mode 100755
index 0000000000..c958110801
--- /dev/null
+++ b/_ci/install-tflint.ps1
@@ -0,0 +1,5 @@
+# Install tflint using Chocolatey
+choco install tflint --version 0.42.2 -y
+# Verify installation
+Get-Command tflint
+tflint --version
diff --git a/tflint/tflint.go b/tflint/tflint.go
index ffc2193726..c0a3a53da3 100644
--- a/tflint/tflint.go
+++ b/tflint/tflint.go
@@ -88,7 +88,7 @@ func findTflintConfigInProject(terragruntOptions *options.TerragruntOptions) (st
 			return "", errors.WithStackTrace(ConfigNotFound{cause: "Traversed all the day to the root"})
 		}
 
-		fileToFind := util.JoinPath(currentDir, ".tflint.hcl")
+		fileToFind := util.JoinPath(previousDir, ".tflint.hcl")
 		if util.FileExists(fileToFind) {
 			terragruntOptions.Logger.Debugf("Found .tflint.hcl in %s", fileToFind)
 			return fileToFind, nil


Test patch:
diff --git a/test/fixture-tflint/no-tf-source/.tflint.hcl b/test/fixture-tflint/no-tf-source/.tflint.hcl
new file mode 100644
index 0000000000..96e458d68f
--- /dev/null
+++ b/test/fixture-tflint/no-tf-source/.tflint.hcl
@@ -0,0 +1,7 @@
+plugin "terraform" {
+  enabled = true
+  version = "0.2.1"
+  source  = "github.com/terraform-linters/tflint-ruleset-terraform"
+}
+
+config { format = "compact" }
diff --git a/test/fixture-tflint/no-tf-source/main.tf b/test/fixture-tflint/no-tf-source/main.tf
new file mode 100644
index 0000000000..863d200923
--- /dev/null
+++ b/test/fixture-tflint/no-tf-source/main.tf
@@ -0,0 +1,13 @@
+terraform {
+  required_providers {
+    random = {
+      version = ">= 3.4.0"
+    }
+  }
+
+  required_version = ">= 1.2.7"
+}
+
+resource "random_id" "env" {
+  byte_length = 8
+}
diff --git a/test/fixture-tflint/no-tf-source/outputs.tf b/test/fixture-tflint/no-tf-source/outputs.tf
new file mode 100644
index 0000000000..0e6cd937d3
--- /dev/null
+++ b/test/fixture-tflint/no-tf-source/outputs.tf
@@ -0,0 +1,1 @@
+# Empty outputs
diff --git a/test/fixture-tflint/no-tf-source/terragrunt.hcl b/test/fixture-tflint/no-tf-source/terragrunt.hcl
new file mode 100644
index 0000000000..ea162df822
--- /dev/null
+++ b/test/fixture-tflint/no-tf-source/terragrunt.hcl
@@ -0,0 +1,12 @@
+terraform {
+
+  before_hook "tflint" {
+    commands = ["apply", "plan"]
+    execute = ["tflint"]
+  }
+}
+
+inputs = {
+  aws_region = "us-west-2"
+  env = "dev"
+}
diff --git a/test/fixture-tflint/no-tf-source/variables.tf b/test/fixture-tflint/no-tf-source/variables.tf
new file mode 100644
index 0000000000..9d5a151939
--- /dev/null
+++ b/test/fixture-tflint/no-tf-source/variables.tf
@@ -0,0 +1,1 @@
+# Empty variables
diff --git a/test/integration_test.go b/test/integration_test.go
index 53a2e2d8ef..60f26406bc 100644
--- a/test/integration_test.go
+++ b/test/integration_test.go
@@ -137,6 +137,7 @@ const (
 	TEST_FIXTURE_TFLINT_ISSUES_FOUND                        = "fixture-tflint/issues-found"
 	TEST_FIXTURE_TFLINT_NO_CONFIG_FILE                      = "fixture-tflint/no-config-file"
 	TEST_FIXTURE_TFLINT_MODULE_FOUND                        = "fixture-tflint/module-found"
+	TEST_FIXTURE_TFLINT_NO_TF_SOURCE_PATH                   = "fixture-tflint/no-tf-source"
 	TERRAFORM_BINARY                                        = "terraform"
 	TERRAFORM_FOLDER                                        = ".terraform"
 	TERRAFORM_STATE                                         = "terraform.tfstate"
@@ -5238,11 +5239,13 @@ func TestTflintFindsNoIssuesWithValidCode(t *testing.T) {
 	errOut := new(bytes.Buffer)
 	rootPath := copyEnvironmentWithTflint(t, TEST_FIXTURE_TFLINT_NO_ISSUES_FOUND)
 	modulePath := util.JoinPath(rootPath, TEST_FIXTURE_TFLINT_NO_ISSUES_FOUND)
-	err := runTerragruntCommand(t, fmt.Sprintf("terragrunt plan --terragrunt-working-dir %s", modulePath), out, errOut)
+	err := runTerragruntCommand(t, fmt.Sprintf("terragrunt plan --terragrunt-log-level debug --terragrunt-working-dir %s", modulePath), out, errOut)
 	assert.NoError(t, err)
 
 	assert.NotContains(t, errOut.String(), "Error while running tflint with args:")
 	assert.NotContains(t, errOut.String(), "Tflint found issues in the project. Check for the tflint logs above.")
+
+	assert.Contains(t, errOut.String(), fmt.Sprintf("--config %s/.tflint.hcl", modulePath))
 }
 
 func TestTflintFindsModule(t *testing.T) {
@@ -5272,3 +5275,15 @@ func TestTflintWithoutConfigFile(t *testing.T) {
 	err := runTerragruntCommand(t, fmt.Sprintf("terragrunt plan --terragrunt-working-dir %s", modulePath), io.Discard, errOut)
 	assert.Error(t, err, "Could not find .tflint.hcl config file in the parent folders:")
 }
+
+func TestTflintFindsConfigInCurrentPath(t *testing.T) {
+	out := new(bytes.Buffer)
+	errOut := new(bytes.Buffer)
+	rootPath := copyEnvironmentWithTflint(t, TEST_FIXTURE_TFLINT_NO_TF_SOURCE_PATH)
+	modulePath := util.JoinPath(rootPath, TEST_FIXTURE_TFLINT_NO_TF_SOURCE_PATH)
+	err := runTerragruntCommand(t, fmt.Sprintf("terragrunt plan --terragrunt-log-level debug --terragrunt-working-dir %s", modulePath), out, errOut)
+	assert.NoError(t, err)
+
+	assert.Contains(t, errOut.String(), "Tflint has run successfully. No issues found")
+	assert.Contains(t, errOut.String(), fmt.Sprintf("--config %s/.tflint.hcl", modulePath))
+}
diff --git a/test/integration_windows_test.go b/test/integration_windows_test.go
index 2576c760e4..df4943df07 100644
--- a/test/integration_windows_test.go
+++ b/test/integration_windows_test.go
@@ -4,11 +4,15 @@
 package test
 
 import (
+	"bytes"
 	"fmt"
 	"os"
 	"path/filepath"
 	"strings"
 	"testing"
+
+	"github.com/gruntwork-io/terragrunt/util"
+	"github.com/stretchr/testify/assert"
 )
 
 const (
@@ -64,3 +68,17 @@ func TestWindowsTerragruntSourceMapDebug(t *testing.T) {
 		})
 	}
 }
+
+func TestWindowsTflintIsInvoked(t *testing.T) {
+	out := new(bytes.Buffer)
+	errOut := new(bytes.Buffer)
+	rootPath := copyEnvironmentWithTflint(t, TEST_FIXTURE_TFLINT_NO_ISSUES_FOUND)
+	modulePath := util.JoinPath(rootPath, TEST_FIXTURE_TFLINT_NO_ISSUES_FOUND)
+	err := runTerragruntCommand(t, fmt.Sprintf("terragrunt plan --terragrunt-log-level debug --terragrunt-working-dir %s", modulePath), out, errOut)
+	assert.NoError(t, err)
+
+	assert.NotContains(t, errOut.String(), "Error while running tflint with args:")
+	assert.NotContains(t, errOut.String(), "Tflint found issues in the project. Check for the tflint logs above.")
+
+	assert.Contains(t, errOut.String(), fmt.Sprintf("--config %s/.tflint.hcl", modulePath))
+}