Skip to content

chore: add internal-tflint strict control#5361

Merged
thisguycodes merged 17 commits intomainfrom
thisguycodes/chore/deprecate-embedded-tflint
Jan 26, 2026
Merged

chore: add internal-tflint strict control#5361
thisguycodes merged 17 commits intomainfrom
thisguycodes/chore/deprecate-embedded-tflint

Conversation

@thisguycodes
Copy link
Copy Markdown
Contributor

@thisguycodes thisguycodes commented Jan 14, 2026

Description

Starts the deprecation process for the embeded version of tflint.

Tflint is tainted by the BUSL license in Terraform; this prevents us from being able to keep the embedded version updated; fortunately our hooks system makes running a local version of tflint pretty easy!

This PR creates a new strict control that forces the use of external tflint, maintaining the automatic tflint init and passing of variables.

TODOs

  • 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)

Add strict control for deprecation of embedded tflint, our ability to embed having been hampered by the BUSL license change in Terraform.

Migration Guide

No breaking changes right now. But if you use the embedded tflint right now you can ensure no breakages when we later remove it by adding the --terragrunt-external-tflint flag:

terraform {
  before_hook "before_hook" {
    commands     = ["apply", "plan"]
    execute      = ["tflint", "--terragrunt-external-tflint"]
  }
}

Or by enabling the legacy-internal-tflint strict control.

When the embedded tflint is later removed, we will still strip this flag, perform automatic tflint init, and pass in variables when running the external tool.

Summary by CodeRabbit

  • New Features

    • Added a strict control to select internal vs external TFLint behavior and a command-line opt-in to force external TFLint.
  • Documentation

    • Updated TFLint integration docs with deprecation notice for the internal mode, usage examples, and guidance for opting into external TFLint.

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

@thisguycodes thisguycodes self-assigned this Jan 14, 2026
@vercel
Copy link
Copy Markdown

vercel bot commented Jan 14, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
terragrunt-docs Error Error Jan 26, 2026 6:33pm

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Jan 14, 2026

📝 Walkthrough

Walkthrough

Adds a legacy strict control InternalTFLint, detects an action-level TfExternalTFLint flag in hook parsing, and propagates an externalTfLint boolean from executeTFLint into RunTflintWithOpts; documentation and tooling updated to reflect deprecation and opt-in behavior.

Changes

Cohort / File(s) Summary
TFLint execution & hook integration
internal/runner/run/hook.go, internal/tflint/tflint.go
Detects TfExternalTFLint in hook action params; unified TFLint invocation through executeTFLint and added externalTfLint bool parameter passed to RunTflintWithOpts. Renamed/exported constant to TfExternalTFLint, adjusted config resolution and error propagation.
Strict controls
internal/strict/controls/controls.go, internal/strict/strict.go
Added exported constant InternalTFLint = "legacy-internal-tflint" and registered a new control in New(). Updated package doc reference path.
Docs
docs-starlight/src/content/docs/04-reference/03-strict-controls.mdx, docs-starlight/src/content/docs/03-features/10-hooks.mdx
Documented legacy-internal-tflint control, deprecation messaging, and opt-in flag --terragrunt-external-tflint; formatting and example updates.
Tooling
mise.toml
Added go:golang.org/x/tools/cmd/goimports = "0.38.0" under [tools].

Sequence Diagram

sequenceDiagram
    participant Hook as Hook Executor
    participant Strict as Strict Controls
    participant TFLint as TFLint Runner

    Hook->>Hook: Inspect actionParams for TfExternalTFLint
    alt TfExternalTFLint present
        Hook->>TFLint: executeTFLint(..., externalTfLint=true)
    else TfExternalTFLint absent
        Hook->>Strict: Query InternalTFLint control
        Strict-->>Hook: control value (true/false)
        Hook->>TFLint: executeTFLint(..., externalTfLint=derived)
    end
    TFLint->>TFLint: RunTflintWithOpts(..., externalTfLint)
    TFLint-->>Hook: return result / error
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • denis256
  • yhakbar
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'chore: add internal-tflint strict control' clearly describes the main change: adding a new strict control for the internal tflint deprecation process.
Description check ✅ Passed The PR description is comprehensive and covers the core requirements: rationale for change, technical approach, documentation updates, and release notes with migration guide. All critical checklist items are addressed.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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.

