veza/Makefile
senke f74b020d4b api-contracts: install openapi-generator-cli and create type generation script
- Completed Action 1.1.2.1: Installed @openapitools/openapi-generator-cli
- Completed Action 1.1.2.2: Created generate-types.sh script
- Added swagger annotations to cmd/modern-server/main.go
- Regenerated swagger.yaml with proper info section
- Successfully generated TypeScript types to src/types/generated/

The script generates types from veza-backend-api/openapi.yaml using
typescript-axios generator and creates barrel exports.
2026-01-11 16:30:43 +01:00

466 lines
21 KiB
Makefile

# ==============================================================================
# VEZA MONOREPO - ULTIMATE CONTROL PLANE
# ==============================================================================
# Stack: Docker + Incus (LXD) Support
# System: Linux / Bash
# ==============================================================================
# --- Auto-Configuration ---
-include .env
# Shell setup
SHELL := /bin/bash
.ONESHELL:
.DEFAULT_GOAL := help
# --- Variables ---
PROJECT_NAME := veza
COMPOSE_FILE := docker-compose.yml
COMPOSE_PROD := docker-compose.prod.yml
# Services
SERVICES := backend-api chat-server stream-server web haproxy
INFRA_SERVICES := postgres redis rabbitmq
# Ports
PORT_GO ?= 8080
PORT_CHAT ?= 3000
PORT_STREAM ?= 3001
PORT_WEB ?= 5173
PORT_HAPROXY ?= 80
# Database & Infra
DB_USER ?= veza
DB_PASS ?= password
DB_NAME ?= veza
DB_HOST ?= localhost
DB_PORT ?= 5432
# Connection Strings
DATABASE_URL = postgres://$(DB_USER):$(DB_PASS)@$(DB_HOST):$(DB_PORT)/$(DB_NAME)?sslmode=disable
REDIS_URL = redis://localhost:6379
AMQP_URL = amqp://$(DB_USER):$(DB_PASS)@localhost:5672
# Directories
DIR_GO := veza-backend-api
DIR_CHAT := veza-chat-server
DIR_STREAM := veza-stream-server
DIR_WEB := apps/web
# Deployment
DEPLOY_TARGET ?= docker
INCUS_PROFILE := veza-profile
INCUS_NETWORK := veza-network
# --- Aesthetics & UI ---
BOLD := \033[1m
RED := \033[0;31m
GREEN := \033[0;32m
YELLOW := \033[0;33m
BLUE := \033[0;34m
PURPLE := \033[0;35m
CYAN := \033[0;36m
NC := \033[0m
ECHO_CMD = echo -e
# ==============================================================================
# HELP & DASHBOARD
# ==============================================================================
.PHONY: help
help: ## Show this dashboard
@$(ECHO_CMD) ""
@$(ECHO_CMD) "${BOLD}${PURPLE}⚡ VEZA MONOREPO CLI ⚡${NC}"
@$(ECHO_CMD) "================================================================="
@$(ECHO_CMD) "${BOLD}INFRASTRUCTURE:${NC}"
@printf " ${CYAN}%-15s${NC} %s\n" "Postgres" "${DATABASE_URL}"
@printf " ${CYAN}%-15s${NC} %s\n" "Redis" "${REDIS_URL}"
@printf " ${CYAN}%-15s${NC} %s\n" "RabbitMQ" "UI: http://localhost:15672 (veza/password)"
@$(ECHO_CMD) ""
@$(ECHO_CMD) "${BOLD}${GREEN}HIGH LEVEL COMMANDS:${NC}"
@grep -E '^[a-zA-Z0-9_-]+:.*?## \[HIGH\] .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " ${YELLOW}%-25s${NC} %s\n", $$1, $$2}'
@$(ECHO_CMD) ""
@$(ECHO_CMD) "${BOLD}${BLUE}INTERMEDIATE COMMANDS:${NC}"
@grep -E '^[a-zA-Z0-9_-]+:.*?## \[MID\] .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " ${CYAN}%-25s${NC} %s\n", $$1, $$2}'
@$(ECHO_CMD) ""
@$(ECHO_CMD) "${BOLD}${PURPLE}LOW LEVEL / DEBUG:${NC}"
@grep -E '^[a-zA-Z0-9_-]+:.*?## \[LOW\] .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " ${PURPLE}%-25s${NC} %s\n", $$1, $$2}'
@$(ECHO_CMD) ""
# ==============================================================================
# HIGH LEVEL COMMANDS
# ==============================================================================
.PHONY: setup stop-all restart-all clean deploy-docker deploy-incus status-full
setup: check-tools install-tools install-deps ## [HIGH] Full project initialization
@$(ECHO_CMD) "${BOLD}${GREEN}✅ Setup Complete! Ready to rock with 'make dev'.${NC}"
stop-all: ## [HIGH] Stop all services (Docker + Local)
@$(ECHO_CMD) "${RED}🛑 Stopping all services...${NC}"
@docker compose -f $(COMPOSE_FILE) down 2>/dev/null || true
@docker compose -f $(COMPOSE_PROD) down 2>/dev/null || true
@$(MAKE) -s stop-local-services
@$(ECHO_CMD) "${GREEN}✅ All services stopped.${NC}"
restart-all: stop-all ## [HIGH] Restart all services
@$(ECHO_CMD) "${BLUE}🔄 Restarting all services...${NC}"
@$(MAKE) -s infra-up
@$(MAKE) -s dev
@$(ECHO_CMD) "${GREEN}✅ All services restarted.${NC}"
clean: ## [HIGH] Clean build artifacts and caches
@$(ECHO_CMD) "${YELLOW}🧹 Cleaning build artifacts...${NC}"
@rm -rf $(DIR_WEB)/node_modules/.cache
@rm -rf $(DIR_CHAT)/target/debug $(DIR_STREAM)/target/debug
@find . -type d -name "node_modules" -prune -o -type f -name "*.log" -delete
@$(ECHO_CMD) "${GREEN}✅ Clean complete.${NC}"
clean-deep: ## [HIGH] ⚠️ Nuclear Clean (Confirm required)
@read -p "${RED}Are you sure? This will delete ALL builds, volumes, and caches! [y/N]${NC} " ans && [ $${ans:-N} = y ]
@$(ECHO_CMD) "${RED}☢️ DESTROYING ARTIFACTS...${NC}"
@rm -rf $(DIR_WEB)/node_modules
@rm -rf $(DIR_CHAT)/target $(DIR_STREAM)/target
@docker compose -f $(COMPOSE_FILE) down -v 2>/dev/null || true
@docker compose -f $(COMPOSE_PROD) down -v 2>/dev/null || true
@$(ECHO_CMD) "${GREEN}System Cleaned.${NC}"
deploy-docker: build-all ## [HIGH] Deploy all services with Docker + HAProxy
@$(ECHO_CMD) "${BOLD}${BLUE}🐳 Deploying with Docker...${NC}"
@docker compose -f $(COMPOSE_PROD) up -d --build
@$(MAKE) -s wait-for-services
@$(ECHO_CMD) "${GREEN}✅ Deployment complete! Access via http://localhost:$(PORT_HAPROXY)${NC}"
deploy-incus: build-all ## [HIGH] Deploy all services with Incus containers
@$(ECHO_CMD) "${BOLD}${BLUE}📦 Deploying with Incus...${NC}"
@$(MAKE) -s incus-setup-network
@$(MAKE) -s incus-deploy-all
@$(ECHO_CMD) "${GREEN}✅ Incus deployment complete!${NC}"
status-full: ## [HIGH] Show complete system status
@$(ECHO_CMD) "${BOLD}${CYAN}📊 SYSTEM STATUS${NC}"
@$(ECHO_CMD) ""
@$(ECHO_CMD) "${BOLD}Docker Containers:${NC}"
@docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep -E "NAME|veza" || echo " No containers running"
@$(ECHO_CMD) ""
@$(ECHO_CMD) "${BOLD}Local Processes:${NC}"
@lsof -i :$(PORT_GO) -i :$(PORT_CHAT) -i :$(PORT_STREAM) -i :$(PORT_WEB) 2>/dev/null | grep LISTEN || echo " No local processes"
@$(ECHO_CMD) ""
@$(ECHO_CMD) "${BOLD}Incus Containers:${NC}"
@incus list veza- 2>/dev/null | grep -E "NAME|veza" || echo " No Incus containers"
@$(ECHO_CMD) ""
# ==============================================================================
# INTERMEDIATE COMMANDS
# ==============================================================================
.PHONY: start-service stop-service restart-service logs-service build-service
start-service: ## [MID] Start a specific service (usage: make start-service SERVICE=backend-api)
@if [ -z "$(SERVICE)" ]; then \
$(ECHO_CMD) "${RED}❌ Please specify SERVICE=name${NC}"; \
exit 1; \
fi
@$(ECHO_CMD) "${BLUE}🚀 Starting $(SERVICE)...${NC}"
@docker compose -f $(COMPOSE_PROD) up -d $(SERVICE) || \
$(MAKE) -s start-local-service SERVICE=$(SERVICE)
@$(ECHO_CMD) "${GREEN}$(SERVICE) started.${NC}"
stop-service: ## [MID] Stop a specific service (usage: make stop-service SERVICE=backend-api)
@if [ -z "$(SERVICE)" ]; then \
$(ECHO_CMD) "${RED}❌ Please specify SERVICE=name${NC}"; \
exit 1; \
fi
@$(ECHO_CMD) "${YELLOW}🛑 Stopping $(SERVICE)...${NC}"
@docker compose -f $(COMPOSE_PROD) stop $(SERVICE) 2>/dev/null || \
$(MAKE) -s stop-local-service SERVICE=$(SERVICE)
@$(ECHO_CMD) "${GREEN}$(SERVICE) stopped.${NC}"
restart-service: stop-service ## [MID] Restart a specific service (usage: make restart-service SERVICE=backend-api)
@$(ECHO_CMD) "${BLUE}🔄 Restarting $(SERVICE)...${NC}"
@$(MAKE) -s start-service SERVICE=$(SERVICE)
@$(ECHO_CMD) "${GREEN}$(SERVICE) restarted.${NC}"
logs-service: ## [MID] Show logs for a service (usage: make logs-service SERVICE=backend-api)
@if [ -z "$(SERVICE)" ]; then \
$(ECHO_CMD) "${RED}❌ Please specify SERVICE=name${NC}"; \
exit 1; \
fi
@docker compose -f $(COMPOSE_PROD) logs -f $(SERVICE) || \
$(ECHO_CMD) "${YELLOW}Service not running in Docker, check local logs${NC}"
build-service: ## [MID] Build a specific service (usage: make build-service SERVICE=backend-api)
@if [ -z "$(SERVICE)" ]; then \
$(ECHO_CMD) "${RED}❌ Please specify SERVICE=name${NC}"; \
exit 1; \
fi
@$(ECHO_CMD) "${BLUE}🔨 Building $(SERVICE)...${NC}"
@$(MAKE) -s build-$(SERVICE)
@$(ECHO_CMD) "${GREEN}$(SERVICE) built.${NC}"
build-all: ## [MID] Build all services
@$(ECHO_CMD) "${BLUE}🔨 Building all services...${NC}"
@$(MAKE) -s build-backend-api
@$(MAKE) -s build-chat-server
@$(MAKE) -s build-stream-server
@$(MAKE) -s build-web
@$(ECHO_CMD) "${GREEN}✅ All services built.${NC}"
# ==============================================================================
# LOW LEVEL / DEBUG COMMANDS
# ==============================================================================
.PHONY: check-tools install-tools install-deps check-ports
check-tools: ## [LOW] Check required tools
@$(ECHO_CMD) "${BLUE}Checking core requirements...${NC}"
@for tool in docker go cargo npm; do \
command -v $$tool >/dev/null 2>&1 || { $(ECHO_CMD) "${RED}$$tool is missing!${NC}"; exit 1; }; \
done
@$(ECHO_CMD) "${GREEN}✅ All tools present.${NC}"
install-tools: ## [LOW] Install Power User tools (Hot Reload, Linters)
@$(ECHO_CMD) "${BLUE}🛠️ Installing Dev Tools...${NC}"
@command -v air >/dev/null 2>&1 || go install github.com/air-verse/air@latest
@command -v cargo-watch >/dev/null 2>&1 || cargo install cargo-watch
@command -v sqlx >/dev/null 2>&1 || cargo install sqlx-cli --no-default-features --features native-tls,postgres
@$(ECHO_CMD) "${GREEN}✅ Tools installed.${NC}"
install-deps: ## [LOW] Install code dependencies
@$(ECHO_CMD) "${BLUE}📦 Installing dependencies...${NC}"
@$(ECHO_CMD) " -> [Go] Downloading modules..."
@(cd $(DIR_GO) && go mod download)
@$(ECHO_CMD) " -> [Rust Chat] Fetching crates..."
@(cd $(DIR_CHAT) && cargo fetch)
@$(ECHO_CMD) " -> [Rust Stream] Fetching crates..."
@(cd $(DIR_STREAM) && cargo fetch)
@$(ECHO_CMD) " -> [Web] Installing npm packages..."
@(cd $(DIR_WEB) && npm install --silent)
check-ports: ## [LOW] Check if ports are available
@$(ECHO_CMD) "${BLUE}🔍 Checking ports...${NC}"
@for port in $(PORT_GO) $(PORT_CHAT) $(PORT_STREAM) $(PORT_WEB); do \
if lsof -i :$$port -t >/dev/null 2>&1; then \
$(ECHO_CMD) "${YELLOW}⚠️ Port $$port is busy${NC}"; \
else \
$(ECHO_CMD) "${GREEN}✅ Port $$port is free${NC}"; \
fi; \
done
# ==============================================================================
# INFRASTRUCTURE
# ==============================================================================
.PHONY: infra-up infra-down wait-for-infra db-shell redis-shell db-migrate
infra-up: ## [MID] Start Docker Infra (with health checks)
@$(ECHO_CMD) "${BLUE}🐳 Starting Infrastructure...${NC}"
@docker compose -f $(COMPOSE_FILE) up -d
@$(MAKE) -s wait-for-infra
infra-down: ## [MID] Stop Docker Infra
@$(ECHO_CMD) "${BLUE}🛑 Stopping Infrastructure...${NC}"
@docker compose -f $(COMPOSE_FILE) down
wait-for-infra: ## [LOW] Wait for infrastructure to be ready
@printf "${BLUE}⏳ Waiting for services...${NC}"
@until docker compose -f $(COMPOSE_FILE) exec -T postgres pg_isready -U $(DB_USER) > /dev/null 2>&1; do printf "."; sleep 1; done
@until docker compose -f $(COMPOSE_FILE) exec -T redis redis-cli ping > /dev/null 2>&1; do printf "."; sleep 1; done
@$(ECHO_CMD) " ${GREEN}OK${NC}"
wait-for-services: ## [LOW] Wait for all application services
@printf "${BLUE}⏳ Waiting for services...${NC}"
@for service in backend-api chat-server stream-server web; do \
until docker compose -f $(COMPOSE_PROD) exec -T $$service echo "ready" > /dev/null 2>&1; do \
printf "."; sleep 1; \
done; \
done
@$(ECHO_CMD) " ${GREEN}OK${NC}"
db-shell: ## [MID] Connect to Postgres shell
@docker compose -f $(COMPOSE_FILE) exec postgres psql -U $(DB_USER) -d $(DB_NAME)
redis-shell: ## [MID] Connect to Redis shell
@docker compose -f $(COMPOSE_FILE) exec redis redis-cli
db-migrate: infra-up ## [MID] Run all database migrations
@$(ECHO_CMD) "${BLUE}🔄 Running Migrations...${NC}"
@$(ECHO_CMD) " -> [Go] Migrating..."
@(cd $(DIR_GO) && go run cmd/migrate_tool/main.go up || $(ECHO_CMD) "${YELLOW}Warning: Go migration failed${NC}")
@$(ECHO_CMD) " -> [Chat] Migrating..."
@(cd $(DIR_CHAT) && sqlx migrate run || $(ECHO_CMD) "${YELLOW}Warning: Chat migration failed${NC}")
@$(ECHO_CMD) " -> [Stream] Migrating..."
@(cd $(DIR_STREAM) && sqlx migrate run || $(ECHO_CMD) "${YELLOW}Warning: Stream migration failed${NC}")
@$(ECHO_CMD) "${GREEN}✅ Migrations done.${NC}"
# ==============================================================================
# DEVELOPMENT
# ==============================================================================
.PHONY: dev dev-backend stop-local-services start-local-service stop-local-service
dev: check-ports infra-up ## [HIGH] Start Everything (Detects Hot Reload tools)
@$(ECHO_CMD) "${BOLD}${PURPLE}🚀 STARTING HYBRID DEV ENVIRONMENT${NC}"
@$(ECHO_CMD) " Go: http://localhost:${PORT_GO}"
@$(ECHO_CMD) " Chat: http://localhost:${PORT_CHAT}"
@$(ECHO_CMD) " Web: http://localhost:${PORT_WEB}"
@$(ECHO_CMD) "${YELLOW}Hit Ctrl+C to stop all.${NC}"
@(trap 'kill 0' SIGINT; \
if command -v air >/dev/null; then \
$(ECHO_CMD) "${GREEN}[Go] Hot Reload Active (Air)${NC}" && cd $(DIR_GO) && air & \
else \
$(ECHO_CMD) "${YELLOW}[Go] Standard Run${NC}" && cd $(DIR_GO) && go run cmd/modern-server/main.go & \
fi; \
if command -v cargo-watch >/dev/null; then \
$(ECHO_CMD) "${GREEN}[Chat] Hot Reload Active${NC}" && cd $(DIR_CHAT) && cargo watch -x run -q & \
$(ECHO_CMD) "${GREEN}[Stream] Hot Reload Active${NC}" && cd $(DIR_STREAM) && cargo watch -x run -q & \
else \
$(ECHO_CMD) "${YELLOW}[Chat] Standard Run${NC}" && cd $(DIR_CHAT) && cargo run -q & \
$(ECHO_CMD) "${YELLOW}[Stream] Standard Run${NC}" && cd $(DIR_STREAM) && cargo run -q & \
fi; \
$(ECHO_CMD) "${GREEN}[Web] Starting Vite...${NC}" && cd $(DIR_WEB) && npm run dev & \
wait)
dev-backend: check-ports infra-up ## [MID] Start Backends Only (Hot Reload supported)
@$(ECHO_CMD) "${BOLD}${PURPLE}🚀 STARTING BACKEND ONLY${NC}"
@(trap 'kill 0' SIGINT; \
if command -v air >/dev/null; then cd $(DIR_GO) && air & else cd $(DIR_GO) && go run cmd/modern-server/main.go & fi; \
if command -v cargo-watch >/dev/null; then cd $(DIR_CHAT) && cargo watch -x run -q & else cd $(DIR_CHAT) && cargo run -q & fi; \
if command -v cargo-watch >/dev/null; then cd $(DIR_STREAM) && cargo watch -x run -q & else cd $(DIR_STREAM) && cargo run -q & fi; \
wait)
stop-local-services: ## [LOW] Stop all local processes
@pkill -f "air\|cargo watch\|npm run dev\|go run.*modern-server" 2>/dev/null || true
start-local-service: ## [LOW] Start a service locally
@case "$(SERVICE)" in \
backend-api) \
if command -v air >/dev/null; then cd $(DIR_GO) && air & else cd $(DIR_GO) && go run cmd/modern-server/main.go & fi ;; \
chat-server) \
if command -v cargo-watch >/dev/null; then cd $(DIR_CHAT) && cargo watch -x run -q & else cd $(DIR_CHAT) && cargo run -q & fi ;; \
stream-server) \
if command -v cargo-watch >/dev/null; then cd $(DIR_STREAM) && cargo watch -x run -q & else cd $(DIR_STREAM) && cargo run -q & fi ;; \
web) \
cd $(DIR_WEB) && npm run dev & ;; \
*) \
$(ECHO_CMD) "${RED}Unknown service: $(SERVICE)${NC}"; exit 1 ;; \
esac
stop-local-service: ## [LOW] Stop a local service
@case "$(SERVICE)" in \
backend-api) pkill -f "air\|go run.*modern-server" ;; \
chat-server|stream-server) pkill -f "cargo.*$(SERVICE)" ;; \
web) pkill -f "npm run dev\|vite" ;; \
*) $(ECHO_CMD) "${RED}Unknown service: $(SERVICE)${NC}" ;; \
esac
# ==============================================================================
# BUILD COMMANDS
# ==============================================================================
.PHONY: build-backend-api build-chat-server build-stream-server build-web
build-backend-api: ## [LOW] Build Go backend
@$(ECHO_CMD) "${BLUE}🔨 Building backend-api...${NC}"
@docker build -t $(PROJECT_NAME)-backend-api:latest -f $(DIR_GO)/Dockerfile.production $(DIR_GO) || \
$(ECHO_CMD) "${YELLOW}Using local Dockerfile...${NC}" && \
docker build -t $(PROJECT_NAME)-backend-api:latest -f $(DIR_GO)/Dockerfile $(DIR_GO)
build-chat-server: ## [LOW] Build Rust chat server
@$(ECHO_CMD) "${BLUE}🔨 Building chat-server...${NC}"
@docker build -t $(PROJECT_NAME)-chat-server:latest -f $(DIR_CHAT)/Dockerfile.production $(DIR_CHAT) || \
docker build -t $(PROJECT_NAME)-chat-server:latest -f $(DIR_CHAT)/Dockerfile $(DIR_CHAT)
build-stream-server: ## [LOW] Build Rust stream server
@$(ECHO_CMD) "${BLUE}🔨 Building stream-server...${NC}"
@docker build -t $(PROJECT_NAME)-stream-server:latest -f $(DIR_STREAM)/Dockerfile.production $(DIR_STREAM) || \
docker build -t $(PROJECT_NAME)-stream-server:latest -f $(DIR_STREAM)/Dockerfile $(DIR_STREAM)
build-web: ## [LOW] Build web frontend
@$(ECHO_CMD) "${BLUE}🔨 Building web...${NC}"
@docker build -t $(PROJECT_NAME)-web:latest -f $(DIR_WEB)/Dockerfile.production $(DIR_WEB) || \
docker build -t $(PROJECT_NAME)-web:latest -f $(DIR_WEB)/Dockerfile $(DIR_WEB)
# ==============================================================================
# INCUS / LXD DEPLOYMENT
# ==============================================================================
.PHONY: incus-setup-network incus-deploy-all incus-deploy-service incus-stop-all incus-logs
incus-setup-network: ## [LOW] Setup Incus network profile
@$(ECHO_CMD) "${BLUE}📦 Setting up Incus network...${NC}"
@incus network show $(INCUS_NETWORK) >/dev/null 2>&1 || \
incus network create $(INCUS_NETWORK) ipv4.address=10.10.10.1/24 ipv4.nat=true
@incus profile show $(INCUS_PROFILE) >/dev/null 2>&1 || \
incus profile create $(INCUS_PROFILE) && \
incus profile device add $(INCUS_PROFILE) eth0 nic network=$(INCUS_NETWORK)
@$(ECHO_CMD) "${GREEN}✅ Incus network ready.${NC}"
incus-deploy-all: incus-setup-network ## [MID] Deploy all services to Incus
@$(ECHO_CMD) "${BLUE}📦 Deploying all services to Incus...${NC}"
@$(MAKE) -s incus-deploy-service SERVICE=backend-api
@$(MAKE) -s incus-deploy-service SERVICE=chat-server
@$(MAKE) -s incus-deploy-service SERVICE=stream-server
@$(MAKE) -s incus-deploy-service SERVICE=web
@$(MAKE) -s incus-deploy-service SERVICE=haproxy
@$(ECHO_CMD) "${GREEN}✅ All services deployed to Incus.${NC}"
incus-deploy-service: ## [LOW] Deploy a service to Incus (usage: make incus-deploy-service SERVICE=backend-api)
@if [ -z "$(SERVICE)" ]; then \
$(ECHO_CMD) "${RED}❌ Please specify SERVICE=name${NC}"; \
exit 1; \
fi
@$(ECHO_CMD) "${BLUE}📦 Deploying $(SERVICE) to Incus...${NC}"
@if incus list -c n --format csv | grep -q "^veza-$(SERVICE)$$"; then \
$(ECHO_CMD) "${YELLOW}Container exists, removing...${NC}"; \
incus delete veza-$(SERVICE) --force; \
fi
@incus init images:ubuntu/22.04 veza-$(SERVICE) --profile $(INCUS_PROFILE)
@incus start veza-$(SERVICE)
@$(ECHO_CMD) "${BLUE}Installing Docker in container...${NC}"
@incus exec veza-$(SERVICE) -- bash -c "apt-get update && apt-get install -y docker.io docker-compose && systemctl enable docker && systemctl start docker" || true
@$(ECHO_CMD) "${GREEN}$(SERVICE) deployed.${NC}"
incus-stop-all: ## [MID] Stop all Incus containers
@$(ECHO_CMD) "${YELLOW}🛑 Stopping all Incus containers...${NC}"
@for container in $$(incus list -c n --format csv | grep veza-); do \
incus stop $$container 2>/dev/null || true; \
done
@$(ECHO_CMD) "${GREEN}✅ All Incus containers stopped.${NC}"
incus-logs: ## [LOW] Show logs from Incus container (usage: make incus-logs SERVICE=backend-api)
@if [ -z "$(SERVICE)" ]; then \
$(ECHO_CMD) "${RED}❌ Please specify SERVICE=name${NC}"; \
exit 1; \
fi
@incus exec veza-$(SERVICE) -- journalctl -f
# ==============================================================================
# TEST & QUALITY
# ==============================================================================
.PHONY: test lint fmt status
test: infra-up ## [MID] Run All Tests (Fastest strategy)
@$(ECHO_CMD) "${BLUE}🧪 Running Tests...${NC}"
@$(ECHO_CMD) " [Go] Unit Tests..."
@(cd $(DIR_GO) && go test ./... -short)
@$(ECHO_CMD) " [Rust] Unit Tests..."
@(cd $(DIR_CHAT) && cargo test --lib -q)
@(cd $(DIR_STREAM) && cargo test --lib -q)
@$(ECHO_CMD) " [Web] Unit Tests..."
@(cd $(DIR_WEB) && npm run test -- --run)
@$(ECHO_CMD) "${GREEN}✅ All tests passed.${NC}"
lint: ## [MID] Lint everything
@$(ECHO_CMD) "${BLUE}🔍 Linting Codebase...${NC}"
@(cd $(DIR_CHAT) && cargo clippy -- -D warnings) || true
@(cd $(DIR_STREAM) && cargo clippy -- -D warnings) || true
@(cd $(DIR_GO) && golangci-lint run ./...) || true
@(cd $(DIR_WEB) && npm run lint) || true
fmt: ## [MID] Format everything
@$(ECHO_CMD) "${BLUE}✨ Formatting...${NC}"
@(cd $(DIR_GO) && go fmt ./...)
@(cd $(DIR_CHAT) && cargo fmt)
@(cd $(DIR_STREAM) && cargo fmt)
@(cd $(DIR_WEB) && npm run format) || true
status: ## [MID] Show system health & stats
@$(ECHO_CMD) "${BOLD}DOCKER STATS:${NC}"
@docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}" 2>/dev/null | grep -E "NAME|veza" || echo "No containers running"
@$(ECHO_CMD) ""
@$(ECHO_CMD) "${BOLD}LOCAL PORTS:${NC}"
@lsof -i :$(PORT_GO) -i :$(PORT_CHAT) -i :$(PORT_STREAM) -i :$(PORT_WEB) 2>/dev/null | grep LISTEN || echo "No apps listening."