From 673c7a6158b60ea5f0f2defc4a208a42c903827a Mon Sep 17 00:00:00 2001 From: Nano Taboada <87288+nanotaboada@users.noreply.github.com> Date: Mon, 9 Mar 2026 09:22:01 -0300 Subject: [PATCH 1/3] chore(docs): add Claude config and update README architecture diagram Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .claude/settings.json | 3 + .github/copilot-instructions.md | 2 +- CLAUDE.md | 1 + README.md | 46 ++++----- scripts/count-tokens.sh | 165 -------------------------------- 5 files changed, 28 insertions(+), 189 deletions(-) create mode 100644 .claude/settings.json create mode 120000 CLAUDE.md delete mode 100755 scripts/count-tokens.sh diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..ad11d51 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,3 @@ +{ + "model": "claude-sonnet-4-6" +} diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 87919e9..a35a7aa 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,4 +1,4 @@ -# GitHub Copilot Instructions +# Custom Instructions ## Overview diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 0000000..02dd134 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +.github/copilot-instructions.md \ No newline at end of file diff --git a/README.md b/README.md index 2bdc472..f6bb7d3 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,10 @@ [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=nanotaboada_Dotnet.Samples.AspNetCore.WebApi&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=nanotaboada_Dotnet.Samples.AspNetCore.WebApi) [![codecov](https://codecov.io/gh/nanotaboada/Dotnet.Samples.AspNetCore.WebApi/graph/badge.svg?token=hgJc1rStJ9)](https://codecov.io/gh/nanotaboada/Dotnet.Samples.AspNetCore.WebApi) [![CodeFactor](https://www.codefactor.io/repository/github/nanotaboada/Dotnet.Samples.AspNetCore.WebApi/badge)](https://www.codefactor.io/repository/github/nanotaboada/Dotnet.Samples.AspNetCore.WebApi) -[![License: MIT](https://img.shields.io/badge/License-MIT-white.svg)](https://opensource.org/licenses/MIT) +[![License: MIT](https://img.shields.io/badge/License-MIT-3DA639.svg)](https://opensource.org/licenses/MIT) +![GitHub Copilot](https://img.shields.io/badge/GitHub_Copilot-contributing-8662C5?logo=githubcopilot&logoColor=white&labelColor=181818) +![Claude](https://img.shields.io/badge/Claude-Sonnet_4.6-D97757?logo=claude&logoColor=white&labelColor=181818) +![CodeRabbit Pull Request Reviews](https://img.shields.io/coderabbit/prs/github/nanotaboada/Dotnet.Samples.AspNetCore.WebApi?utm_source=oss&utm_medium=github&utm_campaign=nanotaboada%2FDotnet.Samples.AspNetCore.WebApi&link=https%3A%2F%2Fcoderabbit.ai&label=CodeRabbit+Reviews&labelColor=181818) 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. @@ -20,7 +23,7 @@ Proof of Concept for a RESTful API built with .NET 10 (LTS) and ASP.NET Core. Ma - [Prerequisites](#prerequisites) - [Quick Start](#quick-start) - [Testing](#testing) -- [Docker](#docker) +- [Containers](#containers) - [Releases](#releases) - [Environment Variables](#environment-variables) - [Command Summary](#command-summary) @@ -33,7 +36,7 @@ Proof of Concept for a RESTful API built with .NET 10 (LTS) and ASP.NET Core. Ma - ๐Ÿ“š **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** - AGENTS.md + auto-loaded Copilot instructions for AI-assisted development +- ๐Ÿ“– **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 @@ -95,6 +98,7 @@ test/Dotnet.Samples.AspNetCore.WebApi.Tests/ Dependencies flow from data layer through repositories and services to controllers. External dependencies (AutoMapper, FluentValidation, Serilog, Swashbuckle) integrate at their respective layers. ```mermaid + %%{init: { "theme": "default", "themeVariables": { @@ -105,43 +109,39 @@ Dependencies flow from data layer through repositories and services to controlle "clusterBorder": "#ddd" } }}%% -graph TB - %% Layer 1: Data - Data[Data] - %% Layer 2: Models - Models[Models] +graph RL - %% Layer 3: Repositories - Repositories[Repositories] + Models[Models] - %% Layer 4: Services subgraph Layer4[" "] + Data[Data] + Repositories[Repositories] + end + + subgraph Layer3[" "] Services[Services] Mappings[Mappings] AutoMapper[AutoMapper] MemoryCache[MemoryCache] end - %% Layer 5: Controllers - subgraph Layer5[" "] + subgraph Layer2[" "] Controllers[Controllers] Validators[Validators] FluentValidation[FluentValidation] Swashbuckle[Swashbuckle] end - %% Layer 6: Program - subgraph Layer6[" "] + subgraph Layer1[" "] Program[Program] Configurations[Configurations] Serilog[Serilog] end - %% Tests (separate) Tests[Tests] - %% Main Application Flow + %% Application flow Data --> Models Models --> Repositories Repositories --> Services @@ -164,8 +164,8 @@ graph TB MemoryCache --> Services %% Tests connections - Controllers -.-> Tests Services -.-> Tests + Controllers -.-> Tests %% Node styling with stroke-width classDef core fill:#b3d9ff,stroke:#6db1ff,stroke-width:2px,color:#555,font-family:monospace; @@ -191,7 +191,7 @@ Interactive API documentation is available via Swagger UI at `https://localhost: - `GET /players` - List all players - `GET /players/{id}` - Get player by ID (requires authentication) -- `GET /players/squad/{squadNumber}` - Get player by squad number +- `GET /players/{squadNumber}` - Get player by squad number - `POST /players` - Create new player - `PUT /players/{squadNumber}` - Update player - `DELETE /players/{squadNumber}` - Remove player @@ -252,7 +252,7 @@ reportgenerator -reports:coverage/**/coverage.cobertura.xml -targetdir:coverage Tests are located in the `test/` directory and use xUnit for unit testing. Coverage reports are generated for controllers and services only. -## Docker +## Containers This project includes full Docker support with multi-stage builds and Docker Compose for easy deployment. @@ -356,7 +356,7 @@ The application can be configured using environment variables for different scen ### Local Development (`.vscode/launch.json`) -For local debugging and development: +For local development and debugging: ```bash # ASP.NET Core environment mode @@ -372,9 +372,9 @@ ASPNETCORE_DETAILEDERRORS=1 ASPNETCORE_SHUTDOWNTIMEOUTSECONDS=3 ``` -### Docker Deployment (`compose.yaml`) +### Container Deployment (`compose.yaml`) -For containerized production deployment: +For production deployment: ```bash # Database storage path diff --git a/scripts/count-tokens.sh b/scripts/count-tokens.sh deleted file mode 100755 index bfacc85..0000000 --- a/scripts/count-tokens.sh +++ /dev/null @@ -1,165 +0,0 @@ -#!/bin/bash -# ๐Ÿ“Š Token Counter for Copilot Instruction Files -# Uses tiktoken (OpenAI's tokenizer) for accurate counting -# Approximation: ~0.75 words per token (English text) - -set -e - -echo "๐Ÿ“Š Token Analysis for Copilot Instructions" -echo "==========================================" -echo "" - -# Check if tiktoken is available -if command -v python3 &> /dev/null; then - # Try to use tiktoken for accurate counting - if python3 -c "import tiktoken" 2>/dev/null; then - echo "โœ… Using tiktoken (accurate Claude/GPT tokenization)" - echo "" - else - # tiktoken not found - offer to install - echo "โš ๏ธ tiktoken not installed" - echo "" - - # Detect non-interactive environment (CI/CD) - if [ ! -t 0 ] || [ -n "$CI" ] || [ -n "$CI_CD" ]; then - echo "๐Ÿค– Non-interactive environment detected (CI/CD)" - echo "๐Ÿ“ Using word-based approximation" - echo " (To auto-install in CI, set AUTO_INSTALL_TIKTOKEN=1)" - echo "" - USE_APPROX=1 - elif [ -n "$AUTO_INSTALL_TIKTOKEN" ]; then - echo "๐Ÿ“ฅ Installing tiktoken (AUTO_INSTALL_TIKTOKEN=1)..." - if pip3 install tiktoken --quiet; then - echo "โœ… tiktoken installed successfully!" - echo "" - # Re-run the script after installation - exec "$0" "$@" - else - echo "โŒ Installation failed. Using word-based approximation instead." - echo "" - USE_APPROX=1 - fi - else - echo "tiktoken provides accurate token counting for Claude/GPT models." - read -p "๐Ÿ“ฆ Install tiktoken now? (y/n): " -n 1 -r - echo "" - if [[ $REPLY =~ ^[Yy]$ ]]; then - echo "๐Ÿ“ฅ Installing tiktoken..." - if pip3 install tiktoken --quiet; then - echo "โœ… tiktoken installed successfully!" - echo "" - # Re-run the script after installation - exec "$0" "$@" - else - echo "โŒ Installation failed. Using word-based approximation instead." - echo "" - USE_APPROX=1 - fi - else - echo "๐Ÿ“ Using word-based approximation instead" - echo " (Install manually: pip3 install tiktoken)" - echo "" - USE_APPROX=1 - fi - fi - fi - - # Only run tiktoken if it's available and we didn't set USE_APPROX - if [ -z "$USE_APPROX" ] && python3 -c "import tiktoken" 2>/dev/null; then - - # Create temporary Python script - cat > /tmp/count_tokens.py << 'PYTHON' -import tiktoken -import sys - -# cl100k_base is used by GPT-4, Claude uses similar tokenization -encoding = tiktoken.get_encoding("cl100k_base") - -file_path = sys.argv[1] -with open(file_path, 'r', encoding='utf-8') as f: - content = f.read() - -tokens = encoding.encode(content) -print(len(tokens)) -PYTHON - - # Count tokens for each file - echo "๐Ÿ“„ .github/copilot-instructions.md" - if [ -f ".github/copilot-instructions.md" ]; then - COPILOT_TOKENS=$(python3 /tmp/count_tokens.py .github/copilot-instructions.md 2>&1 | grep -v "ERROR:root:code for hash" | tail -1) - echo " Tokens: $COPILOT_TOKENS" - else - echo " โš ๏ธ File not found, skipping" - COPILOT_TOKENS=0 - fi - echo "" - - echo "๐Ÿ“„ AGENTS.md" - if [ -f "AGENTS.md" ]; then - AGENTS_TOKENS=$(python3 /tmp/count_tokens.py AGENTS.md 2>&1 | grep -v "ERROR:root:code for hash" | tail -1) - echo " Tokens: $AGENTS_TOKENS" - else - echo " โš ๏ธ File not found, skipping" - AGENTS_TOKENS=0 - fi - echo "" - - # Calculate total - TOTAL=$((COPILOT_TOKENS + AGENTS_TOKENS)) - echo "๐Ÿ“Š Summary" - echo " Base load (auto): $COPILOT_TOKENS tokens" - echo " On-demand load: $AGENTS_TOKENS tokens" - echo " Total (if both): $TOTAL tokens" - echo "" - - # Check against target - TARGET=600 - LIMIT=650 - if [ $COPILOT_TOKENS -le $TARGET ]; then - echo "โœ… copilot-instructions.md within target ($TARGET tokens)" - elif [ $COPILOT_TOKENS -le $LIMIT ]; then - echo "โš ๏ธ copilot-instructions.md over target but within limit ($LIMIT tokens)" - else - echo "โŒ copilot-instructions.md exceeds limit! Optimization required." - fi - - # Calculate savings (guard against division by zero) - if [ $TOTAL -gt 0 ]; then - SAVINGS=$((AGENTS_TOKENS * 100 / TOTAL)) - echo "๐Ÿ’ก Savings: ${SAVINGS}% saved when AGENTS.md not needed" - else - echo "๐Ÿ’ก Savings: 0% (no tokens to count)" - fi - - # Cleanup - rm /tmp/count_tokens.py - fi -else - echo "โŒ Python3 not found" - echo " Python 3 is required for token counting" - echo " Install from: https://www.python.org/downloads/" - echo "" - exit 1 -fi - -# Fallback: word-based approximation -if [ -n "$USE_APPROX" ]; then - echo "๐Ÿ“„ .github/copilot-instructions.md" - WORDS=$(wc -w < .github/copilot-instructions.md | tr -d ' ') - APPROX_TOKENS=$((WORDS * 4 / 3)) - echo " Words: $WORDS" - echo " Approx tokens: $APPROX_TOKENS" - echo "" - - echo "๐Ÿ“„ AGENTS.md" - WORDS=$(wc -w < AGENTS.md | tr -d ' ') - APPROX_TOKENS=$((WORDS * 4 / 3)) - echo " Words: $WORDS" - echo " Approx tokens: $APPROX_TOKENS" - echo "" - - echo "๐Ÿ’ก Note: Run script again to install tiktoken for accurate counts" -fi - -echo "" -echo "==========================================" From 07b96214c923f86afba8a7c4b7ee874177917d2b Mon Sep 17 00:00:00 2001 From: Nano Taboada <87288+nanotaboada@users.noreply.github.com> Date: Mon, 9 Mar 2026 09:38:55 -0300 Subject: [PATCH 2/3] docs(readme): add route type constraints to disambiguate GET endpoints Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f6bb7d3..060fa3e 100644 --- a/README.md +++ b/README.md @@ -190,8 +190,8 @@ Interactive API documentation is available via Swagger UI at `https://localhost: **Quick Reference:** - `GET /players` - List all players -- `GET /players/{id}` - Get player by ID (requires authentication) -- `GET /players/{squadNumber}` - Get player by squad number +- `GET /players/{id:Guid}` - Get player by ID (requires authentication) +- `GET /players/{squadNumber:int}` - Get player by squad number - `POST /players` - Create new player - `PUT /players/{squadNumber}` - Update player - `DELETE /players/{squadNumber}` - Remove player From cbc0f0b9fe284f71e2baffd15733905e8cec78ec Mon Sep 17 00:00:00 2001 From: Nano Taboada <87288+nanotaboada@users.noreply.github.com> Date: Mon, 9 Mar 2026 09:40:18 -0300 Subject: [PATCH 3/3] fix(claude): replace symlink with @-prefixed import in CLAUDE.md Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- CLAUDE.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) mode change 120000 => 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 120000 index 02dd134..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1 +0,0 @@ -.github/copilot-instructions.md \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..a7e292c --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,3 @@ +# CLAUDE.md + +@.github/copilot-instructions.md