SHELL := /bin/bash EARTHLY_ENV_CLEAN := env -u AI_REVIEW_ENDPOINT -u AI_REVIEW_API_KEY -u AI_REVIEW_MODEL .DEFAULT_GOAL := help .PHONY: help guard-dev-tag down dev dev-build dev-up prod-a prod-a-build prod-a-up prod-a-down prod-a-config prod-b prod-b-build prod-b-up prod-b-down prod-b-config fine-tune fine-tune-down fine-tune-config sqlc db-status db-up db-seed FRONTEND_DIR := Frontend FRONTEND_DIST_DIR := $(FRONTEND_DIR)/dist BACKEND_DIR := Backend BACKEND_TMP_DIR := $(BACKEND_DIR)/tmp EARTHLY ?= earthly COMPOSE ?= docker compose PROD_A_TAG ?= latest PROD_A_ENV_FILE ?= .env.prod-a PROD_B_TAG ?= latest PROD_B_ENV_FILE ?= .env.prod-b FINE_TUNE_ENV_FILE ?= FineTune/.env DATABASE_URL ?= postgres://boostai:boostai_dev_password@localhost:5439/boostai?sslmode=disable MOCK_DATA_DIR ?= ../Mock-Data GOOSE := go run github.com/pressly/goose/v3/cmd/goose@v3.26.0 SQLC := go run github.com/sqlc-dev/sqlc/cmd/sqlc@v1.30.0 help: ## Show this help message @echo "Usage: make [target]" @echo "" @echo "Available targets:" @awk 'BEGIN {FS = ":.*## "}; /^[a-zA-Z0-9_.-]+:.*## / {printf " %-12s %s\n", $$1, $$2}' $(MAKEFILE_LIST) guard-dev-tag: @if [ -z "$(DEV_TAG)" ]; then \ echo "Error: DEV_TAG is not set. Please provide a tag for the development image."; \ exit 1; \ fi down: ## Stop all servers and clean up temporary files @DEV_TAG=$${DEV_TAG:-dummy} $(COMPOSE) -f docker-compose.dev.yaml down --remove-orphans -v @rm -rf "$(BACKEND_TMP_DIR)" "$(FRONTEND_DIST_DIR)" dev: guard-dev-tag ## Start the development server @$(EARTHLY_ENV_CLEAN) $(EARTHLY) "./$(FRONTEND_DIR)+dev-image" --IMAGE_NAME="boost-ai/demo-frontend-dev" --TAG=$(DEV_TAG) @$(EARTHLY_ENV_CLEAN) $(EARTHLY) "./$(BACKEND_DIR)+dev-image" --IMAGE_NAME="boost-ai/demo-backend-dev" --TAG=$(DEV_TAG) @DEV_TAG=$(DEV_TAG) $(COMPOSE) -f docker-compose.dev.yaml up -d --remove-orphans --force-recreate dev-build: guard-dev-tag ## Build the development images for frontend and backend @$(EARTHLY_ENV_CLEAN) $(EARTHLY) "./$(FRONTEND_DIR)+dev-image" --IMAGE_NAME="boost-ai/demo-frontend-dev" --TAG=$(DEV_TAG) @$(EARTHLY_ENV_CLEAN) $(EARTHLY) "./$(BACKEND_DIR)+dev-image" --IMAGE_NAME="boost-ai/demo-backend-dev" --TAG=$(DEV_TAG) dev-up: guard-dev-tag ## Start the development stack using docker compose @DEV_TAG=$(DEV_TAG) $(COMPOSE) -f docker-compose.dev.yaml up -d --remove-orphans --force-recreate prod-a: prod-a-build prod-a-up ## Build and start the prod-a stack prod-a-build: ## Build the production prod-a images for frontend and backend @$(EARTHLY_ENV_CLEAN) $(EARTHLY) "+frontend-prod-image" --IMAGE_NAME="boost-ai/demo-frontend-prod-a" --TAG=$(PROD_A_TAG) @$(EARTHLY_ENV_CLEAN) $(EARTHLY) "./$(BACKEND_DIR)+prod-image" --IMAGE_NAME="boost-ai/demo-backend-prod-a" --TAG=$(PROD_A_TAG) prod-a-up: ## Start the prod-a stack using docker compose @PROD_A_ENV_FILE=$(PROD_A_ENV_FILE) $(COMPOSE) --env-file $(PROD_A_ENV_FILE) -f docker-compose.prod-a.yaml up -d --remove-orphans --force-recreate prod-a-down: ## Stop the prod-a stack @PROD_A_ENV_FILE=$(PROD_A_ENV_FILE) $(COMPOSE) --env-file $(PROD_A_ENV_FILE) -f docker-compose.prod-a.yaml down --remove-orphans prod-a-config: ## Render the prod-a docker compose configuration @PROD_A_ENV_FILE=$(PROD_A_ENV_FILE) $(COMPOSE) --env-file $(PROD_A_ENV_FILE) -f docker-compose.prod-a.yaml config prod-b: prod-b-build prod-b-up ## Build and start the prod-b stack prod-b-build: ## Build the production prod-b images for frontend and backend @$(EARTHLY_ENV_CLEAN) $(EARTHLY) "+frontend-prod-image" --IMAGE_NAME="boost-ai/demo-frontend-prod-b" --TAG=$(PROD_B_TAG) @$(EARTHLY_ENV_CLEAN) $(EARTHLY) "./$(BACKEND_DIR)+prod-image" --IMAGE_NAME="boost-ai/demo-backend-prod-b" --TAG=$(PROD_B_TAG) prod-b-up: ## Start the prod-b stack using docker compose @PROD_B_ENV_FILE=$(PROD_B_ENV_FILE) $(COMPOSE) --env-file $(PROD_B_ENV_FILE) -f docker-compose.prod-b.yaml up -d --remove-orphans --force-recreate prod-b-down: ## Stop the prod-b stack @PROD_B_ENV_FILE=$(PROD_B_ENV_FILE) $(COMPOSE) --env-file $(PROD_B_ENV_FILE) -f docker-compose.prod-b.yaml down --remove-orphans prod-b-config: ## Render the prod-b docker compose configuration @PROD_B_ENV_FILE=$(PROD_B_ENV_FILE) $(COMPOSE) --env-file $(PROD_B_ENV_FILE) -f docker-compose.prod-b.yaml config fine-tune: ## Start the isolated local fine-tune helper app @$(COMPOSE) --env-file $(FINE_TUNE_ENV_FILE) -f FineTune/docker-compose.yaml up -d --remove-orphans --force-recreate fine-tune-down: ## Stop the isolated local fine-tune helper app @$(COMPOSE) --env-file $(FINE_TUNE_ENV_FILE) -f FineTune/docker-compose.yaml down --remove-orphans fine-tune-config: ## Render the local fine-tune helper docker compose configuration @$(COMPOSE) --env-file $(FINE_TUNE_ENV_FILE) -f FineTune/docker-compose.yaml config sqlc: ## Generate typed SQL code for the backend @cd "$(BACKEND_DIR)" && $(SQLC) generate -f db/sqlc.yaml db-status: ## Show goose migration status for the backend database @cd "$(BACKEND_DIR)" && $(GOOSE) -dir db/migrations postgres "$(DATABASE_URL)" status db-up: ## Run pending goose migrations against the backend database @cd "$(BACKEND_DIR)" && $(GOOSE) -dir db/migrations postgres "$(DATABASE_URL)" up db-seed: ## Reset and seed the backend database from Mock-Data JSON @cd "$(BACKEND_DIR)" && DATABASE_URL="$(DATABASE_URL)" MOCK_DATA_DIR="$(MOCK_DATA_DIR)" GOTOOLCHAIN=local go run ./cmd/seed