@thisguycodes thisguycodes force-pushed the thisguycodes/chore/deprecate-embedded-tflint branch from 97fd836 to f57d944 Compare January 23, 2026 18:06
@thisguycodes thisguycodes changed the title [WIP] add embedded-tflint deprecation notice add internal-tflint strict control Jan 23, 2026
@thisguycodes thisguycodes marked this pull request as ready for review January 23, 2026 20:13
Comment thread internal/runner/run/hook.go Outdated
Comment thread internal/runner/run/hook.go Outdated
Comment thread internal/tflint/tflint.go Outdated
yhakbar
yhakbar previously approved these changes Jan 23, 2026
Copy link
Copy Markdown
Collaborator

@yhakbar yhakbar left a comment

Choose a reason for hiding this comment

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

Looks good!

Copy link
Copy Markdown
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

🤖 Fix all issues with AI agents
In `@internal/runner/run/hook.go`:
- Around line 190-194: The code calls opts.StrictControls.Find(...) without
guarding against opts.StrictControls being nil; add a nil check for
opts.StrictControls before calling StrictControls.Find to avoid a panic (e.g.,
only call opts.StrictControls.Find(controls.InternalTFLint) when
opts.StrictControls != nil), keep the existing check that strictControl != nil
before calling strictControl.Evaluate(ctx), and ensure forceExternalTFLint is
set based on the guarded result; references: opts.StrictControls,
StrictControls.Find, controls.InternalTFLint, strictControl.Evaluate.

Comment thread internal/runner/run/hook.go
Comment thread internal/strict/controls/controls.go Outdated
yhakbar
yhakbar previously approved these changes Jan 23, 2026
yhakbar
yhakbar previously approved these changes Jan 23, 2026
yhakbar
yhakbar previously approved these changes Jan 23, 2026
@thisguycodes
Copy link
Copy Markdown
Contributor Author

I've discovered that our internal running of tflint was actually automatically running tflint --init, even for external tflint binaries; this means my "totally bypass the tflit package" strategy doesn't work.

I'm refactoring to still do the init automatically.

@thisguycodes thisguycodes force-pushed the thisguycodes/chore/deprecate-embedded-tflint branch from fe693c1 to 89478e9 Compare January 26, 2026 17:01
Copy link
Copy Markdown
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

🤖 Fix all issues with AI agents
In `@internal/tflint/tflint.go`:
- Around line 86-94: Replace the accidental redeclaration of args by creating a
new execArgs slice and use it for the command construction: create execArgs :=
make([]string, 0, 5+len(variables)+len(tfVariables)+len(tflintArgs)), then
append the same items ( "tflint", "--config", configFile, "--chdir",
opts.WorkingDir, variables..., tfVariables..., tflintArgs...) into execArgs and
update all subsequent uses of args in this function to use execArgs (references
around where args is later consumed). This avoids the := redeclaration error
with the existing args identifier and keeps the assembled command in execArgs.
♻️ Duplicate comments (1)
internal/runner/run/hook.go (1)

187-192: Add nil check for opts.StrictControls to prevent potential panic.

If opts.StrictControls is nil, calling Find on it will cause a nil pointer dereference. This was identified in a previous review and the author acknowledged they would add a nil check.

