-
-
Notifications
You must be signed in to change notification settings - Fork 227
Expand file tree
/
Copy pathMakefile
More file actions
393 lines (343 loc) · 16.2 KB
/
Makefile
File metadata and controls
393 lines (343 loc) · 16.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
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
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
.PHONY: help build test test-unit clean format lint lint-migrations generate-schema generate-messages generate-fixtures update-oui seed-dev set-plan-community set-plan-starter set-plan-pro set-plan-team set-plan-business set-plan-enterprise test-plan test-merge test-results install-dev-mac install-dev-linux install-dev-windows snmp-up snmp-down snmp-status docker-proxy-up docker-proxy-up-tls docker-proxy-down docker-proxy-status
help:
@echo "Scanopy Development Commands"
@echo ""
@echo " make fresh-db - Clean and set up a new database"
@echo " make setup-db - Set up database"
@echo " make clean-db - Clean up database"
@echo " make migrate-db - Run any database migrations"
@echo " make seed-dev - Create dev user after migrate-db (dev@localhost / password123)"
@echo " make clean-daemon - Remove daemon config file"
@echo " make dump-db - Dump database to /scanopy"
@echo " make dev-server - Start server dev environment"
@echo " make dev-ui - Start ui"
@echo " make dev-daemon - Start daemon dev environment"
@echo " make dev-container - Start containerized development environment using docker-compose.test.yml (server + ui + daemon)"
@echo " make dev-container-rebuild - Rebuild and start containerized dev environment"
@echo " make dev-container-rebuild-clean - Rebuild, clean, and start containerized dev environment"
@echo " make dev-down - Stop development containers"
@echo " make build - Build production Docker images (server + daemon)"
@echo " make test - Run all tests (includes integration tests)"
@echo " make test-unit - Run unit tests only (no Docker/database required)"
@echo " make lint - Run all linters (includes lint-migrations)"
@echo " make lint-migrations - Lint post-20260501 migrations with squawk"
@echo " make format - Format all code"
@echo " make generate-types - Generate TypeScript types from Rust"
@echo " make generate-messages - Generate i18n message functions from messages/*.json"
@echo " make generate-fixtures - Regenerate billing-plans.json and features.json from backend"
@echo " make generate-schema - Generate database schema diagram (requires tbls)"
@echo " make clean - Clean build artifacts and containers"
@echo " make install-dev-mac - Install development dependencies on macOS"
@echo " make install-dev-linux - Install development dependencies on Linux"
@echo " make install-dev-windows - Install development dependencies on Windows"
@echo ""
@echo "Plan Management (sets plan for all organizations):"
@echo " make set-plan-community - Set to Community (free)"
@echo " make set-plan-starter - Set to Starter"
@echo " make set-plan-pro - Set to Pro"
@echo " make set-plan-team - Set to Team"
@echo " make set-plan-business - Set to Business"
@echo " make set-plan-enterprise - Set to Enterprise"
@echo ""
@echo "Test Environments:"
@echo " make snmp-up - Start SNMP test environment (6 snmpd containers)"
@echo " make snmp-down - Stop SNMP test environment"
@echo " make snmp-status - Show SNMP test environment status"
@echo " make docker-proxy-up - Start Docker proxy test environment (HTTP)"
@echo " make docker-proxy-up-tls - Start Docker proxy with TLS"
@echo " make docker-proxy-down - Stop Docker proxy test environment"
@echo " make docker-proxy-status - Show Docker proxy status"
fresh-db:
make clean-db
make setup-db
setup-db:
@echo "Setting up PostgreSQL..."
@docker run -d \
--name scanopy-postgres \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=password \
-e POSTGRES_DB=scanopy \
-p 5432:5432 \
postgres:17-alpine || echo "Already running"
@sleep 3
@echo "PostgreSQL ready at localhost:5432"
clean-db:
docker stop scanopy-postgres || true
docker rm scanopy-postgres || true
migrate-db:
cd backend && sqlx migrate run --database-url postgresql://postgres:password@localhost:5432/scanopy
lint-migrations:
@cd backend && ./scripts/lint-migrations.sh
seed-dev:
@echo "Seeding dev database with test user..."
@docker exec -i scanopy-postgres psql -U postgres -d scanopy < backend/scripts/seed-dev.sql && \
echo "" && \
echo "Dev user created! Login with:" && \
echo " Email: dev@localhost.com" && \
echo " Password: password123"
clean-daemon:
rm -rf ~/Library/Application\ Support/com.scanopy.daemon
dump-db:
docker exec -t scanopy-postgres pg_dump -U postgres -d scanopy > ~/dev/scanopy/scanopy.sql
dev-fresh:
make fresh-db
make migrate-db
@trap 'kill 0' EXIT; \
cd ui && npm run dev & \
export DATABASE_URL="postgresql://postgres:password@localhost:5432/scanopy" && \
cd backend && cargo run --bin server -- --log-level debug --public-url http://localhost:60072
test-merge:
@if ! git diff --quiet || ! git diff --cached --quiet; then \
echo "Working tree is dirty. Commit or stash changes first."; \
echo " git stash OR git add -A && git commit -m 'WIP'"; \
exit 1; \
fi
@current=$$(git branch --show-current); \
if [ "$$current" = "test" ]; then \
echo "Already on test branch. Reset first with: git checkout dev && git branch -D test"; \
exit 1; \
fi; \
branches=$$(git worktree list --porcelain | grep '^branch' | sed 's|branch refs/heads/||' | grep -v "$$current" | grep -v '^test$$'); \
if [ -z "$$branches" ]; then \
echo "No worktree branches found to merge."; \
exit 1; \
fi; \
echo "Creating test branch from $$current..."; \
echo "Branches to merge:"; \
for b in $$branches; do echo " - $$b"; done; \
echo ""; \
git checkout -b test; \
for branch in $$branches; do \
echo "Merging $$branch..."; \
if git merge "$$branch" --no-edit; then \
echo " ✓ $$branch merged"; \
else \
echo ""; \
echo " ✗ $$branch has conflicts. Resolve, then:"; \
echo " git add -A && git merge --continue"; \
remaining=""; \
skip=true; \
for b in $$branches; do \
if [ "$$skip" = false ]; then remaining="$$remaining $$b"; fi; \
if [ "$$b" = "$$branch" ]; then skip=false; fi; \
done; \
if [ -n "$$remaining" ]; then \
echo " Then merge remaining branches:"; \
for b in $$remaining; do echo " git merge $$b --no-edit"; done; \
fi; \
echo " Then: make generate-types && make test-plan"; \
exit 1; \
fi; \
done; \
echo ""; \
echo "All branches merged. Run 'make generate-types && make test-plan' next."
test-plan:
@echo "Collecting TEST_PLAN.json from worktrees..."
@echo "var TEST_PLANS = [" > tools/testing/test-plans.js
@first=true; \
for f in $$(find .. -maxdepth 2 -name "TEST_PLAN.json" -path "*/scanopy-*/TEST_PLAN.json" 2>/dev/null); do \
if [ "$$first" = true ]; then first=false; else echo "," >> tools/testing/test-plans.js; fi; \
cat "$$f" >> tools/testing/test-plans.js; \
echo " Found: $$f"; \
done
@echo "];" >> tools/testing/test-plans.js
@echo "Opening test runner..."
@open tools/testing/test-runner.html 2>/dev/null || xdg-open tools/testing/test-runner.html 2>/dev/null || echo "Open tools/testing/test-runner.html in your browser"
test-results:
@if [ ! -f TEST_RESULTS.json ]; then \
echo "TEST_RESULTS.json not found. Export from test runner first."; \
exit 1; \
fi
@echo "Distributing results to worktrees..."
@for wt in $$(git worktree list --porcelain | grep '^worktree ' | sed 's/^worktree //'); do \
branch=$$(git -C "$$wt" branch --show-current 2>/dev/null); \
if [ -z "$$branch" ]; then continue; fi; \
if grep -q "\"$$branch\"" TEST_RESULTS.json 2>/dev/null; then \
node -e " \
const r = require('./TEST_RESULTS.json'); \
const d = r['$$branch']; \
if (d) { require('fs').writeFileSync('$$wt/TEST_RESULTS.json', JSON.stringify({'$$branch': d}, null, 2)); } \
" && echo " $$branch -> $$wt/TEST_RESULTS.json"; \
fi; \
done
@echo "Done. Agents can read TEST_RESULTS.json in their worktree."
dev-server:
make generate-fixtures
@export DATABASE_URL="postgresql://postgres:password@localhost:5432/scanopy" && \
cd backend && cargo run --bin server -- --log-level debug --public-url http://localhost:60072
dev-daemon:
cd backend && cargo run --bin daemon -- --server-url http://127.0.0.1:60072 --log-level debug
dev-ui:
cd ui && npm run dev
dev-container:
docker compose -f docker-compose.test.yml up
dev-container-rebuild:
docker compose -f docker-compose.test.yml up --build --force-recreate
dev-container-rebuild-clean:
docker compose -f docker-compose.test.yml build --no-cache
docker compose -f docker-compose.test.yml up
dev-down:
docker compose -f docker-compose.test.yml down --volumes --rmi local
test-unit:
cd ui && npx vite-node scripts/export-daemon-field-defs.ts --output=../backend/src/tests/daemon-config-frontend-fields.json 2>/dev/null
@echo "Running frontend tests..."
cd ui && npm test
@echo "Running backend unit tests..."
cd backend && cargo test --lib
test:
cd ui && npx vite-node scripts/export-daemon-field-defs.ts --output=../backend/src/tests/daemon-config-frontend-fields.json 2>/dev/null
@echo "Running frontend tests..."
cd ui && npm test
@echo "Running backend tests..."
make dev-down
rm -rf ./data/daemon_config/*
@export DATABASE_URL="postgresql://postgres:password@localhost:5432/scanopy_test" && \
cd backend && cargo test -- --nocapture --test-threads=1
format:
@echo "Formatting Server..."
cd backend && cargo fmt
@echo "Formatting UI..."
cd ui && npm run format
@echo "All code formatted!"
lint:
@echo "Linting Server..."
cd backend && cargo fmt -- --check && cargo clippy --bin server -- -D warnings
@echo "Linting Daemon..."
cd backend && cargo clippy --bin daemon -- -D warnings
@echo "Generating paraglide i18n..."
cd ui && npx paraglide-js compile --outdir ./src/lib/paraglide --silent
@echo "Linting UI..."
cd ui && npm run lint && npm run format -- --check && npm run check
@echo "Linting migrations..."
@$(MAKE) lint-migrations
generate-types: generate-api-types generate-error-codes
@echo "All types generated successfully"
generate-api-types:
@echo "Exporting OpenAPI spec from backend..."
cd backend && cargo test generate_openapi_spec -- --nocapture
@echo "Generating TypeScript types from OpenAPI spec..."
cd ui && npm run generate:api
@echo "TypeScript types exported to ui/src/lib/api/schema.d.ts"
generate-error-codes:
@echo "Generating error codes from Rust enum..."
cd backend && cargo run --bin generate-error-codes
@echo "Merging error messages into en.json..."
cd ui && node scripts/merge-error-messages.js
@echo "Error codes generated and merged"
generate-schema:
@command -v tbls >/dev/null 2>&1 || { echo "Install tbls: brew install k1low/tap/tbls"; exit 1; }
@rm -rf /tmp/tbls-schema && \
tbls doc "postgres://postgres:password@localhost:5435/scanopy?sslmode=disable" /tmp/tbls-schema --er-format mermaid --exclude sqlx_migrations --force && \
awk '/^```mermaid$$/,/^```$$/{if(!/^```/)print}' /tmp/tbls-schema/README.md > ui/static/schema.mermaid && \
rm -rf /tmp/tbls-schema
@echo "✅ Generated ui/static/schema.mermaid"
generate-messages:
@echo "Generating i18n messages..."
cd ui && npx paraglide-js compile --outdir ./src/lib/paraglide --silent
@echo "Messages generated successfully"
generate-fixtures:
@echo "Generating metadata fixtures from backend..."
cd backend && cargo run --bin generate-fixtures
@echo "✅ Generated all metadata fixtures in ui/src/lib/data/"
update-oui:
@echo "Downloading latest IEEE OUI database..."
curl -sf --max-time 60 -o backend/assets/oui.csv https://standards-oui.ieee.org/oui/oui.csv
@echo "✅ OUI database updated. Rebuild to embed new data."
stripe-webhook:
stripe listen --forward-to http://localhost:60072/api/billing/webhooks
clean:
make clean-db
docker compose down -v
cd backend && cargo clean
cd ui && rm -rf node_modules dist build .svelte-kit
install-dev-mac:
@echo "Installing Rust toolchain..."
rustup install stable
rustup component add rustfmt clippy
@echo "Installing Node.js dependencies..."
cd ui && npm install
@echo "Installing pre-commit hooks..."
@command -v pre-commit >/dev/null 2>&1 || { \
echo "Installing pre-commit via pip..."; \
pip3 install pre-commit --break-system-packages || pip3 install pre-commit; \
}
pre-commit install
pre-commit install --hook-type pre-push
@echo "Development dependencies installed!"
@echo "Note: Run 'source ~/.zshrc' to update your PATH, or restart your terminal"
install-dev-linux:
@echo "Installing Rust toolchain..."
rustup install stable
rustup component add rustfmt clippy
@echo "Installing Node.js dependencies..."
cd ui && npm install
@echo "Installing pre-commit hooks..."
@command -v pre-commit >/dev/null 2>&1 || { \
echo "Installing pre-commit via pip..."; \
pip3 install pre-commit --break-system-packages || pip3 install pre-commit; \
}
pre-commit install
pre-commit install --hook-type pre-push
@echo ""
@echo "Development dependencies installed!"
install-dev-windows:
@echo "Installing native Windows development dependencies..."
@echo "Installing Rust toolchain..."
rustup install stable
rustup component add rustfmt clippy
@echo "Installing Node.js dependencies..."
cd ui && npm install
@echo ""
@echo "Development dependencies installed!"
@echo ""
@echo "Tip: Install pre-commit for git hooks: pip install pre-commit"
@echo " Then run: pre-commit install && pre-commit install --hook-type pre-push"
# Plan management commands - set all organizations to a specific plan
set-plan-community:
@echo "Setting all organizations to Community plan..."
@docker exec -t scanopy-postgres psql -U postgres -d scanopy -c \
"UPDATE organizations SET plan = '{\"type\": \"Community\", \"base_cents\": 0, \"rate\": \"Month\", \"trial_days\": 0, \"seat_cents\": null, \"network_cents\": null, \"included_seats\": null, \"included_networks\": null}'::jsonb"
@echo "Done!"
set-plan-free:
@echo "Setting all organizations to Free plan..."
@docker exec -t scanopy-postgres psql -U postgres -d scanopy -c \
"UPDATE organizations SET plan = '{\"type\": \"Free\", \"base_cents\": 999, \"rate\": \"Month\", \"trial_days\": 7, \"seat_cents\": null, \"network_cents\": null, \"included_seats\": 1, \"included_networks\": 1, \"included_hosts\": 25}'::jsonb"
@echo "Done!"
set-plan-starter:
@echo "Setting all organizations to Starter plan..."
@docker exec -t scanopy-postgres psql -U postgres -d scanopy -c \
"UPDATE organizations SET plan = '{\"type\": \"Starter\", \"base_cents\": 999, \"rate\": \"Month\", \"trial_days\": 7, \"seat_cents\": null, \"network_cents\": null, \"included_seats\": 1, \"included_networks\": 1}'::jsonb"
@echo "Done!"
set-plan-pro:
@echo "Setting all organizations to Pro plan..."
@docker exec -t scanopy-postgres psql -U postgres -d scanopy -c \
"UPDATE organizations SET plan = '{\"type\": \"Pro\", \"base_cents\": 1999, \"rate\": \"Month\", \"trial_days\": 7, \"seat_cents\": null, \"network_cents\": 800, \"included_seats\": 1, \"included_networks\": 3}'::jsonb"
@echo "Done!"
set-plan-business:
@echo "Setting all organizations to Business plan..."
@docker exec -t scanopy-postgres psql -U postgres -d scanopy -c \
"UPDATE organizations SET plan = '{\"type\": \"Business\", \"base_cents\": 5999, \"rate\": \"Month\", \"trial_days\": 14, \"seat_cents\": 800, \"network_cents\": 500, \"included_seats\": 5, \"included_networks\": 15}'::jsonb"
@echo "Done!"
set-plan-enterprise:
@echo "Setting all organizations to Enterprise plan..."
@docker exec -t scanopy-postgres psql -U postgres -d scanopy -c \
"UPDATE organizations SET plan = '{\"type\": \"Enterprise\", \"base_cents\": 0, \"rate\": \"Month\", \"trial_days\": 0, \"seat_cents\": null, \"network_cents\": null, \"included_seats\": null, \"included_networks\": null}'::jsonb"
@echo "Done!"
set-plan-demo:
@echo "Setting all organizations to Demo plan..."
@docker exec -t scanopy-postgres psql -U postgres -d scanopy -c \
"UPDATE organizations SET plan = '{\"type\": \"Demo\", \"base_cents\": 0, \"rate\": \"Month\", \"trial_days\": 0, \"seat_cents\": null, \"network_cents\": null, \"included_seats\": null, \"included_networks\": null}'::jsonb"
@echo "Done!"
# Test Environments
snmp-verify:
tools/snmp/snmp-test-env.sh verify
snmp-status:
tools/snmp/snmp-test-env.sh status
docker-proxy-up:
tools/docker-proxy/docker-proxy-test-env.sh up
docker-proxy-up-tls:
tools/docker-proxy/docker-proxy-test-env.sh up --tls
docker-proxy-down:
tools/docker-proxy/docker-proxy-test-env.sh down
docker-proxy-status:
tools/docker-proxy/docker-proxy-test-env.sh status