# TYAPI Server Makefile # 应用信息 APP_NAME := tyapi-server VERSION := 1.0.0 # 检测操作系统 ifeq ($(OS),Windows_NT) # Windows 环境 BUILD_TIME := $(shell powershell -Command "Get-Date -Format 'yyyy-MM-ddTHH:mm:ssZ'") GIT_COMMIT := $(shell powershell -Command "try { git rev-parse --short HEAD } catch { 'dev' }") GO_VERSION := $(shell go version) MKDIR := mkdir RM := del /f /q RMDIR := rmdir /s /q else # Unix 环境 BUILD_TIME := $(shell date -u +"%Y-%m-%dT%H:%M:%SZ") GIT_COMMIT := $(shell git rev-parse --short HEAD 2>/dev/null || echo 'dev') GO_VERSION := $(shell go version | awk '{print $$3}') MKDIR := mkdir -p RM := rm -f RMDIR := rm -rf endif # 构建参数 LDFLAGS := -ldflags "-X main.version=$(VERSION) -X main.commit=$(GIT_COMMIT) -X main.date=$(BUILD_TIME)" BUILD_DIR := bin MAIN_PATH := cmd/api/main.go # Go 相关 GOCMD := go GOBUILD := $(GOCMD) build GOCLEAN := $(GOCMD) clean GOTEST := $(GOCMD) test GOGET := $(GOCMD) get GOMOD := $(GOCMD) mod GOFMT := $(GOCMD) fmt # Docker 相关 DOCKER_IMAGE := $(APP_NAME):$(VERSION) DOCKER_LATEST := $(APP_NAME):latest # 默认目标 .DEFAULT_GOAL := help ## 显示帮助信息 help: @echo "TYAPI Server Makefile" @echo "" @echo "Usage: make [target]" @echo "" @echo "Development Basics:" @echo " help Show this help message" @echo " setup Setup development environment" @echo " deps Install dependencies" @echo " fmt Format code" @echo " lint Lint code" @echo " test Run tests" @echo " coverage Generate test coverage report" @echo "" @echo "Build & Compile:" @echo " build Build application" @echo " build-prod Build production version" @echo " build-all Cross compile for all platforms" @echo " clean Clean build files" @echo "" @echo "Run & Manage:" @echo " dev Run in development mode" @echo " run Run compiled application" @echo " migrate Run database migration" @echo " version Show version info" @echo " health Run health check" @echo "" @echo "Docker Containers:" @echo " docker-build Build Docker image" @echo " docker-build-prod Build production Docker image" @echo " docker-push-prod Push image to registry" @echo " docker-run Run Docker container" @echo " docker-stop Stop Docker container" @echo "" @echo "Production Environment:" @echo " deploy-prod Deploy to production" @echo " prod-up Start production services" @echo " prod-down Stop production services" @echo " prod-logs View production logs" @echo " prod-status Check production status" @echo "" @echo "Development Environment:" @echo " services-up Start dev dependencies" @echo " services-down Stop dev dependencies" @echo " services-update Update dev dependencies (rebuild & restart)" @echo " dev-up Alias for services-up" @echo " dev-down Alias for services-down" @echo " dev-update Alias for services-update" @echo "" @echo "Tools & Utilities:" @echo " env Create .env file from template" @echo " logs View application logs" @echo " docs Generate API documentation" @echo " bench Run performance benchmark" @echo " race Run race condition detection" @echo " security Run security scan" @echo " mock Generate mock data" @echo "" @echo "CI/CD Pipeline:" @echo " ci Run complete CI pipeline" @echo " release Run complete release pipeline" ## Install dependencies deps: @echo "Installing dependencies..." $(GOMOD) download $(GOMOD) tidy ## Format code fmt: @echo "Formatting code..." $(GOFMT) ./... ## Lint code lint: @echo "Linting code..." ifeq ($(OS),Windows_NT) @where golangci-lint >nul 2>&1 && golangci-lint run || echo "golangci-lint not installed, skipping lint check" else @if command -v golangci-lint >/dev/null 2>&1; then \ golangci-lint run; \ else \ echo "golangci-lint not installed, skipping lint check"; \ fi endif ## Run tests test: @echo "Running tests..." ifeq ($(OS),Windows_NT) @where gcc >nul 2>&1 && $(GOTEST) -v -race -coverprofile=coverage.out ./... || $(GOTEST) -v -coverprofile=coverage.out ./... else $(GOTEST) -v -race -coverprofile=coverage.out ./... endif ## Generate test coverage report coverage: test @echo "Generating coverage report..." $(GOCMD) tool cover -html=coverage.out -o coverage.html @echo "Coverage report generated: coverage.html" ## Build application (development) build: @echo "Building application..." ifeq ($(OS),Windows_NT) @if not exist "$(BUILD_DIR)" mkdir "$(BUILD_DIR)" else @mkdir -p $(BUILD_DIR) endif $(GOBUILD) $(LDFLAGS) -o $(BUILD_DIR)/$(APP_NAME) $(MAIN_PATH) ## Build production version build-prod: @echo "Building production version..." ifeq ($(OS),Windows_NT) @if not exist "$(BUILD_DIR)" mkdir "$(BUILD_DIR)" else @mkdir -p $(BUILD_DIR) endif CGO_ENABLED=0 GOOS=linux GOARCH=amd64 $(GOBUILD) $(LDFLAGS) -a -installsuffix cgo -o $(BUILD_DIR)/$(APP_NAME)-linux-amd64 $(MAIN_PATH) ## Cross compile build-all: @echo "Cross compiling..." ifeq ($(OS),Windows_NT) @if not exist "$(BUILD_DIR)" mkdir "$(BUILD_DIR)" else @mkdir -p $(BUILD_DIR) endif # Linux AMD64 CGO_ENABLED=0 GOOS=linux GOARCH=amd64 $(GOBUILD) $(LDFLAGS) -o $(BUILD_DIR)/$(APP_NAME)-linux-amd64 $(MAIN_PATH) # Linux ARM64 CGO_ENABLED=0 GOOS=linux GOARCH=arm64 $(GOBUILD) $(LDFLAGS) -o $(BUILD_DIR)/$(APP_NAME)-linux-arm64 $(MAIN_PATH) # macOS AMD64 CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 $(GOBUILD) $(LDFLAGS) -o $(BUILD_DIR)/$(APP_NAME)-darwin-amd64 $(MAIN_PATH) # macOS ARM64 CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 $(GOBUILD) $(LDFLAGS) -o $(BUILD_DIR)/$(APP_NAME)-darwin-arm64 $(MAIN_PATH) # Windows AMD64 CGO_ENABLED=0 GOOS=windows GOARCH=amd64 $(GOBUILD) $(LDFLAGS) -o $(BUILD_DIR)/$(APP_NAME)-windows-amd64.exe $(MAIN_PATH) ## Run application run: build @echo "Starting application..." ./$(BUILD_DIR)/$(APP_NAME) ## Run in development mode dev: @echo "Starting development mode..." $(GOCMD) run $(MAIN_PATH) ## Run database migration migrate: build @echo "Running database migration..." ./$(BUILD_DIR)/$(APP_NAME) -migrate ## Show version info version: build @echo "Version info:" ./$(BUILD_DIR)/$(APP_NAME) -version ## Health check health: build @echo "Running health check..." ./$(BUILD_DIR)/$(APP_NAME) -health ## Clean build files clean: @echo "Cleaning build files..." $(GOCLEAN) ifeq ($(OS),Windows_NT) @if exist "$(BUILD_DIR)" $(RMDIR) "$(BUILD_DIR)" 2>nul || echo "" @if exist "coverage.out" $(RM) "coverage.out" 2>nul || echo "" @if exist "coverage.html" $(RM) "coverage.html" 2>nul || echo "" else $(RMDIR) $(BUILD_DIR) 2>/dev/null || true $(RM) coverage.out coverage.html 2>/dev/null || true endif ## Create .env file env: ifeq ($(OS),Windows_NT) @if not exist ".env" ( \ echo Creating .env file from production template... && \ copy .env.production .env && \ echo .env file created, please modify configuration as needed \ ) else ( \ echo .env file already exists \ ) else @if [ ! -f .env ]; then \ echo "Creating .env file from production template..."; \ cp .env.production .env; \ echo ".env file created, please modify configuration as needed"; \ else \ echo ".env file already exists"; \ fi endif ## Setup development environment setup: deps env @echo "Setting up development environment..." @echo "1. [OK] Dependencies installed" @echo "2. [OK] .env file created from production template" @echo "3. [TODO] Please edit .env file and set your configuration" @echo "4. [NEXT] Run 'make services-up' to start PostgreSQL + Redis" @echo "5. [NEXT] Run 'make migrate' to create database tables" @echo "6. [NEXT] Run 'make dev' to start development server" @echo "" @echo "Tip: Use 'make help' to see all available commands" ## Build Docker image docker-build: @echo "Building Docker image..." docker build -t $(DOCKER_IMAGE) -t $(DOCKER_LATEST) . ## Build production Docker image with registry docker-build-prod: @echo "Building production Docker image..." docker build \ --build-arg VERSION=$(VERSION) \ --build-arg COMMIT=$(GIT_COMMIT) \ --build-arg BUILD_TIME=$(BUILD_TIME) \ -t docker-registry.tianyuanapi.com/tyapi-server:$(VERSION) \ -t docker-registry.tianyuanapi.com/tyapi-server:latest \ . ## Push Docker image to registry docker-push-prod: @echo "Pushing Docker image to production registry..." docker push docker-registry.tianyuanapi.com/tyapi-server:$(VERSION) docker push docker-registry.tianyuanapi.com/tyapi-server:latest ## Deploy to production deploy-prod: @echo "Deploying to production environment..." ifeq ($(OS),Windows_NT) @if exist "scripts\\deploy.sh" ( \ bash scripts/deploy.sh $(VERSION) \ ) else ( \ echo "Deploy script not found" \ ) else @if [ -f scripts/deploy.sh ]; then \ ./scripts/deploy.sh $(VERSION); \ else \ echo "Deploy script not found"; \ fi endif ## Start production services prod-up: @echo "Starting production services..." ifeq ($(OS),Windows_NT) @if exist "docker-compose.prod.yml" ( \ docker-compose -f docker-compose.prod.yml up -d \ ) else ( \ echo docker-compose.prod.yml not found \ ) else @if [ -f docker-compose.prod.yml ]; then \ docker-compose -f docker-compose.prod.yml up -d; \ else \ echo "docker-compose.prod.yml not found"; \ fi endif ## Stop production services prod-down: @echo "Stopping production services..." ifeq ($(OS),Windows_NT) @if exist "docker-compose.prod.yml" ( \ docker-compose -f docker-compose.prod.yml down \ ) else ( \ echo docker-compose.prod.yml not found \ ) else @if [ -f docker-compose.prod.yml ]; then \ docker-compose -f docker-compose.prod.yml down; \ else \ echo "docker-compose.prod.yml not found"; \ fi endif ## View production logs prod-logs: @echo "Viewing production logs..." ifeq ($(OS),Windows_NT) @if exist "docker-compose.prod.yml" ( \ docker-compose -f docker-compose.prod.yml logs -f \ ) else ( \ echo docker-compose.prod.yml not found \ ) else @if [ -f docker-compose.prod.yml ]; then \ docker-compose -f docker-compose.prod.yml logs -f; \ else \ echo "docker-compose.prod.yml not found"; \ fi endif ## Check production status prod-status: @echo "Checking production status..." ifeq ($(OS),Windows_NT) @if exist "docker-compose.prod.yml" ( \ docker-compose -f docker-compose.prod.yml ps \ ) else ( \ echo docker-compose.prod.yml not found \ ) else @if [ -f docker-compose.prod.yml ]; then \ docker-compose -f docker-compose.prod.yml ps; \ else \ echo "docker-compose.prod.yml not found"; \ fi endif ## Run Docker container docker-run: @echo "Running Docker container..." docker run -d --name $(APP_NAME) -p 8080:8080 --env-file .env $(DOCKER_LATEST) ## Stop Docker container docker-stop: @echo "Stopping Docker container..." docker stop $(APP_NAME) || true docker rm $(APP_NAME) || true ## Start development dependencies (Docker Compose) services-up: @echo "Starting development dependencies..." ifeq ($(OS),Windows_NT) @if exist "docker-compose.dev.yml" ( \ docker-compose -f docker-compose.dev.yml up -d \ ) else ( \ echo docker-compose.dev.yml not found \ ) else @if [ -f docker-compose.dev.yml ]; then \ docker-compose -f docker-compose.dev.yml up -d; \ else \ echo "docker-compose.dev.yml not found"; \ fi endif ## Stop development dependencies services-down: @echo "Stopping development dependencies..." ifeq ($(OS),Windows_NT) @if exist "docker-compose.dev.yml" ( \ docker-compose -f docker-compose.dev.yml down \ ) else ( \ echo docker-compose.dev.yml not found \ ) else @if [ -f docker-compose.dev.yml ]; then \ docker-compose -f docker-compose.dev.yml down; \ else \ echo "docker-compose.dev.yml not found"; \ fi endif ## Alias for dev-up (start development dependencies) dev-up: services-up ## Alias for dev-down (stop development dependencies) dev-down: services-down ## Update development dependencies (rebuild and restart) services-update: @echo "Updating development dependencies..." ifeq ($(OS),Windows_NT) @if exist "docker-compose.dev.yml" ( \ docker-compose -f docker-compose.dev.yml down && \ docker-compose -f docker-compose.dev.yml pull && \ docker-compose -f docker-compose.dev.yml up -d --build \ ) else ( \ echo docker-compose.dev.yml not found \ ) else @if [ -f docker-compose.dev.yml ]; then \ docker-compose -f docker-compose.dev.yml down && \ docker-compose -f docker-compose.dev.yml pull && \ docker-compose -f docker-compose.dev.yml up -d --build; \ else \ echo "docker-compose.dev.yml not found"; \ fi endif ## Alias for services-update dev-update: services-update ## View application logs logs: @echo "Viewing application logs..." ifeq ($(OS),Windows_NT) @if exist "logs\\app.log" ( \ powershell -Command "Get-Content logs\\app.log -Wait" \ ) else ( \ echo "Log file does not exist" \ ) else @if [ -f logs/app.log ]; then \ tail -f logs/app.log; \ else \ echo "Log file does not exist"; \ fi endif ## Generate API documentation docs: @echo "Generating API documentation..." ifeq ($(OS),Windows_NT) @where swag >nul 2>&1 && swag init -g $(MAIN_PATH) -o docs/swagger || echo "swag not installed, skipping documentation generation" else @if command -v swag >/dev/null 2>&1; then \ swag init -g $(MAIN_PATH) -o docs/swagger; \ else \ echo "swag not installed, skipping documentation generation"; \ fi endif ## Performance benchmark bench: @echo "Running performance benchmark..." $(GOTEST) -bench=. -benchmem ./... ## Race condition detection race: @echo "Running race condition detection..." $(GOTEST) -race ./... ## Security scan security: @echo "Running security scan..." ifeq ($(OS),Windows_NT) @where gosec >nul 2>&1 && gosec ./... || echo "gosec not installed, skipping security scan" else @if command -v gosec >/dev/null 2>&1; then \ gosec ./...; \ else \ echo "gosec not installed, skipping security scan"; \ fi endif ## Generate mock data mock: @echo "Generating mock data..." ifeq ($(OS),Windows_NT) @where mockgen >nul 2>&1 && echo "Generating mock data..." || echo "mockgen not installed, please install: go install github.com/golang/mock/mockgen@latest" else @if command -v mockgen >/dev/null 2>&1; then \ echo "Generating mock data..."; \ else \ echo "mockgen not installed, please install: go install github.com/golang/mock/mockgen@latest"; \ fi endif ## 完整的 CI 流程 ci: deps fmt lint test build ## 完整的发布流程 release: ci build-all docker-build .PHONY: help deps fmt lint test coverage build build-prod build-all run dev migrate version health clean env setup docker-build docker-run docker-stop docker-push docker-build-prod docker-push-prod deploy-prod prod-up prod-down prod-logs prod-status services-up services-down services-update dev-up dev-down dev-update logs docs bench race security mock ci release