|
| 1 | +# AGENTS.md |
| 2 | + |
| 3 | +> **⚡ Token Efficiency Note**: This file contains complete operational instructions (~2,500 tokens). |
| 4 | +> **Auto-loaded**: NO (load explicitly with `#file:AGENTS.md` when you need detailed procedures) |
| 5 | +> **When to load**: Complex workflows, troubleshooting, CI/CD setup, detailed architecture questions |
| 6 | +> **Related files**: See `#file:.github/copilot-instructions.md` for quick context (auto-loaded, ~500 tokens) |
| 7 | +
|
| 8 | +--- |
| 9 | + |
| 10 | +## Quick Start |
| 11 | + |
| 12 | +```bash |
| 13 | +# Install all dependencies |
| 14 | +pip install -r requirements.txt |
| 15 | +pip install -r requirements-lint.txt |
| 16 | +pip install -r requirements-test.txt |
| 17 | + |
| 18 | +# Start development server |
| 19 | +uvicorn main:app --reload --port 9000 |
| 20 | + |
| 21 | +# View API documentation |
| 22 | +# Open http://localhost:9000/docs in browser |
| 23 | +``` |
| 24 | + |
| 25 | +## Python Version |
| 26 | + |
| 27 | +This project requires **Python 3.13.3** (specified in `.python-version`). |
| 28 | + |
| 29 | +If using pyenv, asdf, or mise, the correct version activates automatically. Otherwise, ensure Python 3.13.3 is installed before running any commands. |
| 30 | + |
| 31 | +## Development Workflow |
| 32 | + |
| 33 | +### Running Tests |
| 34 | + |
| 35 | +```bash |
| 36 | +# Run all tests with verbose output |
| 37 | +pytest -v |
| 38 | + |
| 39 | +# Run tests with coverage report (matches CI) |
| 40 | +pytest --cov=./ --cov-report=xml --cov-report=term |
| 41 | + |
| 42 | +# Run specific test file |
| 43 | +pytest tests/test_main.py -v |
| 44 | + |
| 45 | +# Run specific test function |
| 46 | +pytest tests/test_main.py::test_health_check -v |
| 47 | +``` |
| 48 | + |
| 49 | +**Coverage requirement**: Tests must maintain coverage. The CI pipeline enforces this with `.coveragerc` configuration. |
| 50 | + |
| 51 | +### Code Quality |
| 52 | + |
| 53 | +```bash |
| 54 | +# Lint code (must pass before committing) |
| 55 | +flake8 . |
| 56 | + |
| 57 | +# Check code formatting (must pass before committing) |
| 58 | +black --check . |
| 59 | + |
| 60 | +# Auto-format code |
| 61 | +black . |
| 62 | +``` |
| 63 | + |
| 64 | +**Pre-commit checklist**: |
| 65 | +1. Run `flake8 .` - must pass with no errors |
| 66 | +2. Run `black --check .` - must pass with no formatting changes needed (or run `black .` to auto-fix) |
| 67 | +3. Run `pytest --cov=./ --cov-report=term` - all tests must pass |
| 68 | + |
| 69 | +**Style rules** (enforced by Black + Flake8): |
| 70 | +- Line length: 88 characters |
| 71 | +- Target: Python 3.13 |
| 72 | +- Black configuration in `pyproject.toml` |
| 73 | +- Flake8 configuration in `.flake8` |
| 74 | + |
| 75 | +### Database Management |
| 76 | + |
| 77 | +```bash |
| 78 | +# Database auto-initializes on first app startup via lifespan handler in main.py |
| 79 | +# Pre-seeded database ships in storage/players.db |
| 80 | + |
| 81 | +# To reset database to seed state (local development) |
| 82 | +rm storage/players.db |
| 83 | +# Next app startup will recreate from seed data |
| 84 | + |
| 85 | +# Docker: Reset database by removing volume |
| 86 | +docker compose down -v |
| 87 | +# Next startup will reinitialize from built-in seed |
| 88 | +``` |
| 89 | + |
| 90 | +**Important**: The database is SQLite stored in `storage/players.db`. It auto-seeds with football player data on first run. |
| 91 | + |
| 92 | +## Docker Workflow |
| 93 | + |
| 94 | +```bash |
| 95 | +# Build container image |
| 96 | +docker compose build |
| 97 | + |
| 98 | +# Start application in container |
| 99 | +docker compose up |
| 100 | + |
| 101 | +# Start in detached mode (background) |
| 102 | +docker compose up -d |
| 103 | + |
| 104 | +# View logs |
| 105 | +docker compose logs -f |
| 106 | + |
| 107 | +# Stop application |
| 108 | +docker compose down |
| 109 | + |
| 110 | +# Stop and remove database volume (full reset) |
| 111 | +docker compose down -v |
| 112 | + |
| 113 | +# Health check (when running) |
| 114 | +curl http://localhost:9000/health |
| 115 | +``` |
| 116 | + |
| 117 | +**First run behavior**: Container copies pre-seeded SQLite database into persistent volume. Subsequent runs reuse that volume to preserve data. |
| 118 | + |
| 119 | +## CI/CD Pipeline |
| 120 | + |
| 121 | +### Continuous Integration (python-ci.yml) |
| 122 | + |
| 123 | +**Trigger**: Push to `master` or PR to `master` |
| 124 | + |
| 125 | +**Jobs**: |
| 126 | +1. **Lint**: Commit messages (commitlint) → Flake8 → Black check |
| 127 | +2. **Test**: pytest with verbose output → coverage report generation |
| 128 | +3. **Coverage**: Upload to Codecov and Codacy (requires secrets) |
| 129 | + |
| 130 | +**Local validation** (run this before pushing): |
| 131 | +```bash |
| 132 | +# Matches CI exactly |
| 133 | +flake8 . && \ |
| 134 | +black --check . && \ |
| 135 | +pytest -v && \ |
| 136 | +pytest --cov=./ --cov-report=xml --cov-report=term |
| 137 | +``` |
| 138 | + |
| 139 | +### Continuous Deployment (python-cd.yml) |
| 140 | + |
| 141 | +**Trigger**: Version tags in format `v{MAJOR}.{MINOR}.{PATCH}-{COACH}` |
| 142 | + |
| 143 | +Example: |
| 144 | +```bash |
| 145 | +git tag -a v1.0.0-ancelotti -m "Release 1.0.0 - Ancelotti" |
| 146 | +git push origin v1.0.0-ancelotti |
| 147 | +``` |
| 148 | + |
| 149 | +**Pipeline automatically**: |
| 150 | +- Runs full test suite with coverage |
| 151 | +- Builds multi-stage Docker image |
| 152 | +- Pushes to GHCR with multiple tags (version, coach name, latest) |
| 153 | +- Generates changelog from commits |
| 154 | +- Creates GitHub Release with auto-generated notes |
| 155 | + |
| 156 | +**Coach naming convention**: Famous football coaches A-Z (see README.md for full list) |
| 157 | + |
| 158 | +## Project Architecture |
| 159 | + |
| 160 | +**Structure**: Layered architecture (Routes → Services → Database) |
| 161 | + |
| 162 | +``` |
| 163 | +routes/ # FastAPI endpoints with caching |
| 164 | + ├── player_route.py # CRUD endpoints |
| 165 | + └── health_route.py # Health check |
| 166 | +
|
| 167 | +services/ # Business logic layer |
| 168 | + └── player_service.py # Async database operations |
| 169 | +
|
| 170 | +databases/ # Database setup |
| 171 | + └── player_database.py # SQLAlchemy engine, session, Base |
| 172 | +
|
| 173 | +schemas/ # ORM models |
| 174 | + └── player_schema.py # Player table definition |
| 175 | +
|
| 176 | +models/ # API models |
| 177 | + └── player_model.py # Pydantic validation (camelCase) |
| 178 | +
|
| 179 | +tests/ # Test suite |
| 180 | + ├── conftest.py # Fixtures (TestClient) |
| 181 | + ├── test_main.py # Endpoint tests |
| 182 | + └── player_stub.py # Test data |
| 183 | +``` |
| 184 | + |
| 185 | +**Key patterns**: |
| 186 | +- Dependency injection: `AsyncSession` via `Depends(generate_async_session)` |
| 187 | +- Async everywhere: SQLAlchemy async, aiocache, FastAPI async endpoints |
| 188 | +- Pydantic validation: Request/response with camelCase aliasing |
| 189 | +- In-memory caching: aiocache on GET endpoints |
| 190 | +- Lifespan handler: DB initialization on app startup |
| 191 | + |
| 192 | +## Troubleshooting |
| 193 | + |
| 194 | +### Port already in use |
| 195 | +```bash |
| 196 | +# Kill process on port 9000 |
| 197 | +lsof -ti:9000 | xargs kill -9 |
| 198 | +``` |
| 199 | + |
| 200 | +### Module import errors |
| 201 | +```bash |
| 202 | +# Ensure all dependencies installed |
| 203 | +pip install -r requirements.txt -r requirements-lint.txt -r requirements-test.txt |
| 204 | + |
| 205 | +# Verify Python version |
| 206 | +python --version # Should be 3.13.3 |
| 207 | +``` |
| 208 | + |
| 209 | +### Database locked errors |
| 210 | +```bash |
| 211 | +# Stop all running instances |
| 212 | +pkill -f uvicorn |
| 213 | + |
| 214 | +# Reset database |
| 215 | +rm storage/players.db |
| 216 | +``` |
| 217 | + |
| 218 | +### Docker issues |
| 219 | +```bash |
| 220 | +# Clean slate |
| 221 | +docker compose down -v |
| 222 | +docker compose build --no-cache |
| 223 | +docker compose up |
| 224 | +``` |
| 225 | + |
| 226 | +## Testing the API |
| 227 | + |
| 228 | +### Using FastAPI Docs (Recommended) |
| 229 | +Open http://localhost:9000/docs - Interactive Swagger UI with "Try it out" buttons |
| 230 | + |
| 231 | +### Using Postman |
| 232 | +Pre-configured collection available in `postman_collections/` |
| 233 | + |
| 234 | +### Using curl |
| 235 | +```bash |
| 236 | +# Health check |
| 237 | +curl http://localhost:9000/health |
| 238 | + |
| 239 | +# Get all players |
| 240 | +curl http://localhost:9000/players |
| 241 | + |
| 242 | +# Get player by ID |
| 243 | +curl http://localhost:9000/players/1 |
| 244 | + |
| 245 | +# Create player |
| 246 | +curl -X POST http://localhost:9000/players \ |
| 247 | + -H "Content-Type: application/json" \ |
| 248 | + -d '{"firstName":"Pele","lastName":"Nascimento","club":"Santos","nationality":"Brazil","dateOfBirth":"1940-10-23"}' |
| 249 | + |
| 250 | +# Update player |
| 251 | +curl -X PUT http://localhost:9000/players/1 \ |
| 252 | + -H "Content-Type: application/json" \ |
| 253 | + -d '{"firstName":"Diego","lastName":"Maradona","club":"Napoli","nationality":"Argentina","dateOfBirth":"1960-10-30"}' |
| 254 | + |
| 255 | +# Delete player |
| 256 | +curl -X DELETE http://localhost:9000/players/1 |
| 257 | +``` |
| 258 | + |
| 259 | +## Important Notes |
| 260 | + |
| 261 | +- **Never commit secrets**: No API keys, tokens, or credentials in code |
| 262 | +- **Test coverage**: Maintain existing coverage levels (currently high) |
| 263 | +- **Commit messages**: Follow conventional commits (enforced by commitlint) |
| 264 | +- **Python version**: Must use 3.13.3 for consistency with CI/CD |
| 265 | +- **Dependencies**: Keep requirements files in sync with actual usage |
| 266 | +- **Database**: SQLite is for demo/development only - not production-ready |
0 commit comments