Repository navigation
Expand file tree
/
Copy pathMakefile
More file actions
132 lines (95 loc) · 6.88 KB
/
Copy pathMakefile
File metadata and controls
132 lines (95 loc) · 6.88 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
# Makefile
BACKEND_DIR=fastapi_backend
FRONTEND_DIR=nextjs-frontend
# Compose as a Docker plugin (`docker compose`), or the standalone `docker-compose` where that's what is installed
# (Colima, Podman); `make dev DOCKER_COMPOSE=…` chooses another.
DOCKER_COMPOSE ?= $(shell docker compose version >/dev/null 2>&1 && echo docker compose || echo docker-compose)
.PHONY: help
help: ## List the commands
@awk '/^[a-zA-Z_-]+:.*##/{split($$1, target, ":"); print " " target[1] "\t" substr($$0, index($$0,"##")+3)}' $(MAKEFILE_LIST)
# Local development. The checks run through Nx (nx.json and each project's project.json), as CI runs them, and come
# back from its local cache (.nx/cache) when nothing they read has changed. Nx itself is the root package.json's one
# dependency, installed on first use.
NX = pnpm exec nx
.PHONY: start-backend test-backend lint-backend start-frontend test-frontend lint-frontend openapi worker docs docs-build hooks affected
node_modules/.bin/nx: package.json pnpm-lock.yaml
pnpm install --frozen-lockfile
@touch $@
hooks: ## Install the git hooks: lint on commit, Conventional Commit messages
cd $(BACKEND_DIR) && uv run pre-commit install -c ../.pre-commit-config.yaml
start-backend: $(BACKEND_DIR)/.env $(BACKEND_DIR)/archive.yaml ## Start the API with hot reload (and the OpenAPI watcher), on the embedded database
cd $(BACKEND_DIR) && ./start.sh
worker: ## Run a job worker against the configured database
cd $(BACKEND_DIR) && uv run lens worker
test-backend: node_modules/.bin/nx ## Run the backend tests
$(NX) run backend:test
lint-backend: node_modules/.bin/nx ## Lint, format check and type check the backend
$(NX) run-many -t lint typecheck -p backend
start-frontend: $(FRONTEND_DIR)/.env.local ## Start the web app with hot reload
cd $(FRONTEND_DIR) && ./start.sh
test-frontend: node_modules/.bin/nx ## Run the frontend tests
$(NX) run frontend:test
lint-frontend: node_modules/.bin/nx ## Lint and type check the frontend
$(NX) run-many -t lint typecheck -p frontend
openapi: node_modules/.bin/nx ## Regenerate the OpenAPI schema and the frontend client
$(NX) run backend:openapi
docs: node_modules/.bin/nx ## Serve the documentation (d
8801
ocs-build checks it the way CI does)
$(NX) run docs:serve
docs-build: node_modules/.bin/nx ## Build the documentation site, failing on broken links
$(NX) run docs:build
affected: node_modules/.bin/nx ## Lint, type check, test and build only the projects your changes affect, against main
$(NX) affected -t lint typecheck test build
# Run it (Docker)
PROD_COMPOSE=$(DOCKER_COMPOSE) -f docker-compose.prod.yml
.PHONY: clicks
clicks: env ## Count the clicks, keys and taps each journey takes on a fresh Lens, computer and phone (ci/clicks), vs the baselines
cd $(BACKEND_DIR) && uv sync
cd $(FRONTEND_DIR) && pnpm install && pnpm run build
cd ci/clicks && npm ci
ci/clicks/run.sh --compare ci/clicks/baseline.json
ci/clicks/run.sh --device phone --compare ci/clicks/baseline-phone.json
.PHONY: run dev stop setup-code logs
run: .env ## Build once and run the whole stack, no hot reload (the fast way to use it): http://localhost:3000
$(PROD_COMPOSE) up -d --build
@echo "Lens is at http://localhost:3000. First start: 'make setup-code' for the admin setup code; 'make logs' to follow; 'make stop' to stop."
dev: .env ## Run the stack with hot reload (slower: pages compile on first visit)
$(DOCKER_COMPOSE) up --build --renew-anon-volumes
stop: ## Stop whichever stack is running; the database and the archive stay in their volumes
$(PROD_COMPOSE) down
$(DOCKER_COMPOSE) down
setup-code: ## The first-admin setup code, from the backend log (only until the first account exists)
@($(PROD_COMPOSE) logs backend 2>/dev/null; $(DOCKER_COMPOSE) logs backend 2>/dev/null) | grep -i "setup code" | tail -1 || true
logs: ## Follow the logs of whichever stack is running
@$(PROD_COMPOSE) ps -q 2>/dev/null | grep -q . && $(PROD_COMPOSE) logs -f || $(DOCKER_COMPOSE) logs -f
# The .env files: written with defaults and fresh secrets when missing, never overwritten. The root .env holds the
# secrets; the per-app files for running without Docker take theirs from it, so every way of running Lens shares
# sessions and stored credentials.
.PHONY: env
env: .env $(BACKEND_DIR)/.env $(BACKEND_DIR)/archive.yaml $(FRONTEND_DIR)/.env.local ## Write every .env file that is missing (defaults and fresh secrets)
.env: ## Secrets for Docker (make run, make dev), generated once; keep it: changing ACCESS_SECRET_KEY signs everyone out, ARCHIVE_SECRET_KEY makes stored credentials unreadable
@printf '# Generated by make. Keep it with the volumes.\nACCESS_SECRET_KEY=%s\nARCHIVE_SECRET_KEY=%s\nAUTH_SECRET=%s\n# SurrealDB root password: set before the database volume is first created, and before exposing the port.\nSURREAL_PASS=root\n' "$$(openssl rand -hex 32)" "$$(openssl rand -hex 32)" "$$(openssl rand -hex 32)" > .env
@echo "wrote .env with new secrets"
$(BACKEND_DIR)/.env: .env ## The API's settings for running without Docker: the embedded database, workers in the API process (see .env.example for the rest)
@printf '# Generated by make; .env.example lists everything. Secrets are the root .env'"'"'s, so Docker and native runs share sessions.\nACCESS_SECRET_KEY=%s\nARCHIVE_SECRET_KEY=%s\n# Embedded SurrealDB under data_dir. To share the Docker database instead: SURREAL_URL=ws://localhost:8001\nRUN_BACKGROUND=true\nARCHIVE_CONFIG=archive.yaml\nOPENAPI_OUTPUT_FILE=../nextjs-frontend/openapi.json\nFRONTEND_URL=http://localhost:3000\nCORS_ORIGINS=["http://localhost:3000"]\n' "$$(grep '^ACCESS_SECRET_KEY=' .env | cut -d= -f2-)" "$$(grep '^ARCHIVE_SECRET_KEY=' .env | cut -d= -f2-)" > $@
@echo "wrote $@"
$(BACKEND_DIR)/archive.yaml: ## The processing configuration, from the example
cp $(BACKEND_DIR)/archive.example.yaml $@
$(FRONTEND_DIR)/.env.local: .env ## The web app's settings for running without Docker
@printf '# Generated by make; .env.example explains each. AUTH_SECRET is the root .env'"'"'s.\nAPI_BASE_URL=http://localhost:8000\nAUTH_SECRET=%s\nAUTH_TRUST_HOST=true\nOPENAPI_OUTPUT_FILE=openapi.json\n' "$$(grep '^AUTH_SECRET=' .env | cut -d= -f2-)" > $@
@echo "wrote $@"
# Docker, piece by piece
.PHONY: docker-up docker-build docker-backend-shell docker-frontend-shell docker-test-backend docker-test-frontend docker-logs-setup
docker-up: ## Start the hot-reload stack without rebuilding
$(DOCKER_COMPOSE) up
docker-build: ## Build all the images
$(DOCKER_COMPOSE) build
docker-backend-shell: ## A shell in the backend container
$(DOCKER_COMPOSE) run --rm backend sh
docker-frontend-shell: ## A shell in the frontend container
$(DOCKER_COMPOSE) run --rm frontend sh
docker-test-backend: ## Run the backend tests in Docker
$(DOCKER_COMPOSE) run --rm backend pytest
docker-test-frontend: ## Run the frontend tests in Docker
$(DOCKER_COMPOSE) run --rm frontend pnpm run test
docker-logs-setup: ## Show the first-admin setup code
$(DOCKER_COMPOSE) logs backend | grep -i "setup code"