pgrdf 0.3.0

Rust-native PostgreSQL extension for RDF, SPARQL, SHACL and OWL reasoning
name: ci
on:
  pull_request:
  push:
    branches: [main]

env:
  CARGO_TERM_COLOR: always
  PGRX_VERSION: "0.16"

jobs:
  fmt:
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with: { components: rustfmt }
      - run: cargo fmt --all -- --check

  clippy:
    runs-on: ubuntu-22.04
    strategy:
      fail-fast: false
      matrix:
        pg: ["14", "15", "16", "17"]
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with: { components: clippy }
      - uses: ./.github/actions/setup-pgrx
        with: { pg: "${{ matrix.pg }}" }
      - run: cargo clippy --no-default-features --features pg${{ matrix.pg }} -- -D warnings

  test:
    runs-on: ubuntu-22.04
    strategy:
      fail-fast: false
      matrix:
        pg: ["14", "15", "16", "17"]
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: ./.github/actions/setup-pgrx
        with: { pg: "${{ matrix.pg }}" }
      - run: cargo pgrx test --no-default-features --features pg${{ matrix.pg }} pg${{ matrix.pg }}

  # Compose-based regression suite. Mirrors the local dev loop
  # (`just build-ext && just test-regression`) byte-for-byte: builds the
  # .so inside `compose/builder.Containerfile`, boots the
  # `postgres:17.4-bookworm` runtime with the artifacts bind-mounted,
  # then drives `tests/regression/sql/NN-*.sql` against it.
  #
  # Lives outside the per-PG matrix because the compose stack is
  # pinned to PG 17 today (see specs/ERRATA.v0.2.md E-006 for the
  # pgrx-vs-newer-PG block). Once PG 18 unblocks the matrix here
  # widens.
  regression:
    runs-on: ubuntu-22.04
    needs: test
    steps:
      - uses: actions/checkout@v4
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: Build extension artifacts
        env:
          DOCKER_BUILDKIT: "1"
        run: |
          set -euo pipefail
          docker build --target builder \
            -t pgrdf-builder-rust:pg17 \
            --build-arg PG_MAJOR=17 \
            -f compose/builder.Containerfile .
          docker build \
            -t pgrdf-builder:pg17 \
            --build-arg PG_MAJOR=17 \
            -f compose/builder.Containerfile .
          rm -rf compose/extensions/lib compose/extensions/share
          mkdir -p compose/extensions/lib compose/extensions/share/extension
          docker run --rm \
            -v "$PWD/compose/extensions:/export" \
            pgrdf-builder:pg17
          ls -la compose/extensions/lib compose/extensions/share/extension
      - name: Pre-pull postgres image (retry on transient Hub flakes)
        run: |
          set -euo pipefail
          # Docker Hub occasionally returns 5xx on anonymous pulls.
          # Retry up to 5× with a short backoff so a transient Hub
          # flake doesn't fail the whole job.
          for i in 1 2 3 4 5; do
            if docker pull docker.io/library/postgres:17.4-bookworm; then
              exit 0
            fi
            echo "pull attempt $i failed; sleeping before retry"
            sleep $((i * 5))
          done
          echo "pull failed after 5 attempts"
          exit 1
      - name: Boot compose Postgres
        run: |
          set -euo pipefail
          cd compose && docker compose up -d
          # The compose service includes a healthcheck; wait on it.
          for i in $(seq 1 30); do
            status=$(docker inspect -f '{{.State.Health.Status}}' pgrdf-postgres 2>/dev/null || echo "starting")
            echo "postgres health: $status"
            [ "$status" = "healthy" ] && break
            sleep 2
          done
          docker exec pgrdf-postgres pg_isready -U pgrdf -d pgrdf
      - name: Run regression suite
        env:
          PGRDF_RUNTIME: docker
        run: bash tests/regression/run.sh
      - name: Run W3C-shape SPARQL harness
        env:
          PGRDF_RUNTIME: docker
        # Phase 6 step 2: 18 hand-authored tests covering W3C SPARQL
        # 1.1 patterns. The full TTL-manifest runner against
        # w3c/rdf-tests is v0.4 work — see tests/w3c-sparql/README.md.
        run: bash tests/w3c-sparql/run.sh
      - name: Run LUBM-shape correctness gate
        env:
          PGRDF_RUNTIME: docker
        # Phase 6 step 3 scaffolding: 3 hand-authored LUBM-shape
        # queries against a small fixture. Real LUBM-1/10/100 with
        # the Java generator + cross-engine comparison vs Jena TDB /
        # Apache AGE is v0.4 work — see tests/perf/README.md.
        run: bash tests/perf/lubm-shape/run.sh
      - name: Postgres logs (on failure)
        if: failure()
        run: docker logs pgrdf-postgres | tail -100
      - name: Tear down compose
        if: always()
        run: cd compose && docker compose down -v

  # PLACEHOLDER — W3C SPARQL 1.1 + SHACL conformance runners + LUBM
  # benchmarks. Lives in `.github/workflows/regression-w3c.yml` with
  # `if: false` job gates until the runners exist. Tracked in
  # `docs/10-roadmap.md` Phase 6.