-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathMakefile
More file actions
205 lines (152 loc) · 9.93 KB
/
Copy pathMakefile
File metadata and controls
205 lines (152 loc) · 9.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
.DEFAULT_GOAL := help
.PHONY: help install install-server sync test test-unit test-integration test-e2e test-e2e-local test-e2e-invite test-e2e-feature test-e2e-stream test-e2e-auth test-file test-cov lint lint-fix format format-check typecheck typecheck-warn audit skill-check skill-gen version-sync version-check version-gate-check vnext-check vnext-resolve gate-floor-report release-scope-check changelog changelog-check check-error-codes check-sentinel-guards loc-check loc-report loc-baseline command-sync-check gen-command-reference endpoints-gen endpoints-check check clean hooks web-install web-dev-backend web-dev-frontend web-build web-clean
help: ## Show this help message
@grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-18s\033[0m %s\n", $$1, $$2}'
install: ## Install in development mode (editable)
uv pip install -e ".[dev]"
install-server: ## Install FastAPI/uvicorn for `kbagent serve` (web UI backend)
uv pip install -e ".[server]"
sync: ## Sync dependencies from lockfile
uv sync
# `-n auto` fans the suite across every core (~6k tests, all HTTP mocked, no
# shared mutable state). Measured 152s -> 29s on an 11-core machine. `-v` is
# dropped with it: interleaved per-worker output is unreadable, and a failing
# test prints its own node id. Use `make test-file FILE=...` for a sequential,
# verbose run while debugging a single file.
test: ## Run all tests (excluding e2e — use test-e2e separately)
uv run pytest tests/ -m "not e2e" -n auto
test-unit: ## Run unit tests only (exclude integration and e2e)
uv run pytest tests/ -m "not integration and not e2e" -n auto
test-integration: ## Run integration tests only
uv run pytest tests/ -v -m integration
test-e2e: ## Run E2E tests (E2E_API_TOKEN and E2E_URL required; auth tests skip without session env vars)
uv run pytest tests/test_e2e.py tests/test_server_semantic_layer_routes_e2e.py tests/test_e2e_auth.py -v -s --tb=long
test-e2e-local: ## Run E2E against a project in a local config.json (CONFIG_DIR=/path/.kbagent ALIAS=my-proj)
KBAGENT_E2E_CONFIG_DIR=$(CONFIG_DIR) KBAGENT_E2E_ALIAS=$(ALIAS) \
uv run pytest tests/test_e2e.py -v -s --tb=long
test-e2e-invite: ## Run project invite E2E (E2E_MANAGE_TOKEN + E2E_INVITE_PROJECT_ID required)
uv run pytest tests/test_e2e.py -v -s --tb=long -m e2e_invite
test-e2e-feature: ## Run feature-flag E2E (E2E_MANAGE_TOKEN super-admin + E2E_API_TOKEN + E2E_URL required)
uv run pytest tests/test_e2e.py -v -s --tb=long -k test_feature_flags_read_e2e
test-e2e-stream: ## Run Data Streams OTLP E2E (E2E_API_TOKEN + E2E_URL required; creates + deletes a temp source)
uv run pytest tests/test_e2e.py -v -s --tb=long -k test_stream_otlp_e2e
test-e2e-auth: ## Run programmatic-auth E2E (E2E_URL + E2E_SESSION_REFRESH_TOKEN + E2E_SESSION_PROJECT_ID required)
uv run pytest tests/test_e2e_auth.py -v -s --tb=long
test-file: ## Run a specific test file (FILE=tests/test_cli.py)
uv run pytest $(FILE) -v
test-cov: ## Run the unit suite with a coverage report (informational; no threshold gate)
uv run pytest tests/ -m "not integration" -n auto --cov --cov-report=term-missing
lint: ## Run ruff linter
uv run ruff check src/ tests/ scripts/
lint-fix: ## Run ruff linter with auto-fix
uv run ruff check src/ tests/ scripts/ --fix
format: ## Format code with ruff
uv run ruff format .
format-check: ## Check code formatting (no changes)
uv run ruff format . --check
typecheck: ## Run ty type-checker (Astral). Fails on any error.
uv run ty check
audit: ## Audit locked dependencies (all groups + extras) for known vulnerabilities via OSV
uv audit --frozen
typecheck-warn: ## Run ty in warning-only mode (always exits 0; used by hooks)
@uv run ty check || true
skill-gen: ## Regenerate SKILL.md from CLI command tree
uv run python scripts/generate_skill.py
skill-check: ## Check SKILL.md is up-to-date (fails if stale)
@uv run python scripts/generate_skill.py > /dev/null 2>&1
@if git diff --quiet plugins/kbagent/skills/kbagent/SKILL.md; then \
echo "SKILL.md is up-to-date"; \
else \
echo "ERROR: SKILL.md is out-of-date. Run 'make skill-gen' and commit."; \
git diff plugins/kbagent/skills/kbagent/SKILL.md; \
exit 1; \
fi
version-sync: ## Sync version from pyproject.toml to plugin.json
uv run python scripts/sync_version.py
version-check: ## Check version-bearing files match pyproject.toml (fails if mismatched)
@uv run python scripts/sync_version.py > /dev/null 2>&1
@if git diff --quiet plugins/kbagent/.claude-plugin/plugin.json .claude-plugin/marketplace.json uv.lock; then \
echo "version is in sync (plugin.json, marketplace.json, uv.lock)"; \
else \
echo "ERROR: version mismatch. Run 'make version-sync' and commit."; \
git diff plugins/kbagent/.claude-plugin/plugin.json .claude-plugin/marketplace.json uv.lock; \
exit 1; \
fi
loc-check: ## Check per-layer file-size budgets in CODE LINES (docstrings/comments excluded)
uv run python scripts/check_file_size.py
loc-report: ## List every module by code lines, largest first
uv run python scripts/check_file_size.py --report
loc-baseline: ## Re-record grandfathered over-budget files (run AFTER a split, never to silence growth)
uv run python scripts/check_file_size.py --update-baseline
changelog: ## Generate changelog skeleton from GitHub releases
uv run python scripts/generate_changelog.py
changelog-check: ## Check all releases have changelog entries
uv run python scripts/generate_changelog.py --check
check-error-codes: ## Reject raw error_code string literals in source (use ErrorCode enum)
uv run python scripts/check_error_codes.py
command-sync-check: ## Verify every CLI command is registered + documented (silent-drift gate)
uv run python scripts/check_command_sync.py
version-gate-check: ## Reject a (since vX.Y.Z) / X.Y.Z+ marker naming an unreleased version
uv run python scripts/check_version_gates.py
vnext-check: ## Reject an unresolved version-gate placeholder -- run in the RELEASE PR
uv run python scripts/check_version_gates.py --release
vnext-resolve: ## Rewrite every live vNEXT gate to pyproject's version (RELEASE PR step 4)
@test -n "$(VERSION)" || { echo "usage: make vnext-resolve VERSION=X.Y.Z"; exit 2; }
uv run python scripts/check_version_gates.py --resolve $(VERSION)
gate-floor-report: ## List version gates below the retirement floor (default 0.80.0)
uv run python scripts/check_version_gates.py --list-below $(or $(FLOOR),0.80.0)
release-scope-check: ## Prove the changelog entry covers every PR the tag will contain
uv run python scripts/check_release_scope.py $(SCOPE_ARGS)
check-sentinel-guards: ## Reject an unguarded kbc-session:// sentinel path (silent-drift gate)
uv run python scripts/check_sentinel_guards.py
gen-command-reference: ## Generate command-reference.md from the live Typer app (release asset)
uv run python scripts/gen_command_reference.py --output command-reference.md
endpoints-gen: ## Regenerate docs/web-server-endpoints.md from the live FastAPI app
uv run --extra server python scripts/gen_endpoint_reference.py
endpoints-check: ## Check the serve endpoint reference is up-to-date (fails if stale)
# stdout is dropped, stderr is not: a generator crash must show its traceback
# rather than degrading into a confusing "doc is out-of-date".
@uv run --extra server python scripts/gen_endpoint_reference.py > /dev/null
# Two conditions, because either one alone has a blind spot. `git diff --quiet`
# reports NOTHING for an untracked path, so a doc that fell out of the index
# would pass while documenting nothing; `git status --porcelain` closes that but
# flags a staged-new file (`A `) whose content is perfectly correct -- the state
# of every PR that introduces a generated file. So: git must know the file, AND
# the regenerated content must match what git holds.
@if ! git ls-files --error-unmatch docs/web-server-endpoints.md > /dev/null 2>&1; then \
echo "ERROR: docs/web-server-endpoints.md is untracked. Run 'make endpoints-gen' and 'git add' it."; \
exit 1; \
fi
@if git diff --quiet docs/web-server-endpoints.md; then \
echo "docs/web-server-endpoints.md is up-to-date"; \
else \
echo "ERROR: docs/web-server-endpoints.md is out-of-date. Run 'make endpoints-gen' and commit."; \
git diff docs/web-server-endpoints.md; \
exit 1; \
fi
hooks: ## Install git pre-commit hook (lint + format on staged files)
cp scripts/pre-commit .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
@echo "Pre-commit hook installed."
check: lint format-check typecheck skill-check version-check version-gate-check command-sync-check endpoints-check changelog-check check-error-codes check-sentinel-guards loc-check test ## Run all checks (lint + format + typecheck + skill + version + version-gates + command-sync + endpoints + changelog + error-codes + sentinel-guards + file-size + test)
clean: ## Remove build artifacts and caches
find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
find . -type d -name .pytest_cache -exec rm -rf {} + 2>/dev/null || true
find . -type d -name "*.egg-info" -exec rm -rf {} + 2>/dev/null || true
find . -type d -name .ruff_cache -exec rm -rf {} + 2>/dev/null || true
find . -type f -name "*.pyc" -delete 2>/dev/null || true
# ── Web UI (web/backend Node BFF + web/frontend React) ─────────────
web-install: ## Install web/backend + web/frontend npm dependencies
cd web/backend && npm install
cd web/frontend && npm install
web-dev: ## Spin up kbagent serve + BFF + Vite in ONE terminal (Ctrl+C kills all)
./scripts/web-dev.sh $(if $(CONFIG_DIR),--config-dir $(CONFIG_DIR),)
web-dev-backend: ## Run only the Node BFF in watch mode (needs KBAGENT_SERVE_TOKEN env)
cd web/backend && npm run dev
web-dev-frontend: ## Run only the Vite dev server (proxies /api -> BFF on :8000)
cd web/frontend && npm run dev
web-build: ## Build the React app into web/frontend/dist
cd web/frontend && npm run build
web-clean: ## Remove web/* build artifacts and node_modules
rm -rf web/frontend/dist web/frontend/node_modules
rm -rf web/backend/dist web/backend/node_modules