# evennia/run-tests

# Use this action to run the Evennia test suite after database setup.
# This action handles Python setup, dependency installation, evennia initialization,
# and test execution with optional coverage.

name: Run Evennia tests
description: "Sets up Python, installs dependencies, initializes Evennia, and runs the test suite."

inputs:
  python-version:
    description: "Python version to use for testing."
    required: true
  testing-db:
    description: "Database type being tested (sqlite3, mysql, postgresql)."
    required: true
  coverage-test:
    description: "Whether to run tests with coverage (true/false)."
    required: false
    default: "false"
  needs-mysql-package:
    description: "Whether to install mysqlclient package (true/false)."
    required: false
    default: "false"
  needs-postgres-package:
    description: "Whether to install psycopg package (true/false)."
    required: false
    default: "false"
  coveralls-token:
    description: "Coveralls repository token (optional, only needed for coverage tests)."
    required: false
    default: ""

runs:
  using: "composite"

  steps:
    - name: Set up Python ${{ inputs.python-version }}
      uses: actions/setup-python@v4
      with:
        python-version: ${{ inputs.python-version }}
        cache: pip
        cache-dependency-path: |
          pyproject.toml

    - name: Install package dependencies
      run: |
        python -m pip install --upgrade pip
        pip install wheel
        if [ "${{ inputs.needs-postgres-package }}" == "true" ]; then
          pip install "psycopg[binary]>=3.1.0"   # req by postgresql
        fi
        if [ "${{ inputs.needs-mysql-package }}" == "true" ]; then
          pip install mysqlclient
        fi
        pip install coveralls
        pip install tblib
        pip install .
        pip install .[extra]
      shell: bash

    - name: Initialize evennia
      run: |
        evennia --init testing_mygame
        cp .github/workflows/${{ inputs.testing-db }}_settings.py testing_mygame/server/conf/settings.py
        cd testing_mygame
      shell: bash

    - name: Verify MySQL settings before migrations
      if: ${{ inputs.testing-db == 'mysql' }}
      run: |
        echo "Verifying MySQL server settings:"
        mysql -u evennia -ppassword evennia -e "SELECT @@innodb_default_row_format as row_format, @@character_set_server as charset, @@collation_server as collation;"
      shell: bash

    - name: Run migrations
      working-directory: testing_mygame
      run: |
        evennia migrate
      shell: bash

    - name: Set MySQL table row format after migrations (safety check)
      if: ${{ inputs.testing-db == 'mysql' }}
      run: |
        mysql -h 127.0.0.1 -u evennia -ppassword evennia -e "
        SELECT CONCAT('ALTER TABLE \`', TABLE_NAME, '\` ROW_FORMAT=DYNAMIC;') AS stmt
        FROM information_schema.TABLES
        WHERE TABLE_SCHEMA = 'evennia' AND ENGINE = 'InnoDB'
        " | grep -v stmt | while read stmt; do
          mysql -h 127.0.0.1 -u evennia -ppassword evennia -e "$stmt" 2>/dev/null || true
        done
      shell: bash

    - name: Collect static files
      working-directory: testing_mygame
      run: |
        evennia collectstatic --noinput
      shell: bash

    # For non-coverage tests, run them in parallel.
    - name: Run test suite
      if: ${{ inputs.coverage-test != 'true' }}
      working-directory: testing_mygame
      run: |
        if [ "${{ inputs.testing-db }}" = "postgresql" ]; then
          # PostgreSQL runs in CI have historically been sensitive to reusing
          # stale test DB state; run with explicit verbosity for easier diagnosis.
          evennia test --settings=settings --timing --verbosity 2 evennia
        else
          evennia test --settings=settings --keepdb --timing evennia
        fi
      shell: bash

    # OBS - it's important to not run the coverage tests with --parallel, it messes up the coverage
    # calculation!
    - name: Run test suite with coverage
      if: ${{ inputs.coverage-test == 'true' }}
      working-directory: testing_mygame
      run: |
        coverage run --rcfile=../pyproject.toml ../bin/unix/evennia test --settings=settings --timing evennia
        coverage combine
        coverage xml
        coverage --version
        coverage report | grep TOTAL
      shell: bash

    # we only want to run coverall once, so we only do it for the designated matrix combination(s)
    # it's also not critical if pushing to either service fails (happens for PRs since env is not
    # available outside of the evennia org)
    - name: Send data to Coveralls
      if: ${{ inputs.coverage-test == 'true' && github.ref == 'refs/heads/main' && inputs.coveralls-token != '' }}
      continue-on-error: true
      env:
        COVERALLS_REPO_TOKEN: ${{ inputs.coveralls-token }}
      working-directory: testing_mygame
      run: |
        coveralls
      shell: bash
