-
-
Notifications
You must be signed in to change notification settings - Fork 204
Expand file tree
/
Copy pathMakefile
More file actions
197 lines (157 loc) · 10.2 KB
/
Copy pathMakefile
File metadata and controls
197 lines (157 loc) · 10.2 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
.PHONY: help dev dev-backend dev-frontend dev-unix stop test lint format migrate seed seed-regional seed-cwicr-v3 build qa-screenshots
# ─── Variables ──────────────────────────────────────────────────────────────
BACKEND_DIR = backend
FRONTEND_DIR = frontend
DOCKER_COMPOSE = docker compose
# ─── Help ───────────────────────────────────────────────────────────────────
help: ## Show this help
@echo ""
@echo " OpenConstructionERP — Construction Cost Estimation Platform"
@echo " ─────────────────────────────────────────────────────────────"
@echo ""
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | \
awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-20s\033[0m %s\n", $$1, $$2}'
@echo ""
@echo " Quick start: make quickstart → http://localhost:8080"
@echo " Local dev: make setup && make dev → http://localhost:5173"
@echo ""
# ─── Development ────────────────────────────────────────────────────────────
infra: ## Start infrastructure (PostgreSQL, Redis, MinIO)
$(DOCKER_COMPOSE) up -d postgres redis minio
infra-ai: ## Start infrastructure + AI services (Qdrant)
$(DOCKER_COMPOSE) --profile ai up -d
stop: ## Stop all services
$(DOCKER_COMPOSE) --profile ai down
dev-backend: infra ## Start backend dev server
cd $(BACKEND_DIR) && uvicorn app.main:create_app --factory --reload --port 8000
dev-frontend: ## Start frontend dev server
cd $(FRONTEND_DIR) && npm run dev
dev: ## Show how to start dev (cross-platform: two terminals)
@echo "OpenConstructionERP local dev needs two terminals (cross-platform safe):"
@echo " Terminal 1: make dev-backend (http://localhost:8000)"
@echo " Terminal 2: make dev-frontend (http://localhost:5173)"
@echo ""
@echo "Linux/macOS users may also try the POSIX-only shortcut: make dev-unix"
# POSIX-only: backgrounds the backend with `&` (bash job control).
# Does NOT work in Windows cmd.exe or MSYS2 make — use `make dev-backend`
# and `make dev-frontend` in two terminals instead.
dev-unix: infra ## Start backend (background) + frontend — POSIX shells only
@echo "Starting OpenConstructionERP (POSIX dev)..."
@echo " Backend: http://localhost:8000"
@echo " Frontend: http://localhost:5173"
@echo ""
@cd $(BACKEND_DIR) && uvicorn app.main:create_app --factory --reload --port 8000 &
@cd $(FRONTEND_DIR) && npm run dev
# ─── Testing ────────────────────────────────────────────────────────────────
test: test-backend test-frontend ## Run all tests
test-backend: ## Run backend tests
cd $(BACKEND_DIR) && pytest -x -v
test-backend-cov: ## Run backend tests with coverage
cd $(BACKEND_DIR) && pytest --cov=app --cov-report=term --cov-report=html
test-frontend: ## Run frontend tests
cd $(FRONTEND_DIR) && npm run test
test-unit: ## Run only unit tests (no DB required)
cd $(BACKEND_DIR) && pytest -x -v -m unit
test-integration: ## Run integration tests (requires DB)
cd $(BACKEND_DIR) && pytest -x -v -m integration
qa-screenshots: ## Capture full-app route grid → qa-report/screenshots/<date>/ (needs backend on :8000 + frontend on :5180)
# NODE_PATH lets a Playwright config sitting outside frontend/ still
# resolve @playwright/test from frontend/node_modules — required when
# running from a worktree that doesn't have its own node_modules.
cd $(FRONTEND_DIR) && NODE_PATH="$(CURDIR)/$(FRONTEND_DIR)/node_modules" npx playwright test --config ../qa/screenshots/playwright.config.ts --reporter=line
# ─── Code Quality ───────────────────────────────────────────────────────────
lint: ## Lint all code
cd $(BACKEND_DIR) && ruff check app/ tests/
cd $(FRONTEND_DIR) && npm run lint
format: ## Format the backend code (the frontend has no automatic formatter)
cd $(BACKEND_DIR) && ruff format app/ tests/
typecheck: ## Run type checking
cd $(BACKEND_DIR) && mypy app/
cd $(FRONTEND_DIR) && npm run typecheck
# ─── Database ───────────────────────────────────────────────────────────────
migrate: ## Run all pending migrations
cd $(BACKEND_DIR) && alembic upgrade head
migrate-new: ## Create new migration (usage: make migrate-new MSG="add users table")
cd $(BACKEND_DIR) && alembic revision --autogenerate -m "$(MSG)"
migrate-down: ## Rollback last migration
cd $(BACKEND_DIR) && alembic downgrade -1
seed: ## Load seed data (cost catalog + regional indices). Demo projects are auto-created on first backend startup.
cd $(BACKEND_DIR) && python -m app.scripts.seed_catalog
cd $(BACKEND_DIR) && python -m app.scripts.seed_regional_indices
seed-regional: ## Load regional cost-index seed (v3.12.0, idempotent)
cd $(BACKEND_DIR) && python -m app.scripts.seed_regional_indices
# Override with REGIONS="--regions USA_USD,GB_LONDON" or REGIONS="--top-n 5".
# Default ``--top-n 3`` installs the 3 most-popular catalogues so a fresh
# deployment boots with US/UK/DE rate books pre-loaded — operators no
# longer need to visit /costs and click Install for every region.
REGIONS ?= --top-n 3
seed-cwicr-v3: ## Install CWICR v3 catalogues (REGIONS="--top-n 3" by default; needs CWICR_QDRANT_URL)
cd $(BACKEND_DIR) && python -m scripts.seed_cwicr_v3 $(REGIONS)
db-reset: ## Drop and recreate database (DESTRUCTIVE)
$(DOCKER_COMPOSE) exec postgres psql -U oe -c "DROP DATABASE IF EXISTS openestimate;"
$(DOCKER_COMPOSE) exec postgres psql -U oe -c "CREATE DATABASE openestimate;"
$(MAKE) migrate
$(MAKE) seed
# ─── Module Development ────────────────────────────────────────────────────
module-new: ## Create new module (usage: make module-new NAME=oe_tendering)
cd $(BACKEND_DIR) && python -m app.scripts.scaffold_module $(NAME)
module-test: ## Test specific module (usage: make module-test NAME=oe_boq)
cd $(BACKEND_DIR) && pytest -x -v tests/ -k "$(NAME)"
# ─── Setup (first time) ──────────────────────────────────────────────────
setup: ## First-time setup: install backend + frontend dependencies
@echo "Installing backend dependencies..."
cd $(BACKEND_DIR) && pip install -e .[server]
@echo ""
@echo "Installing frontend dependencies..."
cd $(FRONTEND_DIR) && npm install
@echo ""
@echo "Setup complete! Run 'make dev' to start the application."
@echo " Backend: http://localhost:8000 (FastAPI + SQLite)"
@echo " Frontend: http://localhost:5173 (Vite dev server)"
# ─── Quickstart (single command) ──────────────────────────────────────────
# Building is optional. A failed build used to end at a raw compose error,
# which left people stuck on a step they never had to run, so the failure
# path now names the published image instead.
quickstart: ## Start OpenEstimate (PostgreSQL + App) — zero config
@$(DOCKER_COMPOSE) -f docker-compose.quickstart.yml up --build || $(MAKE) --no-print-directory quickstart-build-failed
quickstart-build-failed:
@echo ""
@echo "The local build did not finish. You do not have to build it:"
@echo ""
@echo " make quickstart-image the same stack, from the image we publish"
@echo ""
@echo "If you would rather we fixed the build, please open an issue with the"
@echo "output above and we will take a look."
@exit 1
# Same stack, but the app comes from the image we publish on every release
# instead of building the frontend here. `pull` is spelled out rather than left
# to `up`, so which artefact runs is stated by the command and not inferred from
# compose's build-versus-pull rules. See docker-compose.quickstart.image.yml.
QUICKSTART_IMAGE_FILES = -f docker-compose.quickstart.yml -f docker-compose.quickstart.image.yml
quickstart-image: ## Start quickstart from the published image (no local build)
$(DOCKER_COMPOSE) $(QUICKSTART_IMAGE_FILES) pull app
$(DOCKER_COMPOSE) $(QUICKSTART_IMAGE_FILES) up -d
@echo " OpenConstructionERP: http://localhost:8080"
quickstart-image-down: ## Stop the published-image quickstart
$(DOCKER_COMPOSE) $(QUICKSTART_IMAGE_FILES) down
quickstart-down: ## Stop quickstart
$(DOCKER_COMPOSE) -f docker-compose.quickstart.yml down
quickstart-reset: ## Reset quickstart (delete data)
$(DOCKER_COMPOSE) -f docker-compose.quickstart.yml down -v
# ─── Build & Deploy ────────────────────────────────────────────────────────
build: ## Build all Docker images
docker build -t openestimate:latest -f deploy/docker/Dockerfile.unified .
docker build -t openestimate-backend:latest -f deploy/docker/Dockerfile.backend .
docker build -t openestimate-frontend:latest -f deploy/docker/Dockerfile.frontend .
build-unified: ## Build single all-in-one Docker image
docker build -t openestimate:latest -f deploy/docker/Dockerfile.unified .
build-wheel: ## Build Python wheel (pip installable)
cd $(FRONTEND_DIR) && npm ci && npm run build
cd $(BACKEND_DIR) && pip install build && python -m build
# ─── Utilities ──────────────────────────────────────────────────────────────
clean: ## Clean build artifacts
find . -type d -name __pycache__ -exec rm -rf {} +
find . -type d -name .pytest_cache -exec rm -rf {} +
find . -type d -name .ruff_cache -exec rm -rf {} +
rm -rf $(BACKEND_DIR)/htmlcov
rm -rf $(FRONTEND_DIR)/dist