name: pgclone CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

env:
  FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true

jobs:
  test:
    name: "PostgreSQL ${{ matrix.pg_version }}"
    runs-on: ubuntu-22.04
    strategy:
      fail-fast: false
      matrix:
        pg_version: [14, 15, 16, 17]

    # Only source-db runs in Docker.
    # Target PostgreSQL runs on the host so `make install` places the
    # .so where the server can find it via shared_preload_libraries.
    services:
      source-db:
        image: postgres:${{ matrix.pg_version }}
        env:
          POSTGRES_PASSWORD: testpass
          POSTGRES_DB: source_db
        ports:
          - 5433:5432
        options: >-
          --health-cmd "pg_isready -U postgres"
          --health-interval 5s
          --health-timeout 5s
          --health-retries 10

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

      - name: Install PostgreSQL ${{ matrix.pg_version }}
        run: |
          PG_VER=${{ matrix.pg_version }}
          sudo apt-get update -qq
          sudo apt-get install -y postgresql-common ca-certificates curl gnupg
          sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -y
          sudo apt-get update -qq
          if ! sudo apt-get install -y postgresql-$PG_VER postgresql-server-dev-$PG_VER libpq-dev build-essential; then
            echo "Primary install failed for PG${PG_VER}. Dumping package candidates..."
            apt-cache policy "postgresql-$PG_VER" || true
            apt-cache policy "postgresql-server-dev-$PG_VER" || true
            apt-cache search "^postgresql-[0-9]+" | sort | tail -n 40 || true
            echo "Retrying with postgresql-server-dev-all fallback..."
            sudo apt-get install -y "postgresql-$PG_VER" postgresql-server-dev-all libpq-dev build-essential
          fi

          # Verify install
          if [ -x "/usr/lib/postgresql/$PG_VER/bin/pg_config" ]; then
            /usr/lib/postgresql/$PG_VER/bin/pg_config --version
          else
            echo "Versioned pg_config not found, showing available pg_config:"
            command -v pg_config || true
            pg_config --version
          fi

      - name: Build pgclone
        run: |
          PG_CONFIG=/usr/lib/postgresql/${{ matrix.pg_version }}/bin/pg_config
          make PG_CONFIG=$PG_CONFIG CFLAGS="-Isrc"

      - name: Install pgclone
        run: |
          PG_CONFIG=/usr/lib/postgresql/${{ matrix.pg_version }}/bin/pg_config
          sudo make install PG_CONFIG=$PG_CONFIG
          echo "=== Installed shared library ==="
          ls -la "$($PG_CONFIG --pkglibdir)"/pgclone*

      - name: Start target PostgreSQL on the host
        run: |
          PG_VER=${{ matrix.pg_version }}
          PGBIN=/usr/lib/postgresql/$PG_VER/bin
          PGDATA="$RUNNER_TEMP/pg_target_$PG_VER"
          PGLOG="$RUNNER_TEMP/pg_target_$PG_VER.log"

          # Stop any pre-installed PostgreSQL to free ports/shmem
          # NOTE: do NOT pkill postgres — that would kill the Docker source-db container
          sudo systemctl stop postgresql 2>/dev/null || true

          rm -rf "$PGDATA"
          "$PGBIN/initdb" -D "$PGDATA" --username=postgres --auth=trust

          {
            echo "port = 5434"
            echo "listen_addresses = 'localhost'"
            echo "shared_buffers = '128MB'"
            echo "max_connections = 50"
            echo "huge_pages = off"
            echo "shared_preload_libraries = 'pgclone'"
            echo "unix_socket_directories = '/tmp'"
            echo "logging_collector = off"
          } >> "$PGDATA/postgresql.conf"

          # Verify pgclone.so is loadable
          echo "=== Checking pgclone.so dependencies ==="
          ldd "$($PGBIN/pg_config --pkglibdir)/pgclone.so" || true

          # Start server — show log immediately if it fails
          if ! "$PGBIN/pg_ctl" -D "$PGDATA" -l "$PGLOG" -w -t 30 start; then
            echo "=== PostgreSQL failed to start. Log output: ==="
            cat "$PGLOG"
            exit 1
          fi

          "$PGBIN/createdb" -h localhost -p 5434 -U postgres target_db

      - name: Seed source database
        run: |
          PGPASSWORD=testpass psql -h localhost -p 5433 -U postgres -d source_db \
            -f test/fixtures/seed.sql

      - name: Install pgTAP
        run: |
          git clone --depth 1 https://github.com/theory/pgtap.git /tmp/pgtap
          cd /tmp/pgtap
          make PG_CONFIG=/usr/lib/postgresql/${{ matrix.pg_version }}/bin/pg_config
          sudo make install PG_CONFIG=/usr/lib/postgresql/${{ matrix.pg_version }}/bin/pg_config
          psql -h localhost -p 5434 -U postgres -d target_db \
            -c "CREATE EXTENSION IF NOT EXISTS pgtap;"

      - name: Create pgclone extension and verify
        run: |
          psql -h localhost -p 5434 -U postgres -d target_db \
            -c "CREATE EXTENSION IF NOT EXISTS pgclone;"
          psql -h localhost -p 5434 -U postgres -d target_db \
            -c "SELECT pgclone_version();"

      - name: Set source conninfo
        run: |
          psql -h localhost -p 5434 -U postgres -d target_db \
            -c "ALTER DATABASE target_db SET app.source_conninfo = 'host=localhost port=5433 dbname=source_db user=postgres password=testpass';"

      - name: Run pgTAP tests
        run: |
          psql -h localhost -p 5434 -U postgres -d target_db \
            -f test/pgclone_test.sql

      - name: Show logs on failure
        if: failure()
        run: |
          PG_VER=${{ matrix.pg_version }}
          PGLOG="$RUNNER_TEMP/pg_target_$PG_VER.log"
          echo "=== PostgreSQL log ==="
          if [ -f "$PGLOG" ]; then
            tail -120 "$PGLOG"
          else
            echo "No target PostgreSQL log found at $PGLOG"
          fi
          echo "=== Port usage ==="
          sudo ss -tlnp | grep -E '5432|5433|5434' || true

      - name: Show build info
        if: always()
        run: |
          echo "PostgreSQL version: ${{ matrix.pg_version }}"
