-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
348 lines (286 loc) · 9.93 KB
/
Copy pathMakefile
File metadata and controls
348 lines (286 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
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
# Makefile for scribbl-py
# Following litestar-workflows pattern
SHELL := /bin/bash
.DEFAULT_GOAL := help
# UV configuration
UV_OPTS ?=
UV := uv $(UV_OPTS)
# Project paths
DOCS_DIR := docs
DOCS_BUILD_DIR := $(DOCS_DIR)/_build
SPHINX_OPTS ?=
SPHINX_BUILD := sphinx-build
SPHINX_AUTOBUILD := sphinx-autobuild
SPHINX_PORT := 8001
# Test configuration
PYTEST_OPTS ?=
PYTEST := $(UV) run --no-sync pytest $(PYTEST_OPTS)
# Ruff configuration
RUFF := $(UV) run --no-sync ruff
RUFF_OPTS ?=
# Type checker configuration
TYPE_CHECKER := $(UV) run --no-sync ty
# Prek configuration
PREK := $(UV) run --no-sync prek
# Security tools
ZIZMOR := zizmor
# Git worktree configuration
WORKTREE_NAME ?= feature
WORKTREE_BASE ?= main
.PHONY: help
help: ## Show this help message
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z0-9_\/-]+:.*?##/ { printf " \033[36m%-28s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
##@ Setup & Installation
.PHONY: install-uv
install-uv: ## Install uv package manager
@command -v uv >/dev/null 2>&1 || { \
echo "Installing uv..."; \
curl -LsSf https://astral.sh/uv/install.sh | sh; \
}
@echo "uv is installed: $$(uv --version)"
.PHONY: install-prek
install-prek: ## Install prek hooks (commit-msg, pre-push)
@echo "Installing prek git hooks..."
$(PREK) install --hook-type commit-msg --hook-type pre-push
@echo "Prek hooks installed successfully"
.PHONY: install
install: ## Production install (uv sync --no-dev)
@echo "Installing production dependencies..."
$(UV) sync --no-dev
@echo "Production dependencies installed"
.PHONY: dev
dev: ## Dev install (uv sync)
@echo "Installing development dependencies..."
$(UV) sync
@echo "Development environment ready"
.PHONY: upgrade
upgrade: ## Upgrade dependencies (prek autoupdate, uv lock --upgrade)
@echo "Updating prek hooks..."
$(PREK) autoupdate
@echo "Upgrading dependencies..."
$(UV) lock --upgrade
@echo "Dependencies upgraded successfully"
##@ Code Quality
.PHONY: lint
lint: ## Run prek hooks (uv run --no-sync prek run --all-files)
@echo "Running prek hooks on all files..."
$(PREK) run --all-files
.PHONY: fmt
fmt: ## Run ruff format
@echo "Formatting code with ruff..."
$(RUFF) format $(RUFF_OPTS) .
.PHONY: fmt-check
fmt-check: ## Check formatting without making changes
@echo "Checking code formatting..."
$(RUFF) format --check $(RUFF_OPTS) .
.PHONY: fmt-fix
fmt-fix: ## Run ruff with auto-fix
@echo "Running ruff with auto-fix..."
$(RUFF) check --fix $(RUFF_OPTS) .
.PHONY: ruff
ruff: ## Run ruff with unsafe fixes
@echo "Running ruff with unsafe fixes..."
$(RUFF) check --fix --unsafe-fixes $(RUFF_OPTS) .
.PHONY: ruff-check
ruff-check: ## Check with ruff without making changes
@echo "Running ruff check..."
$(RUFF) check $(RUFF_OPTS) .
.PHONY: type-check
type-check: ## Run ty type checker
@echo "Running type checker..."
$(TYPE_CHECKER)
##@ Security
.PHONY: security
security: ## Run zizmor on GitHub Actions workflows
@echo "Running security checks on GitHub Actions workflows..."
@command -v $(ZIZMOR) >/dev/null 2>&1 || { \
echo "Error: zizmor is not installed. Install it first."; \
exit 1; \
}
$(ZIZMOR) .github/workflows/
##@ Testing
.PHONY: test
test: ## Run pytest
@echo "Running tests..."
$(PYTEST)
.PHONY: test-cov
test-cov: ## Run tests with coverage report
@echo "Running tests with coverage..."
$(PYTEST) --cov=scribbl_py --cov-report=term-missing --cov-report=html --cov-report=xml
.PHONY: test-fast
test-fast: ## Run quick tests (exit on first failure, minimal output)
@echo "Running fast tests..."
$(PYTEST) -x -q
##@ Documentation
.PHONY: docs
docs: ## Build documentation
@echo "Building documentation..."
$(UV) run --no-sync $(SPHINX_BUILD) -b html $(DOCS_DIR) $(DOCS_BUILD_DIR)/html $(SPHINX_OPTS)
@echo "Documentation built in $(DOCS_BUILD_DIR)/html"
.PHONY: docs-serve
docs-serve: ## Serve documentation with live reload (port 8001)
@echo "Starting documentation server on port $(SPHINX_PORT)..."
$(UV) run --no-sync $(SPHINX_AUTOBUILD) $(DOCS_DIR) $(DOCS_BUILD_DIR)/html \
--port $(SPHINX_PORT) \
--open-browser \
$(SPHINX_OPTS)
.PHONY: docs-clean
docs-clean: ## Clean documentation build artifacts
@echo "Cleaning documentation build artifacts..."
rm -rf $(DOCS_BUILD_DIR)
@echo "Documentation build artifacts removed"
##@ Build & Release
.PHONY: build
build: ## Build distribution packages
@echo "Building distribution packages..."
$(UV) build
@echo "Build complete. Check dist/ directory"
.PHONY: clean
clean: ## Remove autogenerated files (build artifacts, cache, etc.)
@echo "Cleaning autogenerated files..."
rm -rf build/
rm -rf dist/
rm -rf *.egg-info
rm -rf .pytest_cache
rm -rf .ruff_cache
rm -rf .coverage
rm -rf htmlcov/
rm -rf coverage.xml
rm -rf $(DOCS_BUILD_DIR)
find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
find . -type f -name '*.pyc' -delete
find . -type f -name '*.pyo' -delete
find . -type f -name '*.egg' -delete
@echo "Cleanup complete"
.PHONY: destroy
destroy: clean ## Remove .venv (complete reset)
@echo "Removing virtual environment..."
rm -rf .venv
@echo "Virtual environment removed. Run 'make dev' to recreate"
##@ Frontend
.PHONY: frontend-install
frontend-install: ## Install frontend dependencies with Bun
@echo "Installing frontend dependencies..."
@cd frontend && bun install
@echo "Frontend dependencies installed"
.PHONY: frontend-build
frontend-build: ## Build frontend assets for production
@echo "Building frontend assets..."
@cd frontend && bun run build
@echo "Frontend assets built in frontend/dist"
.PHONY: frontend-dev
frontend-dev: ## Watch and rebuild frontend assets
@echo "Starting frontend dev server..."
@cd frontend && bun run dev
##@ Application
.PHONY: serve
serve: frontend-build ## Run the full application (production mode, port 8000)
@echo "=> Starting scribbl-py at http://127.0.0.1:8000"
@echo "=> UI: http://127.0.0.1:8000/ui/"
@echo "=> API: http://127.0.0.1:8000/api/"
@echo "=> Schema: http://127.0.0.1:8000/schema"
@$(UV) run uvicorn scribbl_py.app:app --reload --reload-dir src --port 8000
.PHONY: serve-dev
serve-dev: ## Run with Vite HMR (starts both backend and Vite dev server)
@echo "=> Starting scribbl-py with Vite HMR"
@echo "=> UI: http://127.0.0.1:8000/ui/"
@echo "=> Vite: http://localhost:5173"
@echo ""
@trap 'kill 0' EXIT; \
(cd frontend && bun run dev) & \
sleep 2 && \
DEBUG=true $(UV) run uvicorn scribbl_py.app:app --reload --reload-dir src --port 8000
.PHONY: serve-api
serve-api: ## Run API only without UI (port 8000)
@echo "=> Starting scribbl-py API at http://127.0.0.1:8000"
@$(UV) run uvicorn examples.app:app --reload --reload-dir src --reload-dir examples --port 8000
##@ Git Worktrees
.PHONY: wt worktree
wt worktree: ## Create worktree (usage: make wt NAME=feature-name)
@if [ -z "$(WORKTREE_NAME)" ]; then \
echo "Error: WORKTREE_NAME is required. Usage: make wt NAME=feature-name"; \
exit 1; \
fi
@echo "Creating worktree for branch: $(WORKTREE_NAME)"
@git worktree add -b $(WORKTREE_NAME) ../scribbl-py-$(WORKTREE_NAME) $(WORKTREE_BASE)
@echo "Worktree created at: ../scribbl-py-$(WORKTREE_NAME)"
.PHONY: wt-ls worktree-list
wt-ls worktree-list: ## List all worktrees
@echo "Current worktrees:"
@git worktree list
.PHONY: wt-j worktree-jump
wt-j worktree-jump: ## Jump to worktree (usage: make wt-j NAME=feature-name)
@if [ -z "$(WORKTREE_NAME)" ]; then \
echo "Error: WORKTREE_NAME is required. Usage: make wt-j NAME=feature-name"; \
exit 1; \
fi
@cd ../scribbl-py-$(WORKTREE_NAME) && exec $$SHELL
.PHONY: worktree-prune
worktree-prune: ## Prune stale worktrees
@echo "Pruning stale worktrees..."
@git worktree prune -v
@echo "Worktree pruning complete"
##@ Game Testing
.PHONY: game-test
game-test: ## Open two browser windows for multiplayer testing
@echo "Opening two browser windows for Canvas Clash testing..."
@echo "=> Window 1: Player 1 (regular)"
@echo "=> Window 2: Player 2 (incognito/private)"
@echo ""
@echo "Make sure the server is running: make serve-dev"
@echo ""
@# Open first window (regular)
@open "http://127.0.0.1:8000/canvas-clash/"
@sleep 1
@# Open second window (incognito for separate session)
@open -na "Google Chrome" --args --incognito "http://127.0.0.1:8000/canvas-clash/" 2>/dev/null || \
open -na "Firefox" --args -private-window "http://127.0.0.1:8000/canvas-clash/" 2>/dev/null || \
open "http://127.0.0.1:8000/canvas-clash/"
@echo ""
@echo "Two browser windows opened!"
@echo "1. Create a room in the first window"
@echo "2. Join with the room code in the second window"
.PHONY: game-serve
game-serve: ## Start server and open two browser windows
@echo "Starting server and opening test browsers..."
@$(MAKE) serve-dev &
@sleep 3
@$(MAKE) game-test
##@ CI Helpers
.PHONY: ci
ci: lint type-check fmt-check test ## Run all CI checks (lint, type-check, format check, test)
@echo "All CI checks passed!"
.PHONY: ci-install
ci-install: ## Frozen install for CI (deterministic)
@echo "Installing dependencies for CI..."
$(UV) sync --frozen
@echo "CI dependencies installed"
##@ Local GitHub Actions
.PHONY: act
act: ## Run GitHub Actions locally (default workflow)
@command -v act >/dev/null 2>&1 || { \
echo "Error: act is not installed. Install it from https://github.com/nektos/act"; \
exit 1; \
}
act
.PHONY: act-ci
act-ci: ## Run CI workflow locally
@command -v act >/dev/null 2>&1 || { \
echo "Error: act is not installed. Install it from https://github.com/nektos/act"; \
exit 1; \
}
act push -W .github/workflows/ci.yml
.PHONY: act-docs
act-docs: ## Run docs workflow locally
@command -v act >/dev/null 2>&1 || { \
echo "Error: act is not installed. Install it from https://github.com/nektos/act"; \
exit 1; \
}
act push -W .github/workflows/docs.yml
.PHONY: act-list
act-list: ## List available GitHub Actions workflows
@command -v act >/dev/null 2>&1 || { \
echo "Error: act is not installed. Install it from https://github.com/nektos/act"; \
exit 1; \
}
act -l