diff --git a/README.md b/README.md index cf76f0ac3..dc94d9102 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ trunk check enable {linter} | Terraform | [terraform] (validate and fmt), [checkov], [tflint], [tfsec], [terrascan], [tofu] | | Terragrunt | [terragrunt] | | Textproto | [txtpbfmt] | -| TOML | [taplo] | +| TOML | [taplo], [toml-tidy] | | Typescript | [deno], [eslint], [prettier], [rome], [semgrep] | | YAML | [prettier], [semgrep], [yamlfmt], [yamllint] | @@ -189,6 +189,7 @@ trunk check enable {linter} [swiftformat]: https://github.com/nicklockwood/SwiftFormat#readme [swiftlint]: https://github.com/realm/SwiftLint#readme [taplo]: https://github.com/tamasfe/taplo#readme +[toml-tidy]: https://github.com/AndrewDongminYoo/toml-tidy#readme [terrascan]: https://github.com/tenable/terrascan#readme [terraform]: https://developer.hashicorp.com/terraform/cli/code [tofu]: https://opentofu.org/ diff --git a/linters/toml-tidy/README.md b/linters/toml-tidy/README.md new file mode 100644 index 000000000..888634ea4 --- /dev/null +++ b/linters/toml-tidy/README.md @@ -0,0 +1,21 @@ +# toml-tidy + +[toml-tidy](https://github.com/AndrewDongminYoo/toml-tidy) sorts TOML keys within each table while +preserving table hierarchy, comments, and source formatting. It complements +[taplo](https://github.com/tamasfe/taplo) (formatting) rather than replacing it — the relationship +mirrors `prettier` and `sort-package-json` for `package.json`. + +toml-tidy requires Python >= 3.12, which is newer than the default hermetic Python runtime, so +enable a compatible runtime alongside the linter: + +```yaml +runtimes: + enabled: + - python@3.12.2 +lint: + enabled: + - toml-tidy@0.2.0 +``` + +Per-file defaults (sort order, scope, pinned-first tables) can be configured in the nearest +`pyproject.toml` under `[tool.toml-tidy]`. diff --git a/linters/toml-tidy/plugin.yaml b/linters/toml-tidy/plugin.yaml new file mode 100644 index 000000000..7df8a6312 --- /dev/null +++ b/linters/toml-tidy/plugin.yaml @@ -0,0 +1,26 @@ +version: 0.1 +tools: + definitions: + - name: toml-tidy + runtime: python + package: toml-tidy + shims: [toml-tidy] + known_good_version: 0.2.0 +lint: + definitions: + - name: toml-tidy + description: Sorts TOML keys while preserving table hierarchy, comments, and formatting + files: [toml] + commands: + - name: format + output: rewrite + run: toml-tidy --in-place ${target} + success_codes: [0] + batch: true + in_place: true + formatter: true + tools: [toml-tidy] + suggest_if: never # sorting keys is an opinionated choice; complements taplo (formatting) rather than replacing it + affects_cache: + - pyproject.toml + known_good_version: 0.2.0 diff --git a/linters/toml-tidy/test_data/basic.in.toml b/linters/toml-tidy/test_data/basic.in.toml new file mode 100644 index 000000000..9702e1ad5 --- /dev/null +++ b/linters/toml-tidy/test_data/basic.in.toml @@ -0,0 +1,17 @@ +title = "example" +# alpha gets sorted first and keeps this comment +alpha = 1 + +[zulu] +b = 2 +a = 1 + +[mike] +item10 = "ten" +item2 = "two" + +[[servers]] +name = "second declared" + +[[servers]] +name = "first stays first" diff --git a/linters/toml-tidy/test_data/toml_tidy_v0.2.0_basic.fmt.shot b/linters/toml-tidy/test_data/toml_tidy_v0.2.0_basic.fmt.shot new file mode 100644 index 000000000..effa331ce --- /dev/null +++ b/linters/toml-tidy/test_data/toml_tidy_v0.2.0_basic.fmt.shot @@ -0,0 +1,22 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Testing formatter toml-tidy test basic 1`] = ` +"# alpha gets sorted first and keeps this comment +alpha = 1 +title = "example" + +[mike] +item2 = "two" +item10 = "ten" + +[[servers]] +name = "second declared" + +[[servers]] +name = "first stays first" +[zulu] +a = 1 +b = 2 + +" +`; diff --git a/linters/toml-tidy/toml_tidy.test.ts b/linters/toml-tidy/toml_tidy.test.ts new file mode 100644 index 000000000..5c1b73cb4 --- /dev/null +++ b/linters/toml-tidy/toml_tidy.test.ts @@ -0,0 +1,15 @@ +import { linterFmtTest } from "tests"; +import { TrunkLintDriver } from "tests/driver"; + +// toml-tidy requires python >=3.12, newer than the default hermetic runtime +const preCheck = (driver: TrunkLintDriver) => { + const trunkYamlPath = ".trunk/trunk.yaml"; + const currentContents = driver.readFile(trunkYamlPath); + const newContents = currentContents.concat(`runtimes: + enabled: + - python@3.12.2 +`); + driver.writeFile(trunkYamlPath, newContents); +}; + +linterFmtTest({ linterName: "toml-tidy", preCheck });