name: Docker images

on:
  push:
    tags: [ 'v*' ]
  pull_request:
    paths:
      - 'Dockerfile'
      - '.dockerignore'
      - 'docker/**'
      - 'Makefile'
      - 'pg_integrity_checksums*'
      - '.github/workflows/docker.yml'
  workflow_dispatch:

permissions:
  contents: read
  packages: write

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

jobs:
  build:
    name: Build PostgreSQL ${{ matrix.pg }} image
    if: github.event_name != 'pull_request'
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        pg: [12, 13, 14, 15, 16, 17, 18]

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

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Log in to GHCR
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build and push
        uses: docker/build-push-action@v6
        with:
          context: .
          file: ./Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          build-args: |
            PG_MAJOR=${{ matrix.pg }}
          tags: |
            ghcr.io/victornagibator/pg_integrity_checksums:pg${{ matrix.pg }}-${{ github.ref_name }}
            ghcr.io/victornagibator/pg_integrity_checksums:pg${{ matrix.pg }}

  smoke:
    name: Smoke test PostgreSQL 16 image
    runs-on: ubuntu-latest

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

      - name: Build local image
        run: docker build --build-arg PG_MAJOR=16 -t pg-integrity-checksums:smoke .

      - name: Run image and verify extension
        run: |
          set -euo pipefail
          docker run -d --name pg-integrity-smoke \
            -e POSTGRES_PASSWORD=smoke \
            -e POSTGRES_DB=smoke \
            pg-integrity-checksums:smoke

          cleanup() { docker rm -f pg-integrity-smoke >/dev/null 2>&1 || true; }
          trap cleanup EXIT
          trap 'docker logs pg-integrity-smoke >&2 || true' ERR

          # pg_isready only says the postmaster is accepting connections; the
          # POSTGRES_DB creation and the init script run afterwards.  Wait for
          # the extension itself, not just the server socket.
          extension_ready=0
          for i in $(seq 1 60); do
            if docker exec pg-integrity-smoke psql -U postgres -d smoke -tAc \
              "SELECT 1 FROM pg_extension WHERE extname = 'pg_integrity_checksums'" \
              2>/dev/null | grep -qx 1; then
              extension_ready=1
              break
            fi
            sleep 1
          done

          if [ "$extension_ready" -ne 1 ]; then
            echo "extension was not created in the smoke database" >&2
            exit 1
          fi

          docker exec pg-integrity-smoke psql -U postgres -d smoke -v ON_ERROR_STOP=1 \
            -c "SELECT extversion FROM pg_extension WHERE extname = 'pg_integrity_checksums';" \
            -c "SELECT pg_table_logical_checksum('pg_class'::regclass) IS NOT NULL AS checksum_ok;"
