-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
216 lines (185 loc) · 7.81 KB
/
Copy pathMakefile
File metadata and controls
216 lines (185 loc) · 7.81 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
206
207
208
209
210
211
212
213
214
215
216
# Kida Makefile
# Wraps uv commands to ensure Python 3.14t is used
PYTHON_VERSION ?= 3.14t
VENV_DIR ?= .venv
.PHONY: all help setup install test test-cov test-thread test-async test-safety test-rc-safety lint lint-fix format format-check ty package-smoke verify-stability verify-rc clean shell docs docs-serve build publish release gh-release action-tag
all: help
help:
@echo "Kida Development CLI"
@echo "===================="
@echo "Python Version: $(PYTHON_VERSION)"
@echo ""
@echo "Available commands:"
@echo " make setup - Create virtual environment with Python $(PYTHON_VERSION)"
@echo " make install - Install dependencies in development mode"
@echo " make test - Run the test suite"
@echo " make test-cov - Run tests with coverage report"
@echo " make test-thread - Run thread safety stress tests"
@echo " make test-async - Run async feature tests"
@echo " make test-safety - Run focused safety/concurrency tests"
@echo " make lint - Run ruff linter"
@echo " make lint-fix - Run ruff linter with auto-fix"
@echo " make format - Run ruff formatter"
@echo " make format-check - Check ruff formatting"
@echo " make ty - Run ty type checker (fast, Rust-based)"
@echo " make package-smoke - Build artifacts and smoke-test installed wheel"
@echo " make verify-stability - Run the full local stability gate"
@echo " make verify-rc - Alias for verify-stability"
@echo " make docs - Build documentation site (requires bengal)"
@echo " make docs-serve - Start dev server for docs (requires bengal)"
@echo " make build - Build distribution packages"
@echo " make publish - Publish to PyPI (uses .env for token)"
@echo " make release - Build and publish in one step"
@echo " make gh-release - Create GitHub release (triggers PyPI via workflow), uses site release notes"
@echo " make action-tag - Move the v0 floating action tag to the current version"
@echo " make clean - Remove venv, build artifacts, and caches"
@echo " make shell - Start a shell with the environment activated"
setup:
@echo "Creating virtual environment with Python $(PYTHON_VERSION)..."
uv venv --python $(PYTHON_VERSION) $(VENV_DIR)
install:
@echo "Installing dependencies..."
@if [ ! -d "$(VENV_DIR)" ]; then \
echo "Error: $(VENV_DIR) not found. Run 'make setup' first."; \
exit 1; \
fi
@bash -c 'source "$(VENV_DIR)/bin/activate" && uv sync --active --group dev --frozen'
test:
uv run python -m pytest -q --tb=short
test-cov:
uv run python -m pytest --cov=kida --cov-report=term-missing --cov-fail-under=83
test-thread:
@echo "Running thread safety stress tests..."
PYTHON_GIL=0 uv run python -m pytest \
tests/test_kida_stress_test.py \
tests/test_randomized_thread_stress.py \
-v --tb=short
test-async:
@echo "Running async feature tests..."
PYTHON_GIL=0 uv run python -m pytest tests/test_kida_async_features.py -v --tb=short
test-safety:
@echo "Running focused safety/concurrency tests..."
PYTHON_GIL=0 uv run python -m pytest \
tests/test_render_surface_parity.py \
tests/test_sandbox_fuzz.py \
tests/test_bytecode_cache_concurrency.py \
tests/test_lru_cache_concurrency.py \
tests/test_kida_stress_test.py \
tests/test_randomized_thread_stress.py \
-q --tb=short
test-rc-safety: test-safety
lint:
@echo "Running ruff linter..."
uv run ruff check .
lint-fix:
@echo "Running ruff linter with auto-fix..."
uv run ruff check . --fix
format:
@echo "Running ruff formatter..."
uv run ruff format .
format-check:
@echo "Checking ruff formatting..."
uv run ruff format --check .
ty:
@echo "Running ty type checker (Astral, Rust-based)..."
uv run ty check src/kida/ action_support/
package-smoke:
@echo "Building and smoke-testing package artifacts..."
uv run python scripts/package_smoke.py
verify-stability: lint format-check ty test-cov test-safety package-smoke
@echo "✓ Stability verification gate passed"
verify-rc: verify-stability
docs:
@echo "Building documentation site..."
uv sync --group docs
cd site && uv run bengal build
docs-serve:
@echo "Starting documentation dev server..."
uv sync --group docs
cd site && uv run bengal serve
# =============================================================================
# Build & Release
# =============================================================================
build:
@echo "Building distribution packages..."
rm -rf dist/
uv build
@echo "✓ Built:"
@ls -la dist/
publish:
@echo "Publishing to PyPI..."
@if [ -f .env ]; then \
export $$(cat .env | xargs) && uv publish; \
else \
echo "Warning: No .env file found, trying without token..."; \
uv publish; \
fi
release: build publish
@echo "✓ Release complete"
# Create GitHub release from site release notes; triggers python-publish workflow → PyPI
# Strips YAML frontmatter (--- ... ---) from notes before passing to gh
gh-release:
@VERSION=$$(grep '^version = ' pyproject.toml | sed 's/version = "\(.*\)"/\1/'); \
PROJECT=$$(grep -m1 '^name = ' pyproject.toml | sed 's/name = "\(.*\)"/\1/'); \
TAG="v$$VERSION"; \
NOTES="site/content/releases/$$VERSION.md"; \
if [ -n "$$(git status --porcelain)" ]; then echo "Error: working tree is not clean."; exit 1; fi; \
if [ ! -f "$$NOTES" ]; then echo "Error: $$NOTES not found"; exit 1; fi; \
if gh release view "$$TAG" >/dev/null 2>&1; then echo "Error: release $$TAG already exists"; exit 1; fi; \
git fetch origin main --tags; \
LOCAL=$$(git rev-parse HEAD); \
REMOTE=$$(git rev-parse origin/main); \
if [ "$$LOCAL" != "$$REMOTE" ]; then \
echo "Error: HEAD must match origin/main before releasing."; \
echo "HEAD=$$LOCAL"; \
echo "origin/main=$$REMOTE"; \
exit 1; \
fi; \
REMOTE_TAG=$$(git ls-remote origin "refs/tags/$$TAG" | awk '{print $$1}'); \
if [ -n "$$REMOTE_TAG" ] && [ "$$REMOTE_TAG" != "$$LOCAL" ]; then \
echo "Error: remote $$TAG points at $$REMOTE_TAG, not $$LOCAL"; \
exit 1; \
fi; \
git tag -f "$$TAG" HEAD; \
if [ -z "$$REMOTE_TAG" ]; then git push origin "$$TAG"; fi; \
echo "Creating release $$TAG for $$PROJECT..."; \
awk '/^---$$/{c++;next}c>=2' "$$NOTES" | gh release create "$$TAG" \
--verify-tag \
--target main \
--title "$$PROJECT $$VERSION" \
-F -; \
echo "✓ GitHub release $$TAG created (PyPI publish will run via workflow)"; \
$(MAKE) action-tag
# Move the floating major action tag so `uses: lbliii/kida@v0` tracks the latest release.
# Requires a clean working tree. Skips if the tag already points to the target.
action-tag:
@if [ -n "$$(git status --porcelain)" ]; then \
echo "Error: working tree is not clean. Commit or stash changes first."; \
exit 1; \
fi; \
VERSION=$$(grep '^version = ' pyproject.toml | sed 's/version = "\(.*\)"/\1/'); \
MAJOR=$$(echo $$VERSION | cut -d. -f1); \
CURRENT=$$(git rev-parse v$$MAJOR 2>/dev/null || echo ""); \
TARGET=$$(git rev-parse v$$VERSION 2>/dev/null || echo ""); \
if [ "$$CURRENT" = "$$TARGET" ] && [ -n "$$CURRENT" ]; then \
echo "✓ v$$MAJOR already points to v$$VERSION"; \
exit 0; \
fi; \
echo "Moving action tag v$$MAJOR → v$$VERSION..."; \
git tag -f v$$MAJOR v$$VERSION; \
git push -f origin v$$MAJOR; \
echo "✓ v$$MAJOR now points to v$$VERSION"
# =============================================================================
# Cleanup
# =============================================================================
clean:
rm -rf $(VENV_DIR)
rm -rf build/ dist/ *.egg-info src/*.egg-info
rm -rf site/public
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 ".ruff_cache" -exec rm -rf {} + 2>/dev/null || true
find . -type d -name ".ty_cache" -exec rm -rf {} + 2>/dev/null || true
shell:
@echo "Activating environment with GIL disabled..."
@bash -c 'source $(VENV_DIR)/bin/activate && export PYTHON_GIL=0 && echo "✓ venv active, GIL disabled" && exec bash'