Skip to content

Conversation

rorychatterton
Copy link

@rorychatterton rorychatterton commented Sep 24, 2025

closes #2389

This change adds support for JSON-formatted TFLint configuration files (.tflint.json) in addition to the existing HCL format (.tflint.hcl).

Changes:

  • Update config loading to detect file extension and parse JSON/HCL accordingly
  • Add support for .tflint.json in default file discovery
  • Maintain HCL preference over JSON files
  • Add unit tests for JSON config loading scenarios
  • Add integration tests for JSON config functionality and precedence
  • Update user guide documentation with JSON format examples

The implementation uses the existing hclparse.ParseJSON() from the HCL library, following the same JSON structure conventions as Terraform's .tf.json files. Existing functionality remains unchanged.

Other:

  • Unit Tests Pass
  • Integration Tests Pass in CI
  • Confirm Source Map - As in the other thread, need to confirm that the sources data structure supports JSON, or whether we need to create an intermediary representation as HCL
  • Update Bundled Plugin to use SDK 0.23.0

For full transparency, I used Claude Code to help generate this commit, but am responsible for reviews etc.

@rorychatterton rorychatterton force-pushed the 09-24-feature_-_json_configuration_support branch from a963a04 to 29f637e Compare September 24, 2025 04:14
@rorychatterton rorychatterton marked this pull request as ready for review September 24, 2025 04:44
@rorychatterton rorychatterton marked this pull request as draft September 25, 2025 04:44
@rorychatterton rorychatterton force-pushed the 09-24-feature_-_json_configuration_support branch from 6c5caa0 to c84a32a Compare September 25, 2025 07:47
@rorychatterton
Copy link
Author

rorychatterton commented Sep 25, 2025

This PR has been updated to include a compatibility shim for plugins using SDK versions < 0.23.0.

The Problem

Plugins using SDK < 0.23.0 cannot parse JSON config files with .json extensions - they only recognize .tf.json as valid JSON. This causes errors when rules with custom parameters try to parse the config.

The Solution

Added a compatibility shim that:

  • Detects plugin SDK versions during initialization
  • For plugins with SDK < 0.23.0, the shim renames the json file to tf.json and reparses the configs to ensure the paths are correct.
  • Logs warnings to inform users about compatibility mode
  • Ensures all third-party plugins work regardless of SDK version

Current Test Status

The integration test is failing because the bundled terraform ruleset bypasses the init version checks that apply to third-party plugins. Rather than adding special-case handling for the bundled ruleset, the simpler solution is to wait for this PR to be merged and SDK v0.23.0 to be published.

Once the SDK is updated, the bundled plugin will natively support .json extensions and all tests will pass. The compatibility shim will continue to ensure backward compatibility for any third-party plugins still using older SDK versions.

@rorychatterton rorychatterton force-pushed the 09-24-feature_-_json_configuration_support branch 5 times, most recently from ced163f to e3118f9 Compare September 29, 2025 04:18
@rorychatterton rorychatterton marked this pull request as ready for review September 29, 2025 04:19
@rorychatterton rorychatterton force-pushed the 09-24-feature_-_json_configuration_support branch from e3118f9 to 1335832 Compare September 29, 2025 04:33
@rorychatterton rorychatterton force-pushed the 09-24-feature_-_json_configuration_support branch from 1335832 to e443f8c Compare September 29, 2025 04:51
@rorychatterton rorychatterton marked this pull request as draft September 29, 2025 05:10
@rorychatterton rorychatterton force-pushed the 09-24-feature_-_json_configuration_support branch 2 times, most recently from 672d813 to 089b88d Compare September 29, 2025 10:31
…sion checking

- Add support for JSON configuration files (.tflint.json)
- Detect JSON configs by file extension, not filename pattern
- Centralize all plugin version checking logic into plugin/plugin_version.go
- Enforce SDK version 0.23+ for JSON configuration support
- Split version checking: TFLint constraints checked before ApplyGlobalConfig,
  SDK versions checked after to avoid plugin initialization failures
- Add comprehensive unit tests for SDK version validation
- Update documentation to mention JSON configuration support

