# AGENTS.md This file provides guidance for agentic coding agents working on this repository. ## Build/Lint/Test Commands ### Building ```bash make build # Build executable (trace-backend.exe) make run # Run development server go build -o bin/backend.exe . # Build to custom location ``` ### Testing ```bash make test # Run all integration tests (./tests/...) go test -v ./services/... # Run service layer unit tests go test -v ./tests/... # Run integration tests go test -v -run TestAuthService_ValidateUser_Success ./services/... # Single test go test -v ./services/... -run TestSerialsService # Run test prefix make test-coverage # Generate coverage report ``` ### Code Quality ```bash make lint # Run golangci-lint (configured in .golangci.yml) make fmt # Format code with gofmt make imports # Format imports with goimports make quality # fmt + imports + lint (full check) golangci-lint run ./... # Direct lint check ``` ### Swagger Documentation ```bash make swagger # Generate swagger docs to docs/ directory swag init -g main.go # Alternative command ``` ## Code Style Guidelines ### Project Structure - **controllers/**: HTTP request handlers, use helper functions (GetCurrentUser, BindJSON, ErrorResponse, SuccessResponse) - **services/**: Business logic layer, return errors to controllers - **models/**: Data models with JSON and GORM tags, DTOs for API - **middleware/**: JWT authentication and admin role checks - **database/**: SQLite/PostgreSQL connection and migrations ### Import Organization Standard imports followed by third-party imports, then project imports (sorted alphabetically): ```go import ( "errors" "net/http" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5" "git.beifan.cn/trace-system/backend-go/config" "git.beifan.cn/trace-system/backend-go/models" ) ``` ### Naming Conventions - **Controllers**: `AuthController`, `SerialsController`, `CompaniesController` - **Services**: `AuthService`, `SerialsService`, `CompaniesService` - **Models**: `User`, `Company`, `Serial` (use PascalCase for exported structs) - **DTOs**: `LoginDTO`, `ChangePasswordDTO`, `UpdateProfileDTO` (DTO suffix) - **Functions**: `ValidateUser`, `Generate`, `Query` (PascalCase for exported) - **Variables**: camelCase for local variables, PascalCase for exported ### Struct Tags - **JSON tags**: lowercase camelCase, `json:"username"`, `json:"accessToken"` - **GORM tags**: PascalCase, `gorm:"primaryKey"`, `gorm:"uniqueIndex;size:255"` - **Validate tags**: `validate:"required,min=6"`, `validate:"omitempty,email"` - **Omit empty**: `json:"omitempty"` for optional fields - **Ignore in JSON**: `json:"-"` for sensitive fields (Password, DeletedAt) ### Error Handling **Services**: Return errors, don't handle them directly: ```go func (s *AuthService) ValidateUser(username, password string) (models.User, error) { var user models.User err := database.DB.Where("username = ?", username).First(&user).Error if err != nil { return models.User{}, errors.New("用户名或密码错误") } return user, nil } ``` **Controllers**: Use helper functions for consistent responses: ```go func (c *AuthController) Login(ctx *gin.Context) { var loginData models.LoginDTO if !BindJSON(ctx, &loginData) { return } user, err := c.authService.ValidateUser(loginData.Username, loginData.Password) if err != nil { ErrorResponse(ctx, http.StatusUnauthorized, err.Error()) return } SuccessResponse(ctx, "登录成功", gin.H{"user": user}) } ``` ### Response Format **Success response**: ```json { "message": "操作成功", "data": { ... } } ``` **Error response**: ```json { "message": "错误描述", "error": "详细错误信息" } ``` ### Logging Use structured logger from `logger` package: ```go logger.Info("用户登录", logger.String("username", user.Username)) logger.Error("数据库错误", logger.Err(err)) logger.Fatal("致命错误", logger.Err(err)) ``` ### Database Operations - Use `database.DB` for GORM operations - Always check for errors: `if err != nil { ... }` - Use Unscoped for permanent deletion: `database.DB.Unscoped().Delete(...)` - Test cleanup: `database.DB.Unscoped().Where("1 = 1").Delete(&models.User{})` ### Testing - Use `testify/assert` for assertions - Use `TestMain` for setup/cleanup (init DB, create test data, cleanup on exit) - Test naming: `Test{Service}_{Method}_{Scenario}` - Clean up test data after tests: delete all records - Use bcrypt for password hashing in tests ### Swagger Annotations Add Swagger comments to controller methods: ```go // @Summary Brief description // @Description Detailed description // @Tags Category // @Accept json // @Produce json // @Security BearerAuth // @Param name body models.DTO true "Description" // @Success 200 {object} models.ResponseDTO // @Failure 400 {object} models.ErrorResponse // @Router /path [method] ``` After modifying Swagger annotations, run `make swagger`. ### Configuration - Load with `config.LoadConfig()` - Access with `config.GetAppConfig()` - Environment variables: `APP_SERVER_PORT`, `APP_DATABASE_DRIVER`, etc. - .env file for local development (not committed) ### Middleware - **JWTAuthMiddleware**: Validates JWT tokens, sets user in context - **AdminMiddleware**: Checks if user has admin role - Access current user: `user, ok := GetCurrentUser(ctx)` ### Git Hooks Run `make quality` before committing to ensure code passes all checks.