|
| 1 | +# GitHub Copilot Instructions |
| 2 | + |
| 3 | +## Project Context |
| 4 | + |
| 5 | +This is a project focused on two parts |
| 6 | +- A .NET website to observe the health of various servers that expose a standard schema. Intended use is via a docker instance |
| 7 | +- A list of projects (per language) that are easy to use libraries that expose that standard observability schema |
| 8 | +The codebase emphasizes simplicity, developer experience, and production-ready patterns |
| 9 | + |
| 10 | +## Code Style & Standards |
| 11 | + |
| 12 | +### General .NET Guidelines |
| 13 | +- Use modern C# features (pattern matching, records, nullable reference types, file-scoped namespaces) |
| 14 | +- Follow Microsoft's C# coding conventions (enforced via `.editorconfig`) |
| 15 | +- Prefer `async`/`await` for I/O operations |
| 16 | +- Use meaningful, descriptive names (avoid abbreviations unless widely known) |
| 17 | +- All comments should be in English and finish with a period |
| 18 | + |
| 19 | +### Code Organization |
| 20 | +- Use file-scoped namespaces |
| 21 | +- One class per file (match filename to class name) |
| 22 | +- Group using statements (System namespaces first, then third-party, then local) |
| 23 | +- Order class members: fields, constructors, properties, methods (public before private) |
| 24 | + |
| 25 | +### Error Handling |
| 26 | +- Use exceptions for exceptional cases, not control flow |
| 27 | +- Provide meaningful exception messages with context |
| 28 | +- Use guard clauses for parameter validation |
| 29 | +- Consider custom exceptions for domain-specific errors |
| 30 | +- Always validate input parameters (use ArgumentNullException, ArgumentException) |
| 31 | + |
| 32 | +### Async/Await |
| 33 | +- Always use `ConfigureAwait(false)` in library code (not in ASP.NET Core endpoints) |
| 34 | +- Pass `CancellationToken` to all async methods |
| 35 | +- Don't use `.Result` or `.Wait()` - always await |
| 36 | +- Return `Task` or `Task<T>`, not `async void` (except event handlers) |
| 37 | + |
| 38 | +### Logging |
| 39 | +- Use structured logging with ILogger |
| 40 | +- Include relevant context in log messages |
| 41 | +- Use appropriate log levels (Trace, Debug, Information, Warning, Error, Critical) |
| 42 | +- Log at method entry/exit for important operations |
| 43 | +- Include correlation IDs where applicable |
| 44 | + |
| 45 | +### Testing |
| 46 | +- Write unit tests for all public APIs |
| 47 | +- Use xUnit as the testing framework and specifically xunit v3 using the latest Microsft Test Platform version |
| 48 | +- Follow AAA pattern (Arrange, Act, Assert) |
| 49 | +- Always comment in a test the "Arrange.", "Act.", and "Assert." sections |
| 50 | +- Use meaningful test names (e.g., `AddMessageAsync_WithLargeContent_StoresInBlob`) |
| 51 | +- Mock external dependencies (use Moq or NSubstitute) |
| 52 | +- Aim for high code coverage on business logic |
| 53 | +- Each method being tested should have it's own class to xunit can run tests in parallel |
| 54 | +- Each method being tested should have at least one test for success and one for failure |
| 55 | + |
| 56 | +### Documentation |
| 57 | +- Use XML documentation comments for public APIs |
| 58 | +- Include `<summary>`, `<param>`, `<returns>`, and `<exception>` tags |
| 59 | +- Provide code examples in remarks when helpful |
| 60 | +- Keep README.md updated with examples |
| 61 | +- Document breaking changes in release notes |
| 62 | + |
| 63 | +### Performance |
| 64 | +- Avoid allocations in hot paths |
| 65 | +- Use `Span<T>`, `Memory<T>`, and `ReadOnlySpan<T>` where appropriate |
| 66 | +- Consider object pooling for frequently allocated objects |
| 67 | +- Profile before optimizing |
| 68 | +- Use `ValueTask<T>` for high-performance scenarios |
| 69 | + |
| 70 | +### Dependencies |
| 71 | +- Minimize external dependencies |
| 72 | +- Use well-maintained, popular NuGet packages |
| 73 | +- Keep packages up-to-date |
| 74 | +- Prefer Microsoft packages for common functionality |
| 75 | +- Review package licenses for compatibility |
| 76 | + |
| 77 | +### Design Patterns |
| 78 | +- Favor composition over inheritance |
| 79 | +- Use dependency injection |
| 80 | +- Apply SOLID principles |
| 81 | +- Keep classes focused (Single Responsibility Principle) |
| 82 | +- Program to interfaces, not implementations |
| 83 | +- Use builder pattern for complex object construction |
| 84 | + |
| 85 | +### Records and Data Types |
| 86 | +- Use `record` for DTOs and immutable data |
| 87 | +- Use `readonly struct` for small, immutable value types |
| 88 | +- Prefer immutability where possible |
| 89 | +- Use nullable reference types (`?`) appropriately |
| 90 | + |
| 91 | +### API Design |
| 92 | +- Keep public API surface small and focused |
| 93 | +- Make it hard to use incorrectly (pit of success) |
| 94 | +- Provide async methods for I/O operations |
| 95 | +- Accept interfaces in constructors, return concrete types |
| 96 | +- Version APIs carefully to avoid breaking changes |
| 97 | + |
| 98 | +## What NOT to Do |
| 99 | + |
| 100 | +- ❌ Don't ignore CA (Code Analysis) warnings without justification |
| 101 | +- ❌ Don't commit commented-out code |
| 102 | +- ❌ Don't use magic numbers/strings (use constants) |
| 103 | +- ❌ Don't catch generic exceptions without rethrowing |
| 104 | +- ❌ Don't use `Thread.Sleep` in async code (use `Task.Delay`) |
| 105 | +- ❌ Don't expose internal implementation details in public APIs |
| 106 | +- ❌ Don't write methods longer than ~50 lines (refactor into smaller methods) |
| 107 | +- ❌ Don't use regions to hide code |
| 108 | +- ❌ Don't use dynamic types |
| 109 | +- ❌ Don't use static classes for stateful operations |
| 110 | +- ❌ Don't use Automapper or MediatR |
| 111 | + |
| 112 | +## Code Review Checklist |
| 113 | + |
| 114 | +When reviewing code suggestions, ensure: |
| 115 | +- [ ] Code follows project conventions |
| 116 | +- [ ] All public APIs have XML documentation |
| 117 | +- [ ] Async methods use `CancellationToken` |
| 118 | +- [ ] Proper exception handling is in place |
| 119 | +- [ ] Tests are included for new functionality |
| 120 | +- [ ] No hardcoded values (use configuration) |
| 121 | +- [ ] Logging is appropriate and structured |
| 122 | +- [ ] Performance implications are considered |
| 123 | +- [ ] Breaking changes are documented |
| 124 | + |
| 125 | +## Additional Context |
| 126 | + |
| 127 | +- This project prioritizes **simplicity** and **developer experience** |
| 128 | +- Code should be self-documenting where possible |
| 129 | +- Favor clarity over cleverness |
| 130 | +- Consider the library consumer's perspective |
| 131 | +- Maintain backward compatibility when possible |
0 commit comments