|
| 1 | +# GitHub Copilot Instructions |
| 2 | + |
| 3 | +## Code Style & Quality Guidelines |
| 4 | + |
| 5 | +When generating code for this project, please ensure compliance with the following standards: |
| 6 | + |
| 7 | +### Go Code Standards |
| 8 | +- **Follow Go conventions**: Use `gofmt`, `goimports`, and standard Go idioms |
| 9 | +- **Naming conventions**: |
| 10 | + - Use camelCase for variables and functions |
| 11 | + - Use PascalCase for exported types and functions |
| 12 | + - Use meaningful, descriptive names |
| 13 | + - Avoid abbreviations unless they're well-known (e.g., `HTTP`, `URL`, `ID`) |
| 14 | + |
| 15 | +### Linting Compliance |
| 16 | +- **golangci-lint**: All generated code must pass our golangci-lint configuration |
| 17 | +- **Common lint rules to follow**: |
| 18 | + - No unused variables or imports |
| 19 | + - Proper error handling (never ignore errors) |
| 20 | + - Use `require` for error assertions in tests, `assert` for other validations |
| 21 | + - Avoid useless assertions (comparing variables to themselves) |
| 22 | + - Add proper context to error messages |
| 23 | + |
| 24 | +### Testing Standards |
| 25 | +- **Test naming**: Use `Test<FunctionName>` pattern |
| 26 | +- **Test structure**: Follow Arrange-Act-Assert pattern |
| 27 | +- **Parallel tests**: Use `t.Parallel()` for independent tests |
| 28 | +- **Error testing**: Use `require.Error()` for error assertions, `assert` for other checks |
| 29 | +- **Coverage**: Aim for meaningful test coverage, not just line coverage |
| 30 | +- **Table-driven tests**: Use for multiple test cases with similar structure |
| 31 | + |
| 32 | +### Package Organization |
| 33 | +- **Internal packages** (`internal/`): Private application code |
| 34 | + - `config/`: Configuration management |
| 35 | + - `db/`: Database repositories and data access |
| 36 | + - `handlers/`: HTTP request handlers |
| 37 | + - `middleware/`: HTTP middleware components |
| 38 | + - `models/`: Domain models and data structures |
| 39 | + - `server/`: HTTP server setup and lifecycle |
| 40 | + - `utilities/`: Internal utility functions |
| 41 | +- **Public packages** (`pkg/`): Reusable libraries |
| 42 | + - `logger/`: Structured logging utilities |
| 43 | + - `mongodb/`: MongoDB connection management |
| 44 | + |
| 45 | +### Code Patterns to Follow |
| 46 | + |
| 47 | +#### Error Handling |
| 48 | +```go |
| 49 | +// Good: Proper error wrapping |
| 50 | +if err != nil { |
| 51 | + return fmt.Errorf("failed to process request: %w", err) |
| 52 | +} |
| 53 | + |
| 54 | +// Good: Context-aware operations |
| 55 | +func (r *Repository) GetByID(ctx context.Context, id string) (*Model, error) { |
| 56 | + // Implementation with proper context usage |
| 57 | +} |
| 58 | +``` |
| 59 | + |
| 60 | +#### Testing Patterns |
| 61 | +```go |
| 62 | +// Good: Table-driven tests |
| 63 | +func TestFunction(t *testing.T) { |
| 64 | + t.Parallel() |
| 65 | + |
| 66 | + tests := []struct { |
| 67 | + name string |
| 68 | + input string |
| 69 | + expected string |
| 70 | + wantErr bool |
| 71 | + }{ |
| 72 | + // Test cases |
| 73 | + } |
| 74 | + |
| 75 | + for _, tt := range tests { |
| 76 | + t.Run(tt.name, func(t *testing.T) { |
| 77 | + t.Parallel() |
| 78 | + // Test implementation |
| 79 | + }) |
| 80 | + } |
| 81 | +} |
| 82 | +``` |
| 83 | + |
| 84 | +#### MongoDB Patterns |
| 85 | +```go |
| 86 | +// Good: Use functional options pattern |
| 87 | +dbConnMgr, err := mongodb.NewMongoManager( |
| 88 | + svcEnv.DBHosts, |
| 89 | + svcEnv.DBName, |
| 90 | + credentials, |
| 91 | + mongodb.WithQueryLogging(true), |
| 92 | + mongodb.WithReplicaSet("rs0"), |
| 93 | +) |
| 94 | +``` |
| 95 | + |
| 96 | +#### Logging Patterns |
| 97 | +```go |
| 98 | +// Good: Structured logging with context |
| 99 | +lgr.Info(). |
| 100 | + Str("requestID", reqID). |
| 101 | + Str("operation", "create_order"). |
| 102 | + Dur("elapsed", elapsed). |
| 103 | + Msg("operation completed successfully") |
| 104 | +``` |
| 105 | + |
| 106 | +### Architecture Principles |
| 107 | +- **Dependency Injection**: Use interfaces and inject dependencies |
| 108 | +- **Single Responsibility**: Each function/type should have one clear purpose |
| 109 | +- **Interface Segregation**: Keep interfaces small and focused |
| 110 | +- **Error Boundaries**: Handle errors at appropriate levels |
| 111 | +- **Context Propagation**: Pass context through all operations that might be cancelled |
| 112 | + |
| 113 | +### Security Considerations |
| 114 | +- **Input Validation**: Always validate and sanitize inputs |
| 115 | +- **Secrets Management**: Never hardcode secrets, use environment variables or sidecar files |
| 116 | +- **SQL Injection Prevention**: Use parameterized queries (though we use MongoDB) |
| 117 | +- **OWASP Compliance**: Follow security headers and validation patterns |
| 118 | + |
| 119 | +### Performance Guidelines |
| 120 | +- **Connection Pooling**: Reuse database connections |
| 121 | +- **Context Timeouts**: Set appropriate timeouts for operations |
| 122 | +- **Graceful Shutdown**: Implement proper cleanup on application termination |
| 123 | +- **Resource Management**: Always close/cleanup resources (defer patterns) |
| 124 | + |
| 125 | +## Specific to This Project |
| 126 | + |
| 127 | +### MongoDB Connection Management |
| 128 | +- Use the `pkg/mongodb` package for all database connections |
| 129 | +- Follow the functional options pattern for configuration |
| 130 | +- Always use context-aware operations |
| 131 | +- Implement proper connection cleanup |
| 132 | + |
| 133 | +### Middleware Chain |
| 134 | +- Keep middleware focused and composable |
| 135 | +- Use proper request ID propagation |
| 136 | +- Implement structured logging in middleware |
| 137 | +- Handle panics gracefully |
| 138 | + |
| 139 | +### Configuration Management |
| 140 | +- Use the `internal/config` package for environment configuration |
| 141 | +- Validate all required configuration at startup |
| 142 | +- Provide sensible defaults where appropriate |
| 143 | + |
| 144 | +When generating code, please ensure it follows these patterns and will pass both our linting rules and maintain consistency with the existing codebase architecture. |
0 commit comments