From d95af4ed902d387dba2427ce0c4097b96aeb7089 Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Sat, 14 Feb 2026 08:30:37 -0600 Subject: [PATCH 1/4] Optimize CLAUDE.md from 116 to 37 lines Remove boilerplate, directory tree listing, and discoverable architecture docs. Keep commands, key patterns, env vars, and important gotchas. Co-Authored-By: Claude Opus 4.6 --- CLAUDE.md | 128 ++++++++++-------------------------------------------- 1 file changed, 24 insertions(+), 104 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 542521c..72eaae6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,116 +1,36 @@ -# CLAUDE.md +# Major Domo Database API -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. +FastAPI backend serving SBA fantasy league data. Peewee ORM with PostgreSQL. -## Project Overview +## Commands -This is the Database API component of the Major Domo system - a FastAPI backend serving data for a Strat-o-Matic Baseball Association (SBA) fantasy league. It provides REST endpoints for Discord bots and web frontends to access league data. +```bash +docker-compose up # Start PostgreSQL + API + Adminer +docker-compose up --build # Rebuild and start +docker-compose --profile sync up sync-prod # One-time production data sync +python migrations.py # Run migrations (SQL files in migrations/) +``` -## Development Commands - -### Local Development -- **Dev server location**: `10.10.0.42` -- **Start all services**: `docker-compose up` (PostgreSQL + API + Adminer) -- **Build and start**: `docker-compose up --build` (rebuilds image with latest changes) -- **Sync from production**: `docker-compose --profile sync up sync-prod` (one-time production data sync) -- **Database migrations**: `python migrations.py` (uses files in root directory) -- **Database admin interface**: Available at `http://10.10.0.42:8080` (Adminer) - -### Docker Deployment -- **Production deployment**: Uses same `docker-compose up` workflow -- **Production server access**: `ssh akamai` then `cd container-data/sba-database` -- **Manual build**: `docker build -f Dockerfile -t major-domo-database .` +- **Dev server**: `10.10.0.42` | **Adminer**: `http://10.10.0.42:8080` +- **Production**: `ssh akamai` → `cd container-data/sba-database` ## Architecture -### Application Structure -``` -app/ -├── main.py # FastAPI application setup, router registration -├── db_engine.py # Peewee ORM models, database configuration -├── dependencies.py # Authentication, error handling decorators -└── routers_v3/ # API endpoints organized by domain - ├── awards.py # League awards and recognition endpoints - ├── battingstats.py # Batting statistics (seasonal and career) - ├── current.py # Current season/week status and configuration - ├── custom_commands.py # Custom command creation and management - ├── decisions.py # Strat-o-Matic game decisions and choices - ├── divisions.py # League division information - ├── draftdata.py # Draft status and current pick tracking - ├── draftlist.py # Team draft priority lists and rankings - ├── draftpicks.py # Draft pick ownership and trading - ├── fieldingstats.py # Fielding statistics (seasonal and career) - ├── injuries.py # Player injury tracking and management - ├── keepers.py # Keeper selection and management - ├── managers.py # Team manager information and profiles - ├── pitchingstats.py # Pitching statistics (seasonal and career) - ├── players.py # Player information, rosters, and statistics - ├── results.py # Game results and outcomes - ├── sbaplayers.py # SBA player pool and eligibility - ├── schedules.py # Game scheduling and matchups - ├── standings.py # League standings and team records - ├── stratgame.py # Strat-o-Matic game data and simulation - ├── stratplay.py # Individual play-by-play data and analysis - ├── teams.py # Team data, rosters, and organization - ├── transactions.py # Player transactions (trades, waivers, etc.) - └── views.py # Database views and aggregated statistics -``` - -### Database Configuration -- **Database**: PostgreSQL via `PooledPostgresqlDatabase` (production and development) -- **ORM**: Peewee with model-based schema definition -- **Migrations**: SQL migration files in `migrations/` directory -- **Table Naming**: Peewee models must specify `Meta.table_name` to match PostgreSQL table names - -### Authentication & Error Handling -- **Authentication**: OAuth2 bearer token validation via `API_TOKEN` environment variable -- **Error Handling**: `@handle_db_errors` decorator provides comprehensive logging, rollback, and HTTP error responses +- **Routers**: Domain-based in `app/routers_v3/` under `/api/v3/` prefix +- **ORM**: Peewee — always specify `Meta.table_name` to match PostgreSQL naming +- **Auth**: OAuth2 bearer token via `API_TOKEN` env var +- **Error handling**: `@handle_db_errors` decorator (logging, rollback, HTTP errors) +- **POST models**: Use `Optional[int] = None` for `id` fields (DB auto-generates) - **Logging**: Rotating file handler (`/tmp/sba-database.log`, 8MB max, 5 backups) -### API Design Patterns -- **Routers**: Domain-based organization under `/api/v3/` prefix -- **Models**: Pydantic models for request/response validation -- **Database Access**: Direct Peewee ORM queries with automatic connection pooling -- **Response Format**: Consistent JSON with proper HTTP status codes -- **POST Requests**: Pydantic models for POST (create) endpoints should use `Optional[int] = None` for `id` fields since the database auto-generates IDs +## Environment Variables -### Environment Variables -**Required**: -- `API_TOKEN` - Authentication token for API access +**Required**: `API_TOKEN`, `POSTGRES_HOST`, `POSTGRES_DB`, `POSTGRES_USER`, `POSTGRES_PASSWORD` +**Optional**: `POSTGRES_PORT` (5432), `LOG_LEVEL` (WARNING), `PRIVATE_IN_SCHEMA` -**PostgreSQL Configuration** (required): -- `POSTGRES_HOST` - PostgreSQL server hostname (default: 10.10.0.42) -- `POSTGRES_DB` - Database name (default: sba_master) -- `POSTGRES_USER` - Database user (default: sba_admin) -- `POSTGRES_PASSWORD` - Database password -- `POSTGRES_PORT` - Database port (default: 5432) +## Important -**Optional**: -- `LOG_LEVEL` - INFO or WARNING (defaults to WARNING) -- `PRIVATE_IN_SCHEMA` - Include private endpoints in OpenAPI schema - -### Key Data Models -- **Current**: Season/week status, trade deadlines, playoff schedule -- **Player/Team**: Core entities with seasonal and career statistics -- **Statistics**: Separate models for batting, pitching, fielding (seasonal + career) -- **Draft System**: Draft picks, draft lists, keeper selections -- **Game Data**: Schedules, results, Strat-o-Matic play-by-play data -- **League Management**: Standings, transactions, injuries, decisions -- **Custom Commands**: User-created Discord bot commands with creator tracking and usage statistics -- **Help Commands**: Static help text for Discord bot commands - -### Testing & Quality -- **No formal test framework currently configured** -- **API Documentation**: Auto-generated OpenAPI/Swagger at `/api/docs` -- **Health Checks**: Built into Docker configuration -- **Database Integrity**: Transaction rollback on errors via decorator - -## Important Notes - -- All active development occurs in the `/app` directory -- Root directory files (`main.py`, `db_engine.py`, etc.) are legacy and not in use -- **PostgreSQL migration completed**: System now uses PostgreSQL exclusively (no SQLite fallback) -- Database migrations are SQL files in `migrations/` directory, applied manually via psql -- Authentication is required for all endpoints except documentation and public read endpoints -- **Peewee Models**: Always specify `Meta.table_name` to match PostgreSQL naming conventions -- **Custom Commands**: Fully functional with creator tracking, usage statistics, and Discord bot integration \ No newline at end of file +- All active code is in `/app` — root-level `main.py`, `db_engine.py` are legacy, not in use +- PostgreSQL only (no SQLite fallback) +- Migrations are SQL files in `migrations/`, applied manually via psql +- API docs auto-generated at `/api/docs` From 2eab484ffbc8ef8aa81e1309499c9f6d77f1bfb1 Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Tue, 17 Feb 2026 15:13:49 -0600 Subject: [PATCH 2/4] chore: bump version to 2.7.0 Co-Authored-By: Claude Opus 4.6 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 6a6a3d8..24ba9a3 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.6.1 +2.7.0 From bcdde572e81610564221f9cb7e23d492bb56d82d Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Tue, 17 Feb 2026 15:22:33 -0600 Subject: [PATCH 3/4] docs: Add subdirectory CLAUDE.md files for routers, stratplay, and services Provide targeted context for each app subdirectory so Claude Code understands local patterns without relying on the root CLAUDE.md. Also simplifies root CLAUDE.md dev/prod environment sections. Co-Authored-By: Claude Opus 4.6 --- app/routers_v3/CLAUDE.md | 26 ++++++++++++++++++++++++++ app/routers_v3/stratplay/CLAUDE.md | 24 ++++++++++++++++++++++++ app/services/CLAUDE.md | 17 +++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 app/routers_v3/CLAUDE.md create mode 100644 app/routers_v3/stratplay/CLAUDE.md create mode 100644 app/services/CLAUDE.md diff --git a/app/routers_v3/CLAUDE.md b/app/routers_v3/CLAUDE.md new file mode 100644 index 0000000..be2e36e --- /dev/null +++ b/app/routers_v3/CLAUDE.md @@ -0,0 +1,26 @@ +# Routers (v3) + +Domain-based FastAPI routers under `/api/v3/` prefix. Each file = one resource. + +## Patterns + +- Every endpoint uses `@handle_db_errors` decorator (from `dependencies.py`) +- GET endpoints use `@cache_result(ttl=N, key_prefix="name")` for Redis caching +- Auth: `token: str = Depends(oauth2_scheme)` + `valid_token(token)` check on mutating endpoints +- Pydantic models for POST/PATCH bodies are defined inline in router files (not db_engine) +- POST models: `id` fields must be `Optional[int] = None` (DB auto-generates) + +## Two Styles Coexist + +- **Refactored** (players, teams): Thin HTTP layer → delegates to `services/` layer +- **Legacy** (most others): Business logic directly in router, imports models from `db_engine` + +## Adding a New Router + +1. Create `app/routers_v3/newrouter.py` with `router = APIRouter(prefix="/api/v3/name", tags=["name"])` +2. Import and register in `app/main.py`: `from .routers_v3 import newrouter` + `app.include_router(newrouter.router)` + +## IMPORTANT + +- PATCH endpoints: build update dict explicitly from parameters. Never use `locals()`. +- `stratplay/` is a sub-package with its own `__init__.py` and sub-routers (batting, pitching, fielding, plays, crud) diff --git a/app/routers_v3/stratplay/CLAUDE.md b/app/routers_v3/stratplay/CLAUDE.md new file mode 100644 index 0000000..e5bad1c --- /dev/null +++ b/app/routers_v3/stratplay/CLAUDE.md @@ -0,0 +1,24 @@ +# Stratplay Router (sub-package) + +Play-by-play data for Strat-o-Matic games. Mounted at `/api/v3/plays`. + +## Structure + +| File | Purpose | +|------|---------| +| `__init__.py` | Assembles sub-routers into parent `router` | +| `common.py` | Shared `build_season_games()` filter builder | +| `models.py` | Pydantic models (`PlayModel`, `POS_LIST` literal) | +| `plays.py` | General play queries | +| `batting.py` | Batting stats aggregated from plays | +| `pitching.py` | Pitching stats aggregated from plays | +| `fielding.py` | Fielding stats aggregated from plays | +| `crud.py` | POST/PATCH/DELETE operations (auth required) | + +## Key Patterns + +- All stat endpoints use `build_season_games()` from `common.py` for consistent filtering +- Filter params: `season`, `week`, `s_type` (regular/post), `week_start`/`week_end`, `manager_id` +- `week` and `s_type` are mutually exclusive; `week` and `week_start`/`week_end` are mutually exclusive +- Stats aggregate from `StratPlay` joined to `StratGame` via `game_id` +- CRUD writes trigger `update_season_batting_stats()` / `update_season_pitching_stats()` from `dependencies.py` diff --git a/app/services/CLAUDE.md b/app/services/CLAUDE.md new file mode 100644 index 0000000..256a4d1 --- /dev/null +++ b/app/services/CLAUDE.md @@ -0,0 +1,17 @@ +# Services Layer + +Business logic extracted from routers for testability. Uses dependency injection. + +## Architecture + +- `interfaces.py` — Protocol classes (`AbstractPlayerRepository`, `AbstractTeamRepository`, `AbstractCacheService`) +- `base.py` — `BaseService` with lazy-loaded default repos (imports from `db_engine` on first access) +- `mocks.py` — Mock implementations for testing without DB/Redis +- `player_service.py`, `team_service.py` — Domain services (class methods, no instance needed for reads) + +## Key Patterns + +- Services use `@staticmethod`/`@classmethod` for read operations (no instantiation needed) +- Default repos are created lazily inside `@property` methods to avoid circular imports with `db_engine` +- For testing: pass mock repos via `ServiceConfig` or constructor kwargs +- Only `players` and `teams` routers currently use the service layer; others call `db_engine` directly From 49911c53ac6976d899bac8dff788a4cb41d9314a Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Tue, 17 Feb 2026 16:29:38 -0600 Subject: [PATCH 4/4] ci: Switch to CalVer (YYYY.MM.BUILD) with auto-generated versions Remove manual semver validation from PR checks. Versions are now auto-generated on merge to main by counting existing monthly tags. Co-Authored-By: Claude Opus 4.6 --- .gitea/workflows/docker-build.yml | 286 +++++++----------------------- CLAUDE.md | 2 + 2 files changed, 62 insertions(+), 226 deletions(-) diff --git a/.gitea/workflows/docker-build.yml b/.gitea/workflows/docker-build.yml index 0e5043b..d70b544 100644 --- a/.gitea/workflows/docker-build.yml +++ b/.gitea/workflows/docker-build.yml @@ -1,13 +1,10 @@ -# Gitea Actions: Major Domo Database - Docker Build, Push, and Notify +# Gitea Actions: Docker Build, Push, and Notify # -# This workflow provides a complete CI/CD pipeline for the Major Domo Database API: -# - Validates semantic versioning on PRs +# CI/CD pipeline for Major Domo Database API: # - Builds Docker images on every push/PR -# - Pushes to Docker Hub on main branch merges +# - Auto-generates CalVer version (YYYY.MM.BUILD) on main branch merges +# - Pushes to Docker Hub and creates git tag on main # - Sends Discord notifications on success/failure -# -# Created: 2026-02-04 -# Adapted from: paper-dynasty-database template name: Build Docker Image @@ -24,192 +21,91 @@ jobs: runs-on: ubuntu-latest steps: - # ============================================== - # 1. CHECKOUT CODE - # ============================================== - name: Checkout code uses: actions/checkout@v4 + with: + fetch-depth: 0 # Full history for tag counting - # ============================================== - # 2. SEMANTIC VERSION VALIDATION (PRs only) - # ============================================== - # Enforces proper semantic versioning: - # - Blocks PRs that don't bump VERSION file - # - Validates version changes follow semver rules - # - Prevents skipping versions or going backwards - # - # Valid bumps: - # - Patch: 2.4.1 → 2.4.2 (bug fixes) - # - Minor: 2.4.1 → 2.5.0 (new features) - # - Major: 2.4.1 → 3.0.0 (breaking changes) - # - # Invalid bumps: - # - 2.4.1 → 2.6.0 (skipped minor version) - # - 2.4.1 → 2.3.0 (went backwards) - # - 2.4.1 → 2.5.1 (didn't reset patch) - # - - name: Check VERSION was bumped (semantic versioning) - if: github.event_name == 'pull_request' - run: | - # Get VERSION from this PR branch - PR_VERSION=$(cat VERSION 2>/dev/null || echo "0.0.0") - - # Get VERSION from main branch - git fetch origin main:main - MAIN_VERSION=$(git show main:VERSION 2>/dev/null || echo "0.0.0") - - echo "📋 Semantic Version Check" - echo "Main branch version: $MAIN_VERSION" - echo "PR branch version: $PR_VERSION" - echo "" - - # Parse versions into components - IFS='.' read -r MAIN_MAJOR MAIN_MINOR MAIN_PATCH <<< "$MAIN_VERSION" - IFS='.' read -r PR_MAJOR PR_MINOR PR_PATCH <<< "$PR_VERSION" - - # Remove any non-numeric characters - MAIN_MAJOR=${MAIN_MAJOR//[!0-9]/} - MAIN_MINOR=${MAIN_MINOR//[!0-9]/} - MAIN_PATCH=${MAIN_PATCH//[!0-9]/} - PR_MAJOR=${PR_MAJOR//[!0-9]/} - PR_MINOR=${PR_MINOR//[!0-9]/} - PR_PATCH=${PR_PATCH//[!0-9]/} - - # Check if VERSION unchanged - if [ "$PR_VERSION" = "$MAIN_VERSION" ]; then - echo "❌ ERROR: VERSION file has not been updated!" - echo "" - echo "Please update the VERSION file in your PR." - echo "Current version: $MAIN_VERSION" - exit 1 - fi - - # Validate semantic version bump - VALID=false - BUMP_TYPE="" - - # Check for major version bump (X.0.0) - if [ "$PR_MAJOR" -eq $((MAIN_MAJOR + 1)) ] && [ "$PR_MINOR" -eq 0 ] && [ "$PR_PATCH" -eq 0 ]; then - VALID=true - BUMP_TYPE="major" - # Check for minor version bump (x.X.0) - elif [ "$PR_MAJOR" -eq "$MAIN_MAJOR" ] && [ "$PR_MINOR" -eq $((MAIN_MINOR + 1)) ] && [ "$PR_PATCH" -eq 0 ]; then - VALID=true - BUMP_TYPE="minor" - # Check for patch version bump (x.x.X) - elif [ "$PR_MAJOR" -eq "$MAIN_MAJOR" ] && [ "$PR_MINOR" -eq "$MAIN_MINOR" ] && [ "$PR_PATCH" -eq $((MAIN_PATCH + 1)) ]; then - VALID=true - BUMP_TYPE="patch" - fi - - if [ "$VALID" = true ]; then - echo "✅ Valid $BUMP_TYPE version bump: $MAIN_VERSION → $PR_VERSION" - else - echo "❌ ERROR: Invalid semantic version change!" - echo "" - echo "Current version: $MAIN_VERSION" - echo "PR version: $PR_VERSION" - echo "" - echo "Valid version bumps:" - echo " - Patch: $MAIN_MAJOR.$MAIN_MINOR.$((MAIN_PATCH + 1))" - echo " - Minor: $MAIN_MAJOR.$((MAIN_MINOR + 1)).0" - echo " - Major: $((MAIN_MAJOR + 1)).0.0" - echo "" - echo "Common issues:" - echo " ❌ Skipping versions (e.g., 2.5.0 → 2.7.0)" - echo " ❌ Going backwards (e.g., 2.5.0 → 2.4.0)" - echo " ❌ Not resetting lower components (e.g., 2.5.0 → 2.6.1)" - exit 1 - fi - - # ============================================== - # 3. DOCKER BUILDX SETUP - # ============================================== - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - # ============================================== - # 4. DOCKER HUB LOGIN (main branch only) - # ============================================== - # Requires secrets in Gitea: - # - DOCKERHUB_USERNAME: Your Docker Hub username (manticorum67) - # - DOCKERHUB_TOKEN: Docker Hub access token (not password!) - # - # To create token: - # 1. Go to hub.docker.com - # 2. Account Settings → Security → New Access Token - # 3. Copy token to Gitea repo → Settings → Secrets → Actions - # - name: Login to Docker Hub - if: github.ref == 'refs/heads/main' uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - # ============================================== - # 5. EXTRACT METADATA - # ============================================== - # Reads VERSION file and generates image tags: - # - version: From VERSION file (e.g., "2.4.1") - # - sha_short: First 7 chars of commit SHA - # - version_sha: Combined version+commit (e.g., "v2.4.1-a1b2c3d") - # - branch: Current branch name - # - timestamp: ISO 8601 format for Discord - # - - name: Extract metadata + # Generate CalVer: YYYY.MM.BUILD + # BUILD = count of tags matching current month + 1 + - name: Generate CalVer version id: meta run: | - VERSION=$(cat VERSION 2>/dev/null || echo "0.0.0") + YEAR=$(date -u +%Y) + MONTH=$(date -u +%-m) + PREFIX="${YEAR}.${MONTH}." + + # Count existing tags for this month + git fetch --tags + BUILD=$(git tag -l "${PREFIX}*" | wc -l) + BUILD=$((BUILD + 1)) + + VERSION="${PREFIX}${BUILD}" SHA_SHORT=$(echo ${{ github.sha }} | cut -c1-7) + echo "version=${VERSION}" >> $GITHUB_OUTPUT echo "sha_short=${SHA_SHORT}" >> $GITHUB_OUTPUT - echo "version_sha=v${VERSION}-${SHA_SHORT}" >> $GITHUB_OUTPUT + echo "version_sha=${VERSION}-${SHA_SHORT}" >> $GITHUB_OUTPUT echo "branch=${{ github.ref_name }}" >> $GITHUB_OUTPUT echo "timestamp=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT - # ============================================== - # 6. BUILD AND PUSH DOCKER IMAGE - # ============================================== - # Creates 3 tags for each build: - # - latest: Always points to newest build - # - v{VERSION}: Semantic version from VERSION file - # - v{VERSION}-{COMMIT}: Version + commit hash for traceability - # - # Example tags: - # - manticorum67/major-domo-database:latest - # - manticorum67/major-domo-database:v2.4.1 - # - manticorum67/major-domo-database:v2.4.1-a1b2c3d - # - # Push behavior: - # - PRs: Build only (test), don't push - # - Main: Build and push to Docker Hub - # - - name: Build Docker image + echo "CalVer version: ${VERSION}" + + # Dev build: push with dev + dev-SHA tags (PR/feature branches) + - name: Build Docker image (dev) + if: github.ref != 'refs/heads/main' uses: docker/build-push-action@v5 with: context: . - push: ${{ github.ref == 'refs/heads/main' }} + push: true + tags: | + manticorum67/major-domo-database:dev + manticorum67/major-domo-database:dev-${{ steps.meta.outputs.sha_short }} + cache-from: type=registry,ref=manticorum67/major-domo-database:buildcache + cache-to: type=registry,ref=manticorum67/major-domo-database:buildcache,mode=max + + # Production build: push with latest + CalVer tags (main only) + - name: Build Docker image (production) + if: github.ref == 'refs/heads/main' + uses: docker/build-push-action@v5 + with: + context: . + push: true tags: | manticorum67/major-domo-database:latest - manticorum67/major-domo-database:v${{ steps.meta.outputs.version }} + manticorum67/major-domo-database:${{ steps.meta.outputs.version }} manticorum67/major-domo-database:${{ steps.meta.outputs.version_sha }} cache-from: type=registry,ref=manticorum67/major-domo-database:buildcache cache-to: type=registry,ref=manticorum67/major-domo-database:buildcache,mode=max - # ============================================== - # 7. BUILD SUMMARY - # ============================================== - # Creates a formatted summary visible in Actions UI - # Shows: image tags, build details, push status - # + # Create git tag and update VERSION file on successful push + - name: Tag release + if: success() && github.ref == 'refs/heads/main' + run: | + git config user.name "Gitea Actions" + git config user.email "actions@git.manticorum.com" + echo "${{ steps.meta.outputs.version }}" > VERSION + git add VERSION + git commit -m "chore: bump version to ${{ steps.meta.outputs.version }} [skip ci]" || true + git tag "${{ steps.meta.outputs.version }}" + git push origin main --tags + - name: Build Summary run: | - echo "## 🐳 Docker Build Successful! ✅" >> $GITHUB_STEP_SUMMARY + echo "## Docker Build Successful" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Image Tags:**" >> $GITHUB_STEP_SUMMARY echo "- \`manticorum67/major-domo-database:latest\`" >> $GITHUB_STEP_SUMMARY - echo "- \`manticorum67/major-domo-database:v${{ steps.meta.outputs.version }}\`" >> $GITHUB_STEP_SUMMARY + echo "- \`manticorum67/major-domo-database:${{ steps.meta.outputs.version }}\`" >> $GITHUB_STEP_SUMMARY echo "- \`manticorum67/major-domo-database:${{ steps.meta.outputs.version_sha }}\`" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Build Details:**" >> $GITHUB_STEP_SUMMARY @@ -218,39 +114,26 @@ jobs: echo "- Timestamp: \`${{ steps.meta.outputs.timestamp }}\`" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY if [ "${{ github.ref }}" == "refs/heads/main" ]; then - echo "🚀 **Pushed to Docker Hub!**" >> $GITHUB_STEP_SUMMARY + echo "Pushed to Docker Hub!" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "Pull with: \`docker pull manticorum67/major-domo-database:latest\`" >> $GITHUB_STEP_SUMMARY else echo "_PR build - image not pushed to Docker Hub_" >> $GITHUB_STEP_SUMMARY fi - # ============================================== - # 8. DISCORD NOTIFICATION - SUCCESS - # ============================================== - # Sends green embed to Discord on successful builds - # - # Only fires on main branch pushes (not PRs) - # - # Setup: - # 1. Create webhook in Discord channel: - # Right-click channel → Edit → Integrations → Webhooks → New - # 2. Copy webhook URL - # 3. Add as secret: DISCORD_WEBHOOK_URL in Gitea repo settings - # - name: Discord Notification - Success if: success() && github.ref == 'refs/heads/main' run: | curl -H "Content-Type: application/json" \ -d '{ "embeds": [{ - "title": "✅ Major Domo Database Build Successful", - "description": "Docker image built and pushed to Docker Hub!", + "title": "Major Domo Database - Build Successful", + "description": "Docker image built and pushed to Docker Hub", "color": 3066993, "fields": [ { "name": "Version", - "value": "`v${{ steps.meta.outputs.version }}`", + "value": "`${{ steps.meta.outputs.version }}`", "inline": true }, { @@ -258,11 +141,6 @@ jobs: "value": "`${{ steps.meta.outputs.version_sha }}`", "inline": true }, - { - "name": "Branch", - "value": "`${{ steps.meta.outputs.branch }}`", - "inline": true - }, { "name": "Commit", "value": "`${{ steps.meta.outputs.sha_short }}`", @@ -273,11 +151,6 @@ jobs: "value": "${{ github.actor }}", "inline": true }, - { - "name": "Docker Hub", - "value": "[manticorum67/major-domo-database](https://hub.docker.com/r/manticorum67/major-domo-database)", - "inline": false - }, { "name": "View Run", "value": "[Click here](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})", @@ -289,13 +162,6 @@ jobs: }' \ ${{ secrets.DISCORD_WEBHOOK_URL }} - # ============================================== - # 9. DISCORD NOTIFICATION - FAILURE - # ============================================== - # Sends red embed to Discord on build failures - # - # Only fires on main branch pushes (not PRs) - # - name: Discord Notification - Failure if: failure() && github.ref == 'refs/heads/main' run: | @@ -303,7 +169,7 @@ jobs: curl -H "Content-Type: application/json" \ -d '{ "embeds": [{ - "title": "❌ Major Domo Database Build Failed", + "title": "Major Domo Database - Build Failed", "description": "Docker build encountered an error.", "color": 15158332, "fields": [ @@ -332,35 +198,3 @@ jobs: }] }' \ ${{ secrets.DISCORD_WEBHOOK_URL }} - -# ============================================== -# SETUP REQUIRED -# ============================================== -# Before this workflow will work: -# -# ✅ Add secrets to Gitea repo (Settings → Secrets → Actions): -# - DOCKERHUB_USERNAME: manticorum67 -# - DOCKERHUB_TOKEN: Docker Hub access token -# - DISCORD_WEBHOOK_URL: Discord webhook for build notifications -# -# ✅ Ensure VERSION file exists in repo root (currently: 2.4.1) -# -# ============================================== -# TROUBLESHOOTING -# ============================================== -# Common issues and solutions: -# -# 1. VERSION validation failing unexpectedly -# - Ensure VERSION file contains only version number (no 'v' prefix) -# - Verify version follows semver: MAJOR.MINOR.PATCH -# -# 2. Docker Hub push failing -# - Verify DOCKERHUB_USERNAME and DOCKERHUB_TOKEN secrets are set -# - Check Docker Hub token has push permissions -# -# 3. Discord notifications not appearing -# - Test webhook URL manually with curl -# - Check webhook still exists in Discord channel settings -# - Look for HTTP error codes in Actions logs -# -# ============================================== diff --git a/CLAUDE.md b/CLAUDE.md index 72eaae6..3a5a653 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -28,6 +28,8 @@ python migrations.py # Run migrations (SQL files in migrat **Required**: `API_TOKEN`, `POSTGRES_HOST`, `POSTGRES_DB`, `POSTGRES_USER`, `POSTGRES_PASSWORD` **Optional**: `POSTGRES_PORT` (5432), `LOG_LEVEL` (WARNING), `PRIVATE_IN_SCHEMA` +- **CI/CD**: Gitea Actions on PR to `main` — builds Docker image, auto-generates CalVer version (`YYYY.MM.BUILD`) on merge + ## Important - All active code is in `/app` — root-level `main.py`, `db_engine.py` are legacy, not in use