-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
370 lines (316 loc) · 12.7 KB
/
Copy pathMakefile
File metadata and controls
370 lines (316 loc) · 12.7 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
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
.PHONY: install format lint test run clean help db-init dev dev-down dev-logs dev-rebuild dev-frontend docker-clean stage stage-down prod prod-down
# === Environments ===========================================================
# `make dev` — local development (docker-compose.dev.yml + bind-mounted source)
# `make stage` — staging (docker-compose.yml — built images, no live reload)
# `make prod` — production (docker-compose.prod.yml — needs backend/.env + nginx)
# Each env has matching -down / -logs / -rebuild siblings.
# Wait for postgres to accept connections. Polls pg_isready instead of a
# fixed sleep — handles slow startups and cold-start image pulls.
define _wait_for_db
@echo "Waiting for PostgreSQL ($(1))..."
@for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do \
if docker compose -f $(1) exec -T db pg_isready -U postgres >/dev/null 2>&1; then \
echo " ✅ DB ready"; exit 0; \
fi; \
printf '.'; sleep 2; \
done; \
echo " ❌ DB not ready after 30s — check 'make dev-logs'"; exit 1
endef
# === Local dev: build → up → migrate ===
# Idempotent — re-run anytime. Migrations are no-ops when already at head;
# admin seeding is a separate target (`make seed`) so re-running `make dev`
# doesn't keep retrying user creation.
dev:
@echo "▶ Building backend image…"
docker compose -f docker-compose.dev.yml build app
@echo "▶ Starting services…"
@if ! docker compose -f docker-compose.dev.yml $(COMPOSE_DEV_PROFILES) up -d; then \
echo ""; \
echo "⚠ First start failed. Tearing down stale containers and retrying once…"; \
echo " (volumes preserved — DB data is safe; use 'make clean' for a full wipe)"; \
docker compose -f docker-compose.dev.yml down --remove-orphans; \
docker compose -f docker-compose.dev.yml $(COMPOSE_DEV_PROFILES) up -d; \
fi
$(call _wait_for_db,docker-compose.dev.yml)
@echo "▶ Applying migrations…"
docker compose -f docker-compose.dev.yml exec -T app proj2 db upgrade
@echo ""
@echo "🚀 Dev stack ready:"
@echo " API: http://localhost:8000"
@echo " Docs: http://localhost:8000/docs"
@echo " Admin: http://localhost:8000/admin"
@echo " Frontend: http://localhost:3000 (run 'make dev-frontend' or 'cd frontend && bun dev')"
@echo ""
@echo "First time? Run 'make seed' to create the default admin user."
# === First-time setup: seed default admin user (one-shot) ===
# Skipped when admin@example.com already exists. Safe to run again — exits
# clean either way. Replace email/password before deploying anywhere real.
seed:
@echo "▶ Seeding admin user (admin@example.com / admin123)…"
@if docker compose -f docker-compose.dev.yml exec -T app \
proj2 user list 2>/dev/null \
| grep -q "admin@example.com"; then \
echo " (admin@example.com already exists — nothing to do)"; \
else \
docker compose -f docker-compose.dev.yml exec -T app \
proj2 user create \
--email admin@example.com --password admin123 --superuser \
&& echo " ✅ Admin created. Login at http://localhost:8000/admin"; \
fi
# Convenience: bootstrap a fresh checkout end-to-end.
bootstrap: dev seed
dev-down:
docker compose -f docker-compose.dev.yml $(COMPOSE_DEV_PROFILES) down
# Full wipe — containers, networks, AND volumes. Use after a corrupted state
# (e.g. detached networks, port conflicts that left orphans). DESTROYS DB data.
docker-clean:
@echo "▶ Removing containers, networks, AND volumes for the dev stack…"
@echo " ⚠️ This deletes all local DB data and uploaded files."
docker compose -f docker-compose.dev.yml $(COMPOSE_DEV_PROFILES) down -v --remove-orphans
@echo "✅ Cleaned. Run 'make dev' to start fresh."
dev-logs:
docker compose -f docker-compose.dev.yml $(COMPOSE_DEV_PROFILES) logs -f
dev-rebuild:
docker compose -f docker-compose.dev.yml build --no-cache app
docker compose -f docker-compose.dev.yml up -d --force-recreate app
dev-frontend:
docker compose -f docker-compose.frontend.yml up -d
@echo ""
@echo "✅ Frontend at http://localhost:3000 (backend must be up — 'make dev')"
# === Staging: built images, no bind mounts (production-like, local DB) ===
stage:
docker compose -f docker-compose.yml up -d --build
$(call _wait_for_db,docker-compose.yml)
docker compose -f docker-compose.yml exec -T app proj2 db upgrade
@echo "✅ Staging stack at http://localhost:8000"
stage-down:
docker compose -f docker-compose.yml down
# === Production: external Nginx, real secrets in backend/.env ===
prod:
@test -f backend/.env || (echo "❌ backend/.env missing — run 'cp backend/.env.example backend/.env' and fill in real secrets" && exit 1)
docker compose --env-file backend/.env -f docker-compose.prod.yml up -d --build
@echo "▶ Waiting for DB then running migrations…"
@sleep 5
docker compose --env-file backend/.env -f docker-compose.prod.yml exec -T app proj2 db upgrade
@echo "✅ Production stack up. Configure your nginx host with nginx/nginx.conf"
prod-down:
docker compose --env-file backend/.env -f docker-compose.prod.yml down
prod-logs:
docker compose --env-file backend/.env -f docker-compose.prod.yml logs -f
# Legacy alias
quickstart: dev
# === Setup ===
install:
uv sync --directory backend --dev
@if git rev-parse --git-dir > /dev/null 2>&1; then \
uv run --directory backend pre-commit install; \
else \
echo "⚠️ Not a git repository - skipping pre-commit install"; \
echo " Run 'git init && make install' to set up pre-commit hooks"; \
fi
@echo ""
@echo "✅ Installation complete!"
@echo ""
@echo "Next steps:"
@echo " • make docker-db # Start PostgreSQL"
@echo " • make db-upgrade # Apply migrations"
@echo " • make run # Start development server"
@echo ""
@echo "Note: backend/.env is pre-configured for development"
# === Code Quality ===
format:
uv run --directory backend ruff format app tests cli
uv run --directory backend ruff check app tests cli --fix
lint:
uv run --directory backend ruff check app tests cli
uv run --directory backend ruff format app tests cli --check
uv run --directory backend ty check
# === Testing ===
test:
uv run --directory backend pytest tests/ -v
test-cov:
uv run --directory backend pytest tests/ -v --cov=app --cov-report=html --cov-report=term-missing
# === Database ===
db-init: docker-db
@echo "Waiting for PostgreSQL to be ready..."
@sleep 8
cd backend && uv run proj2 db migrate -m "initial" || true
cd backend && uv run proj2 db upgrade
@echo ""
@echo "✅ Database initialized!"
db-migrate:
@read -p "Migration message: " msg; \
uv run --directory backend proj2 db migrate -m "$$msg"
db-upgrade:
uv run --directory backend proj2 db upgrade
db-downgrade:
uv run --directory backend proj2 db downgrade
db-current:
uv run --directory backend proj2 db current
db-history:
uv run --directory backend proj2 db history
# === Server ===
run:
uv run --directory backend proj2 server run --reload
run-prod:
uv run --directory backend proj2 server run --host 0.0.0.0 --port 8000
routes:
uv run --directory backend proj2 server routes
# === Users ===
create-admin:
@echo "Creating admin user..."
uv run --directory backend proj2 user create-admin
user-create:
uv run --directory backend proj2 user create
user-list:
uv run --directory backend proj2 user list
# === Taskiq ===
taskiq-worker:
uv run --directory backend proj2 taskiq worker
taskiq-scheduler:
uv run --directory backend proj2 taskiq scheduler
# === Docker: Backend (Development) ===
docker-up:
docker compose build app
docker compose up -d
@echo ""
@echo "✅ Backend services started!"
@echo " API: http://localhost:8000"
@echo " Docs: http://localhost:8000/docs"
@echo " PostgreSQL: localhost:5432"
@echo " Redis: localhost:6379"
docker-down:
docker compose down
docker compose -f docker-compose.frontend.yml down 2>/dev/null || true
docker-logs:
docker compose logs -f
docker-build:
docker compose build
docker-shell:
docker compose exec app /bin/bash
# === Docker: Frontend (Development) ===
docker-frontend:
docker compose -f docker-compose.frontend.yml up -d
@echo ""
@echo "✅ Frontend started!"
@echo " URL: http://localhost:3000"
@echo ""
@echo "Note: Backend must be running (make docker-up)"
docker-frontend-down:
docker compose -f docker-compose.frontend.yml down
docker-frontend-logs:
docker compose -f docker-compose.frontend.yml logs -f
docker-frontend-build:
docker compose -f docker-compose.frontend.yml build
# === Docker: Production (with Traefik) ===
docker-prod:
docker compose -f docker-compose.prod.yml up -d
@echo ""
@echo "✅ Production services started with Traefik!"
@echo ""
@echo "Endpoints (replace DOMAIN with your domain):"
@echo " Frontend: https://$$DOMAIN"
@echo " API: https://api.$$DOMAIN"
@echo " Traefik: https://traefik.$$DOMAIN"
docker-prod-down:
docker compose -f docker-compose.prod.yml down
docker-prod-logs:
docker compose -f docker-compose.prod.yml logs -f
docker-prod-build:
docker compose -f docker-compose.prod.yml build
# === Docker: Individual Services ===
docker-db:
docker compose up -d db
@echo ""
@echo "✅ PostgreSQL started on port 5432"
@echo " Connection: postgresql://postgres:postgres@localhost:5432/proj2"
docker-db-stop:
docker compose stop db
docker-redis:
docker compose up -d redis
@echo ""
@echo "✅ Redis started on port 6379"
docker-redis-stop:
docker compose stop redis
# === Vercel (Frontend Deployment) ===
vercel-deploy:
cd frontend && npx vercel --prod
@echo ""
@echo "✅ Frontend deployed to Vercel!"
@echo " Set environment variables in Vercel dashboard:"
@echo " BACKEND_URL=https://api.your-domain.com"
@echo " BACKEND_WS_URL=wss://api.your-domain.com"
@echo " NEXT_PUBLIC_AUTH_ENABLED=true"
# === Cleanup ===
clean:
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
rm -rf htmlcov/ .coverage coverage.xml
# === Help ===
help:
@echo ""
@echo "proj2 - Available Commands"
@echo "======================================"
@echo ""
@echo "🚀 Bootstrap (first-time setup):"
@echo " make bootstrap 'make dev' + 'make seed' — full setup from a fresh clone"
@echo ""
@echo "Day-to-day dev:"
@echo " make dev Build + start dev stack + apply migrations (idempotent)"
@echo " make seed One-shot admin seed (admin@example.com / admin123)"
@echo " make dev-down Stop dev stack"
@echo " make dev-logs Tail dev container logs"
@echo " make dev-rebuild Force-rebuild backend image"
@echo " make docker-clean Wipe containers + networks + volumes (DESTROYS data)"
@echo " make dev-frontend Start frontend container (after 'make dev')"
@echo ""
@echo "📦 Other environments:"
@echo " make stage Production-like stack on localhost (no bind mounts)"
@echo " make prod Production stack (requires backend/.env + nginx)"
@echo ""
@echo "Setup (without Docker):"
@echo " make install Install Python deps + pre-commit hooks"
@echo ""
@echo "Development:"
@echo " make run Start dev server (with hot reload)"
@echo " make test Run tests"
@echo " make lint Check code quality"
@echo " make format Auto-format code"
@echo ""
@echo "Database:"
@echo " make db-init Initialize database (start + migrate)"
@echo " make db-migrate Create new migration"
@echo " make db-upgrade Apply migrations"
@echo " make db-downgrade Rollback last migration"
@echo " make db-current Show current migration"
@echo ""
@echo "Users:"
@echo " make create-admin Create admin user (for SQLAdmin access)"
@echo " make user-create Create new user (interactive)"
@echo " make user-list List all users"
@echo ""
@echo "Taskiq:"
@echo " make taskiq-worker Start Taskiq worker"
@echo " make taskiq-scheduler Start Taskiq scheduler"
@echo ""
@echo "Docker (Development):"
@echo " make docker-up Start backend services"
@echo " make docker-down Stop all services"
@echo " make docker-logs View backend logs"
@echo " make docker-build Build backend images"
@echo " make docker-frontend Start frontend (separate)"
@echo " make docker-frontend-down Stop frontend"
@echo " make docker-db Start only PostgreSQL"
@echo " make docker-redis Start only Redis"
@echo ""
@echo "Docker (Production with Traefik):"
@echo " make docker-prod Start production stack"
@echo " make docker-prod-down Stop production stack"
@echo " make docker-prod-logs View production logs"
@echo ""
@echo "Other:"
@echo " make routes Show all API routes"
@echo " make clean Clean cache files"
@echo ""