From 16582f4ddde1f518fd5b3b22680518557e3889a8 Mon Sep 17 00:00:00 2001 From: Nano Taboada <87288+nanotaboada@users.noreply.github.com> Date: Sun, 5 Apr 2026 12:11:05 -0300 Subject: [PATCH 1/2] docs: normalize README structure and add RELEASES.md (#448) Co-Authored-By: Claude Sonnet 4.6 --- .markdownlint.json | 6 ++ README.md | 219 +++++++++------------------------------------ RELEASES.md | 63 +++++++++++++ 3 files changed, 109 insertions(+), 179 deletions(-) create mode 100644 .markdownlint.json create mode 100644 RELEASES.md diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 0000000..ef592cf --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,6 @@ +{ + "MD013": false, + "MD024": { + "siblings_only": true + } +} diff --git a/README.md b/README.md index c7fe010..2193dfb 100644 --- a/README.md +++ b/README.md @@ -14,34 +14,14 @@ Proof of Concept for a RESTful API built with .NET 10 (LTS) and ASP.NET Core. Manage football player data with SQLite, Entity Framework Core, Swagger documentation, and in-memory caching. -## Table of Contents - -- [Features](#features) -- [Tech Stack](#tech-stack) -- [Project Structure](#project-structure) -- [Architecture](#architecture) -- [Architecture Decisions](#architecture-decisions) -- [API Reference](#api-reference) -- [Prerequisites](#prerequisites) -- [Quick Start](#quick-start) -- [Testing](#testing) -- [Containers](#containers) -- [Releases](#releases) -- [Environment Variables](#environment-variables) -- [Command Summary](#command-summary) -- [Contributing](#contributing) -- [Legal](#legal) - ## Features - ๐Ÿ—๏ธ **Clean layered architecture** - Repository pattern, dependency injection, and async operations throughout - ๐Ÿ“š **Interactive API exploration** - Swagger UI documentation with health monitoring endpoints - โšก **Performance optimizations** - In-memory caching, rate limiting, and efficient database queries - ๐Ÿงช **High test coverage** - xUnit tests with automated reporting to Codecov and SonarCloud -- ๐Ÿ“– **Token-efficient documentation** - Custom instructions with coding guidelines, architecture rules, and agent workflows for AI-assisted development - ๐Ÿณ **Full containerization** - Multi-stage Docker builds with Docker Compose orchestration - ๐Ÿ”„ **Complete CI/CD pipeline** - Automated testing, code quality checks, Docker publishing, and GitHub releases -- ๐ŸŸ๏ธ **Stadium-themed semantic versioning** - Memorable, alphabetical release names from World Cup venues ## Tech Stack @@ -58,51 +38,6 @@ Proof of Concept for a RESTful API built with .NET 10 (LTS) and ASP.NET Core. Ma | **Testing** | [xUnit](https://github.com/xunit/xunit), [Moq](https://github.com/devlooped/moq), [FluentAssertions](https://github.com/fluentassertions/fluentassertions) | | **Containerization** | [Docker](https://github.com/docker) & [Docker Compose](https://github.com/docker/compose) | -## Project Structure - -```text -src/Dotnet.Samples.AspNetCore.WebApi/ -โ”œโ”€โ”€ Program.cs # Entry point: DI setup, middleware pipeline -โ”œโ”€โ”€ Controllers/ # HTTP handlers (request/response logic) -โ”‚ โ””โ”€โ”€ PlayerController.cs -โ”œโ”€โ”€ Services/ # Business logic + caching layer -โ”‚ โ”œโ”€โ”€ IPlayerService.cs -โ”‚ โ””โ”€โ”€ PlayerService.cs -โ”œโ”€โ”€ Repositories/ # Data access abstraction -โ”‚ โ”œโ”€โ”€ IPlayerRepository.cs -โ”‚ โ”œโ”€โ”€ IRepository.cs -โ”‚ โ”œโ”€โ”€ PlayerRepository.cs -โ”‚ โ””โ”€โ”€ Repository.cs -โ”œโ”€โ”€ Models/ # Domain entities and DTOs -โ”‚ โ”œโ”€โ”€ Player.cs -โ”‚ โ”œโ”€โ”€ PlayerRequestModel.cs -โ”‚ โ””โ”€โ”€ PlayerResponseModel.cs -โ”œโ”€โ”€ Data/ # EF Core DbContext and migrations -โ”‚ โ””โ”€โ”€ PlayerDbContext.cs -โ”œโ”€โ”€ Mappings/ # AutoMapper profiles -โ”‚ โ””โ”€โ”€ PlayerMappingProfile.cs -โ”œโ”€โ”€ Validators/ # FluentValidation rules -โ”‚ โ””โ”€โ”€ PlayerRequestModelValidator.cs -โ”œโ”€โ”€ Configurations/ # Swagger, rate limiting config -โ”œโ”€โ”€ Enums/ # Domain enumerations (e.g. Position) -โ”œโ”€โ”€ Extensions/ # Service registration extensions -โ”œโ”€โ”€ Middlewares/ # Custom ASP.NET Core middleware -โ”œโ”€โ”€ Utilities/ # Helper classes -โ”œโ”€โ”€ Migrations/ # EF Core migrations -โ””โ”€โ”€ storage/ # Pre-seeded SQLite database - -test/Dotnet.Samples.AspNetCore.WebApi.Tests/ -โ”œโ”€โ”€ Unit/ # Unit tests with xUnit -โ”‚ โ”œโ”€โ”€ PlayerControllerTests.cs -โ”‚ โ”œโ”€โ”€ PlayerServiceTests.cs -โ”‚ โ””โ”€โ”€ PlayerValidatorTests.cs -โ””โ”€โ”€ Utilities/ # Shared test helpers - โ”œโ”€โ”€ DatabaseFakes.cs - โ”œโ”€โ”€ PlayerFakes.cs - โ”œโ”€โ”€ PlayerMocks.cs - โ””โ”€โ”€ PlayerStubs.cs -``` - ## Architecture Layered architecture with dependency injection via constructors and interface-based contracts. @@ -196,31 +131,9 @@ graph RL class AspNetCore,EFCore,MemoryCache feat; ``` -### Arrow Semantics - -Arrows follow the injection direction: `A --> B` means A is injected into B. Solid arrows (`-->`) represent active ASP.NET Core dependencies โ€” services registered with the IoC container and invoked at runtime. Dotted arrows (`-.->`) represent test dependencies โ€” test classes reference the types they exercise but are not injected into them. - -### Composition Root Pattern - -`Program` is the composition root: it registers all services, repositories, DbContext, mappers, validators, and middleware with the ASP.NET Core IoC container, which resolves them at runtime via constructor injection. - -### Layered Architecture - -Four layers: Initialization (`Program`), HTTP (`Controllers`, `Validators`), Business (`Services`, `Mappings`), and Data (`Repositories`, `Data`). - -Framework and third-party packages are placed inside the subgraph of the layer that uses them โ€” `Serilog` and `Swashbuckle` in Initialization, `ASP.NET Core` and `FluentValidation` in HTTP, `AutoMapper` in Business, `EF Core` in Data. - -`Models` is a cross-cutting type concern โ€” shared entities and DTOs consumed across all layers, with no logic of its own. - -### Color Coding - -Blue = core application packages, yellow = Microsoft platform packages, red = third-party libraries, green = tests. - -*Simplified, conceptual view โ€” not all components or dependencies are shown.* - -## Architecture Decisions - -See [Architecture Decision Records (ADRs)](adr/README.md) for documented decisions about this project's architecture, technology choices, and development practices. +> *Arrows follow the injection direction (A โ†’ B means A depends on B). Solid = runtime dependency, dotted = structural. Blue = core domain, red = third-party, green = tests.* +> +> *Significant design decisions are documented as ADRs in [`adr/`](adr/README.md).* ## API Reference @@ -228,15 +141,17 @@ Interactive API documentation is available via Swagger UI at `https://localhost: > ๐Ÿ’ก Swagger documentation is only available in development mode for security reasons. -**Quick Reference:** +| Method | Endpoint | Description | Status | +| ------ | -------- | ----------- | ------ | +| `GET` | `/players` | List all players | `200 OK` | +| `GET` | `/players/{id:Guid}` | Get player by ID *(requires authentication)* | `200 OK` | +| `GET` | `/players/squadNumber/{squadNumber:int}` | Get player by squad number | `200 OK` | +| `POST` | `/players` | Create new player | `201 Created` | +| `PUT` | `/players/squadNumber/{squadNumber:int}` | Update player by squad number | `200 OK` | +| `DELETE` | `/players/squadNumber/{squadNumber:int}` | Remove player by squad number | `204 No Content` | +| `GET` | `/health` | Health check | `200 OK` | -- `GET /players` - List all players -- `GET /players/{id:Guid}` - Get player by ID (requires authentication) -- `GET /players/squadNumber/{squadNumber:int}` - Get player by squad number -- `POST /players` - Create new player -- `PUT /players/squadNumber/{squadNumber:int}` - Update player -- `DELETE /players/squadNumber/{squadNumber:int}` - Remove player -- `GET /health` - Health check +Error codes: `400 Bad Request` (validation failed) ยท `404 Not Found` (player not found) ยท `409 Conflict` (duplicate squad number on `POST`) For complete endpoint documentation with request/response schemas, explore the [interactive Swagger UI](https://localhost:9000/swagger/index.html). @@ -275,24 +190,6 @@ The server will start on `https://localhost:9000`. - Swagger Documentation: `https://localhost:9000/swagger/index.html` - Health Check: `https://localhost:9000/health` -## Testing - -Run the test suite with xUnit: - -```bash -# Run all tests -dotnet test - -# Run tests with coverage report -dotnet test --results-directory "coverage" --collect:"XPlat Code Coverage" --settings .runsettings - -# View coverage report -dotnet tool install --global dotnet-reportgenerator-globaltool -reportgenerator -reports:coverage/**/coverage.cobertura.xml -targetdir:coverage -reporttypes:Html -``` - -Tests are located in the `test/` directory and use xUnit for unit testing. Coverage reports are generated for controllers and services only. - ## Containers This project includes full Docker support with multi-stage builds and Docker Compose for easy deployment. @@ -327,56 +224,7 @@ docker compose down -v The containerized application runs on port 9000 and includes health checks that monitor the `/health` endpoint. -## Releases - -This project uses **stadium-themed release names** inspired by famous football stadiums that hosted FIFA World Cup matches. Each release is named after a stadium (A-Z alphabetically), making versions memorable and fun. - -### Release Naming Convention - -Releases follow the pattern: `v{SEMVER}-{STADIUM}` (e.g., `v1.0.0-azteca`) - -- **Semantic Version**: Standard versioning (MAJOR.MINOR.PATCH) -- **Stadium Name**: Alphabetically ordered codename from the [stadium list](CHANGELOG.md#stadium-release-names) - -### Create a Release - -To create a new release, follow this workflow: - -#### 1. Update CHANGELOG.md - -First, create a `release/` branch and document your changes in [CHANGELOG.md](CHANGELOG.md): - -```bash -git checkout -b release/1.0.0-azteca -# Move items from [Unreleased] to new release section -# Example: [1.0.0 - azteca] - 2026-01-22 -git add CHANGELOG.md -git commit -m "docs: prepare changelog for v1.0.0-azteca release" -git push origin release/1.0.0-azteca -# Open a PR, get it reviewed, and merge into master -``` - -#### 2. Create and Push Tag - -Then create and push the version tag: - -```bash -git tag -a v1.0.0-azteca -m "Release 1.0.0 - Azteca" -git push origin v1.0.0-azteca -``` - -#### 3. Automated CD Workflow - -This triggers the CD workflow which automatically: - -1. Validates the stadium name -2. Builds and tests the project in Release configuration -3. Publishes Docker images to GitHub Container Registry with three tags -4. Creates a GitHub Release with auto-generated changelog from commits - -> ๐Ÿ’ก Always update CHANGELOG.md before creating the tag. See [CHANGELOG.md](CHANGELOG.md#how-to-release) for detailed release instructions. - -### Pull Docker Images +### Pull Docker images Each release publishes multiple tags for flexibility: @@ -391,8 +239,6 @@ docker pull ghcr.io/nanotaboada/dotnet-samples-aspnetcore-webapi:azteca docker pull ghcr.io/nanotaboada/dotnet-samples-aspnetcore-webapi:latest ``` -> ๐Ÿ’ก See [CHANGELOG.md](CHANGELOG.md) for the complete stadium list (A-Z) and release history. - ## Environment Variables The application can be configured using environment variables for different scenarios: @@ -427,6 +273,29 @@ STORAGE_PATH=/storage/players-sqlite3.db > ๐Ÿ’ก Additional environment variables (`ASPNETCORE_ENVIRONMENT=Production` and `ASPNETCORE_URLS=http://+:9000`) are set in the `Dockerfile`. +## Contributing + +Contributions are welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on the code of conduct and the process for submitting pull requests. + +**Key guidelines:** + +- Follow [Conventional Commits](https://www.conventionalcommits.org/) for commit messages +- Ensure all tests pass (`dotnet test`) +- Keep changes small and focused +- Review [.github/copilot-instructions.md](.github/copilot-instructions.md) for architectural patterns + +**Testing:** + +Run the test suite with xUnit: + +```bash +# Run all tests +dotnet test + +# Run tests with coverage report +dotnet test --results-directory "coverage" --collect:"XPlat Code Coverage" --settings .runsettings +``` + ## Command Summary | Command | Description | @@ -443,17 +312,9 @@ STORAGE_PATH=/storage/players-sqlite3.db | `docker compose up` | Start Docker container | | `docker compose down` | Stop Docker container | | `docker compose down -v` | Stop and remove Docker volume | - -## Contributing - -Contributions are welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on the code of conduct and the process for submitting pull requests. - -**Key guidelines:** - -- Follow [Conventional Commits](https://www.conventionalcommits.org/) for commit messages -- Ensure all tests pass (`dotnet test`) -- Keep changes small and focused -- Review [.github/copilot-instructions.md](.github/copilot-instructions.md) for architectural patterns +| **AI Commands** | | +| `/pre-commit` | Runs linting, tests, and quality checks before committing | +| `/pre-release` | Runs pre-release validation workflow | ## Legal diff --git a/RELEASES.md b/RELEASES.md new file mode 100644 index 0000000..efa8391 --- /dev/null +++ b/RELEASES.md @@ -0,0 +1,63 @@ +# Releases + +Releases follow the pattern `v{SEMVER}-{STADIUM}` (e.g., `v1.0.0-azteca`). Codenames are drawn alphabetically from the [stadium list](CHANGELOG.md#stadium-release-names) of famous football stadiums that hosted FIFA World Cup matches. + +## Workflow + +### 1. Create a Release Branch + +Branch protection prevents direct pushes to `master`, so all release prep goes through a PR: + +```bash +git checkout master && git pull +git checkout -b release/v1.0.0-azteca +``` + +### 2. Update CHANGELOG.md + +Move items from `[Unreleased]` to a new release section in [CHANGELOG.md](CHANGELOG.md): + +```bash +# Move items from [Unreleased] to new release section +# Example: [1.0.0 - azteca] - 2026-01-22 +git add CHANGELOG.md +git commit -m "docs: prepare changelog for v1.0.0-azteca release" +git push origin release/v1.0.0-azteca +# Open a PR, get it reviewed, and merge into master +``` + +### 3. Create and Push Tag + +After the PR is merged, create and push the version tag from `master`: + +```bash +git checkout master && git pull +git tag -a v1.0.0-azteca -m "Release 1.0.0 - Azteca" +git push origin v1.0.0-azteca +``` + +### 4. Automated CD Workflow + +Pushing the tag triggers the CD workflow which automatically: + +1. Validates the stadium name +2. Builds and tests the project in Release configuration +3. Publishes Docker images to GitHub Container Registry with three tags +4. Creates a GitHub Release with auto-generated changelog from commits + +> ๐Ÿ’ก Always update CHANGELOG.md before creating the tag. See [CHANGELOG.md](CHANGELOG.md) for the complete stadium list (A-Z) and release history. + +## Docker Pull + +Each release publishes multiple tags for flexibility: + +```bash +# By semantic version (recommended for production) +docker pull ghcr.io/nanotaboada/dotnet-samples-aspnetcore-webapi:1.0.0 + +# By stadium name (memorable alternative) +docker pull ghcr.io/nanotaboada/dotnet-samples-aspnetcore-webapi:azteca + +# Latest release +docker pull ghcr.io/nanotaboada/dotnet-samples-aspnetcore-webapi:latest +``` From 50b31b4195081b7433782bce9b8d617ccf1a6217 Mon Sep 17 00:00:00 2001 From: Nano Taboada <87288+nanotaboada@users.noreply.github.com> Date: Sun, 5 Apr 2026 12:26:41 -0300 Subject: [PATCH 2/2] docs: fix arrow semantics and add pre-release checklist (#448) Co-Authored-By: Claude Sonnet 4.6 --- README.md | 2 +- RELEASES.md | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2193dfb..3746f3f 100644 --- a/README.md +++ b/README.md @@ -131,7 +131,7 @@ graph RL class AspNetCore,EFCore,MemoryCache feat; ``` -> *Arrows follow the injection direction (A โ†’ B means A depends on B). Solid = runtime dependency, dotted = structural. Blue = core domain, red = third-party, green = tests.* +> *Arrows follow the injection direction (A โ†’ B means A is injected into B). Solid = runtime dependency, dotted = structural. Blue = core domain, red = third-party, green = tests. Controllers call Services; Services call Repositories โ€” bypassing layers is not permitted.* > > *Significant design decisions are documented as ADRs in [`adr/`](adr/README.md).* diff --git a/RELEASES.md b/RELEASES.md index efa8391..86b14c6 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -26,6 +26,16 @@ git push origin release/v1.0.0-azteca # Open a PR, get it reviewed, and merge into master ``` +### Pre-release Checklist + +Before creating the tag, verify all of the following: + +- [ ] `CHANGELOG.md` `[Unreleased]` section is moved to a new versioned release entry +- [ ] `dotnet build --configuration Release` passes +- [ ] `dotnet test --settings .runsettings` passes +- [ ] Stadium name is valid and follows alphabetical order (see [stadium list](CHANGELOG.md#stadium-release-names)) +- [ ] All CI checks on `master` are green + ### 3. Create and Push Tag After the PR is merged, create and push the version tag from `master`: