kdrift 0.1.0__tar.gz
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.
- kdrift-0.1.0/.cruft.json +21 -0
- kdrift-0.1.0/.editorconfig +15 -0
- kdrift-0.1.0/.env.example +6 -0
- kdrift-0.1.0/.github/workflows/build.yaml +48 -0
- kdrift-0.1.0/.github/workflows/publish.yaml +40 -0
- kdrift-0.1.0/.gitignore +25 -0
- kdrift-0.1.0/.pre-commit-config.yaml +32 -0
- kdrift-0.1.0/.python-version +1 -0
- kdrift-0.1.0/AGENTS.md +123 -0
- kdrift-0.1.0/CLAUDE.md +1 -0
- kdrift-0.1.0/Makefile +43 -0
- kdrift-0.1.0/PKG-INFO +13 -0
- kdrift-0.1.0/README.md +115 -0
- kdrift-0.1.0/docs/agents/AGENTS.md +21 -0
- kdrift-0.1.0/docs/agents/knowledge/KNOWLEDGE.md +129 -0
- kdrift-0.1.0/docs/agents/skills/SKILL.md +147 -0
- kdrift-0.1.0/docs/configuration.md +17 -0
- kdrift-0.1.0/docs/decisions/README.md +34 -0
- kdrift-0.1.0/docs/development.md +48 -0
- kdrift-0.1.0/pyproject.toml +127 -0
- kdrift-0.1.0/src/kdrift/__init__.py +5 -0
- kdrift-0.1.0/src/kdrift/__main__.py +5 -0
- kdrift-0.1.0/src/kdrift/cli.py +188 -0
- kdrift-0.1.0/src/kdrift/config.py +106 -0
- kdrift-0.1.0/src/kdrift/diff.py +232 -0
- kdrift-0.1.0/src/kdrift/discover.py +317 -0
- kdrift-0.1.0/src/kdrift/git.py +184 -0
- kdrift-0.1.0/src/kdrift/logging.py +82 -0
- kdrift-0.1.0/src/kdrift/lsp_server.py +576 -0
- kdrift-0.1.0/src/kdrift/mcp_server.py +165 -0
- kdrift-0.1.0/src/kdrift/models.py +145 -0
- kdrift-0.1.0/src/kdrift/pipeline.py +223 -0
- kdrift-0.1.0/src/kdrift/py.typed +0 -0
- kdrift-0.1.0/src/kdrift/render.py +182 -0
- kdrift-0.1.0/src/kdrift/watch.py +163 -0
- kdrift-0.1.0/tests/__init__.py +0 -0
- kdrift-0.1.0/tests/conftest.py +17 -0
- kdrift-0.1.0/tests/test_cli.py +85 -0
- kdrift-0.1.0/tests/test_config.py +66 -0
- kdrift-0.1.0/tests/test_diff.py +205 -0
- kdrift-0.1.0/tests/test_discover.py +140 -0
- kdrift-0.1.0/tests/test_git.py +165 -0
- kdrift-0.1.0/tests/test_logging.py +28 -0
- kdrift-0.1.0/tests/test_mcp_integration.py +196 -0
- kdrift-0.1.0/tests/test_models.py +113 -0
- kdrift-0.1.0/tests/test_pipeline.py +273 -0
- kdrift-0.1.0/tests/test_render.py +87 -0
- kdrift-0.1.0/tests/test_watch.py +51 -0
- kdrift-0.1.0/uv.lock +1209 -0
- kdrift-0.1.0/vscode-kdrift/.gitignore +4 -0
- kdrift-0.1.0/vscode-kdrift/.vscode/launch.json +13 -0
- kdrift-0.1.0/vscode-kdrift/.vscodeignore +7 -0
- kdrift-0.1.0/vscode-kdrift/README.md +98 -0
- kdrift-0.1.0/vscode-kdrift/esbuild.js +57 -0
- kdrift-0.1.0/vscode-kdrift/media/screenshots/hero.jpg +0 -0
- kdrift-0.1.0/vscode-kdrift/package.json +109 -0
- kdrift-0.1.0/vscode-kdrift/src/diffRunner.ts +77 -0
- kdrift-0.1.0/vscode-kdrift/src/driftPreviewProvider.ts +226 -0
- kdrift-0.1.0/vscode-kdrift/src/extension.ts +45 -0
- kdrift-0.1.0/vscode-kdrift/src/lspClient.ts +47 -0
- kdrift-0.1.0/vscode-kdrift/src/types.ts +39 -0
- kdrift-0.1.0/vscode-kdrift/src/webview/preview.ts +225 -0
- kdrift-0.1.0/vscode-kdrift/src/webview/styles.css +260 -0
- kdrift-0.1.0/vscode-kdrift/tsconfig.json +19 -0
kdrift-0.1.0/.cruft.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"template": "https://github.com/missionlane/templates",
|
|
3
|
+
"commit": "81b9e092d4929564ea2805dc3f6c357765b2b6ee",
|
|
4
|
+
"checkout": null,
|
|
5
|
+
"context": {
|
|
6
|
+
"cookiecutter": {
|
|
7
|
+
"project_name": "kdrift",
|
|
8
|
+
"project_slug": "kdrift",
|
|
9
|
+
"package_name": "kdrift",
|
|
10
|
+
"description": "Kustomize manifest drift detection tool",
|
|
11
|
+
"python_version": "3.13",
|
|
12
|
+
"sonarqube_project_key": "mikedougherty.kdrift",
|
|
13
|
+
"has_web_server": "no",
|
|
14
|
+
"has_cli": "yes",
|
|
15
|
+
"needs_k8s_access": "no",
|
|
16
|
+
"_template": "https://github.com/missionlane/templates",
|
|
17
|
+
"_commit": "81b9e092d4929564ea2805dc3f6c357765b2b6ee"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"directory": "python-service"
|
|
21
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
name: Build
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths-ignore:
|
|
7
|
+
- "*.md"
|
|
8
|
+
- "!README.md"
|
|
9
|
+
pull_request:
|
|
10
|
+
branches: [main]
|
|
11
|
+
paths-ignore:
|
|
12
|
+
- "*.md"
|
|
13
|
+
- "!README.md"
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
pull-requests: write
|
|
18
|
+
checks: write
|
|
19
|
+
|
|
20
|
+
concurrency:
|
|
21
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
22
|
+
cancel-in-progress: true
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
validate:
|
|
26
|
+
name: Lint, Type Check, Test
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v4
|
|
30
|
+
|
|
31
|
+
- uses: astral-sh/setup-uv@v5
|
|
32
|
+
with:
|
|
33
|
+
enable-cache: true
|
|
34
|
+
|
|
35
|
+
- name: Install dependencies
|
|
36
|
+
run: uv sync --all-groups
|
|
37
|
+
|
|
38
|
+
- name: Lint
|
|
39
|
+
run: uv run ruff check .
|
|
40
|
+
|
|
41
|
+
- name: Format check
|
|
42
|
+
run: uv run ruff format --check .
|
|
43
|
+
|
|
44
|
+
- name: Type check
|
|
45
|
+
run: uv run mypy src/kdrift
|
|
46
|
+
|
|
47
|
+
- name: Test
|
|
48
|
+
run: uv run pytest
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
id-token: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
name: Build distribution
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- uses: astral-sh/setup-uv@v5
|
|
19
|
+
|
|
20
|
+
- name: Build package
|
|
21
|
+
run: uv build
|
|
22
|
+
|
|
23
|
+
- uses: actions/upload-artifact@v4
|
|
24
|
+
with:
|
|
25
|
+
name: dist
|
|
26
|
+
path: dist/
|
|
27
|
+
|
|
28
|
+
publish:
|
|
29
|
+
name: Publish to PyPI
|
|
30
|
+
needs: build
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
environment: pypi
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/download-artifact@v4
|
|
35
|
+
with:
|
|
36
|
+
name: dist
|
|
37
|
+
path: dist/
|
|
38
|
+
|
|
39
|
+
- name: Publish to PyPI
|
|
40
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
kdrift-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*$py.class
|
|
4
|
+
*.egg-info/
|
|
5
|
+
*.egg
|
|
6
|
+
dist/
|
|
7
|
+
build/
|
|
8
|
+
|
|
9
|
+
.venv/
|
|
10
|
+
.env
|
|
11
|
+
|
|
12
|
+
.mypy_cache/
|
|
13
|
+
.ruff_cache/
|
|
14
|
+
.pytest_cache/
|
|
15
|
+
|
|
16
|
+
coverage.xml
|
|
17
|
+
htmlcov/
|
|
18
|
+
test-results/
|
|
19
|
+
.coverage
|
|
20
|
+
|
|
21
|
+
.scannerwork/
|
|
22
|
+
.claude/
|
|
23
|
+
|
|
24
|
+
*.db
|
|
25
|
+
*.sqlite3
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
3
|
+
rev: v5.0.0
|
|
4
|
+
hooks:
|
|
5
|
+
- id: trailing-whitespace
|
|
6
|
+
- id: end-of-file-fixer
|
|
7
|
+
- id: check-yaml
|
|
8
|
+
- id: check-toml
|
|
9
|
+
- id: check-added-large-files
|
|
10
|
+
- id: check-merge-conflict
|
|
11
|
+
|
|
12
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
13
|
+
rev: v0.11.12
|
|
14
|
+
hooks:
|
|
15
|
+
- id: ruff
|
|
16
|
+
args: [--fix]
|
|
17
|
+
- id: ruff-format
|
|
18
|
+
|
|
19
|
+
- repo: local
|
|
20
|
+
hooks:
|
|
21
|
+
- id: mypy
|
|
22
|
+
name: mypy
|
|
23
|
+
entry: uv run mypy src/kdrift
|
|
24
|
+
language: system
|
|
25
|
+
types: [python]
|
|
26
|
+
pass_filenames: false
|
|
27
|
+
|
|
28
|
+
- repo: https://github.com/compilerla/conventional-pre-commit
|
|
29
|
+
rev: v4.0.0
|
|
30
|
+
hooks:
|
|
31
|
+
- id: conventional-pre-commit
|
|
32
|
+
stages: [commit-msg]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13
|
kdrift-0.1.0/AGENTS.md
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# kdrift
|
|
2
|
+
|
|
3
|
+
Kustomize manifest drift detection tool
|
|
4
|
+
|
|
5
|
+
## Quick Reference
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
make deps # Install dependencies
|
|
9
|
+
make validate # Run all checks (lint + typecheck + test)
|
|
10
|
+
make test # Run tests
|
|
11
|
+
make typecheck # Run mypy
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Architecture
|
|
15
|
+
|
|
16
|
+
- **Package layout:** `src/kdrift/` (src layout)
|
|
17
|
+
- **Config:** `pydantic-settings` BaseSettings in `config.py`, env vars with `KDRIFT_` prefix
|
|
18
|
+
- **Project config:** `.kdrift.yaml` with upward directory walking (project > org > user XDG)
|
|
19
|
+
- **Logging:** structlog with JSON output (production) / console (development)
|
|
20
|
+
- **Testing:** pytest with `unit`/`integration` markers, 80% coverage minimum
|
|
21
|
+
|
|
22
|
+
### Module Map
|
|
23
|
+
|
|
24
|
+
| Module | Purpose |
|
|
25
|
+
|--------|---------|
|
|
26
|
+
| `cli.py` | click entry point, --watch/--check/--format flags |
|
|
27
|
+
| `discover.py` | Parse kustomization.yaml files, build reverse dependency DAG, find affected overlays |
|
|
28
|
+
| `render.py` | Run kustomize build as subprocess, baseline caching, parallel rendering |
|
|
29
|
+
| `diff.py` | Two-phase resource matching (exact GVK+ns+name, then generator-aware), unified diff |
|
|
30
|
+
| `pipeline.py` | Shared discover->render->diff orchestration for all frontends |
|
|
31
|
+
| `git.py` | Ref resolution, changed files, temporary worktree management |
|
|
32
|
+
| `models.py` | Pydantic models (ResourceId, OverlayResult, DiffResult, RenderResult) |
|
|
33
|
+
| `config.py` | AppConfig (env vars) + ProjectConfig (.kdrift.yaml hierarchy) |
|
|
34
|
+
| `watch.py` | Filesystem monitoring with debouncing via watchfiles |
|
|
35
|
+
| `logging.py` | structlog configuration |
|
|
36
|
+
|
|
37
|
+
### Key Design Decisions
|
|
38
|
+
|
|
39
|
+
- **Kustomize as subprocess, not library:** decouples from kustomize version, user controls the binary
|
|
40
|
+
- **Git-status-driven discovery:** `git diff --name-only` determines changed files, dependency graph maps to overlays
|
|
41
|
+
- **Two-phase resource matching:** Phase 1 exact GVK+ns+name, Phase 2 generator-aware with kustomize hash charset (`bcdfghjklmnpqrstvwxz2456789`)
|
|
42
|
+
- **Baseline caching:** keyed by ref+overlay+kustomize-args+version, stored in `~/.cache/kdrift/`
|
|
43
|
+
- **Read-only git operations only:** worktrees for baseline rendering (separate index, no locks)
|
|
44
|
+
|
|
45
|
+
## Conventions
|
|
46
|
+
|
|
47
|
+
- All tool config in `pyproject.toml` (ruff, mypy, pytest, coverage)
|
|
48
|
+
- mypy strict mode -- avoid `type: ignore` unless no alternative exists
|
|
49
|
+
- Use `pydantic.SecretStr` for credential fields in config
|
|
50
|
+
- Pre-commit hooks enforce formatting and type checking on every commit
|
|
51
|
+
|
|
52
|
+
## CLI
|
|
53
|
+
|
|
54
|
+
- click-based CLI registered as `kdrift` entrypoint
|
|
55
|
+
- Run via `uv run kdrift` or `make run`
|
|
56
|
+
- Supports `-C`/`--repo` flag to target external repositories
|
|
57
|
+
|
|
58
|
+
## Verification Commands
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
make validate # Full CI-equivalent check
|
|
62
|
+
make test # Tests with coverage
|
|
63
|
+
make typecheck # mypy strict mode
|
|
64
|
+
make lint # ruff linter
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## CI/CD
|
|
68
|
+
|
|
69
|
+
- CI runs on push to main and PRs: lint -> format-check -> typecheck -> test
|
|
70
|
+
- ubuntu-latest runners (not self-hosted)
|
|
71
|
+
|
|
72
|
+
## Key Files
|
|
73
|
+
|
|
74
|
+
| File | Purpose |
|
|
75
|
+
|------|---------|
|
|
76
|
+
| `src/kdrift/config.py` | Application config (pydantic-settings) |
|
|
77
|
+
| `src/kdrift/logging.py` | structlog configuration |
|
|
78
|
+
| `src/kdrift/lsp_server.py` | LSP server (pygls) |
|
|
79
|
+
| `src/kdrift/mcp_server.py` | MCP server (FastMCP) |
|
|
80
|
+
| `tests/conftest.py` | Shared test fixtures |
|
|
81
|
+
| `tests/test_mcp_integration.py` | MCP integration test harness |
|
|
82
|
+
| `Makefile` | Standard development targets |
|
|
83
|
+
| `pyproject.toml` | All tool configuration |
|
|
84
|
+
|
|
85
|
+
## Agent Development Loop
|
|
86
|
+
|
|
87
|
+
When iterating on kdrift itself, use `--debug` to enable file logging and verbose output:
|
|
88
|
+
|
|
89
|
+
### LSP development
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# Configure VS Code: glspc.serverCommand="kdrift", glspc.serverCommandArguments=["lsp", "--debug"]
|
|
93
|
+
# Or without debug: glspc.serverCommandArguments=["lsp"]
|
|
94
|
+
|
|
95
|
+
# Hot-reload after code changes (no VS Code restart needed):
|
|
96
|
+
pkill -USR1 -f "kdrift lsp"
|
|
97
|
+
|
|
98
|
+
# Full reinstall (needed if lsp_server.py itself changes):
|
|
99
|
+
uv tool install -e ~/src/github.com/mikedougherty/kdrift --force
|
|
100
|
+
pkill -f "kdrift lsp" # VS Code auto-restarts
|
|
101
|
+
|
|
102
|
+
# Monitor logs:
|
|
103
|
+
tail -f ~/.cache/kdrift/kdrift.log
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### MCP development
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# Run integration tests (self-contained, no session restart):
|
|
110
|
+
uv run python tests/test_mcp_integration.py
|
|
111
|
+
|
|
112
|
+
# Or test against a specific repo:
|
|
113
|
+
uv run python tests/test_mcp_integration.py /path/to/kustomize-repo
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Debug flag behavior
|
|
117
|
+
|
|
118
|
+
`--debug` on `lsp` and `mcp` subcommands enables:
|
|
119
|
+
- DEBUG log level (all internal events logged)
|
|
120
|
+
- File logging to `~/.cache/kdrift/kdrift.log`
|
|
121
|
+
- Full-repo diff on SIGUSR1 reload (LSP only)
|
|
122
|
+
|
|
123
|
+
Without `--debug`, LSP/MCP run quietly with WARNING level, no file log.
|
kdrift-0.1.0/CLAUDE.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@./AGENTS.md
|
kdrift-0.1.0/Makefile
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
.PHONY: deps run lint format format-check typecheck test test-unit test-integration validate clean help
|
|
2
|
+
|
|
3
|
+
deps: ## Install/sync all dependencies
|
|
4
|
+
@uv sync --all-groups
|
|
5
|
+
|
|
6
|
+
run: ## Run the CLI
|
|
7
|
+
@uv run kdrift
|
|
8
|
+
|
|
9
|
+
lint: ## Run linter
|
|
10
|
+
@uv run ruff check .
|
|
11
|
+
|
|
12
|
+
format: ## Format code and fix auto-fixable lint issues
|
|
13
|
+
@uv run ruff format .
|
|
14
|
+
@uv run ruff check --fix .
|
|
15
|
+
|
|
16
|
+
format-check: ## Check formatting without modifying files
|
|
17
|
+
@uv run ruff format --check .
|
|
18
|
+
|
|
19
|
+
typecheck: ## Run type checker
|
|
20
|
+
@uv run mypy src/kdrift
|
|
21
|
+
|
|
22
|
+
test: ## Run all tests
|
|
23
|
+
@uv run pytest
|
|
24
|
+
|
|
25
|
+
test-unit: ## Run unit tests only
|
|
26
|
+
@uv run pytest -m unit
|
|
27
|
+
|
|
28
|
+
test-integration: ## Run integration tests only
|
|
29
|
+
@uv run pytest -m integration
|
|
30
|
+
|
|
31
|
+
validate: ## Run all checks (CI equivalent)
|
|
32
|
+
@$(MAKE) lint
|
|
33
|
+
@$(MAKE) format-check
|
|
34
|
+
@$(MAKE) typecheck
|
|
35
|
+
@$(MAKE) test
|
|
36
|
+
|
|
37
|
+
clean: ## Remove build artifacts
|
|
38
|
+
@rm -rf .mypy_cache .pytest_cache .ruff_cache htmlcov coverage.xml test-results/ .coverage
|
|
39
|
+
|
|
40
|
+
help: ## Show this help
|
|
41
|
+
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
|
|
42
|
+
|
|
43
|
+
.DEFAULT_GOAL := help
|
kdrift-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kdrift
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Kustomize manifest drift detection tool
|
|
5
|
+
Requires-Python: >=3.13
|
|
6
|
+
Requires-Dist: click>=8.0
|
|
7
|
+
Requires-Dist: mcp>=1.27.2
|
|
8
|
+
Requires-Dist: pydantic-settings>=2.0
|
|
9
|
+
Requires-Dist: pydantic>=2.0
|
|
10
|
+
Requires-Dist: pygls>=2.1.1
|
|
11
|
+
Requires-Dist: pyyaml>=6.0.3
|
|
12
|
+
Requires-Dist: structlog>=24.0
|
|
13
|
+
Requires-Dist: watchfiles>=1.2.0
|
kdrift-0.1.0/README.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# kdrift
|
|
2
|
+
|
|
3
|
+
CLI, MCP, LSP, and VS Code extension for kustomize manifest drift detection. Discovers which overlays are affected by your changes, renders baselines and candidates, and diffs per-resource.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# From GitHub (recommended for now)
|
|
9
|
+
uv tool install git+https://github.com/mikedougherty/kdrift
|
|
10
|
+
|
|
11
|
+
# From PyPI (once published)
|
|
12
|
+
uv tool install kdrift
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Requires Python 3.13+ and `kustomize` on PATH.
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
kdrift diff # diff all affected overlays vs HEAD
|
|
21
|
+
kdrift diff k8s/base/deployment.yaml # diff overlays affected by this file
|
|
22
|
+
kdrift diff --overlay k8s/dev # diff only this overlay
|
|
23
|
+
kdrift diff --ref main~3 # diff against a specific ref
|
|
24
|
+
kdrift diff --ref main~5..main~2 # compare two commits
|
|
25
|
+
kdrift diff -C /path/to/repo # target a different repository
|
|
26
|
+
kdrift diff --format json # structured JSON output
|
|
27
|
+
kdrift diff --check # exit non-zero if drift exists (CI/pre-commit)
|
|
28
|
+
kdrift diff --watch # continuous mode: re-diff on file save
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## How It Works
|
|
32
|
+
|
|
33
|
+
1. `git diff --name-only HEAD` finds changed files
|
|
34
|
+
2. Dependency graph maps changes to affected leaf overlays (parses all `kustomization.yaml` reference types)
|
|
35
|
+
3. `kustomize build` renders baseline (via git worktree, cached) and candidate (working tree)
|
|
36
|
+
4. Two-phase per-resource diff: exact GVK+namespace+name match, then generator-aware matching for hash-suffixed ConfigMap/Secret names
|
|
37
|
+
5. Output as unified diff or structured JSON
|
|
38
|
+
|
|
39
|
+
## Configuration
|
|
40
|
+
|
|
41
|
+
Create `.kdrift.yaml` anywhere in your directory tree (searched upward from CWD):
|
|
42
|
+
|
|
43
|
+
```yaml
|
|
44
|
+
kustomize_args:
|
|
45
|
+
- "--enable-helm"
|
|
46
|
+
- "--load-restrictor"
|
|
47
|
+
- "LoadRestrictionsNone"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Development
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
make deps # Install dependencies
|
|
54
|
+
make validate # Run all checks (lint + typecheck + test)
|
|
55
|
+
make test # Tests only
|
|
56
|
+
make typecheck # mypy strict mode
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
See [docs/development.md](docs/development.md) for detailed setup.
|
|
60
|
+
|
|
61
|
+
## Quick Start: MCP Server for Claude Code
|
|
62
|
+
|
|
63
|
+
Give your AI agent kustomize drift detection in two steps:
|
|
64
|
+
|
|
65
|
+
**1. Install kdrift:**
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
uv tool install git+https://github.com/mikedougherty/kdrift
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**2. Add to your Claude Code MCP config** (`.claude.json` or project `.mcp.json`):
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"mcpServers": {
|
|
76
|
+
"kdrift": {
|
|
77
|
+
"command": "kdrift",
|
|
78
|
+
"args": ["mcp"]
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
That's it. Your agent now has four tools: `kdrift_diff`, `kdrift_discover`, `kdrift_affected`, `kdrift_render`. Ask it to "check what my kustomize changes affect" and it will use them.
|
|
85
|
+
|
|
86
|
+
**3. (Optional) Add agent instructions** for deeper context on how to use kdrift:
|
|
87
|
+
|
|
88
|
+
```markdown
|
|
89
|
+
@path/to/kdrift/docs/agents/AGENTS.md
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Or copy `docs/agents/` into your project's agent instructions directory. The files are self-contained and agent-agnostic.
|
|
93
|
+
|
|
94
|
+
## Agent Integration
|
|
95
|
+
|
|
96
|
+
kdrift ships with agent-readable instructions in `docs/agents/`. These work with any AI coding assistant that supports `AGENTS.md` or similar instruction files.
|
|
97
|
+
|
|
98
|
+
### VS Code Extension
|
|
99
|
+
|
|
100
|
+
The `vscode-kdrift/` directory contains a VS Code extension that shows drift diffs in a side panel, modeled after the built-in Markdown Preview. See [vscode-kdrift/README.md](vscode-kdrift/README.md) for setup and development.
|
|
101
|
+
|
|
102
|
+
### LSP Server (IDE integration)
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
kdrift lsp # stdio transport, configure in your LSP client
|
|
106
|
+
kdrift lsp --debug # enable file logging to ~/.cache/kdrift/kdrift.log
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Provides diagnostics on save, CodeLens annotations, and hover info.
|
|
110
|
+
|
|
111
|
+
## Documentation
|
|
112
|
+
|
|
113
|
+
- [Development Guide](docs/development.md)
|
|
114
|
+
- [Configuration](docs/configuration.md)
|
|
115
|
+
- [Agent Instructions](docs/agents/AGENTS.md)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# kdrift Agent Instructions
|
|
2
|
+
|
|
3
|
+
Agent-readable instructions for using kdrift in kustomize repositories.
|
|
4
|
+
|
|
5
|
+
## Load When
|
|
6
|
+
|
|
7
|
+
- Working in a repository with `kustomization.yaml` files
|
|
8
|
+
- Using kustomize, kubectl, or Helm to manage Kubernetes manifests
|
|
9
|
+
- Reviewing PRs that touch kustomize overlays, bases, or patches
|
|
10
|
+
|
|
11
|
+
## Knowledge
|
|
12
|
+
|
|
13
|
+
Concepts, architecture, configuration, and tool reference:
|
|
14
|
+
|
|
15
|
+
@./knowledge/KNOWLEDGE.md
|
|
16
|
+
|
|
17
|
+
## Skills
|
|
18
|
+
|
|
19
|
+
How to use kdrift (MCP tools and CLI) to detect manifest drift:
|
|
20
|
+
|
|
21
|
+
@./skills/SKILL.md
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# kdrift Knowledge
|
|
2
|
+
|
|
3
|
+
Kustomize manifest drift detection. Shows exactly what your kustomize edits will change in rendered Kubernetes manifests before you commit, push, or apply.
|
|
4
|
+
|
|
5
|
+
## Core Concepts
|
|
6
|
+
|
|
7
|
+
**Leaf overlay**: A kustomization directory that no other kustomization references. These are deployment targets (e.g., `k8s/dev`, `k8s/prod`). Base directories that get referenced by overlays are not leaves.
|
|
8
|
+
|
|
9
|
+
**Dependency graph**: kdrift builds a reverse dependency map from every file to the leaf overlays that transitively include it. When you edit `k8s/base/deployment.yaml`, kdrift knows which overlays (`k8s/dev`, `k8s/staging`, `k8s/prod`) are affected.
|
|
10
|
+
|
|
11
|
+
**Baseline vs candidate**: The baseline is the rendered output at a git ref (default: HEAD). The candidate is the rendered output from the working tree (or a second ref). kdrift diffs them per-resource.
|
|
12
|
+
|
|
13
|
+
**Two-phase resource matching**: Phase 1 matches resources by exact GVK + namespace + name. Phase 2 handles configMapGenerator/secretGenerator hash-suffixed names using the kustomize hash charset (`bcdfghjklmnpqrstvwxz2456789`).
|
|
14
|
+
|
|
15
|
+
**Two-ref comparison**: Compare any two git refs (`--ref main~5..main~2`) instead of working tree vs HEAD. Uses two temporary worktrees.
|
|
16
|
+
|
|
17
|
+
## Delivery Surfaces
|
|
18
|
+
|
|
19
|
+
| Surface | Invocation | Best for |
|
|
20
|
+
|---------|-----------|----------|
|
|
21
|
+
| **CLI** | `kdrift diff` | Terminal workflows, CI/CD, pre-commit hooks |
|
|
22
|
+
| **MCP** | `kdrift mcp` (stdio) | AI agents (Claude Code, etc.) with structured JSON |
|
|
23
|
+
| **LSP** | `kdrift lsp` (stdio) | IDE integration (VS Code, Neovim) with diagnostics on save |
|
|
24
|
+
|
|
25
|
+
## Configuration
|
|
26
|
+
|
|
27
|
+
### Project config (`.kdrift.yaml`)
|
|
28
|
+
|
|
29
|
+
kdrift searches upward from CWD for `.kdrift.yaml`:
|
|
30
|
+
|
|
31
|
+
```yaml
|
|
32
|
+
kustomize_args:
|
|
33
|
+
- "--enable-helm"
|
|
34
|
+
- "--load-restrictor"
|
|
35
|
+
- "LoadRestrictionsNone"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Search order: project directory, parent directories, `$XDG_CONFIG_HOME/kdrift/`.
|
|
39
|
+
|
|
40
|
+
### Environment variables
|
|
41
|
+
|
|
42
|
+
| Variable | Default | Description |
|
|
43
|
+
|----------|---------|-------------|
|
|
44
|
+
| `KDRIFT_LOG_LEVEL` | `WARNING` | Log level (DEBUG, INFO, WARNING, ERROR) |
|
|
45
|
+
| `KDRIFT_LOG_FORMAT` | `json` | Log format (`json` or `console`) |
|
|
46
|
+
|
|
47
|
+
### MCP configuration
|
|
48
|
+
|
|
49
|
+
Add to your agent's MCP config (e.g., `.claude.json`, `claude_desktop_config.json`):
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"mcpServers": {
|
|
54
|
+
"kdrift": {
|
|
55
|
+
"command": "kdrift",
|
|
56
|
+
"args": ["mcp"]
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### LSP configuration (VS Code)
|
|
63
|
+
|
|
64
|
+
Using the Generic LSP Client (glspc) extension:
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"glspc.serverCommand": "kdrift",
|
|
69
|
+
"glspc.serverCommandArguments": ["lsp"]
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Add `--debug` to enable file logging to `~/.cache/kdrift/kdrift.log`.
|
|
74
|
+
|
|
75
|
+
## MCP Tools Reference
|
|
76
|
+
|
|
77
|
+
| Tool | Description |
|
|
78
|
+
|------|-------------|
|
|
79
|
+
| `kdrift_diff` | Diff overlays against a baseline ref. Returns per-overlay, per-resource structured JSON. Supports `target_ref` for two-ref comparison. |
|
|
80
|
+
| `kdrift_discover` | Find leaf overlays. Defaults to git-changed overlays; `show_all=true` for the full list. |
|
|
81
|
+
| `kdrift_affected` | Given a list of changed files, find which overlays are affected. |
|
|
82
|
+
| `kdrift_render` | Render a single overlay to YAML. |
|
|
83
|
+
|
|
84
|
+
## Output Structure
|
|
85
|
+
|
|
86
|
+
All tools return JSON. The diff result structure:
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"ref": "abc1234",
|
|
91
|
+
"target_ref": null,
|
|
92
|
+
"overlays": [
|
|
93
|
+
{
|
|
94
|
+
"path": "k8s/dev",
|
|
95
|
+
"changes": [
|
|
96
|
+
{
|
|
97
|
+
"resource_id": {
|
|
98
|
+
"group": "apps", "version": "v1", "kind": "Deployment",
|
|
99
|
+
"namespace": "myapp", "name": "api-server"
|
|
100
|
+
},
|
|
101
|
+
"status": "modified",
|
|
102
|
+
"diff_text": "...",
|
|
103
|
+
"lines_added": 1,
|
|
104
|
+
"lines_removed": 1
|
|
105
|
+
}
|
|
106
|
+
],
|
|
107
|
+
"error": null
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Status values: `modified`, `added`, `removed`.
|
|
114
|
+
|
|
115
|
+
## Error Handling
|
|
116
|
+
|
|
117
|
+
When `kustomize build` fails for one overlay, kdrift reports the error and continues with others. The `error` field is set per-overlay. Exit code is non-zero if any overlay errored.
|
|
118
|
+
|
|
119
|
+
Baseline build failures (the ref version was already broken) are reported as `"baseline build failed (pre-existing)"` to distinguish from regressions you introduced.
|
|
120
|
+
|
|
121
|
+
## Caching
|
|
122
|
+
|
|
123
|
+
Baseline renders are cached at `~/.cache/kdrift/` keyed by ref SHA + overlay path + kustomize version + args. Working tree renders are never cached.
|
|
124
|
+
|
|
125
|
+
## Prerequisites
|
|
126
|
+
|
|
127
|
+
- `kustomize` binary on PATH (kdrift shells out to it, does not embed kustomize)
|
|
128
|
+
- Git repository with at least one commit
|
|
129
|
+
- Python 3.13+ (for installation via `uv tool install`)
|