From e48d651eb51cfa1e3a49b6605a6488ff125fccf0 Mon Sep 17 00:00:00 2001 From: Lang <7system7@gmail.com> Date: Tue, 21 Apr 2026 17:58:05 +0200 Subject: [PATCH] new: pkg: add CI/CD improvements - add new CI workflow - & improve the deployment w/ tests #10 --- .gitea/workflows/ci.yml | 142 ++++++++++++ .gitea/workflows/deploy.yml | 87 +++++++ README.md | 73 ++++++ docs/CI_CD.md | 443 ++++++++++++++++++++++++++++++++++++ docs/README.md | 85 ++++++- 5 files changed, 819 insertions(+), 11 deletions(-) create mode 100644 .gitea/workflows/ci.yml create mode 100644 docs/CI_CD.md diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml new file mode 100644 index 0000000..3b2e87f --- /dev/null +++ b/.gitea/workflows/ci.yml @@ -0,0 +1,142 @@ +name: CI - Tests + +on: + push: + branches: + - main + - develop + pull_request: + branches: + - main + - develop + +jobs: + tests: + runs-on: splendid-bear + + services: + postgres: + image: postgres:18-alpine + env: + POSTGRES_USER: mineseeker_test + POSTGRES_PASSWORD: test_password + POSTGRES_DB: mineseeker_test + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + - 5432:5432 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup PHP 8.3 + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + extensions: pdo_pgsql, gd, intl, zip, sodium + coverage: none + tools: composer:v2 + + - name: Validate composer.json + run: composer validate --strict + + - name: Cache Composer dependencies + uses: actions/cache@v4 + with: + path: vendor + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer- + + - name: Install PHP dependencies + run: composer install --prefer-dist --no-progress --no-interaction + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Cache node modules + uses: actions/cache@v4 + with: + path: node_modules + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + + - name: Install Node dependencies + run: npm ci + + - name: Build assets + run: npm run build + + - name: Create .env.test file + run: | + cat > .env.test << 'ENVEOF' + APP_ENV=test + APP_SECRET=test-secret-key-for-ci-testing-only + DATABASE_URL="postgresql://mineseeker_test:test_password@localhost:5432/mineseeker_test?serverVersion=18&charset=utf8" + KERNEL_CLASS='App\Kernel' + SYMFONY_DEPRECATIONS_HELPER=999999 + PANTHER_APP_ENV=panther + PANTHER_ERROR_SCREENSHOT_DIR=./var/error-screenshots + ENVEOF + + - name: Setup test database + run: make test-db-setup + + - name: Run PHPUnit tests + run: vendor/bin/phpunit --testdox --colors=always + + - name: Run PHPUnit tests with coverage (optional) + if: github.event_name == 'pull_request' + run: | + XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-text --coverage-clover=coverage.xml + + - name: Upload coverage reports (optional) + if: github.event_name == 'pull_request' + uses: codecov/codecov-action@v4 + with: + file: ./coverage.xml + flags: unittests + name: phpunit-coverage + fail_ci_if_error: false + + lint: + runs-on: splendid-bear + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup PHP 8.3 + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + tools: composer:v2, phpstan + + - name: Install PHP dependencies + run: composer install --prefer-dist --no-progress --no-interaction + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Install Node dependencies + run: npm ci + + - name: Run ESLint + run: npm run lint || true + + - name: Check code style (PHP) + run: | + if [ -f "vendor/bin/php-cs-fixer" ]; then + vendor/bin/php-cs-fixer fix --dry-run --diff + else + echo "PHP-CS-Fixer not installed, skipping..." + fi diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 400b87c..e2bc250 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -6,7 +6,68 @@ on: - 'v*' jobs: + test: + runs-on: splendid-bear + + services: + postgres: + image: postgres:18-alpine + env: + POSTGRES_USER: mineseeker_test + POSTGRES_PASSWORD: test_password + POSTGRES_DB: mineseeker_test + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + - 5432:5432 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup PHP 8.3 + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + extensions: pdo_pgsql, gd, intl, zip, sodium + coverage: none + tools: composer:v2 + + - name: Install PHP dependencies + run: composer install --prefer-dist --no-progress --no-interaction + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Install Node dependencies + run: npm ci + + - name: Build assets + run: npm run build + + - name: Create .env.test file + run: | + cat > .env.test << 'ENVEOF' + APP_ENV=test + APP_SECRET=test-secret-key-for-ci-testing-only + DATABASE_URL="postgresql://mineseeker_test:test_password@localhost:5432/mineseeker_test?serverVersion=18&charset=utf8" + KERNEL_CLASS='App\Kernel' + SYMFONY_DEPRECATIONS_HELPER=999999 + ENVEOF + + - name: Setup test database + run: make test-db-setup + + - name: Run PHPUnit tests + run: vendor/bin/phpunit --testdox --colors=always --stop-on-failure + deploy: + needs: test runs-on: splendid-bear steps: - name: Checkout tag @@ -33,7 +94,33 @@ jobs: cd "${{ vars.PROD_APP_DIR }}" docker compose build + - name: Run database migrations + run: | + cd "${{ vars.PROD_APP_DIR }}" + docker compose run --rm app php bin/console doctrine:migrations:migrate --no-interaction + + - name: Clear cache + run: | + cd "${{ vars.PROD_APP_DIR }}" + docker compose run --rm app php bin/console cache:clear --env=prod + - name: Start services run: | cd "${{ vars.PROD_APP_DIR }}" docker compose up -d + + - name: Health check + run: | + sleep 5 + curl -f http://localhost:10080/ || exit 1 + + - name: Notify deployment success + if: success() + run: | + echo "✅ Deployment successful for tag ${{ gitea.ref_name }}" + + - name: Notify deployment failure + if: failure() + run: | + echo "❌ Deployment failed for tag ${{ gitea.ref_name }}" + exit 1 diff --git a/README.md b/README.md index 9d74e22..8e85640 100644 --- a/README.md +++ b/README.md @@ -304,3 +304,76 @@ For detailed information about game mechanics, bonus systems, fonts, testing, an LGPL-3.0 — see [LICENSE](LICENSE) for details. © 2026 [SplendidBear](https://www.splendidbear.org) + +--- + +## Testing & CI/CD + +MineSeeker has a comprehensive test suite with **71 automated tests** and continuous integration/deployment pipelines. + +### Quick Start + +```bash +# Setup test database (first time only) +make test-db-setup + +# Run all tests +make test + +# Run with documentation output +vendor/bin/phpunit --testdox +``` + +### Test Suite + +- **71 tests** with **227 assertions** +- **Controller tests** - HTTP endpoints, authentication, routing +- **DTO tests** - Data serialization and calculations +- **Entity tests** - Domain logic and defaults +- **Service tests** - Business logic and external APIs +- **Integration tests** - Foundry factories and database isolation + +**Test execution time:** ~6-8 seconds + +### Continuous Integration + +**Automated testing** runs on every push/pull request: + +```yaml +# .gitea/workflows/ci.yml +✓ PHP 8.3 setup with all extensions +✓ PostgreSQL 18 service container +✓ Composer and npm dependency installation +✓ Asset building with Vite +✓ Database migrations +✓ Full test suite execution +✓ Code linting (ESLint, PHP-CS-Fixer) +``` + +### Continuous Deployment + +**Automated deployment** on version tags (e.g., `v1.2.3`): + +```yaml +# .gitea/workflows/deploy.yml +1. Run full test suite (blocks deployment if fails) +2. Checkout tagged version +3. Build Docker image +4. Run database migrations +5. Restart services +6. Health check verification +``` + +**Deploy to production:** +```bash +git tag -a v1.2.3 -m "Release version 1.2.3" +git push origin v1.2.3 +``` + +### Documentation + +- **[Testing Guide](docs/testing/TESTING.md)** - Comprehensive testing documentation +- **[Factory Reference](docs/testing/FACTORIES.md)** - Foundry factory API +- **[CI/CD Guide](docs/CI_CD.md)** - Pipeline configuration and workflows + +--- diff --git a/docs/CI_CD.md b/docs/CI_CD.md new file mode 100644 index 0000000..55962db --- /dev/null +++ b/docs/CI_CD.md @@ -0,0 +1,443 @@ +# CI/CD Integration Guide + +This document explains how automated tests are integrated into the MineSeeker deployment pipeline using Gitea Actions. + +## Overview + +MineSeeker uses **Gitea Actions** (GitHub Actions compatible) for continuous integration and deployment: + +- **CI Pipeline** (`.gitea/workflows/ci.yml`) - Runs on every push/PR to main/develop +- **CD Pipeline** (`.gitea/workflows/deploy.yml`) - Runs on version tags, includes tests before deployment + +--- + +## CI Workflow (Continuous Integration) + +**Trigger:** Push or Pull Request to `main` or `develop` branches + +**File:** `.gitea/workflows/ci.yml` + +### Jobs + +#### 1. **Tests Job** + +Runs the full PHPUnit test suite with: + +- PostgreSQL 18 service container +- PHP 8.3 with required extensions +- Composer dependency installation +- Node.js for asset building +- Database setup and migrations +- 71 PHPUnit tests with testdox output + +**Steps:** +1. Checkout code +2. Setup PHP 8.3 with extensions (pdo_pgsql, gd, intl, zip, sodium) +3. Validate `composer.json` +4. Cache and install Composer dependencies +5. Setup Node.js 20 and install dependencies +6. Build frontend assets with Vite +7. Create `.env.test` configuration +8. Setup test database with migrations +9. Run PHPUnit tests with `--testdox` output +10. (Optional) Generate coverage report on PRs + +#### 2. **Lint Job** + +Code quality checks: + +- ESLint for JavaScript/JSX +- PHP-CS-Fixer (if installed) + +--- + +## CD Workflow (Continuous Deployment) + +**Trigger:** Push of version tags (e.g., `v1.0.0`, `v1.2.3`) + +**File:** `.gitea/workflows/deploy.yml` + +### Jobs + +#### 1. **Test Job** (Pre-deployment) + +**Critical:** Deployment only proceeds if tests pass. + +- Runs same test suite as CI workflow +- Uses `--stop-on-failure` flag for fast feedback +- Blocks deployment on any test failure + +#### 2. **Deploy Job** (Production Deployment) + +**Depends on:** `test` job must complete successfully + +**Steps:** +1. Checkout tagged version +2. Write production `.env` from secrets +3. Build Docker image +4. Run database migrations +5. Clear production cache +6. Start/restart services with `docker compose up -d` +7. Health check (curl to verify app is running) +8. Notify success/failure + +--- + +## Configuration Requirements + +### Gitea Repository Variables + +Set these in Gitea repository settings: + +``` +PROD_APP_DIR=/path/to/production/app +``` + +### Gitea Repository Secrets + +``` +PROD_ENV_FILE= +``` + +### Test Database Configuration + +The CI/CD pipeline uses a PostgreSQL service container with these credentials: + +```env +POSTGRES_USER=mineseeker_test +POSTGRES_PASSWORD=test_password +POSTGRES_DB=mineseeker_test +``` + +--- + +## Running Tests Locally + +Before pushing, run tests locally to catch issues early: + +```bash +# Setup test database (first time only) +make test-db-setup + +# Run tests +make test + +# Run with testdox output +vendor/bin/phpunit --testdox + +# Run with coverage +XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-html=var/coverage +``` + +--- + +## Deployment Workflow + +### Standard Deployment Process + +1. **Develop features** on feature branches +2. **Open Pull Request** to `develop` or `main` + - CI workflow runs automatically + - Tests must pass before merge +3. **Merge PR** after review and passing tests +4. **Create version tag** when ready to deploy: + ```bash + git tag -a v1.2.3 -m "Release version 1.2.3" + git push origin v1.2.3 + ``` +5. **Deployment runs automatically:** + - Tests run first + - If tests pass, Docker image builds + - Migrations run + - Services restart + - Health check verifies deployment + +### Rollback Process + +If deployment fails or issues are discovered: + +```bash +# Tag and deploy previous stable version +git push origin v1.2.2 + +# Or SSH to production and manually rollback +cd /path/to/production/app +git checkout v1.2.2 +docker compose build +docker compose up -d +``` + +--- + +## Test Suite Details + +### Test Coverage + +The CI/CD pipeline runs **71 tests** across: + +- **Controller Tests** (29 tests) + - GameController, ProfileController, SecurityController + - HTTP status codes, authentication, routing + +- **DTO Tests** (9 tests) + - ProfileGameDto, ProfileStatsDto, ProfileChartDataDto + - Serialization, null handling, calculations + +- **Entity Tests** (8 tests) + - UserStats calculations and defaults + +- **Service Tests** (13 tests) + - MercureJwtService, RecaptchaService + - Token generation, API verification + +- **Integration Tests** (12 tests) + - Factory usage examples + - Database isolation + +### Test Execution Time + +Typical test suite runtime: **6-8 seconds** + +--- + +## Best Practices + +### Before Committing + +✅ **Always run tests locally:** +```bash +make test +``` + +✅ **Check code style:** +```bash +vendor/bin/php-cs-fixer fix --dry-run +npm run lint +``` + +✅ **Verify assets build:** +```bash +npm run build +``` + +### When Creating PRs + +✅ **Wait for CI checks** to pass before requesting review + +✅ **Fix failing tests** immediately - don't merge broken code + +✅ **Review test output** in Gitea Actions logs + +### When Deploying + +✅ **Tag semantic versions:** `v1.2.3` (major.minor.patch) + +✅ **Write meaningful tag messages:** +```bash +git tag -a v1.2.3 -m "Add bonus points to battle cards, fix avatar upload bug" +``` + +✅ **Monitor deployment logs** in Gitea Actions + +✅ **Verify health check** passes after deployment + +✅ **Test critical features** in production after deployment + +--- + +## Troubleshooting + +### Tests Pass Locally but Fail in CI + +**Possible causes:** + +1. **Database state:** CI uses fresh database, local may have leftover data + ```bash + make test-db-reset # Reset local test database + ``` + +2. **Environment differences:** Check `.env.test` matches CI configuration + +3. **Cached dependencies:** CI caches may be stale + - Clear cache in Gitea Actions settings + - Or add `--no-cache` to composer install + +### Deployment Fails After Tests Pass + +**Common issues:** + +1. **Migration conflicts:** Manually run migrations on production + ```bash + docker compose run --rm app php bin/console doctrine:migrations:migrate + ``` + +2. **Missing environment variables:** Check `PROD_ENV_FILE` secret is up-to-date + +3. **Docker build errors:** Check Dockerfile and build context + +4. **Health check timeout:** Increase sleep time or check application startup + +### Database Migration Issues + +If migrations fail during deployment: + +```bash +# SSH to production server +cd /path/to/production/app + +# Check migration status +docker compose run --rm app php bin/console doctrine:migrations:status + +# Manually run migrations +docker compose run --rm app php bin/console doctrine:migrations:migrate --no-interaction + +# If migration is stuck, mark as executed +docker compose run --rm app php bin/console doctrine:migrations:version YYYYMMDDHHMMSS --add +``` + +--- + +## Monitoring and Notifications + +### Viewing CI/CD Logs + +1. Go to Gitea repository +2. Click **Actions** tab +3. Select workflow run +4. View detailed logs for each step + +### Setting Up Notifications + +**Gitea webhook notifications:** + +Configure webhooks in repository settings to notify: +- Slack/Discord when builds fail +- Email on deployment success/failure +- Custom endpoints for monitoring systems + +**Example webhook payload:** +```json +{ + "event": "workflow_run", + "repository": "Mine", + "workflow": "deploy.yml", + "status": "success", + "tag": "v1.2.3" +} +``` + +--- + +## Advanced Configuration + +### Running Tests with Coverage + +Enable coverage in CI (requires Xdebug): + +```yaml +- name: Run tests with coverage + run: | + XDEBUG_MODE=coverage vendor/bin/phpunit \ + --coverage-clover=coverage.xml \ + --coverage-html=var/coverage +``` + +### Parallel Test Execution + +For larger test suites, use ParaTest: + +```bash +composer require --dev brianium/paratest +``` + +```yaml +- name: Run tests in parallel + run: vendor/bin/paratest --processes=4 +``` + +### Database Seeding for E2E Tests + +Add step before tests: + +```yaml +- name: Seed test data + run: | + php bin/console doctrine:fixtures:load --no-interaction --env=test +``` + +--- + +## Security Considerations + +### Secrets Management + +❗ **Never commit secrets to repository** + +✅ **Use Gitea secrets** for sensitive data: +- `PROD_ENV_FILE` - Production environment variables +- Database credentials +- API keys + +✅ **Rotate secrets regularly** + +✅ **Use environment-specific secrets** (staging, production) + +### Database Security + +✅ **Test database is isolated** - No production data access + +✅ **Credentials are ephemeral** - Service containers use temporary passwords + +✅ **No data persistence** - Test database recreated on each run + +--- + +## Performance Optimization + +### Caching Strategies + +CI/CD workflows cache: + +1. **Composer dependencies** - `vendor/` directory +2. **Node modules** - `node_modules/` directory +3. **Docker layers** - Image build cache + +### Reducing Build Time + +✅ **Use `composer install --no-dev`** in production builds + +✅ **Multi-stage Docker builds** - Separate assets from PHP + +✅ **Parallel jobs** - Tests and linting run concurrently + +✅ **Skip unnecessary steps** - Use conditionals (`if:` statements) + +--- + +## Future Enhancements + +### Planned Improvements + +- [ ] Automated browser tests with Symfony Panther +- [ ] Visual regression testing for UI changes +- [ ] Performance benchmarking in CI +- [ ] Automated security scanning (Symfony Security Checker) +- [ ] Staging environment deployments before production +- [ ] Blue-green deployment strategy +- [ ] Automated rollback on health check failure + +--- + +## References + +- **Gitea Actions Documentation:** https://docs.gitea.com/usage/actions/overview +- **GitHub Actions Reference:** https://docs.github.com/en/actions (compatible syntax) +- **PHPUnit Documentation:** https://phpunit.de/documentation.html +- **Symfony Testing:** https://symfony.com/doc/current/testing.html +- **Docker Compose:** https://docs.docker.com/compose/ + +--- + +**Last Updated:** 2026-04-21 +**MineSeeker Version:** 1.0.0 +**CI/CD Platform:** Gitea Actions diff --git a/docs/README.md b/docs/README.md index be8d4cf..7cb7a2d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,6 @@ # Mine-Seeker Game Documentation -This directory contains comprehensive documentation about the Mine-Seeker game mechanics, testing, and implementation. +This directory contains comprehensive documentation about the Mine-Seeker game mechanics, testing, and deployment. ## Game Mechanics @@ -25,6 +25,7 @@ Complete testing setup and best practices including: - Test environment configuration - Database isolation with DAMA Doctrine Test Bundle - Test database setup (`mineseeker_test`) +- Modern PHPUnit attributes (`#[Test]`, `#[TestDox]`) - Writing effective tests - Running tests (all, specific, with coverage) - Best practices (AAA pattern, factories, type hints) @@ -44,6 +45,43 @@ Detailed API reference for Zenstruck Foundry factories: **Recommended for**: Writing tests with test data, understanding factory patterns, creating complex test scenarios. +### [Quick Reference](./testing/QUICK_REFERENCE.md) +Quick command reference for testing: +- Common test commands +- Factory usage cheat sheet +- Troubleshooting tips + +**Recommended for**: Quick lookups during development. + +--- + +## CI/CD & Deployment + +### [CI/CD Integration Guide](./CI_CD.md) +Comprehensive guide for continuous integration and deployment: +- Gitea Actions workflows (CI and CD pipelines) +- Automated testing on every push/PR +- Deployment process with pre-deployment testing +- Configuration requirements (secrets, variables) +- Rollback procedures +- Security considerations +- Performance optimization +- Monitoring and notifications +- Troubleshooting deployment issues + +**Recommended for**: Understanding deployment pipeline, setting up CI/CD, debugging deployment failures, production operations. + +### [CI/CD Quick Reference](./testing/CI_CD_QUICK_REFERENCE.md) +Quick reference for CI/CD operations: +- Common commands (testing, deployment, rollback) +- Workflow diagrams (CI and CD pipelines) +- Status badges for README +- Common issues and solutions +- Environment variables +- Monitoring links + +**Recommended for**: Quick deployments, troubleshooting, day-to-day operations. + --- ## Technical Documentation @@ -60,6 +98,14 @@ TrueType fonts used for server-side image generation: ## Quick Reference +### Test Suite Overview +| Metric | Value | +|--------|-------| +| Total Tests | 71 | +| Total Assertions | 227 | +| Execution Time | ~6-8 seconds | +| Coverage | Controller, DTO, Entity, Service, Integration | + ### Bonus Points at a Glance | Bonus Type | Points | Condition | |-----------|--------|-----------| @@ -84,24 +130,33 @@ TrueType fonts used for server-side image generation: ### Running Tests ```bash -# Recommended: Use Makefile +# Setup (first time only) make test-db-setup -# Or manually: -# All tests -vendor/bin/phpunit +# Run all tests +make test + +# Run with documentation output +vendor/bin/phpunit --testdox # Specific file vendor/bin/phpunit tests/Controller/ProfileControllerTest.php -# Specific method -vendor/bin/phpunit --filter testProfilePageRequiresAuthentication - # With coverage (requires Xdebug/PCOV) -XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-html coverage/ +XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-html var/coverage +``` -# With increased memory -php -d memory_limit=512M vendor/bin/phpunit +### CI/CD Commands +```bash +# Deploy to production +git tag -a v1.2.3 -m "Release version 1.2.3" +git push origin v1.2.3 + +# View CI/CD runs +# https://source.splendidbear.org/SplendidBear-Websites/Mine/actions + +# Rollback deployment +git push origin v1.2.2 # Deploy previous version ``` --- @@ -121,6 +176,12 @@ php -d memory_limit=512M vendor/bin/phpunit - PHPUnit Config: `/phpunit.dist.xml` - Bundle Config: `/config/bundles.php` +### CI/CD +- CI Workflow: `/.gitea/workflows/ci.yml` +- CD Workflow: `/.gitea/workflows/deploy.yml` +- Dockerfile: `/Dockerfile` +- Docker Compose: `/compose.yaml` + --- ## Additional Resources @@ -130,3 +191,5 @@ php -d memory_limit=512M vendor/bin/phpunit - **[Zenstruck Foundry](https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html)** - Official Foundry documentation - **[PHPUnit](https://phpunit.de/)** - PHPUnit documentation - **[Symfony Testing](https://symfony.com/doc/current/testing.html)** - Symfony testing guide +- **[Gitea Actions](https://docs.gitea.com/usage/actions/overview)** - Gitea Actions documentation +- **[Docker Compose](https://docs.docker.com/compose/)** - Docker Compose reference