@theglitchking/gimme-the-lint 2.5.0 → 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +20 -0
- package/lib/adapters/adapter.js +32 -0
- package/lib/adapters/tflint.js +24 -8
- package/lib/baseline.js +10 -8
- package/package.json +1 -1
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
},
|
|
7
7
|
"metadata": {
|
|
8
8
|
"description": "Official marketplace for gimme-the-lint - polyglot progressive linting with per-app baselines and drift detection",
|
|
9
|
-
"version": "2.5.
|
|
9
|
+
"version": "2.5.1"
|
|
10
10
|
},
|
|
11
11
|
"plugins": [
|
|
12
12
|
{
|
|
13
13
|
"name": "gimme-the-lint",
|
|
14
14
|
"description": "Polyglot progressive linting for monorepos — adapter-driven baselines, per-app drift detection, and idempotent skips across JavaScript/TypeScript, Python, Go, Rust, Terraform, and Ansible.",
|
|
15
|
-
"version": "2.5.
|
|
15
|
+
"version": "2.5.1",
|
|
16
16
|
"author": {
|
|
17
17
|
"name": "TheGlitchKing"
|
|
18
18
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gimme-the-lint",
|
|
3
3
|
"description": "Polyglot progressive linting for monorepos — adapter-driven baselines, per-app drift detection, and idempotent skips across JavaScript/TypeScript, Python, Go, Rust, Terraform, and Ansible.",
|
|
4
|
-
"version": "2.5.
|
|
4
|
+
"version": "2.5.1",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "TheGlitchKing",
|
|
7
7
|
"email": "theglitchking@users.noreply.github.com"
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,26 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.5.1] - 2026-05-17
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- **tflint config resolution is now root-aware.** In the standard Terraform
|
|
12
|
+
monorepo — one repo-root `.tflint.hcl`, many nested `modules/*` / `envs/*`
|
|
13
|
+
units — the adapter resolved config only in the unit directory, so every
|
|
14
|
+
unit was linted with tflint defaults: the repo's preset, plugin declarations
|
|
15
|
+
and `rule { enabled = false }` overrides were silently ignored and
|
|
16
|
+
`tflint --init` never ran. Meanwhile `configHashFor()` *did* find the
|
|
17
|
+
repo-root config, so the baseline's `config_hash` reflected a config the
|
|
18
|
+
linter never actually used — a silent correctness bug. A new shared resolver,
|
|
19
|
+
`LinterAdapter.resolveConfigPath()`, walks up from the unit directory to the
|
|
20
|
+
project root; `buildCommand()` and `initCommand()` now pass the resolved
|
|
21
|
+
file as an absolute `--config`, and `configHashFor()` hashes that same file —
|
|
22
|
+
the hashed config and the linted config can no longer disagree. A unit with
|
|
23
|
+
its own `.tflint.hcl` still wins (nearest-first); a repo with no config
|
|
24
|
+
anywhere still runs the zero-config core ruleset. The resolver is generic
|
|
25
|
+
(no provider name in code) and root-aware config-hashing now benefits every
|
|
26
|
+
adapter.
|
|
27
|
+
|
|
8
28
|
## [2.5.0] - 2026-05-17
|
|
9
29
|
|
|
10
30
|
### Added
|
package/lib/adapters/adapter.js
CHANGED
|
@@ -65,6 +65,38 @@ class LinterAdapter {
|
|
|
65
65
|
return [];
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Resolve the EFFECTIVE config file for the unit being linted: walk up from
|
|
70
|
+
* `startDir` (default: appRoot) to projectRoot inclusive and return the
|
|
71
|
+
* absolute path of the nearest file named by configFiles(), or null if none
|
|
72
|
+
* exists anywhere on that path.
|
|
73
|
+
*
|
|
74
|
+
* Root-aware — this is what lets a single repo-root config (the standard
|
|
75
|
+
* monorepo layout: one config, many nested units) govern every unit. It is
|
|
76
|
+
* the SINGLE source of truth shared by the config-hash (baseline.js) and the
|
|
77
|
+
* linter invocation, so the hashed config and the linted config can never
|
|
78
|
+
* disagree.
|
|
79
|
+
* @param {string} [startDir]
|
|
80
|
+
* @returns {string|null}
|
|
81
|
+
*/
|
|
82
|
+
resolveConfigPath(startDir) {
|
|
83
|
+
const names = this.configFiles();
|
|
84
|
+
if (!names || names.length === 0) return null;
|
|
85
|
+
const root = path.resolve(this.projectRoot);
|
|
86
|
+
let dir = path.resolve(startDir || this.appRoot);
|
|
87
|
+
while (true) {
|
|
88
|
+
for (const name of names) {
|
|
89
|
+
const candidate = path.join(dir, name);
|
|
90
|
+
if (fs.existsSync(candidate)) return candidate;
|
|
91
|
+
}
|
|
92
|
+
if (dir === root) break; // checked projectRoot — stop
|
|
93
|
+
const parent = path.dirname(dir);
|
|
94
|
+
if (parent === dir) break; // filesystem root reached
|
|
95
|
+
dir = parent;
|
|
96
|
+
}
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
|
|
68
100
|
/** Return the first candidate path that exists, else the last candidate. */
|
|
69
101
|
resolveBinary(candidates) {
|
|
70
102
|
for (const candidate of candidates) {
|
package/lib/adapters/tflint.js
CHANGED
|
@@ -66,16 +66,22 @@ class TflintAdapter extends LinterAdapter {
|
|
|
66
66
|
|
|
67
67
|
// --- .tflint.hcl introspection (generic — no provider is special-cased) ---
|
|
68
68
|
|
|
69
|
-
/** True when the unit
|
|
69
|
+
/** True when an effective .tflint.hcl exists (the unit dir or up to root). */
|
|
70
70
|
_hasConfig(dir) {
|
|
71
|
-
return
|
|
71
|
+
return this.resolveConfigPath(dir) !== null;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
/**
|
|
74
|
+
/**
|
|
75
|
+
* Enumerate every `plugin "<name>"` block in the EFFECTIVE .tflint.hcl —
|
|
76
|
+
* the one resolveConfigPath() resolves, which may live up at the repo root,
|
|
77
|
+
* not in the unit dir.
|
|
78
|
+
*/
|
|
75
79
|
_declaredPlugins(dir) {
|
|
80
|
+
const configPath = this.resolveConfigPath(dir);
|
|
81
|
+
if (!configPath) return [];
|
|
76
82
|
let hcl;
|
|
77
83
|
try {
|
|
78
|
-
hcl = fs.readFileSync(
|
|
84
|
+
hcl = fs.readFileSync(configPath, 'utf8');
|
|
79
85
|
} catch {
|
|
80
86
|
return [];
|
|
81
87
|
}
|
|
@@ -105,10 +111,12 @@ class TflintAdapter extends LinterAdapter {
|
|
|
105
111
|
* base adapter). A repo with no .tflint.hcl gets core linting, no init.
|
|
106
112
|
*/
|
|
107
113
|
initCommand(cwd) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
114
|
+
const configPath = this.resolveConfigPath(cwd);
|
|
115
|
+
if (!configPath) return null;
|
|
116
|
+
// Pass the resolved config explicitly so `--init` reads the right
|
|
117
|
+
// .tflint.hcl for its plugin declarations — even when it lives up at the
|
|
118
|
+
// repo root rather than in the unit dir.
|
|
119
|
+
return { cmd: this.binary, args: ['--init', `--config=${configPath}`] };
|
|
112
120
|
}
|
|
113
121
|
|
|
114
122
|
// --- availability: agree with what lint() will actually see --------------
|
|
@@ -178,6 +186,14 @@ class TflintAdapter extends LinterAdapter {
|
|
|
178
186
|
// Unresolvable target — fall back to the default cwd.
|
|
179
187
|
}
|
|
180
188
|
}
|
|
189
|
+
|
|
190
|
+
// tflint runs IN the unit dir; pass the effective config — which may live
|
|
191
|
+
// up at the repo root — as an absolute --config so the unit is linted with
|
|
192
|
+
// the repo's preset / plugin declarations / rule overrides, not tflint
|
|
193
|
+
// defaults. No config anywhere → plain tflint (zero-config core ruleset).
|
|
194
|
+
const configPath = this.resolveConfigPath(cwd);
|
|
195
|
+
if (configPath) args.push(`--config=${configPath}`);
|
|
196
|
+
|
|
181
197
|
return { cmd: this.binary, args, cwd };
|
|
182
198
|
}
|
|
183
199
|
|
package/lib/baseline.js
CHANGED
|
@@ -18,15 +18,17 @@ const gtlManifest = require('./gtl-manifest');
|
|
|
18
18
|
// the baseline CLI, the hooks installer) can refuse to gate commits against a
|
|
19
19
|
// baseline that never actually captured a linter.
|
|
20
20
|
|
|
21
|
-
/**
|
|
21
|
+
/**
|
|
22
|
+
* Hash the EFFECTIVE config file for an adapter. Resolution walks up from the
|
|
23
|
+
* unit dir to the project root via the adapter's shared resolver, so the
|
|
24
|
+
* hashed config is exactly the one the linter is invoked with — a repo-root
|
|
25
|
+
* config governing nested units is hashed correctly, never missed or faked.
|
|
26
|
+
*/
|
|
27
|
+
// eslint-disable-next-line no-unused-vars
|
|
22
28
|
async function configHashFor(projectRoot, unitRoot, adapter) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (hash !== 'unknown') return hash;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
return 'unknown';
|
|
29
|
+
const configPath = adapter.resolveConfigPath(unitRoot);
|
|
30
|
+
if (!configPath) return 'unknown';
|
|
31
|
+
return manifestManager.hashFile(configPath);
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
/** Baseline a single unit across all its bound linters. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theglitchking/gimme-the-lint",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.1",
|
|
4
4
|
"description": "Polyglot progressive linting for monorepos — adapter-driven baselines, per-app drift detection, and idempotent skips across JavaScript/TypeScript, Python, Go, Rust, Terraform, and Ansible.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"linting",
|