name: CI

on:
  push:
  pull_request:

permissions:
  contents: read

concurrency:
  group: ci-${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  quality:
    name: Quality and tests
    runs-on: ubuntu-latest

    services:
      mysql:
        image: mysql:8.4
        env:
          MYSQL_DATABASE: oasb_test
          MYSQL_USER: oasb
          MYSQL_PASSWORD: oasb_ci
          MYSQL_ROOT_PASSWORD: root_ci
        ports:
          - 3306:3306
        options: >-
          --health-cmd="mysqladmin ping -h 127.0.0.1 -uroot -proot_ci"
          --health-interval=5s
          --health-timeout=5s
          --health-retries=20

    env:
      APP_ENV: test
      APP_DEBUG: 0
      APP_SECRET: ci-only-placeholder
      DATABASE_URL: mysql://oasb:oasb_ci@127.0.0.1:3306/oasb?serverVersion=8.4&charset=utf8mb4

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Set up PHP 8.4
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.4'
          extensions: pdo_mysql, intl, zip, mbstring
          coverage: none
          tools: composer:v2

      - name: Resolve Composer cache directory
        id: composer-cache
        run: echo "dir=$(composer config cache-files-dir)" >> "$GITHUB_OUTPUT"

      - name: Cache Composer downloads
        uses: actions/cache@v4
        with:
          path: ${{ steps.composer-cache.outputs.dir }}
          key: composer-${{ runner.os }}-php84-${{ hashFiles('composer.lock') }}
          restore-keys: composer-${{ runner.os }}-php84-

      - name: Validate Composer configuration
        run: composer validate

      - name: Install dependencies from lock file
        run: composer install --prefer-dist --no-interaction --no-progress

      - name: Audit dependencies
        run: composer audit

      - name: Lint Symfony configuration and templates
        run: composer lint

      - name: Run PHPStan level 9
        run: composer phpstan

      - name: Verify isolated test database
        run: php bin/console dbal:run-sql "SELECT DATABASE() AS database_name" --env=test | grep -q oasb_test

      - name: Run migrations on empty test database
        run: php bin/console doctrine:migrations:migrate --no-interaction --env=test

      - name: Check migration status
        run: php bin/console doctrine:migrations:status --env=test

      - name: Validate Doctrine mapping and schema
        run: php bin/console doctrine:schema:validate --env=test

      - name: Require a neutral Doctrine schema dump
        shell: bash
        run: |
          schema_output="$(php bin/console doctrine:schema:update --dump-sql --env=test)"
          printf '%s\n' "$schema_output"
          grep -q 'Nothing to update' <<< "$schema_output"

      - name: Require a neutral Doctrine migrations diff
        shell: bash
        run: |
          set +e
          diff_output="$(php bin/console doctrine:migrations:diff --env=test --no-interaction 2>&1)"
          diff_status=$?
          set -e
          printf '%s\n' "$diff_output"
          test "$diff_status" -ne 0
          grep -q 'No changes detected in your mapping information' <<< "$diff_output"
          git diff --exit-code -- migrations
          test -z "$(git ls-files --others --exclude-standard migrations)"

      - name: Reject legacy Doctrine type comments
        shell: bash
        run: |
          comment_output="$(php bin/console dbal:run-sql "SELECT IF(COUNT(*) = 0, 'DC2TYPE_COMMENTS_OK', 'DC2TYPE_COMMENTS_FOUND') AS result FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND COLUMN_COMMENT LIKE '%DC2Type%'" --env=test)"
          printf '%s\n' "$comment_output"
          grep -q 'DC2TYPE_COMMENTS_OK' <<< "$comment_output"

      - name: Run PHPUnit
        run: composer test

  docker-build:
    name: Docker build
    runs-on: ubuntu-latest
    permissions:
      contents: read

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Build application image
        run: docker build --tag oasb-ci:${{ github.sha }} .
