From 501e1b7e237b7a7ce59e3099f07f085119ffaab3 Mon Sep 17 00:00:00 2001 From: David Gwilliam Date: Wed, 1 Apr 2026 05:03:14 +0000 Subject: [PATCH] fix: version bumping and Docker registry authentication (#17) ## Summary This PR fixes the release workflow to properly handle version bumping on PR merge and uses the new Docker registry authentication secrets. ## Changes ### Release Workflow (release.yml) - **Version Bumping**: Now automatically bumps version on PR merge - Determines bump type from commit messages (major/minor/patch) - Commits version bump to `package.json` and `CHANGELOG.md` - Creates git tag for the release - **Docker Registry Auth**: Uses `DOCKER_LOGIN` and `DOCKER_PASSWORD` secrets - Falls back gracefully if secrets are not configured - **Tag Handling**: Checks if tag exists before creating (prevents failures) ### PR Workflow (pr.yml) - NEW - Runs unit tests on every PR - Analyzes commits to suggest bump type - Comments the suggested bump type on the PR ### Documentation - Added `WORKFLOW_ARCHITECTURE.md` explaining the workflow design ## Workflow Architecture **Two-step process:** 1. **PR Workflow** (on PR): Analyzes commits and suggests bump type 2. **Release Workflow** (on merge): Bumps version, creates tag, builds Docker image ## Benefits 1. **No CI Loops**: Version bump commits are detected and skipped 2. **Clear Communication**: PR comments inform developers of version impact 3. **Semantic Versioning**: Automated adherence to semver rules 4. **Traceability**: Git tags and changelog reflect all changes ## Testing The new workflows will be tested when this PR is merged. Closes #13 (Add database test safety configuration) Reviewed-on: https://git.notsosm.art/david/euchre_camp/pulls/17 Co-authored-by: David Gwilliam Co-committed-by: David Gwilliam --- .gitea/WORKFLOW_ARCHITECTURE.md | 167 ++++++++++++++ .gitea/workflows/pr.yml | 129 +++++++++++ .gitea/workflows/release.yml | 114 +++++++--- .gitea/workflows/test.yml | 44 +--- AGENTS.md | 44 ++++ CHANGELOG.md | 19 ++ README.md | 90 +++++++- TODO.md | 102 --------- docs/FILE_ORGANIZATION.md | 125 +++++++++++ docs/TODO.md | 204 ++++++++---------- .../deployment/CASAOS_DEPLOYMENT.md | 0 DOCKER.md => docs/deployment/DOCKER.md | 0 justfile | 110 +++++++++- package.json | 2 +- scripts/bump-version.js | 1 + .../python/generate_games.py | 0 .../python/update_partnership_stats.py | 0 .../python/update_player_stats.py | 0 scripts/run-tests-in-container.sh | 15 ++ src/lib/prisma.ts | 21 +- 20 files changed, 884 insertions(+), 303 deletions(-) create mode 100644 .gitea/WORKFLOW_ARCHITECTURE.md create mode 100644 .gitea/workflows/pr.yml delete mode 100644 TODO.md create mode 100644 docs/FILE_ORGANIZATION.md rename CASAOS_DEPLOYMENT.md => docs/deployment/CASAOS_DEPLOYMENT.md (100%) rename DOCKER.md => docs/deployment/DOCKER.md (100%) rename generate_games.py => scripts/python/generate_games.py (100%) rename update_partnership_stats.py => scripts/python/update_partnership_stats.py (100%) rename update_player_stats.py => scripts/python/update_player_stats.py (100%) create mode 100755 scripts/run-tests-in-container.sh diff --git a/.gitea/WORKFLOW_ARCHITECTURE.md b/.gitea/WORKFLOW_ARCHITECTURE.md new file mode 100644 index 0000000..3cdaff6 --- /dev/null +++ b/.gitea/WORKFLOW_ARCHITECTURE.md @@ -0,0 +1,167 @@ +# Gitea Actions Workflow Architecture + +This document describes the workflow architecture for version bumping, testing, and releases. + +## Overview + +The workflow architecture uses a three-step process: +1. **PR Workflow**: Runs tests on PRs and analyzes commits for bump type +2. **Test Workflow**: Runs unit tests on all branch pushes (except version bumps) +3. **Release Workflow**: Bumps version, creates tags, builds Docker images, and deploys on main branch pushes + +## Workflow Files + +### 1. `.gitea/workflows/pr.yml` (Pull Request Workflow) + +**Trigger**: Pull requests to `main` branch + +**Purpose**: +- Run unit tests on every PR (fast feedback) +- Run acceptance tests with SQLite database +- Analyze commits to determine bump type (major/minor/patch) +- Comment the suggested bump type on the PR + +**Test Execution**: +- **Unit Tests**: Run first, fast execution +- **Acceptance Tests**: Run after unit tests pass, uses SQLite database +- **Database**: SQLite with `DATABASE_URL=file:./prisma/ci.db` +- **Secrets**: Uses `BETTER_AUTH_SECRET` for authentication + +**Bump Type Detection**: +- **Major**: Breaking changes detected (`BREAKING CHANGE` or `!:` in commit messages) +- **Minor**: Feature commits detected (`feat:` prefix) +- **Patch**: Default for fixes and other changes + +### 2. `.gitea/workflows/test.yml` (Test Workflow) + +**Trigger**: Pushes to any branch (including main) + +**Purpose**: +- Run unit tests on all branch pushes +- Skip auto-generated version bump commits (handled by release workflow) + +**Key Features**: +- Runs on all branches including main +- Skips commits with "chore: bump version" message +- Fast execution for quick feedback + +### 3. `.gitea/workflows/release.yml` (Release Workflow) + +**Trigger**: Pushes to `main` branch (after PR merge) + +**Purpose**: +- Determine bump type from merge commit or PR commits +- Bump version in `package.json` and `CHANGELOG.md` +- Commit the version bump +- Create git tag for the release +- Run tests inside Docker container (with PostgreSQL) +- Build production Docker image +- Push images to registry +- Deploy to dev environment + +**Key Features**: +- Skips commits that are auto-generated version bumps +- Uses `DOCKER_LOGIN` and `DOCKER_PASSWORD` secrets for registry auth +- Handles existing git tags gracefully +- Runs comprehensive tests in production-like environment + +## Version Bump Logic + +### Step 1: PR Analysis (pr.yml) +When a PR is opened or updated: +1. Fetch the merge base with `main` +2. Analyze all commits in the PR +3. Determine bump type based on commit messages: + - Breaking changes → major + - Features → minor + - Fixes → patch +4. Comment the suggested bump type on the PR + +### Step 2: Release (release.yml) +When a PR is merged to `main`: +1. Check if the commit is an auto-bump (skip if so) +2. Analyze the merge commit message or PR commits +3. Run `node scripts/bump-version.js --yes` +4. Commit the version bump changes +5. Create and push git tag +6. Build and push Docker images + +## Environment Variables & Secrets + +### Required Secrets +- `DOCKER_LOGIN`: Username for Docker registry authentication +- `DOCKER_PASSWORD`: Password for Docker registry authentication +- `GITEA_TOKEN` (optional): For pushing back to repo (if needed) + +### Environment Variables +- `REGISTRY`: Docker registry URL (default: `docker.notsosm.art`) +- `IMAGE_NAME`: Docker image name (default: `euchre-camp`) + +## Example Workflow + +### Scenario: Feature PR +1. Developer opens PR with commits: + - "feat: add new feature" + - "fix: resolve edge case" +2. PR workflow runs: + - Unit tests pass + - Bump type analysis suggests "minor" + - Comment posted on PR: "Suggested bump: MINOR" +3. Developer merges PR +4. Release workflow runs: + - Detects minor bump from commits + - Bumps version from 0.1.1 → 0.2.0 + - Commits version bump + - Creates tag v0.2.0 + - Builds and pushes Docker image + - Deploys to dev + +### Scenario: Breaking Change PR +1. Developer opens PR with commit: + - "feat!: breaking API change" +2. PR workflow runs: + - Detects breaking change marker + - Suggests "major" bump + - Comments on PR +3. Developer merges PR +4. Release workflow runs: + - Detects major bump + - Bumps version from 0.1.1 → 1.0.0 + - Creates tag v1.0.0 + - Proceeds with build and deploy + +## Database Configuration for CI + +### SQLite for CI Acceptance Tests +- **Why SQLite**: No database server required, perfect for CI environments +- **Usage**: PR workflow runs acceptance tests with SQLite database +- **Configuration**: `DATABASE_PROVIDER=sqlite`, `DATABASE_URL=file:./prisma/ci.db` +- **Benefits**: Fast, isolated, no external dependencies + +### PostgreSQL for Production +- **Usage**: Release workflow runs tests in Docker with PostgreSQL +- **Configuration**: Uses dummy PostgreSQL URL for Docker builds +- **Benefits**: Production-like environment, catches PostgreSQL-specific issues + +### Database Provider Detection +The application automatically detects the database provider: +- `DATABASE_PROVIDER` environment variable (defaults to `sqlite`) +- `prisma.ts` conditionally uses PrismaPg adapter for PostgreSQL +- Better Auth configured with appropriate provider + +## Benefits + +1. **No CI Loops**: Version bump commits are detected and skipped +2. **Clear Communication**: PR comments inform developers of impact +3. **Semantic Versioning**: Automated adherence to semver rules +4. **Traceability**: Git tags and changelog reflect all changes +5. **Safe Releases**: Tests run before version bump and deployment +6. **Fast CI**: SQLite tests run quickly without database server setup +7. **Comprehensive Testing**: Both unit and acceptance tests in PR workflow + +## Future Enhancements + +- Add GitHub/Gitea Release creation +- Slack/Discord notifications on release +- Automatic rollback on test failure +- Multi-environment deployment (dev/staging/prod) diff --git a/.gitea/workflows/pr.yml b/.gitea/workflows/pr.yml new file mode 100644 index 0000000..9a2660d --- /dev/null +++ b/.gitea/workflows/pr.yml @@ -0,0 +1,129 @@ +name: Pull Request + +on: + pull_request: + branches: + - main + +jobs: + unit-tests: + runs-on: ubuntu-latest + container: + image: node:20-alpine + options: --user root + + steps: + - name: Install system dependencies + run: | + apk add --no-cache bash git + + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install dependencies + run: npm ci + + - name: Run unit tests + run: npm run test:run + + acceptance-tests: + runs-on: ubuntu-latest + needs: unit-tests + container: + image: node:20-alpine + options: --user root + env: + DATABASE_PROVIDER: sqlite + DATABASE_URL: file:./prisma/ci.db + BETTER_AUTH_SECRET: test-secret-key-for-ci-only + + steps: + - name: Install system dependencies + run: | + apk add --no-cache bash git + + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install dependencies + run: npm ci + + - name: Generate Prisma client + run: npx prisma generate + + - name: Setup SQLite database + run: | + # Create SQLite database file + mkdir -p prisma + npx prisma migrate deploy + + - name: Run acceptance tests + run: npm run test:acceptance + env: + DATABASE_PROVIDER: sqlite + DATABASE_URL: file:./prisma/ci.db + BETTER_AUTH_SECRET: test-secret-key-for-ci-only + + analyze-bump-type: + runs-on: ubuntu-latest + needs: acceptance-tests + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Analyze commits for bump type + id: bump_type + run: | + # Get the merge base and PR commits + git fetch origin main:main 2>/dev/null || true + MERGE_BASE=$(git merge-base HEAD main 2>/dev/null || echo "HEAD~1") + + # Analyze commits in this PR + COMMITS=$(git log --oneline ${MERGE_BASE}..HEAD 2>/dev/null || git log --oneline -10) + + echo "Commits in this PR:" + echo "$COMMITS" + echo "" + + # Determine bump type + if echo "$COMMITS" | grep -qE "(BREAKING CHANGE|!:)"; then + BUMP="major" + REASON="Breaking change detected in commit messages" + elif echo "$COMMITS" | grep -qE "^feat"; then + BUMP="minor" + REASON="Feature commits detected" + else + BUMP="patch" + REASON="Defaulting to patch (fixes or other changes)" + fi + + echo "Suggested bump type: $BUMP" + echo "Reason: $REASON" + echo "bump=$BUMP" >> $GITHUB_OUTPUT + echo "reason=$REASON" >> $GITHUB_OUTPUT + + - name: Comment bump type on PR + uses: actions/github-script@v7 + with: + script: | + const bump = '${{ steps.bump_type.outputs.bump }}'; + const reason = '${{ steps.bump_type.outputs.reason }}'; + + const comment = ` + ## 🏷️ Version Bump Analysis + + **Suggested bump type:** \`${bump.toUpperCase()}\` + **Reason:** ${reason} + + This PR will bump the version to the next ${bump} version when merged. + `; + + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: comment + }); diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 70d567f..b64aaa4 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -10,8 +10,9 @@ env: IMAGE_NAME: euchre-camp jobs: - build-and-test: + release: runs-on: ubuntu-latest + # Skip if this is an auto-generated version bump commit if: "!contains(github.event.head_commit.message, 'chore: bump version')" steps: @@ -19,14 +20,75 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 + token: ${{ secrets.GITEA_TOKEN || github.token }} - - name: Get current version + - name: Configure Git + run: | + git config user.name "Gitea Actions" + git config user.email "actions@gitea.com" + + - name: Determine version bump type + id: bump_type + run: | + # Get the merge commit message or use commits since last tag + MERGE_MSG="${{ github.event.head_commit.message }}" + echo "Commit message: $MERGE_MSG" + + # Determine bump type from commit message or commits + if echo "$MERGE_MSG" | grep -qE "(BREAKING CHANGE|!:)"; then + echo "bump=major" >> $GITHUB_OUTPUT + echo "Bump type: major (breaking change detected)" + elif echo "$MERGE_MSG" | grep -qE "^feat"; then + echo "bump=minor" >> $GITHUB_OUTPUT + echo "Bump type: minor (feature detected)" + else + # Check actual commits in the PR + LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") + if [ -n "$LAST_TAG" ]; then + COMMITS=$(git log --oneline ${LAST_TAG}..HEAD 2>/dev/null | head -5) + else + COMMITS=$(git log --oneline | head -5) + fi + echo "Recent commits: $COMMITS" + + if echo "$COMMITS" | grep -qE "BREAKING\|!:"; then + echo "bump=major" >> $GITHUB_OUTPUT + echo "Bump type: major (breaking change in commits)" + elif echo "$COMMITS" | grep -qE "^feat"; then + echo "bump=minor" >> $GITHUB_OUTPUT + echo "Bump type: minor (feature in commits)" + else + echo "bump=patch" >> $GITHUB_OUTPUT + echo "Bump type: patch (default)" + fi + fi + + - name: Bump version id: version run: | - # Read version from package.json - CURRENT_VERSION=$(node -p "require('./package.json').version") - echo "version=$CURRENT_VERSION" >> $GITHUB_OUTPUT - echo "Current version: $CURRENT_VERSION" + BUMP="${{ steps.bump_type.outputs.bump }}" + echo "Bumping version: $BUMP" + + # Run the bump script + node scripts/bump-version.js "$BUMP" --yes + + # Get new version + NEW_VERSION=$(node -p "require('./package.json').version") + echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT + echo "New version: $NEW_VERSION" + + - name: Commit version bump + run: | + git add package.json CHANGELOG.md + git commit -m "chore: bump version to v${{ steps.version.outputs.new_version }}" + git push origin main + + - name: Create git tag for release + run: | + TAG_NAME="v${{ steps.version.outputs.new_version }}" + echo "Creating tag $TAG_NAME" + git tag -a "$TAG_NAME" -m "Release $TAG_NAME" + git push origin "$TAG_NAME" - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -36,14 +98,14 @@ jobs: docker build \ --target test-runner \ --build-arg GIT_COMMIT=${{ github.sha }} \ - -t ${{ env.IMAGE_NAME }}-test:${{ steps.version.outputs.version }} \ + -t ${{ env.IMAGE_NAME }}-test:${{ steps.version.outputs.new_version }} \ . - name: Run tests inside test-capable container run: | docker run --rm \ -e DATABASE_URL="postgresql://user:pass@localhost:5432/dummy" \ - ${{ env.IMAGE_NAME }}-test:${{ steps.version.outputs.version }} \ + ${{ env.IMAGE_NAME }}-test:${{ steps.version.outputs.new_version }} \ npm run test:run - name: Build production image @@ -51,37 +113,35 @@ jobs: docker build \ --target runner \ --build-arg GIT_COMMIT=${{ github.sha }} \ - -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version }} \ + -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.new_version }} \ -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest \ . - - name: Configure Git - run: | - git config user.name "Gitea Actions" - git config user.email "actions@gitea.com" - - - name: Create git tag for release - run: | - git tag -a "v${{ steps.version.outputs.version }}" -m "Release v${{ steps.version.outputs.version }}" - git push origin "v${{ steps.version.outputs.version }}" - - name: Push Docker images run: | echo "Pushing to ${{ env.REGISTRY }}..." - # Check if we can authenticate to the registry - if docker login ${{ env.REGISTRY }} -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} 2>/dev/null; then - docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version }} - docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest - echo "Successfully pushed images to ${{ env.REGISTRY }}" + # Check if we can authenticate to the registry using DOCKER_LOGIN and DOCKER_PASSWORD secrets + if [ -n "${{ secrets.DOCKER_LOGIN }}" ] && [ -n "${{ secrets.DOCKER_PASSWORD }}" ]; then + if docker login ${{ env.REGISTRY }} -u ${{ secrets.DOCKER_LOGIN }} -p ${{ secrets.DOCKER_PASSWORD }} 2>/dev/null; then + docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.new_version }} + docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest + echo "Successfully pushed images to ${{ env.REGISTRY }}" + else + echo "Warning: Docker login failed with provided credentials" + echo "Images built locally but not pushed to registry" + echo "Manual push required:" + echo " docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.new_version }}" + echo " docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" + fi else - echo "Warning: Could not authenticate to ${{ env.REGISTRY }}" + echo "Warning: DOCKER_LOGIN or DOCKER_PASSWORD secrets not configured" echo "Images built locally but not pushed to registry" echo "Manual push required:" - echo " docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version }}" + echo " docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.new_version }}" echo " docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" fi - name: Deploy to dev (placeholder) run: | - echo "Deploying version ${{ steps.version.outputs.version }} to dev environment..." + echo "Deploying version ${{ steps.version.outputs.new_version }} to dev environment..." # TODO: Add actual deployment steps diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml index 7ba1182..bcf53e3 100644 --- a/.gitea/workflows/test.yml +++ b/.gitea/workflows/test.yml @@ -4,52 +4,26 @@ on: push: branches: - '**' - - '!main' # Skip main branch (release workflow handles that) - pull_request: - branches: - - main jobs: unit-tests: runs-on: ubuntu-latest + container: + image: node:20-alpine + options: --user root + # Skip if this is an auto-generated version bump commit (handled by release workflow) + if: "!contains(github.event.head_commit.message, 'chore: bump version')" steps: + - name: Install system dependencies + run: | + apk add --no-cache bash git + - name: Checkout code uses: actions/checkout@v4 - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '20' - cache: 'npm' - - name: Install dependencies run: npm ci - name: Run unit tests run: npm run test:run - - # Acceptance tests that don't require DB read/write - # Only run on pull requests to main - safe-acceptance-tests: - runs-on: ubuntu-latest - needs: unit-tests - if: github.event_name == 'pull_request' - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '20' - cache: 'npm' - - - name: Install dependencies - run: npm ci - - - name: Run safe acceptance tests - # These tests should not read/write to the database - # They might test UI components, routing, or static content - run: npm run test:acceptance -- --grep "safe|static|ui|component" diff --git a/AGENTS.md b/AGENTS.md index 7dd4506..464ab1c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -109,10 +109,50 @@ npm run db:setup-postgres **Note:** The database provider is automatically detected by Better Auth and Prisma. ### Running Tests + +**Using just (recommended):** +- **All tests**: `just test` (unit + acceptance with SQLite) +- **Unit tests**: `just test-unit` +- **Acceptance tests (SQLite)**: `just test-acceptance-sqlite` +- **Acceptance tests (PostgreSQL)**: `just test-acceptance-postgres` +- **PR validation**: `just pr-validate` (what runs on pull requests) + +**Using npm scripts:** - **Unit tests**: `npm run test` - **Acceptance tests**: `npm run test:acceptance` - **Specific test**: `npm run test:acceptance -- --grep "test name"` +**CI-style acceptance tests with SQLite:** +```bash +DATABASE_PROVIDER=sqlite DATABASE_URL=file:./prisma/ci.db npm run test:acceptance +``` + +### CI/CD Pipeline +The project uses Gitea Actions for continuous integration: + +**PR Workflow** (`.gitea/workflows/pr.yml`): +- Runs on pull requests to main +- Executes unit tests and acceptance tests with SQLite +- Analyzes commits for semantic versioning +- Comments suggested bump type on PRs + +**Test Workflow** (`.gitea/workflows/test.yml`): +- Runs on all branch pushes +- Executes unit tests for quick feedback +- Skips auto-generated version bump commits + +**Release Workflow** (`.gitea/workflows/release.yml`): +- Runs on main branch pushes +- Determines version bump type +- Bumps version and creates git tags +- Builds Docker images and runs tests +- Pushes to registry and deploys + +**Database Strategy**: +- CI tests use SQLite (fast, no server required) +- Production uses PostgreSQL +- Switch with `DATABASE_PROVIDER` environment variable + ## Key Files ### Configuration @@ -170,6 +210,10 @@ npm run db:setup-postgres - Utilities: camelCase (e.g., `elo-utils.ts`) - Tests: `.test.ts` or `.test.tsx` suffix +## File Organization + +See [docs/FILE_ORGANIZATION.md](docs/FILE_ORGANIZATION.md) for detailed file organization and structure. + ## Resources - **Better Auth Docs**: https://better-auth.com/docs diff --git a/CHANGELOG.md b/CHANGELOG.md index 98d6c33..8b25b2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,22 @@ +## [0.1.2] - 2026-04-01 + +### Patch Changes + +- fix: handle Docker registry authentication gracefully in release workflow +- fix: run unit tests on branch commits, skip main branch +- feat: add test workflow for every commit +- trigger: release with test-capable image +- feat: build test-capable image, run tests, then build production image +- trigger: release workflow +- fix: release workflow should not commit, only tag +- trigger: manual workflow trigger for docker.notsosm.art +- fix: update Docker build script to use docker.notsosm.art registry +- fix: update workflow to use docker.notsosm.art registry +- trigger: manual workflow trigger +- fix: update workflow to use correct Docker registries +- feat: add Gitea Actions release workflow +- feat: add view match link to admin matches page + ## [0.1.1] - 2026-04-01 ### Patch Changes diff --git a/README.md b/README.md index 9ea63ac..2dd2f42 100644 --- a/README.md +++ b/README.md @@ -17,20 +17,29 @@ EuchreCamp is a full-stack web application built with Next.js 14+ and TypeScript - **Framework**: Next.js 14+ (App Router) - **Language**: TypeScript -- **Database**: Prisma ORM with SQLite +- **Database**: Prisma ORM with SQLite (default) or PostgreSQL - **Styling**: Tailwind CSS - **Authentication**: Better Auth - **Form Handling**: React Hook Form + Zod validation - **CSV Parsing**: PapaParse - **Unit Testing**: Vitest - **Acceptance Testing**: Playwright +- **CI/CD**: Gitea Actions with SQLite for CI tests ## Project Structure ``` euchre_camp/ -├── src/ -│ ├── app/ +├── .gitea/workflows/ # CI/CD workflows (Gitea Actions) +├── docs/ # Documentation +│ ├── deployment/ # Deployment guides +│ └── planning/ # Planning documents +├── prisma/ # Prisma schema and migrations +├── public/ # Static assets +├── scripts/ # Utility scripts +│ └── python/ # Python scripts (legacy) +├── src/ # Source code +│ ├── app/ # Next.js app directory │ │ ├── api/ # API routes │ │ ├── auth/ # Authentication pages │ │ ├── admin/ # Admin pages @@ -39,16 +48,15 @@ euchre_camp/ │ │ └── components/ # Shared components │ ├── lib/ # Utilities and configuration │ │ ├── auth.ts # Better Auth configuration -│ │ ├── prisma.ts # Prisma client +│ │ ├── prisma.ts # Prisma client (SQLite/PostgreSQL) │ │ ├── permissions.ts # Authorization functions │ │ └── elo-utils.ts # Elo calculation utilities │ └── __tests__/ # Vitest and Playwright tests -├── prisma/ # Prisma schema and migrations -├── docs/ # Documentation -├── scripts/ # Utility scripts -└── public/ # Static assets +└── ... # Configuration files in root ``` +See [docs/FILE_ORGANIZATION.md](docs/FILE_ORGANIZATION.md) for detailed file organization. + ## Features Implemented ### Epic 1: Authentication & User Management @@ -242,6 +250,36 @@ Visit `/` to see: ## Development +### Using just (recommended) +The project includes a `justfile` with common development tasks: + +```bash +# Show all available tasks +just help + +# Development mode +just dev + +# Run all tests (unit + acceptance with SQLite) +just test + +# Run PR validation (what runs on pull requests) +just pr-validate + +# Run CI pipeline locally +just ci + +# Switch database provider +just db-switch-sqlite +just db-switch-postgres + +# Docker shortcuts +just docker-up +just docker-down +just docker-logs +``` + +### Using npm scripts directly ```bash # Development mode npm run dev @@ -255,6 +293,9 @@ npm run test # Run acceptance tests npm run test:acceptance + +# Run acceptance tests with SQLite (CI-style) +DATABASE_PROVIDER=sqlite DATABASE_URL=file:./prisma/ci.db npm run test:acceptance ``` ### Database Commands @@ -313,6 +354,39 @@ User stories are organized into epics in `docs/USER_STORIES.md`: 7. Mobile Responsiveness 8. Data Management & Export +## CI/CD Pipeline + +The application uses Gitea Actions for continuous integration and deployment: + +### Workflow Architecture +1. **PR Workflow** (`.gitea/workflows/pr.yml`): Runs on pull requests + - Unit tests (fast feedback) + - Acceptance tests with SQLite database + - Semantic version bump analysis + +2. **Test Workflow** (`.gitea/workflows/test.yml`): Runs on all branch pushes + - Unit tests for quick feedback + - Skips auto-generated version bumps + +3. **Release Workflow** (`.gitea/workflows/release.yml`): Runs on main branch pushes + - Version bumping and tagging + - Docker image building and testing + - Registry push and deployment + +### Database Strategy for CI +- **CI Tests**: SQLite database (fast, no server required) +- **Production**: PostgreSQL (production-like environment) +- **Configuration**: `DATABASE_PROVIDER` environment variable + +### Running CI Locally +```bash +# Run unit tests (same as CI) +npm run test:run + +# Run acceptance tests with SQLite +DATABASE_PROVIDER=sqlite DATABASE_URL=file:./prisma/ci.db npm run test:acceptance +``` + ## Docker Deployment This application can be run using Docker and Docker Compose. See [DOCKER.md](DOCKER.md) for detailed instructions. diff --git a/TODO.md b/TODO.md deleted file mode 100644 index b5529c0..0000000 --- a/TODO.md +++ /dev/null @@ -1,102 +0,0 @@ -# EuchreCamp - Todo List - -## Current Tasks - -### Completed ✅ -- [x] Add `site_admin` role to database schema and permissions system -- [x] Add `isCasual` boolean field to Match model (already existed) -- [x] Update match upload API to support casual matches -- [x] Update match upload UI to include casual checkbox -- [x] Add tournament deletion API endpoint with delete/orphan options -- [x] Add delete tournament button and modal to tournament detail page -- [x] Run tests and verify implementation (84 tests passing) -- [x] Fix session issues with tournament admin access -- [x] Fix Elo recalculation error for player merge (delete elo snapshots before deleting players) -- [x] Add admin player management page -- [x] Add player name editing functionality in admin UI -- [x] Add admin panel links to navigation header -- [x] Add tournament update API endpoint (PUT /api/tournaments/[id]) -- [x] Consolidate delete endpoint from admin API to main tournaments API -- [x] Update database schema to add variant scoring fields (targetScore, allowTies) -- [x] Fix tie handling logic in partnership stats (ties now correctly tracked) -- [x] Fix test files for normalizedName field in Player model -- [x] Fix auth.ts to include normalizedName in Player creation -- [x] Write TODO list to repository file -- [x] Auto-create tournament when uploading matches without selecting one - -### In Progress 🔄 -- [ ] Update API routes to handle new variant scoring fields -- [ ] Update EditTournamentForm to add variant scoring controls -- [ ] Update MatchEditor to use tournament-specific target score -- [ ] Run tests and verify variant scoring implementation - -### Recently Completed ✅ -- [x] Add OpenSkill rating system support (src/lib/openskill-utils.ts) -- [x] Add Glicko2 rating system support (src/lib/glicko2-utils.ts) -- [x] Reset database and run all migrations from scratch -- [x] Regenerate Prisma client with new rating models -- [x] Update match upload page to auto-create tournament if none selected -- [x] Update all admin scripts to use PrismaPg adapter and dotenv -- [x] Fix match diagram player positioning -- [x] Add CasaOS deployment configuration and documentation -- [x] Create migration to add rating system tables (elo_ratings, glicko2_ratings, open_skill_ratings) -- [x] Add tabbed rankings page to display Elo, OpenSkill, and Glicko2 ratings - -### Backlog 📋 -- [ ] Add UI controls for variant scoring in tournament creation/edit -- [ ] Test variant tournament functionality end-to-end -- [ ] Add validation for tie scores based on tournament configuration -- [ ] Document variant tournament features - -## Recently Completed (Detailed) - -### Variant Euchre Scoring Support -- Added `targetScore` and `allowTies` fields to Event model -- Created database migration for new fields -- Fixed partnership stats tie handling (ties now increment neither wins nor losses) -- Updated Elo calculation functions to handle ties correctly (0.5 points for draw) - -### Tournament Deletion -- Consolidated delete endpoint to `/api/tournaments/[id]` -- Added options to delete matches or orphan them -- Updated DeleteTournamentButton to use consolidated endpoint - -### Player Management -- Added admin players page at `/admin/players` -- Added player name editing functionality via PATCH endpoint -- Added player merge functionality with automatic Elo recalculation -- Fixed foreign key constraint issues with elo_snapshots - -### Permissions -- Added `site_admin` role as highest privilege level -- Updated all permission functions to include site_admin support -- Fixed session cache issues by reading roles from database - -## Notes -- All 84 unit tests passing -- Database migrations applied successfully -- TypeScript compilation has pre-existing errors unrelated to our changes - -### Completed After Commit 1729dac - -#### Next.js 16 Breaking Change Fixes -- [x] Fixed `params.id` usage in all page components (must use `await params`) -- [x] Fixed `params.id` usage in all API routes (must use `await params`) -- [x] Updated client components to use `Promise<{ id: string }>` type -- [x] Added regression tests for Next.js 16 params Promise handling -- [x] Verified all 100 unit tests pass - -#### Files Updated: -- Player pages: `profile.tsx`, `schedule.tsx` -- Tournament pages: `page.tsx`, `results.tsx`, `edit.tsx`, `entry.tsx` -- API routes: `admin/players/[id]/route.ts`, `users/[id]/route.ts`, `users/[id]/role/route.ts` -- Tournament API routes: `[id]/route.ts`, `[id]/participants/route.ts`, `[id]/games/bulk/route.ts` - -#### Root Cause -Next.js 16 requires `params` to be awaited in both server components and API routes: -- Before: `const { id } = params` -- After: `const { id } = await params` - -This was not caught by the unit test suite because: -- Unit tests test individual functions in isolation -- E2E tests (Playwright) would catch this but weren't run after the upgrade diff --git a/docs/FILE_ORGANIZATION.md b/docs/FILE_ORGANIZATION.md new file mode 100644 index 0000000..179e3fe --- /dev/null +++ b/docs/FILE_ORGANIZATION.md @@ -0,0 +1,125 @@ +# File Organization + +This document describes the organization of files in the EuchreCamp project. + +## Root Directory + +### Essential Files (Keep in Root) +- `README.md` - Main project documentation +- `AGENTS.md` - AI agent guide +- `CHANGELOG.md` - Version changelog +- `package.json` - Node.js dependencies and scripts +- `package-lock.json` - Dependency lock file +- `tsconfig.json` - TypeScript configuration +- `next.config.js` - Next.js configuration +- `.gitignore` - Git ignore file +- `Dockerfile` - Docker build configuration +- `justfile` - Development task automation + +### Configuration Files (Keep in Root) +- `.eslintrc.json` - ESLint configuration +- `postcss.config.mjs` - PostCSS configuration +- `playwright.config.ts` - Playwright test configuration +- `vitest.config.mts` - Vitest configuration +- `vitest.setup.ts` - Vitest setup +- `.dockerignore` - Docker ignore file +- `mise.toml` - Mise version manager config + +### Docker Files (Keep in Root) +- `docker-compose.yml` - Main Docker Compose +- `docker-compose.dev.yml` - Development Docker Compose +- `docker-compose.override.yml` - Override for dev +- `docker-compose.casaos.yml` - CasaOS specific + +### Environment Files (Keep in Root, Gitignored) +- `.env` - Environment variables +- `.env.development` - Development environment + +## Organized Directories + +### `.gitea/` - Gitea Actions Workflows +- `workflows/pr.yml` - Pull request workflow (unit + acceptance tests) +- `workflows/test.yml` - Test workflow (unit tests on branch pushes) +- `workflows/release.yml` - Release workflow (version bump + Docker build) +- `WORKFLOW_ARCHITECTURE.md` - Workflow architecture documentation + +### `docs/` - Documentation +- `deployment/` - Deployment documentation + - `CASAOS_DEPLOYMENT.md` - CasaOS deployment guide + - `DOCKER.md` - Docker deployment instructions +- `TODO.md` - Project TODO list (in docs root for visibility) +- `USER_STORIES.md` - User stories organized by epic +- Other documentation files (design, implementation, testing, etc.) + +### `scripts/` - Utility Scripts +- `python/` - Python scripts (legacy/old functionality) + - `generate_games.py` - Generate sample games + - `update_partnership_stats.py` - Update partnership stats + - `update_player_stats.py` - Update player stats +- `bump-version.js` - Version bumping script +- `build-and-push-docker.js` - Docker build and push script +- `switch-database.js` - Database provider switching +- `create-admin-via-api.js` - Admin user creation via API +- `create-admin-better-auth.js` - Admin user creation via database +- `list-users.js` - List all users +- `update-admin-password.js` - Update admin password +- `seed.js` - Database seeding +- And other Node.js scripts... + +### `src/` - Source Code +- `app/` - Next.js app directory + - `api/` - API routes + - `auth/` - Authentication pages + - `admin/` - Admin pages + - `players/` - Player pages + - `rankings/` - Rankings page + - `components/` - Shared components +- `lib/` - Utilities and configuration + - `auth.ts` - Better Auth configuration + - `prisma.ts` - Prisma client (supports SQLite and PostgreSQL) + - `permissions.ts` - Authorization functions + - `elo-utils.ts` - Elo calculation utilities +- `__tests__/` - Vitest and Playwright tests + - `unit/` - Unit tests + - `e2e/` - End-to-end acceptance tests + +### `prisma/` - Database +- `schema.prisma` - Prisma schema +- `migrations/` - Database migrations +- `dev.db` - SQLite development database (if using SQLite) + +### `public/` - Static Assets +- Images, fonts, and other static files + +### `playwright/` - Playwright Test Data +- Authentication state files + +## Generated Directories (Gitignored) +- `.next/` - Next.js build output +- `node_modules/` - Node.js dependencies +- `playwright-report/` - Playwright test reports +- `test-results/` - Test results + +## File Organization Principles + +1. **Keep standard files in root**: package.json, tsconfig.json, etc. +2. **Organize by function**: Group related files in directories +3. **Separate generated from source**: Keep build outputs and dependencies separate +4. **Document organization**: Use this file to explain structure +5. **Follow conventions**: Use standard naming and organization patterns + +## CI/CD File Organization + +### Workflows +- `.gitea/workflows/pr.yml` - Pull request validation +- `.gitea/workflows/test.yml` - Branch testing +- `.gitea/workflows/release.yml` - Main branch release + +### Database Strategy +- **CI/Testing**: SQLite (fast, no server) +- **Production**: PostgreSQL (production-like) + +### Testing +- Unit tests: `npm run test:run` +- Acceptance tests (SQLite): `DATABASE_PROVIDER=sqlite npm run test:acceptance` +- Acceptance tests (PostgreSQL): `npm run test:acceptance` (with Docker) diff --git a/docs/TODO.md b/docs/TODO.md index 7dc890b..b5529c0 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -1,134 +1,102 @@ -# EuchreCamp - Project Todo List +# EuchreCamp - Todo List -## Completed Features +## Current Tasks -### Backend -- [x] Database schema for matches, players, teams, events -- [x] Elo rating calculator and job -- [x] Partnership tracking and analytics -- [x] Tournament generator (round-robin, single elim, double elim, Swiss) -- [x] ROM relations and repositories -- [x] Acceptance test suite (8 tests passing) +### Completed ✅ +- [x] Add `site_admin` role to database schema and permissions system +- [x] Add `isCasual` boolean field to Match model (already existed) +- [x] Update match upload API to support casual matches +- [x] Update match upload UI to include casual checkbox +- [x] Add tournament deletion API endpoint with delete/orphan options +- [x] Add delete tournament button and modal to tournament detail page +- [x] Run tests and verify implementation (84 tests passing) +- [x] Fix session issues with tournament admin access +- [x] Fix Elo recalculation error for player merge (delete elo snapshots before deleting players) +- [x] Add admin player management page +- [x] Add player name editing functionality in admin UI +- [x] Add admin panel links to navigation header +- [x] Add tournament update API endpoint (PUT /api/tournaments/[id]) +- [x] Consolidate delete endpoint from admin API to main tournaments API +- [x] Update database schema to add variant scoring fields (targetScore, allowTies) +- [x] Fix tie handling logic in partnership stats (ties now correctly tracked) +- [x] Fix test files for normalizedName field in Player model +- [x] Fix auth.ts to include normalizedName in Player creation +- [x] Write TODO list to repository file +- [x] Auto-create tournament when uploading matches without selecting one -### Frontend -- [x] Basic player rankings page -- [x] Match entry form +### In Progress 🔄 +- [ ] Update API routes to handle new variant scoring fields +- [ ] Update EditTournamentForm to add variant scoring controls +- [ ] Update MatchEditor to use tournament-specific target score +- [ ] Run tests and verify variant scoring implementation -## In Progress - UI Development +### Recently Completed ✅ +- [x] Add OpenSkill rating system support (src/lib/openskill-utils.ts) +- [x] Add Glicko2 rating system support (src/lib/glicko2-utils.ts) +- [x] Reset database and run all migrations from scratch +- [x] Regenerate Prisma client with new rating models +- [x] Update match upload page to auto-create tournament if none selected +- [x] Update all admin scripts to use PrismaPg adapter and dotenv +- [x] Fix match diagram player positioning +- [x] Add CasaOS deployment configuration and documentation +- [x] Create migration to add rating system tables (elo_ratings, glicko2_ratings, open_skill_ratings) +- [x] Add tabbed rankings page to display Elo, OpenSkill, and Glicko2 ratings -### Completed -- [x] Navigation layout (Next.js components) -- [x] UI Design document (UI_DESIGN.md) -- [x] Player Profile page (Next.js) -- [x] Basic CSS styling (Tailwind CSS) -- [x] Player Schedule page (Next.js) -- [x] Route for player schedule +### Backlog 📋 +- [ ] Add UI controls for variant scoring in tournament creation/edit +- [ ] Test variant tournament functionality end-to-end +- [ ] Add validation for tie scores based on tournament configuration +- [ ] Document variant tournament features -### View Types to Implement -- [ ] Tournament Admin View (Phase 2-3) - - Create/manage tournaments - - Set up brackets and matchups - - Record match results - - View tournament standings +## Recently Completed (Detailed) -- [ ] Club Admin View (Superuser) (Phase 3-4) - - Manage all players - - View club-wide statistics - - Configure club settings - - Manage tournaments +### Variant Euchre Scoring Support +- Added `targetScore` and `allowTies` fields to Event model +- Created database migration for new fields +- Fixed partnership stats tie handling (ties now increment neither wins nor losses) +- Updated Elo calculation functions to handle ties correctly (0.5 points for draw) -- [ ] Player Profile View (Phase 1-2) - - Display player info and Elo rating - - Show partnership analytics - - Display match history - - Tournament participation - - Enhance existing template +### Tournament Deletion +- Consolidated delete endpoint to `/api/tournaments/[id]` +- Added options to delete matches or orphan them +- Updated DeleteTournamentButton to use consolidated endpoint -- [ ] Player Tournament Schedule View (Phase 4) - - Show upcoming matches - - Display tournament brackets - - Record personal match results +### Player Management +- Added admin players page at `/admin/players` +- Added player name editing functionality via PATCH endpoint +- Added player merge functionality with automatic Elo recalculation +- Fixed foreign key constraint issues with elo_snapshots -### UI Components Needed -- [x] Navigation system (role-based) - Started -- [ ] Dashboard layouts -- [ ] Forms for data entry -- [ ] Tables for displaying data -- [ ] Charts for statistics -- [ ] Bracket visualization +### Permissions +- Added `site_admin` role as highest privilege level +- Updated all permission functions to include site_admin support +- Fixed session cache issues by reading roles from database -### Implementation Phases -- [x] Phase 1: Navigation & Layout -- [x] Phase 2: Player Profile Enhancements -- [x] Phase 3: Tournament Admin View -- [x] Phase 4: Club Admin View -- [x] Phase 5: Player Schedule View -- [ ] Phase 6: Authentication & Authorization -- [x] Phase 7: Polish & Testing +## Notes +- All 84 unit tests passing +- Database migrations applied successfully +- TypeScript compilation has pre-existing errors unrelated to our changes -## Future Enhancements +### Completed After Commit 1729dac -### Features -- [ ] Real-time match updates (WebSockets) -- [ ] Mobile-responsive design improvements -- [ ] Email notifications -- [ ] Import/Export functionality -- [ ] API for third-party integrations -- [ ] Advanced analytics charts +#### Next.js 16 Breaking Change Fixes +- [x] Fixed `params.id` usage in all page components (must use `await params`) +- [x] Fixed `params.id` usage in all API routes (must use `await params`) +- [x] Updated client components to use `Promise<{ id: string }>` type +- [x] Added regression tests for Next.js 16 params Promise handling +- [x] Verified all 100 unit tests pass -### Technical -- [ ] Performance optimization -- [ ] Caching strategy -- [ ] Security hardening -- [ ] Deployment pipeline -- [ ] CI/CD setup +#### Files Updated: +- Player pages: `profile.tsx`, `schedule.tsx` +- Tournament pages: `page.tsx`, `results.tsx`, `edit.tsx`, `entry.tsx` +- API routes: `admin/players/[id]/route.ts`, `users/[id]/route.ts`, `users/[id]/role/route.ts` +- Tournament API routes: `[id]/route.ts`, `[id]/participants/route.ts`, `[id]/games/bulk/route.ts` -## AAA System (Authentication, Authorization, Accounting) - Next.js Implementation +#### Root Cause +Next.js 16 requires `params` to be awaited in both server components and API routes: +- Before: `const { id } = params` +- After: `const { id } = await params` -### Authentication (Better Auth + Prisma) -- [x] Set up Better Auth with Prisma -- [x] Create users table schema -- [x] Build login page (`/auth/login`) -- [x] Build registration page (`/auth/register`) -- [x] Implement session management with Better Auth -- [x] Add authentication middleware -- [ ] Password reset functionality -- [ ] Email confirmation system -- [ ] OAuth providers (optional) - -### Authorization (RBAC) -- [x] Define roles in Prisma schema (PLAYER, TOURNAMENT_ADMIN, CLUB_ADMIN) -- [x] Implement authorization helpers -- [x] Add authorization to admin dashboard -- [x] Add authorization to player management -- [x] Add authorization to tournament management -- [x] Add 5-minute match edit window (player role) -- [ ] Add role assignment UI for club admins -- [ ] Add permission checks to all API routes - -### Accounting (Activity Logging) -- [ ] Create activity logging system (Prisma model) -- [ ] Track authentication events -- [ ] Track tournament management events -- [ ] Track match recording events -- [ ] Build audit reports UI - -### Security -- [x] Rate limiting (Better Auth built-in) -- [ ] IP-based lockout -- [x] Secure cookie settings (Better Auth) -- [x] CSRF protection (Next.js built-in) -- [ ] Security headers -- [ ] Session fixation prevention - -## Known Issues -- [ ] Database IDs not resetting between tests (workaround: query by round_number) -- [ ] Need to clean up debug output from acceptance tests -- [ ] Password reset flow not yet implemented - -## Next Steps -1. Design UI mockups for each view type -2. Implement navigation system -3. Build out Tournament Admin view -4. Add role-based access control -5. Create reusable UI components +This was not caught by the unit test suite because: +- Unit tests test individual functions in isolation +- E2E tests (Playwright) would catch this but weren't run after the upgrade diff --git a/CASAOS_DEPLOYMENT.md b/docs/deployment/CASAOS_DEPLOYMENT.md similarity index 100% rename from CASAOS_DEPLOYMENT.md rename to docs/deployment/CASAOS_DEPLOYMENT.md diff --git a/DOCKER.md b/docs/deployment/DOCKER.md similarity index 100% rename from DOCKER.md rename to docs/deployment/DOCKER.md diff --git a/justfile b/justfile index 09b06f5..eb24680 100644 --- a/justfile +++ b/justfile @@ -9,8 +9,8 @@ set positional-arguments # Project name PROJECT := "euchre-camp" -# Docker registry (CasaOS local registry) -REGISTRY := "euchre-camp" # Update to your registry host if needed +# Docker registry +REGISTRY := "docker.notsosm.art" IMAGE_TAG := "latest" # Get git commit hash (short version) @@ -22,6 +22,8 @@ IMAGE_TAG_COMMIT := `git rev-parse --short HEAD` # --- Variables --- # Database DB_CONTAINER := "euchre-camp-postgres" +DATABASE_PROVIDER := env_var_or_default("DATABASE_PROVIDER", "sqlite") +DATABASE_URL := env_var_or_default("DATABASE_URL", "file:./prisma/dev.db") # --- Setup & Installation --- @@ -54,15 +56,24 @@ format: # --- Testing --- -# Run all tests (unit + acceptance) -test: test-unit test-acceptance +# Run all tests (unit + acceptance with SQLite) +# Note: Uses Docker containers for consistent environment +test: test-unit test-acceptance-sqlite + +# Run all tests with PostgreSQL (Docker) +test-pg: test-unit test-acceptance-postgres # Run unit tests (Vitest) test-unit: npm run test:run -# Run acceptance tests (Playwright) -test-acceptance: +# Run acceptance tests with SQLite (fast, no Docker needed) +test-acceptance-sqlite: + @echo "Running acceptance tests with SQLite..." + DATABASE_PROVIDER=sqlite DATABASE_URL=file:./prisma/ci.db BETTER_AUTH_SECRET=test-secret-key npm run test:acceptance + +# Run acceptance tests with PostgreSQL (Docker) +test-acceptance-postgres: @echo "Starting Docker containers for acceptance tests..." docker compose up -d @echo "Waiting for services to be ready..." @@ -80,6 +91,13 @@ migrate: seed: npm run db:seed +# Switch database provider +db-switch-sqlite: + npm run db:switch sqlite + +db-switch-postgres: + npm run db:switch postgresql + # --- Docker --- # Build the Docker image (standard build) @@ -143,9 +161,18 @@ docker-push: docker-build-full # --- CI/CD Pipeline Simulation --- # Run full CI pipeline locally (lint, test, build, push) -ci: lint typecheck test-unit docker-build +# Matches the Gitea Actions workflow +ci: lint typecheck test-unit test-acceptance-sqlite docker-build @echo "CI Pipeline completed successfully!" +# PR validation (what runs on pull requests) +pr-validate: lint typecheck test-unit test-acceptance-sqlite + @echo "PR validation completed successfully!" + +# Run CI with PostgreSQL (for release workflow simulation) +ci-postgres: lint typecheck test-unit test-acceptance-postgres docker-build + @echo "CI Pipeline with PostgreSQL completed successfully!" + # --- Utilities --- # Show help information @@ -158,3 +185,72 @@ clean: rm -rf node_modules .next dist @echo "Cleaning Docker artifacts..." docker system prune -f + +# Generate Prisma client +prisma-generate: + npx prisma generate + +# Reset development database +db-reset-dev: + npm run db:reset-dev + +# Setup development database +db-setup-dev: + npm run db:setup-dev + +# Clean production database (remove test records) +db-clean-prod: + npm run db:cleanup-prod + +# Check production database for test records +db-check-prod: + npm run db:check-prod + +# Create admin user +admin-create: + node scripts/create-admin-via-api.js + +# List all users +users-list: + node scripts/list-users.js + +# Update admin password +admin-update-password: + node scripts/update-admin-password.js + +# Bump version +version-bump-patch: + npm run version:patch + +version-bump-minor: + npm run version:minor + +version-bump-major: + npm run version:major + +# Docker Compose shortcuts +docker-up: + npm run docker:up + +docker-down: + npm run docker:down + +docker-logs: + npm run docker:logs + +# View workflow status +workflow-status: + @echo "Current workflows in .gitea/workflows/:" + ls -la .gitea/workflows/ + @echo "" + @echo "PR Workflow: Runs unit + acceptance tests on pull requests" + @echo "Test Workflow: Runs unit tests on all branch pushes" + @echo "Release Workflow: Runs on main branch pushes (version bump + Docker build)" + +# Check current database provider +db-status: + @echo "Database Provider: ${DATABASE_PROVIDER}" + @echo "Database URL: ${DATABASE_URL}" + @echo "" + @echo "Current schema.prisma provider:" + grep -A 2 "datasource db" prisma/schema.prisma | head -3 diff --git a/package.json b/package.json index cdf1f63..c66dbc2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "euchre_camp", - "version": "0.1.1", + "version": "0.1.2", "private": true, "scripts": { "dev": "NEXT_PUBLIC_GIT_COMMIT=$(git rev-parse --short HEAD) next dev", diff --git a/scripts/bump-version.js b/scripts/bump-version.js index 8012174..989a4b7 100755 --- a/scripts/bump-version.js +++ b/scripts/bump-version.js @@ -17,6 +17,7 @@ const path = require('path'); // Parse command line arguments const args = process.argv.slice(2); const forcedVersion = args[0]; // e.g., "0.2.0" or "patch/minor/major" +const skipConfirm = args.includes('--yes') || args.includes('-y'); // Skip confirmation prompt // Paths const packageJsonPath = path.join(__dirname, '..', 'package.json'); diff --git a/generate_games.py b/scripts/python/generate_games.py similarity index 100% rename from generate_games.py rename to scripts/python/generate_games.py diff --git a/update_partnership_stats.py b/scripts/python/update_partnership_stats.py similarity index 100% rename from update_partnership_stats.py rename to scripts/python/update_partnership_stats.py diff --git a/update_player_stats.py b/scripts/python/update_player_stats.py similarity index 100% rename from update_player_stats.py rename to scripts/python/update_player_stats.py diff --git a/scripts/run-tests-in-container.sh b/scripts/run-tests-in-container.sh new file mode 100755 index 0000000..b3f5a1f --- /dev/null +++ b/scripts/run-tests-in-container.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# Run tests in a Node.js container (for consistent environment) + +set -e + +echo "Running tests in node:20-alpine container..." +echo "This avoids Node.js setup time and ensures consistent environment." +echo "" + +# Run unit tests in container +docker run --rm \ + -v "$(pwd):/app" \ + -w /app \ + node:20-alpine \ + sh -c "apk add --no-cache bash git && npm ci && npm run test:run" diff --git a/src/lib/prisma.ts b/src/lib/prisma.ts index 955900d..c906801 100644 --- a/src/lib/prisma.ts +++ b/src/lib/prisma.ts @@ -1,6 +1,4 @@ import { PrismaClient } from '@prisma/client' -import { PrismaPg } from '@prisma/adapter-pg' -import pg from 'pg' import dotenv from 'dotenv' // Load .env file if it exists @@ -10,11 +8,24 @@ const globalForPrisma = globalThis as unknown as { prisma: PrismaClient | undefined } -const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL }) +// Detect database provider from environment (default to sqlite for local development) +const databaseProvider = process.env.DATABASE_PROVIDER || 'sqlite' -// Create PrismaClient with adapter +// Create PrismaClient with appropriate adapter const createPrismaClient = () => { - const client = new PrismaClient({ adapter }) + let client: PrismaClient + + if (databaseProvider === 'postgresql') { + // Use PrismaPg adapter for PostgreSQL + const { PrismaPg } = require('@prisma/adapter-pg') + const pg = require('pg') + const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL }) + client = new PrismaClient({ adapter }) + } else { + // No adapter needed for SQLite + client = new PrismaClient() + } + return client }