# ═══════════════════════════════════════════════════ # Variables # ═══════════════════════════════════════════════════ DATABASE_URL ?= postgres://wrenn:wrenn@localhost:5432/wrenn?sslmode=disable BIN_DIR := $(shell pwd)/builds COMMIT := $(shell git rev-parse --short HEAD 2>/dev/null || echo "unknown") VERSION_CP := $(shell cat VERSION_CP 2>/dev/null | tr -d '[:space:]' || echo "0.0.0-dev") VERSION_AGENT := $(shell cat VERSION_AGENT 2>/dev/null | tr -d '[:space:]' || echo "0.0.0-dev") LDFLAGS := -s -w # ═══════════════════════════════════════════════════ # Build # ═══════════════════════════════════════════════════ .PHONY: build build-cp build-agent build-envd build-frontend build: build-cp build-agent build-envd build-frontend: cd frontend && bun install --frozen-lockfile && bun run build build-cp: go build -v -ldflags="$(LDFLAGS) -X main.version=$(VERSION_CP) -X main.commit=$(COMMIT)" -o $(BIN_DIR)/wrenn-cp ./cmd/control-plane build-agent: go build -v -ldflags="$(LDFLAGS) -X main.version=$(VERSION_AGENT) -X main.commit=$(COMMIT)" -o $(BIN_DIR)/wrenn-agent ./cmd/host-agent build-envd: cd envd-rs && ENVD_COMMIT=$(COMMIT) cargo build --release --target x86_64-unknown-linux-musl @cp envd-rs/target/x86_64-unknown-linux-musl/release/envd $(BIN_DIR)/envd @readelf -h $(BIN_DIR)/envd | grep -q 'Type:.*DYN' && \ readelf -d $(BIN_DIR)/envd | grep -q 'FLAGS_1.*PIE' && \ ! readelf -d $(BIN_DIR)/envd | grep -q '(NEEDED)' && \ { ! readelf -lW $(BIN_DIR)/envd | grep -q 'Requesting program interpreter' || \ readelf -lW $(BIN_DIR)/envd | grep -Fq '[Requesting program interpreter: /lib/ld-musl-x86_64.so.1]'; } || \ (echo "ERROR: envd must be PIE, have no DT_NEEDED shared libs, and either have no interpreter or use /lib/ld-musl-x86_64.so.1" && exit 1) # ═══════════════════════════════════════════════════ # Development # ═══════════════════════════════════════════════════ .PHONY: dev dev-cp dev-agent dev-envd dev-frontend dev-infra dev-down ## One command to start everything for local dev dev: dev-infra migrate-up dev-cp dev-infra: docker compose -f deploy/docker-compose.dev.yml up -d @echo "Waiting for PostgreSQL..." @until docker compose -f deploy/docker-compose.dev.yml exec -T postgres pg_isready -q 2>/dev/null; do sleep 0.5; done @echo "Dev infrastructure ready." dev-down: docker compose -f deploy/docker-compose.dev.yml down -v dev-cp: @if command -v air > /dev/null; then air -c .air.cp.toml; \ else go run ./cmd/control-plane; fi dev-agent: sudo go run ./cmd/host-agent dev-frontend: cd frontend && bun run dev --port 5173 --host 0.0.0.0 dev-envd: cd envd-rs && cargo run -- --isnotfc --port 49983 # ═══════════════════════════════════════════════════ # Database (goose) # ═══════════════════════════════════════════════════ .PHONY: migrate-up migrate-down migrate-status migrate-create migrate-reset migrate-up: goose -dir db/migrations postgres "$(DATABASE_URL)" up migrate-down: goose -dir db/migrations postgres "$(DATABASE_URL)" down migrate-status: goose -dir db/migrations postgres "$(DATABASE_URL)" status migrate-create: goose -dir db/migrations create $(name) sql migrate-reset: goose -dir db/migrations postgres "$(DATABASE_URL)" reset goose -dir db/migrations postgres "$(DATABASE_URL)" up # ═══════════════════════════════════════════════════ # Code Generation # ═══════════════════════════════════════════════════ .PHONY: generate proto sqlc generate: proto sqlc proto: cd proto/envd && buf generate cd proto/hostagent && buf generate sqlc: sqlc generate # ═══════════════════════════════════════════════════ # Quality & Testing # ═══════════════════════════════════════════════════ .PHONY: fmt lint vet test test-integration test-all tidy check fmt: gofmt -w . lint: golangci-lint run ./... vet: go vet ./... test: go test -race -v ./internal/... cd envd-rs && cargo test test-integration: go test -race -v -tags=integration ./tests/integration/... test-all: test test-integration tidy: go mod tidy ## Run all quality checks in CI order check: fmt vet lint test # ═══════════════════════════════════════════════════ # Rootfs Images # ═══════════════════════════════════════════════════ .PHONY: images image-minimal image-python image-node images: build-envd image-minimal image-python image-node image-minimal: sudo bash images/templates/minimal/build.sh image-python: sudo bash images/templates/python312/build.sh image-node: sudo bash images/templates/node20/build.sh # ═══════════════════════════════════════════════════ # Deployment # ═══════════════════════════════════════════════════ .PHONY: setup-host install setup-host: sudo bash scripts/setup-host.sh install: build sudo cp $(BIN_DIR)/wrenn-cp /usr/local/bin/ sudo cp $(BIN_DIR)/wrenn-agent /usr/local/bin/ sudo cp deploy/systemd/*.service /etc/systemd/system/ sudo systemctl daemon-reload # ═══════════════════════════════════════════════════ # Clean # ═══════════════════════════════════════════════════ .PHONY: clean clean: rm -rf builds/ cd envd-rs && cargo clean # ═══════════════════════════════════════════════════ # Help # ═══════════════════════════════════════════════════ .DEFAULT_GOAL := help .PHONY: help help: @echo "Wrenn Sandbox" @echo "" @echo " make dev Full local dev (infra + migrate + seed + control plane)" @echo " make dev-infra Start PostgreSQL + Prometheus + Grafana" @echo " make dev-down Stop dev infra" @echo " make dev-cp Control plane (hot reload if air installed)" @echo " make dev-frontend Vite dev server with HMR (port 5173)" @echo " make dev-agent Host agent (sudo required)" @echo " make dev-envd envd in debug mode (--isnotfc, port 49983)" @echo "" @echo " make build Build all binaries → builds/" @echo " make build-frontend Build SvelteKit dashboard → frontend/build/" @echo " make build-envd Build envd static binary (Rust, musl)" @echo "" @echo " make migrate-up Apply migrations" @echo " make migrate-create name=xxx New migration" @echo " make migrate-reset Drop + re-apply all" @echo "" @echo " make generate Proto + sqlc codegen" @echo " make check fmt + vet + lint + test" @echo " make test-all Unit + integration tests" @echo "" @echo " make images Build all rootfs images" @echo " make setup-host One-time host setup" @echo " make install Install binaries + systemd units"