This allows users to use JSON configuration files with any name when
using the --config flag, while ensuring proper plugin compatibility.
@rorychatterton rorychatterton force-pushed the 09-24-feature_-_json_configuration_support branch from 089b88d to 0807dfb Compare September 29, 2025 10:37
@rorychatterton
Copy link
Author

Sorry about the commit noise. I use Graphite to manage my CI in the backend and it gets a little pushy.

This should be ready to review now. In summary:

Changes by Component

Plugin Version Checking (plugin/plugin_version.go)

  • Extracted all version validation logic from cmd/inspect.go into
    centralised functions
  • Created CheckTFLintVersionConstraints() and
    CheckSDKVersionSatisfiesConstraints()
  • Added version constants: DefaultSDKVersionConstraints (>=0.16.0),
    JSONConfigSDKVersionConstraints (>=0.23.0)

Config Loading (tflint/config.go, tflint/config_test.go)

  • Modified LoadConfig() to detect JSON files by extension and parse
    accordingly
  • Added isJSONConfig field and IsJSONConfig() method to track config
    type
  • Updated tests to cover JSON loading scenarios

Inspection Flow (cmd/inspect.go)

  • Removed inline version checking code, now calls centralized functions
  • Split checks: TFLint constraints in launchPlugins() before
    ApplyGlobalConfig, SDK checks in ValidatePluginVersions() after

Language Server (langserver/handler.go)

  • Updated to use centralized version checking functions
  • Now properly detects JSON configs via cfg.IsJSONConfig() and enforces
    appropriate SDK requirements

Testing

  • Added plugin/plugin_version_test.go with SDK version validation tests
  • Added integration tests in integrationtest/cli/ for JSON config loading
    and HCL/JSON precedence

@rorychatterton rorychatterton marked this pull request as ready for review September 29, 2025 10:39
Copy link
Member

@bendrucker bendrucker left a comment

Choose a reason for hiding this comment

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

Nice work here! Couple minor code readability comments, if you have time, it would be helpful. Otherwise I can make those edits.

Comment on lines +252 to +257
switch {
case strings.HasSuffix(strings.ToLower(file.Name()), ".json"):
f, diags = parser.ParseJSON(src, file.Name())
default:
f, diags = parser.ParseHCL(src, file.Name())
}
Copy link
Member

Choose a reason for hiding this comment

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

A switch expression with case expressions is easier to read than a bare switch:

Suggested change
switch {
case strings.HasSuffix(strings.ToLower(file.Name()), ".json"):
f, diags = parser.ParseJSON(src, file.Name())
default:
f, diags = parser.ParseHCL(src, file.Name())
}
switch filepath.Ext(file.Name()) {
case ".json":
f, diags = parser.ParseJSON(src, file.Name())
default:
f, diags = parser.ParseHCL(src, file.Name())
}

You'll need to import filepath too

config := EmptyConfig()
config.sources = parser.Sources()
// Set the flag if this is a JSON config file
config.isJSONConfig = strings.HasSuffix(strings.ToLower(file.Name()), ".json")
Copy link
Member

Choose a reason for hiding this comment

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

Declare the empty config earlier so you can just do config.isJSONConfig = true in the switch statement rather than repeating the extension check.


// IsJSONConfig returns true if the configuration was loaded from a JSON file
func (c *Config) IsJSONConfig() bool {
return c.isJSONConfig
Copy link
Member

Choose a reason for hiding this comment

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

Alternatively, you could just store the config path on the config object, unexported. Or expect it as the first/only key in sources. And then call return filepath.Ext(filename) == ".json" here

@rorychatterton
Copy link
Author

rorychatterton commented Oct 18, 2025

I'm travelling without my work computer til the 5th of November. Happy to make the changes on my return, else feel free to make them :).

Copy link
Member

@wata727 wata727 left a comment

Choose a reason for hiding this comment

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

👍

Once you've addressed Ben's comments, we can merge this PR.

@@ -1,4 +1,4 @@
package main
package inspection
Copy link
Member

Choose a reason for hiding this comment

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

Is there a reason why you changed the package name?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

TFLInt JSON Configuration Support

3 participants