🛡️ Proposed defensive check
 	} else {
-		strictControl := opts.StrictControls.Find(controls.InternalTFLint)
-
 		forceExternalTFLint := false
-		if strictControl != nil && strictControl.Evaluate(ctx) != nil {
-			forceExternalTFLint = true
+		if opts.StrictControls != nil {
+			strictControl := opts.StrictControls.Find(controls.InternalTFLint)
+			if strictControl != nil && strictControl.Evaluate(ctx) != nil {
+				forceExternalTFLint = true
+			}
 		}

 		return executeTFLint(ctx, l, opts, cfg, curHook, workingDir, forceExternalTFLint)
 	}
🧹 Nitpick comments (2)
mise.toml (1)

8-8: Version format inconsistency with other Go tools.

Other Go tool entries use the v prefix (e.g., v0.9.0, v0.6.0, v0.20.0), but this entry uses 0.38.0 without the prefix. For consistency and to match the actual release tags on golang.org/x/tools, consider adding the v prefix.

♻️ Suggested fix
-"go:golang.org/x/tools/cmd/goimports" = "0.38.0"
+"go:golang.org/x/tools/cmd/goimports" = "v0.38.0"
docs-starlight/src/content/docs/03-features/10-hooks.mdx (1)

300-300: Minor: Extra whitespace in example.

There's an extra space after "tflint" before the comma that's inconsistent with other examples in the file.

📝 Suggested fix
-    execute = ["tflint" , "--terragrunt-external-tflint", "--minimum-failure-severity=error", "--config", "custom.tflint.hcl"]
+    execute = ["tflint", "--terragrunt-external-tflint", "--minimum-failure-severity=error", "--config", "custom.tflint.hcl"]

Comment thread internal/tflint/tflint.go
@thisguycodes thisguycodes force-pushed the thisguycodes/chore/deprecate-embedded-tflint branch from c9f7bdc to b1e36b6 Compare January 26, 2026 18:33
Copy link
Copy Markdown
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

🤖 Fix all issues with AI agents
In `@docs-starlight/src/content/docs/03-features/10-hooks.mdx`:
- Around line 276-279: In the <Aside type="warning"> block remove the duplicated
phrase "due to the adoption of a BUSL license" and rephrase the clause that
currently reads "due to the adoption of a BUSL license in `tflint` (due to the
adoption of a BUSL license in Terraform)" into a single concise explanation (for
example: "after Terraform adopted a BUSL license, `tflint` did as well"), so the
sentence reads clearly and without repetition while keeping the same meaning.

Comment on lines +276 to +279
<Aside type="warning">
Previous versions of Terragrunt shipped with a version of `tflint` compiled into the binary to allow for more convenient usage without installing `tflint` directly. Due to the adoption of a BUSL license in `tflint` (due to the adoption of a BUSL license in Terraform), the version included in Terragrunt was frozen.

Use of the internal `tflint` is deprecated, and will be removed in the future. You may opt in ahead of time by
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Tighten duplicated clause in the BUSL explanation.

The sentence repeats “due to the adoption…” twice. Consider tightening for clarity.

📝 Proposed fix
-    Previous versions of Terragrunt shipped with a version of `tflint` compiled into the binary to allow for more convenient usage without installing `tflint` directly. Due to the adoption of a BUSL license in `tflint` (due to the adoption of a BUSL license in Terraform), the version included in Terragrunt was frozen.
+    Previous versions of Terragrunt shipped with a version of `tflint` compiled into the binary to allow for more convenient usage without installing `tflint` directly. Due to the adoption of a BUSL license in `tflint` (following Terraform’s move), the version included in Terragrunt was frozen.
🤖 Prompt for AI Agents
In `@docs-starlight/src/content/docs/03-features/10-hooks.mdx` around lines 276 -
279, In the <Aside type="warning"> block remove the duplicated phrase "due to
the adoption of a BUSL license" and rephrase the clause that currently reads
"due to the adoption of a BUSL license in `tflint` (due to the adoption of a
BUSL license in Terraform)" into a single concise explanation (for example:
"after Terraform adopted a BUSL license, `tflint` did as well"), so the sentence
reads clearly and without repetition while keeping the same meaning.

Copy link
Copy Markdown
Collaborator

@yhakbar yhakbar left a comment

Choose a reason for hiding this comment

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

Looks good.

@thisguycodes thisguycodes merged commit 3371c49 into main Jan 26, 2026
48 of 51 checks passed
@thisguycodes thisguycodes deleted the thisguycodes/chore/deprecate-embedded-tflint branch January 26, 2026 19:44
@thisguycodes thisguycodes mentioned this pull request Jan 26, 2026
6 tasks
@coderabbitai coderabbitai bot mentioned this pull request Jan 28, 2026
6 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