From 09249032e772c91379faf06ab34af9ee50989424 Mon Sep 17 00:00:00 2001 From: rizzOn Date: Sun, 30 Nov 2025 03:18:41 +0530 Subject: [PATCH] chore(makefile): Define backend project makefile Available targets:\033[0m help Show this help message dev Run development server with hot reload (requires Air) run Run server without hot reload build Build production binary build-local Build binary for local OS test Run all tests test-coverage Run tests and show coverage report test-unit Run unit tests only test-integration Run integration tests only bench Run benchmarks clean Clean build artifacts and caches deps Download dependencies deps-update Update all dependencies lint Run linter fmt Format code vet Run go vet check Run all checks (fmt, vet, lint, test) migrate-up Run database migrations migrate-down Rollback last migration migrate-create Create new migration (usage: make migrate-create NAME=add_users_table) docker-build Build Docker image docker-run Run Docker container install-air Install Air for hot reload install-linter Install golangci-lint install-migrate Install golang-migrate install-tools Install all development tools db-psql Connect to database with psql seed Run database seed script mod-graph Show dependency graph mod-why Show why a package is needed (usage: make mod-why PKG=github.com/pkg/errors) version Show version information info Show project information This commit establishes the foundation for all future development. Story: E1-002 - Backend Project Initialization (makefile) --- backend/.air.toml | 94 +++++++++++++++ backend/Makefile | 256 ++++++++++++++++++++++++++++++++++++++++ backend/cmd/api/main.go | 4 +- 3 files changed, 352 insertions(+), 2 deletions(-) create mode 100644 backend/.air.toml create mode 100644 backend/Makefile diff --git a/backend/.air.toml b/backend/.air.toml new file mode 100644 index 0000000..0785915 --- /dev/null +++ b/backend/.air.toml @@ -0,0 +1,94 @@ +# ============================================================================ +# AIR CONFIGURATION - HOT RELOAD FOR GO +# ============================================================================ + +root = "." +testdata_dir = "testdata" +tmp_dir = "tmp" + + + + +[build] + # Array of commands to run before each build + pre_cmd = [] + + # Just plain old shell command + cmd = "go build -o ./tmp/main.exe ./cmd/api" + + # Binary file yields from `cmd` + bin = "tmp/main.exe" + + # Customize binary, can setup environment variables when run your app + # full_bin = "tmp\\main.exe" + + # Watch these filename extensions + include_ext = ["go", "tpl", "tmpl", "html"] + + # Ignore these filename extensions or directories + exclude_dir = ["assets", "tmp", "vendor", "testdata", "migrations"] + + # Watch these directories if you specified + include_dir = [] + + # Exclude files + exclude_file = [] + + # Exclude specific regular expressions + exclude_regex = ["_test\\.go"] + + # Exclude unchanged files + exclude_unchanged = false + + # Follow symbolic links + follow_symlink = false + + # This log file places in your tmp_dir + log = "build-errors.log" + + # Poll for file changes instead of using fsnotify (useful for Docker) + poll = false + + # Poll interval (ms) + poll_interval = 0 + + # It's not necessary to trigger build each time file changes if it's too frequent + delay = 1000 # ms + + # Stop running old binary when build errors occur + stop_on_error = false + + # Send Interrupt signal before killing process (useful for graceful shutdown) + send_interrupt = true + + # Delay after sending Interrupt signal + kill_delay = 1000 # ms + + # Add additional arguments when running binary + args_bin = [] + +[log] + # Show log time + time = true + + # Only show main log (silences the watcher, build, runner) + main_only = false + +[color] + # Customize each part's color + main = "magenta" + watcher = "cyan" + build = "yellow" + runner = "green" + +[misc] + # Delete tmp directory on exit + clean_on_exit = true + +[screen] + # Clear screen on rebuild + clear_on_rebuild = true + + # Enable or disable keep screen scrolling + keep_scroll = true + diff --git a/backend/Makefile b/backend/Makefile new file mode 100644 index 0000000..545a075 --- /dev/null +++ b/backend/Makefile @@ -0,0 +1,256 @@ +# ============================================================================ +# AURGANIZE V6.2 - BACKEND MAKEFILE +# ============================================================================ +# +# Common development tasks for the backend API server. +# Run 'make help' to see all available commands. + +# Variables +APP_NAME=aurganize-api +VERSION=6.2.0 +MAIN_PATH=cmd/api/main.go +BUILD_DIR=bin +BINARY_NAME=api + +# Go commands +GOCMD=go +GOBUILD=$(GOCMD) build +GOCLEAN=$(GOCMD) clean +GOTEST=$(GOCMD) test +GOGET=$(GOCMD) get +GOMOD=$(GOCMD) mod +GOFMT=$(GOCMD) fmt + +# Build flags +LDFLAGS=-ldflags "-X main.Version=$(VERSION) -X main.BuildTime=$(shell date -u +%Y-%m-%dT%H:%M:%SZ)" + +# Colors for output +COLOR_RESET=\033[0m +COLOR_GREEN=\033[32m +COLOR_YELLOW=\033[33m +COLOR_BLUE=\033[34m + +.PHONY: help +help: ## Show this help message + @echo '$(COLOR_BLUE)Aurganize V6.2 - Backend Makefile$(COLOR_RESET)' + @echo '' + @echo '$(COLOR_GREEN)Usage:$(COLOR_RESET)' + @echo ' make [target]' + @echo '' + @echo '$(COLOR_GREEN)Available targets:$(COLOR_RESET)' + @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf " $(COLOR_YELLOW)%-15s$(COLOR_RESET) %s\n", $$1, $$2}' $(MAKEFILE_LIST) + +.PHONY: dev +dev: ## Run development server with hot reload (requires Air) + @echo '$(COLOR_GREEN)Starting development server...$(COLOR_RESET)' + @if command -v air > /dev/null; then \ + air; \ + else \ + echo '$(COLOR_YELLOW)Air not installed. Run: make install-air$(COLOR_RESET)'; \ + echo '$(COLOR_YELLOW)Running without hot reload...$(COLOR_RESET)'; \ + $(GOCMD) run $(MAIN_PATH); \ + fi + +.PHONY: run +run: ## Run server without hot reload + @echo '$(COLOR_GREEN)Starting server...$(COLOR_RESET)' + $(GOCMD) run $(MAIN_PATH) + +.PHONY: build +build: ## Build production binary + @echo '$(COLOR_GREEN)Building production binary...$(COLOR_RESET)' + @mkdir -p $(BUILD_DIR) + CGO_ENABLED=0 GOOS=linux $(GOBUILD) $(LDFLAGS) -a -installsuffix cgo -o $(BUILD_DIR)/$(BINARY_NAME) $(MAIN_PATH) + @echo '$(COLOR_GREEN)Binary created at: $(BUILD_DIR)/$(BINARY_NAME)$(COLOR_RESET)' + +.PHONY: build-local +build-local: ## Build binary for local OS + @echo '$(COLOR_GREEN)Building local binary...$(COLOR_RESET)' + @mkdir -p $(BUILD_DIR) + $(GOBUILD) -o $(BUILD_DIR)/$(BINARY_NAME) $(MAIN_PATH) + @echo '$(COLOR_GREEN)Binary created at: $(BUILD_DIR)/$(BINARY_NAME)$(COLOR_RESET)' + +.PHONY: test +test: ## Run all tests + @echo '$(COLOR_GREEN)Running tests...$(COLOR_RESET)' + $(GOTEST) -v -race -coverprofile=coverage.out ./... + @echo '' + @echo '$(COLOR_GREEN)Coverage summary:$(COLOR_RESET)' + @$(GOCMD) tool cover -func=coverage.out | grep total + +.PHONY: test-coverage +test-coverage: test ## Run tests and show coverage report + @echo '$(COLOR_GREEN)Generating HTML coverage report...$(COLOR_RESET)' + $(GOCMD) tool cover -html=coverage.out -o coverage.html + @echo '$(COLOR_GREEN)Coverage report: coverage.html$(COLOR_RESET)' + +.PHONY: test-unit +test-unit: ## Run unit tests only + @echo '$(COLOR_GREEN)Running unit tests...$(COLOR_RESET)' + $(GOTEST) -v -short ./... + +.PHONY: test-integration +test-integration: ## Run integration tests only + @echo '$(COLOR_GREEN)Running integration tests...$(COLOR_RESET)' + $(GOTEST) -v -run Integration ./... + +.PHONY: bench +bench: ## Run benchmarks + @echo '$(COLOR_GREEN)Running benchmarks...$(COLOR_RESET)' + $(GOTEST) -bench=. -benchmem ./... + +.PHONY: clean +clean: ## Clean build artifacts and caches + @echo '$(COLOR_GREEN)Cleaning...$(COLOR_RESET)' + $(GOCLEAN) + rm -rf $(BUILD_DIR) + rm -rf tmp + rm -f coverage.out coverage.html + @echo '$(COLOR_GREEN)Clean complete$(COLOR_RESET)' + +.PHONY: deps +deps: ## Download dependencies + @echo '$(COLOR_GREEN)Downloading dependencies...$(COLOR_RESET)' + $(GOMOD) download + $(GOMOD) tidy + @echo '$(COLOR_GREEN)Dependencies updated$(COLOR_RESET)' + +.PHONY: deps-update +deps-update: ## Update all dependencies + @echo '$(COLOR_GREEN)Updating dependencies...$(COLOR_RESET)' + $(GOGET) -u ./... + $(GOMOD) tidy + @echo '$(COLOR_GREEN)Dependencies updated$(COLOR_RESET)' + +.PHONY: lint +lint: ## Run linter + @echo '$(COLOR_GREEN)Running linter...$(COLOR_RESET)' + @if command -v golangci-lint > /dev/null; then \ + golangci-lint run; \ + else \ + echo '$(COLOR_YELLOW)golangci-lint not installed. Run: make install-linter$(COLOR_RESET)'; \ + fi + +.PHONY: fmt +fmt: ## Format code + @echo '$(COLOR_GREEN)Formatting code...$(COLOR_RESET)' + $(GOFMT) ./... + @if command -v goimports > /dev/null; then \ + goimports -w .; \ + fi + +.PHONY: vet +vet: ## Run go vet + @echo '$(COLOR_GREEN)Running go vet...$(COLOR_RESET)' + $(GOCMD) vet ./... + +.PHONY: check +check: fmt vet lint test ## Run all checks (fmt, vet, lint, test) + @echo '$(COLOR_GREEN)All checks passed!$(COLOR_RESET)' + +.PHONY: migrate-up +migrate-up: ## Run database migrations + @echo '$(COLOR_GREEN)Running database migrations...$(COLOR_RESET)' + @if command -v migrate > /dev/null; then \ + migrate -path migrations -database "$$(grep DB_ .env | xargs | sed 's/ /\&/g' | sed 's/DB_/postgresql:\/\//g')" up; \ + else \ + echo '$(COLOR_YELLOW)golang-migrate not installed. Run: make install-migrate$(COLOR_RESET)'; \ + fi + +.PHONY: migrate-down +migrate-down: ## Rollback last migration + @echo '$(COLOR_GREEN)Rolling back last migration...$(COLOR_RESET)' + @if command -v migrate > /dev/null; then \ + migrate -path migrations -database "$$(grep DB_ .env | xargs | sed 's/ /\&/g' | sed 's/DB_/postgresql:\/\//g')" down 1; \ + else \ + echo '$(COLOR_YELLOW)golang-migrate not installed. Run: make install-migrate$(COLOR_RESET)'; \ + fi + +.PHONY: migrate-create +migrate-create: ## Create new migration (usage: make migrate-create NAME=add_users_table) + @if [ -z "$(NAME)" ]; then \ + echo '$(COLOR_YELLOW)Usage: make migrate-create NAME=add_users_table$(COLOR_RESET)'; \ + exit 1; \ + fi + @echo '$(COLOR_GREEN)Creating migration: $(NAME)...$(COLOR_RESET)' + @if command -v migrate > /dev/null; then \ + migrate create -ext sql -dir migrations -seq $(NAME); \ + else \ + echo '$(COLOR_YELLOW)golang-migrate not installed. Run: make install-migrate$(COLOR_RESET)'; \ + fi + +.PHONY: docker-build +docker-build: ## Build Docker image + @echo '$(COLOR_GREEN)Building Docker image...$(COLOR_RESET)' + docker build -t $(APP_NAME):$(VERSION) -t $(APP_NAME):latest . + @echo '$(COLOR_GREEN)Docker image built: $(APP_NAME):$(VERSION)$(COLOR_RESET)' + +.PHONY: docker-run +docker-run: ## Run Docker container + @echo '$(COLOR_GREEN)Running Docker container...$(COLOR_RESET)' + docker run -p 8080:8080 --env-file .env $(APP_NAME):latest + +.PHONY: install-air +install-air: ## Install Air for hot reload + @echo '$(COLOR_GREEN)Installing Air...$(COLOR_RESET)' + $(GOGET) -u github.com/cosmtrek/air + @echo '$(COLOR_GREEN)Air installed. Run: make dev$(COLOR_RESET)' + +.PHONY: install-linter +install-linter: ## Install golangci-lint + @echo '$(COLOR_GREEN)Installing golangci-lint...$(COLOR_RESET)' + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin + @echo '$(COLOR_GREEN)golangci-lint installed$(COLOR_RESET)' + +.PHONY: install-migrate +install-migrate: ## Install golang-migrate + @echo '$(COLOR_GREEN)Installing golang-migrate...$(COLOR_RESET)' + @if [ "$$(uname)" = "Darwin" ]; then \ + brew install golang-migrate; \ + else \ + echo '$(COLOR_YELLOW)Please install manually: https://github.com/golang-migrate/migrate$(COLOR_RESET)'; \ + fi + +.PHONY: install-tools +install-tools: install-air install-linter install-migrate ## Install all development tools + @echo '$(COLOR_GREEN)All tools installed!$(COLOR_RESET)' + +.PHONY: db-psql +db-psql: ## Connect to database with psql + @if [ -f .env ]; then \ + export $$(cat .env | xargs) && psql "postgresql://$$DB_USER:$$DB_PASSWORD@$$DB_HOST:$$DB_PORT/$$DB_NAME?sslmode=$$DB_SSLMODE"; \ + else \ + echo '$(COLOR_YELLOW).env file not found$(COLOR_RESET)'; \ + fi + +.PHONY: seed +seed: ## Run database seed script + @echo '$(COLOR_GREEN)Seeding database...$(COLOR_RESET)' + $(GOCMD) run scripts/seed/main.go + +.PHONY: mod-graph +mod-graph: ## Show dependency graph + $(GOMOD) graph + +.PHONY: mod-why +mod-why: ## Show why a package is needed (usage: make mod-why PKG=github.com/pkg/errors) + $(GOMOD) why $(PKG) + +.PHONY: version +version: ## Show version information + @echo 'Application: $(APP_NAME)' + @echo 'Version: $(VERSION)' + @echo 'Go version: $(shell go version)' + +.PHONY: info +info: ## Show project information + @echo '$(COLOR_BLUE)Project Information$(COLOR_RESET)' + @echo ' Name: $(APP_NAME)' + @echo ' Version: $(VERSION)' + @echo ' Main Path: $(MAIN_PATH)' + @echo ' Build Dir: $(BUILD_DIR)' + @echo '' + @echo '$(COLOR_BLUE)Environment$(COLOR_RESET)' + @echo ' Go Version: $(shell go version)' + @echo ' GOPATH: $(GOPATH)' + @echo ' GOROOT: $(GOROOT)' \ No newline at end of file diff --git a/backend/cmd/api/main.go b/backend/cmd/api/main.go index fa1ab43..2c853a7 100644 --- a/backend/cmd/api/main.go +++ b/backend/cmd/api/main.go @@ -151,7 +151,7 @@ func main() { log.Info().Msg("Middleware configured") // ========================================================================= - // Middleware Pipeline + // Route Mapping // ========================================================================= e.GET("/health", healthCheckHandler(cfg)) // (Public - health check) @@ -159,7 +159,7 @@ func main() { api.GET("/ping", func(c echo.Context) error { // (Public - connectivity test) return c.JSON(http.StatusOK, map[string]string{ - "message": "pika pikaaa", + "message": "pika pikaaa --- PIKAAA CHUUUUU", "timestamp": time.Now().UTC().Format(time.RFC3339), "version": "0.6.2", })