Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 92 additions & 64 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -1,91 +1,119 @@
# GitHub Copilot Instructions

> **Token Budget**: Target 600, limit 650 (auto-loaded)
> Details: `#file:AGENTS.md` (~2,550 tokens, on-demand)
> Skills: `#file:SKILLS/<name>/SKILL.md` (on-demand)
## Overview

## Quick Context
REST API for managing football players built with ASP.NET Core 10. Implements CRUD operations with a layered architecture, EF Core + SQLite persistence, FluentValidation, AutoMapper, and in-memory caching. Part of a cross-language comparison study (Go, Java, Python, Rust, TypeScript).

ASP.NET Core 10 REST API with layered architecture
**Stack**: .NET 10 LTS, EF Core 10, SQLite, Docker, xUnit
**Pattern**: Repository + Service + AutoMapper + FluentValidation
**Focus**: Learning PoC emphasizing clarity and best practices
## Tech Stack

## Core Conventions

- **Naming**: PascalCase (public), camelCase (private)
- **DI**: Primary constructors everywhere
- **Async**: All I/O operations use async/await
- **Logging**: Serilog with structured logging
- **Language**: C# (.NET 10 LTS)
- **Framework**: ASP.NET Core (MVC controllers)
- **ORM**: Entity Framework Core 10
- **Database**: SQLite
- **Mapping**: AutoMapper
- **Validation**: FluentValidation
- **Caching**: `IMemoryCache` (1-hour TTL)
- **Logging**: Serilog (structured, console + file)
- **Testing**: xUnit + Moq + FluentAssertions
- **Formatting**: CSharpier
- **Commits**: Conventional Commits with issue number suffix
- Format: `type(scope): description (#issue)` (max 80 chars)
- Types: feat, fix, chore, docs, test, refactor
- Example: `feat(api): add player search endpoint (#123)`
- Body lines ≤80 chars
- **Containerization**: Docker

## Architecture
## Structure

```text
Controller → Service → Repository → Database
↓ ↓
Validation Caching
src/Dotnet.Samples.AspNetCore.WebApi/
├── Controllers/ — HTTP handlers; minimal logic, delegate to services [HTTP layer]
├── Services/ — Business logic + IMemoryCache caching [business layer]
├── Repositories/ — Generic Repository<T> + specific implementations [data layer]
├── Models/ — Player entity + DTOs
├── Validators/ — FluentValidation (structure only; business rules in services)
├── Profiles/ — AutoMapper profiles
├── Data/ — DbContext + DbInitializer
└── Storage/ — SQLite database file

test/Dotnet.Samples.AspNetCore.WebApi.Tests/
├── ControllersTests/
└── ServicesTests/
```

Controllers: Minimal logic, delegate to services
Services: Business logic + `IMemoryCache` caching
Repositories: Generic `Repository<T>` + specific implementations
Models: `Player` entity + DTOs
Validators: FluentValidation (structure only, business rules in services)

## Copilot Should
**Layer rule**: `Controller → Service → Repository → Database`. Controllers must not access repositories directly. Business logic must not live in controllers.

- Generate idiomatic ASP.NET Core code with minimal controller logic
- Use EF Core async APIs with `AsNoTracking()` for reads
- Follow Repository + Service pattern consistently
- Write tests with xUnit/Moq/FluentAssertions
- Apply RFC 7807 Problem Details for errors
- Use primary constructors for DI
- Implement structured logging with `ILogger<T>`
## Coding Guidelines

## Copilot Should Avoid
- **Naming**: PascalCase (public members), camelCase (private fields)
- **DI**: Primary constructors everywhere
- **Async**: All I/O operations use `async`/`await`; no `ConfigureAwait(false)` (unnecessary in ASP.NET Core)
- **Reads**: Use `AsNoTracking()` for all EF Core read queries
- **Errors**: RFC 7807 Problem Details for all error responses
- **Logging**: Structured logging via `ILogger<T>`; never `Console.Write`
- **Tests**: xUnit + Moq + FluentAssertions; test naming mirrors method under test
- **Avoid**: synchronous EF Core APIs, controller business logic, static service/repository classes

- Synchronous EF Core APIs
- Controller business logic (belongs in services)
- Static service/repository classes
- `ConfigureAwait(false)` (unnecessary in ASP.NET Core)
## Commands

## Quick Commands
### Quick Start

```bash
# Run with hot reload
dotnet watch run --project src/Dotnet.Samples.AspNetCore.WebApi
dotnet restore
dotnet build
dotnet run --project src/Dotnet.Samples.AspNetCore.WebApi # https://localhost:9000
dotnet watch run --project src/Dotnet.Samples.AspNetCore.WebApi # hot reload
dotnet test --settings .runsettings # with coverage
docker compose up
```

# Test with coverage
dotnet test --settings .runsettings
### Pre-commit Checks

# Docker
docker compose up
1. Update `CHANGELOG.md` `[Unreleased]` section (Added / Changed / Fixed / Removed)
2. `dotnet build --configuration Release` — must succeed
3. `dotnet test --settings .runsettings` — all tests must pass
4. Verify code formatting with CSharpier
5. Commit message follows Conventional Commits format (enforced by commitlint)

# Swagger: https://localhost:9000/swagger
```
### Commits

Format: `type(scope): description (#issue)` — max 80 chars
Types: `feat` `fix` `chore` `docs` `test` `refactor` `ci` `perf`
Example: `feat(api): add player search endpoint (#123)`

## Load On-Demand Files
## Agent Mode

**Load `#file:AGENTS.md` when:**
- "How do I run tests with coverage?"
- "CI/CD pipeline setup or troubleshooting"
- "Database migration procedures"
- "Publishing/deployment workflows"
- "Detailed troubleshooting guides"
### Proceed freely

**Load `#file:SKILLS/<skill-name>/SKILL.md` (planned):**
- Docker optimization: `docker-containerization/SKILL.md`
- Testing patterns: `testing-patterns/SKILL.md`
- Route handlers and controllers
- Service layer logic and caching
- Repository implementations
- Unit and integration tests
- Documentation and CHANGELOG updates
- Bug fixes and refactoring within existing patterns

**Human-readable overview**: See `README.md` (not auto-loaded)
### Ask before changing

---
- Database schema (entity fields, migrations)
- Dependencies (`*.csproj`, `global.json`)
- CI/CD configuration (`.github/workflows/`)
- Docker setup
- Application configuration (`appsettings.json`)
- API contracts (breaking DTO changes)
- Caching strategy or TTL values

**Why this structure?** Base instructions (~600 tokens) load automatically. On-demand files (~2,550 tokens) load only when needed, saving 80% of tokens per chat.
### Never modify

- Production configurations or deployment secrets
- `.runsettings` coverage thresholds
- Port configuration (9000)
- Database type (SQLite — demo/dev only)

### Key workflows

**Add an endpoint**: Add DTO in `Models/` → update `PlayerMappingProfile` in `Mappings/` (AutoMapper) → add repository method(s) in `Repositories/` → add service method in `Services/` → add controller action in `Controllers/` → add validator in `Validators/` → add tests → run pre-commit checks.

**Modify schema**: Update `Player` entity → update DTOs → update AutoMapper profile → reset `Storage/players.db` → update tests → run `dotnet test`.

**After completing work**: Suggest a branch name (e.g. `feat/add-player-search`) and a commit message following Conventional Commits including co-author line:

```text
feat(scope): description (#issue)

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
```
Loading