-
-
Notifications
You must be signed in to change notification settings - Fork 84
Expand file tree
/
Copy pathMakefile
More file actions
351 lines (291 loc) · 14.8 KB
/
Makefile
File metadata and controls
351 lines (291 loc) · 14.8 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
349
350
351
SHELL := /bin/bash
# =============================================================================
# Variables
# =============================================================================
.DEFAULT_GOAL:=help
.ONESHELL:
.EXPORT_ALL_VARIABLES:
MAKEFLAGS += --no-print-directory
# Docker compose configuration
COMPOSE_DIR := tools/deploy/docker
COMPOSE_INFRA := $(COMPOSE_DIR)/docker-compose.infra.yml
COMPOSE_APP := $(COMPOSE_DIR)/docker-compose.yml
# Define project name for docker-compose
COMPOSE_PROJECT_NAME := fullstack-spa
# Define colors and formatting
BLUE := $(shell printf "\033[1;34m")
GREEN := $(shell printf "\033[1;32m")
RED := $(shell printf "\033[1;31m")
YELLOW := $(shell printf "\033[1;33m")
NC := $(shell printf "\033[0m")
INFO := $(shell printf "$(BLUE)ℹ$(NC)")
OK := $(shell printf "$(GREEN)✓$(NC)")
WARN := $(shell printf "$(YELLOW)⚠$(NC)")
ERROR := $(shell printf "$(RED)✖$(NC)")
.PHONY: help
help: ## Display this help text for Makefile
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
# =============================================================================
# Developer Utils
# =============================================================================
.PHONY: install-uv
install-uv: ## Install latest version of uv
@echo "${INFO} Installing uv..."
@curl -LsSf https://astral.sh/uv/install.sh | sh >/dev/null 2>&1
@echo "${OK} UV installed successfully"
.PHONY: install-bun
install-bun: ## Install latest version of bun
@echo "${INFO} Installing bun..."
@curl -fsSL https://bun.sh/install | bash >/dev/null 2>&1
@echo "${OK} Bun installed successfully"
.PHONY: install
install: destroy clean ## Install the project, dependencies, and pre-commit for local development
@echo "${INFO} Starting fresh installation..."
@uv python pin 3.13 >/dev/null 2>&1
@uv venv >/dev/null 2>&1
@uv sync --all-extras --dev
@if ! command -v bun >/dev/null 2>&1; then \
$(MAKE) install-bun; \
fi
@cd src/js/web && bun install --frozen-lockfile >/dev/null 2>&1
@echo "${OK} Installation complete! 🎉"
.PHONY: upgrade
upgrade: ## Upgrade all dependencies to the latest stable versions
@echo "${INFO} Updating all dependencies... 🔄"
@uv lock --upgrade
@cd src/js/web && bun update
@echo "${OK} Dependencies updated 🔄"
@uv run pre-commit autoupdate
@echo "${OK} Updated Pre-commit hooks 🔄"
.PHONY: clean
clean: ## Cleanup temporary build artifacts
@echo "${INFO} Cleaning working directory..."
@rm -rf pytest_cache .ruff_cache .hypothesis build/ -rf dist/ .eggs/ .coverage coverage.xml coverage.json htmlcov/ .pytest_cache src/py/tests/.pytest_cache src/py/tests/**/.pytest_cache .mypy_cache .unasyncd_cache/ .auto_pytabs_cache node_modules src/js/web/node_modules src/js/templates/node_modules >/dev/null 2>&1
@find . -name '*.egg-info' -exec rm -rf {} + >/dev/null 2>&1
@find . -type f -name '*.egg' -exec rm -f {} + >/dev/null 2>&1
@find . -name '*.pyc' -exec rm -f {} + >/dev/null 2>&1
@find . -name '*.pyo' -exec rm -f {} + >/dev/null 2>&1
@find . -name '*~' -exec rm -f {} + >/dev/null 2>&1
@find . -name '__pycache__' -exec rm -rf {} + >/dev/null 2>&1
@find . -name '.ipynb_checkpoints' -exec rm -rf {} + >/dev/null 2>&1
@echo "${OK} Working directory cleaned"
$(MAKE) docs-clean
.PHONY: destroy
destroy: ## Destroy the virtual environment
@echo "${INFO} Destroying virtual environment... 🗑️"
@rm -rf .venv
@echo "${OK} Virtual environment destroyed 🗑️"
.PHONY: lock
lock: ## Rebuild lockfiles from scratch, updating all dependencies
@echo "${INFO} Rebuilding lockfiles... 🔄"
@uv lock --upgrade >/dev/null 2>&1
@echo "${OK} Lockfiles updated"
.PHONY: release
release: ## Bump version and create release tag
@echo "${INFO} Preparing for release... 📦"
@make clean
@uv run bump-my-version bump $(bump)
@make build
@echo "${OK} Release complete 🎉"
# =============================================================================
# Tests, Linting, Coverage
# =============================================================================
.PHONY: ruff
ruff: ## Run ruff
@echo "${INFO} Running ruff... 🔍"
@uv run ruff check --fix src/py/app src/py/tests tools
@uv run ruff format src/py/app src/py/tests tools
@echo "${OK} Ruff checks passed ✨"
.PHONY: biome
biome: ## Run biome
@echo "${INFO} Running biome... 🔍"
@cd src/js/web && bun run lint
@echo "${OK} Biome checks passed ✨"
.PHONY: codespell
codespell: ## Run codespell
@echo "${INFO} Running codespell... 🔍"
@uv run codespell
@echo "${OK} Codespell checks passed ✨"
.PHONY: mypy
mypy: ## Run mypy
@echo "${INFO} Running mypy... 🔍"
@uv run dmypy run src/py/app src/py/tests tools
@echo "${OK} Mypy checks passed ✨"
.PHONY: pyright
pyright: ## Run pyright
@echo "${INFO} Running pyright... 🔍"
@uv run pyright
@echo "${OK} Pyright checks passed ✨"
.PHONY: type-check
type-check: mypy pyright ## Run all type checking
.PHONY: pre-commit
pre-commit: ## Runs pre-commit hooks; includes ruff formatting and linting, codespell
@echo "${INFO} Running pre-commit checks... 🔎"
@uv run pre-commit run --color=always --all-files
@echo "${OK} Pre-commit checks passed ✨"
.PHONY: slotscheck
slotscheck: ## Run slotscheck
@echo "${INFO} Running slots check... 🔍"
@uv run slotscheck -m app
@echo "${OK} Slots check passed ✨"
.PHONY: fix
fix: ## Run formatting scripts
@echo "${INFO} Running code formatters... 🔧"
@uv run ruff check --fix --unsafe-fixes
@cd src/js/web && bun run lint
@echo "${OK} Code formatting complete ✨"
.PHONY: lint
lint: ruff type-check slotscheck biome codespell ## Run all linting
.PHONY: coverage
coverage: ## Run the tests and generate coverage report
@echo "${INFO} Running tests with coverage... 📊"
@uv run pytest src/py/tests --cov --quiet
@uv run coverage html >/dev/null 2>&1
@uv run coverage xml >/dev/null 2>&1
@echo "${OK} Coverage report generated ✨"
.PHONY: test
test: ## Run the tests
@echo "${INFO} Running test cases... 🧪"
@uv run pytest src/py/tests --quiet
@echo "${OK} Tests passed ✨"
.PHONY: test-all
test-all: ## Run all tests
@echo "${INFO} Running all test cases... 🧪"
@uv run pytest src/py/tests -m '' --quiet
@echo "${OK} All tests passed ✨"
.PHONY: check-all
check-all: lint test-all coverage ## Run all linting, tests, and coverage checks
# =============================================================================
# Docs
# =============================================================================
.PHONY: docs-clean
docs-clean: ## Dump the existing built docs
@echo "${INFO} Cleaning documentation build assets... 🧹"
@rm -rf docs/_build >/dev/null 2>&1
@echo "${OK} Documentation assets cleaned"
.PHONY: docs-serve
docs-serve: docs-clean ## Serve the docs locally
@echo "${INFO} Starting documentation server... 📚"
@uv run sphinx-autobuild docs docs/_build/ -j auto --watch app --watch docs --watch tests --watch CONTRIBUTING.rst --port 8002
.PHONY: docs
docs: docs-clean ## Dump the existing built docs and rebuild them
@echo "${INFO} Building documentation... 📝"
@uv run sphinx-build -M html docs docs/_build/ -E -a -j auto -W --keep-going
@echo "${OK} Documentation built successfully"
.PHONY: docs-linkcheck
docs-linkcheck: ## Run the link check on the docs
@echo "${INFO} Checking documentation links... 🔗"
@uv run sphinx-build -b linkcheck ./docs ./docs/_build -D linkcheck_ignore='http://.*','https://.*' >/dev/null 2>&1
@echo "${OK} Link check complete"
.PHONY: docs-linkcheck-full
docs-linkcheck-full: ## Run the full link check on the docs
@echo "${INFO} Running full link check... 🔗"
@uv run sphinx-build -b linkcheck ./docs ./docs/_build -D linkcheck_anchors=0 >/dev/null 2>&1
@echo "${OK} Full link check complete"
# =============================================================================
# Build
# =============================================================================
.PHONY: build
build: build-emails build-assets build-wheel ## Build wheel with frontend assets
.PHONY: build-assets
build-assets: ## Build frontend assets
@echo "${INFO} Building frontend assets... 🎨"
@uv run app assets build
@echo "${OK} Frontend assets built"
.PHONY: build-wheel
build-wheel: ## Build Python wheel
@echo "${INFO} Building Python wheel... 📦"
@uv build --wheel >/dev/null 2>&1
@echo "${OK} Wheel built: dist/*.whl"
.PHONY: build-emails
build-emails: ## Build React email templates to HTML
@echo "${INFO} Building email templates... 📧"
@cd src/js/templates && (bun install --frozen-lockfile 2>/dev/null || bun install) && bun run build
@echo "${OK} Email templates built to src/py/app/server/static/email/"
# =============================================================================
# Local Infrastructure (Database only - for normal development)
# =============================================================================
.PHONY: start-infra
start-infra: ## Start local infrastructure (PostgreSQL)
@echo "${INFO} Starting local infrastructure... 🚀"
@docker compose -f $(COMPOSE_INFRA) up -d --force-recreate
@echo "${OK} Infrastructure is ready"
.PHONY: stop-infra
stop-infra: ## Stop local infrastructure
@echo "${INFO} Stopping infrastructure... 🛑"
@docker compose -f $(COMPOSE_INFRA) down
@echo "${OK} Infrastructure stopped"
.PHONY: wipe-infra
wipe-infra: ## Remove local infrastructure and volumes
@echo "${INFO} Wiping infrastructure... 🧹"
@docker compose -f $(COMPOSE_INFRA) down -v --remove-orphans
@echo "${OK} Infrastructure wiped clean"
.PHONY: infra-logs
infra-logs: ## Tail infrastructure logs
@docker compose -f $(COMPOSE_INFRA) logs -f
.PHONY: mailpit
mailpit: ## Open Mailpit web interface
@echo "${INFO} Opening Mailpit web interface... 📧"
@echo "${INFO} Mailpit UI: http://localhost:18025"
@echo "${INFO} SMTP Server: localhost:11025"
@if command -v open >/dev/null 2>&1; then \
open http://localhost:18025; \
elif command -v xdg-open >/dev/null 2>&1; then \
xdg-open http://localhost:18025; \
else \
echo "${WARN} Please open http://localhost:18025 in your browser"; \
fi
# =============================================================================
# Full Docker Stack - Production (Distroless)
# =============================================================================
.PHONY: start-all-docker
start-all-docker: ## Start production Docker stack (distroless + database)
@echo "${INFO} Building and starting production Docker stack... 🐳"
@docker compose -f $(COMPOSE_APP) up -d --build --force-recreate
@echo "${OK} Production Docker stack is running"
.PHONY: stop-all-docker
stop-all-docker: ## Stop production Docker stack
@echo "${INFO} Stopping production Docker stack... 🛑"
@docker compose -f $(COMPOSE_APP) down
@echo "${OK} Production Docker stack stopped"
.PHONY: wipe-all-docker
wipe-all-docker: ## Remove production Docker stack, images, and volumes
@echo "${INFO} Wiping production Docker stack... 🧹"
@docker compose -f $(COMPOSE_APP) down -v --remove-orphans --rmi local
@echo "${OK} Production Docker stack wiped clean"
.PHONY: docker-logs
docker-logs: ## Tail production Docker stack logs
@docker compose -f $(COMPOSE_APP) logs -f
# =============================================================================
# Full Docker Stack - Development
# =============================================================================
.PHONY: start-all-docker-dev
start-all-docker-dev: ## Start development Docker stack (with hot-reload)
@echo "${INFO} Building and starting development Docker stack... 🐳"
@docker compose -f $(COMPOSE_APP) -f $(COMPOSE_DIR)/docker-compose.override.yml up -d --build --force-recreate
@echo "${OK} Development Docker stack is running"
.PHONY: stop-all-docker-dev
stop-all-docker-dev: ## Stop development Docker stack
@echo "${INFO} Stopping development Docker stack... 🛑"
@docker compose -f $(COMPOSE_APP) -f $(COMPOSE_DIR)/docker-compose.override.yml down
@echo "${OK} Development Docker stack stopped"
.PHONY: wipe-all-docker-dev
wipe-all-docker-dev: ## Remove development Docker stack, images, and volumes
@echo "${INFO} Wiping development Docker stack... 🧹"
@docker compose -f $(COMPOSE_APP) -f $(COMPOSE_DIR)/docker-compose.override.yml down -v --remove-orphans --rmi local
@echo "${OK} Development Docker stack wiped clean"
.PHONY: docker-dev-logs
docker-dev-logs: ## Tail development Docker stack logs
@docker compose -f $(COMPOSE_APP) -f $(COMPOSE_DIR)/docker-compose.override.yml logs -f
.PHONY: docker-shell
docker-shell: ## Open a shell in the app container
@docker compose -f $(COMPOSE_APP) -f $(COMPOSE_DIR)/docker-compose.override.yml exec app /bin/bash || docker compose -f $(COMPOSE_APP) -f $(COMPOSE_DIR)/docker-compose.override.yml exec app /bin/sh
# =============================================================================
# Type Generation
# =============================================================================
.PHONY: types
types: ## Export OpenAPI schema and generate TypeScript types/client
@echo "${INFO} Exporting OpenAPI schema and generating TypeScript types..."
@mkdir -p tmp
@TMPDIR=$(PWD)/tmp uv run app assets generate-types
@echo "${OK} TypeScript types and client generated from OpenAPI schema."