512 lines
15 KiB
Makefile
512 lines
15 KiB
Makefile
# 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)
|
|
$(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 |