name: Release Gates

on:
  workflow_dispatch:
    inputs:
      run_fuzz_campaign:
        description: "Run the long-duration release fuzz campaign"
        required: false
        default: "false"
        type: choice
        options:
          - "false"
          - "true"
      fuzz_duration_seconds:
        description: "Per-target fuzz duration in seconds"
        required: false
        default: "86400"
      fuzz_jobs:
        description: "Concurrent fuzz targets"
        required: false
        default: "1"

jobs:
  supported-postgres:
    name: PostgreSQL ${{ matrix.pg }} release checks
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        include:
          - pg: "17"
            feature: pg17
          - pg: "18"
            feature: pg18
    steps:
      - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
      - uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # pinned
        with:
          toolchain: 1.96.0
          components: rustfmt, clippy
      - name: Install PostgreSQL ${{ matrix.pg }} development files
        run: |
          sudo apt-get update
          sudo apt-get install -y postgresql-common
          sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -y
          sudo apt-get install -y postgresql-${{ matrix.pg }} postgresql-server-dev-${{ matrix.pg }}
      - name: Install cargo-pgrx
        run: |
          source release/tool-versions.env
          cargo install cargo-pgrx --version "${CARGO_PGRX_VERSION}" --locked
      - name: Initialize pgrx
        run: cargo pgrx init --pg${{ matrix.pg }} /usr/lib/postgresql/${{ matrix.pg }}/bin/pg_config
      - name: Check context-pg
        run: cargo check -p context-pg --no-default-features --features ${{ matrix.feature }}
      - name: Generate extension SQL
        run: |
          mkdir -p target/release-sql
          cargo pgrx schema -p context-pg pg${{ matrix.pg }} --out target/release-sql/pg${{ matrix.pg }}.sql
          {
            echo "command: cargo pgrx schema -p context-pg pg${{ matrix.pg }} --out target/release-sql/pg${{ matrix.pg }}.sql"
            echo "commit: $(git rev-parse --verify HEAD)"
            echo "artifact: target/release-sql/pg${{ matrix.pg }}.sql"
            echo "sha256: $(shasum -a 256 target/release-sql/pg${{ matrix.pg }}.sql | awk '{print $1}')"
          } > target/release-sql/pg${{ matrix.pg }}.sql.build.log
      - name: Check checked-in extension SQL
        if: matrix.pg == '17'
        run: scripts/check-extension-sql-artifact.sh --pg-major 17
      - name: Record release artifact report
        run: |
          scripts/run-release-artifact-report.sh \
            --artifact target/release-sql/pg${{ matrix.pg }}.sql \
            --out-dir target/release-artifacts/pg${{ matrix.pg }}
      - name: Upload generated SQL artifact
        if: always()
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
        with:
          name: postgres-${{ matrix.pg }}-release-sql
          path: |
            target/release-sql/pg${{ matrix.pg }}.sql
            target/release-sql/pg${{ matrix.pg }}.sql.build.log
      - name: Run pgrx SQL tests
        if: matrix.pg == '17'
        run: scripts/run-v1-pgrx-tests.sh
      - name: Run heavy PostgreSQL matrix
        run: scripts/run-postgres-matrix-gates.sh --major ${{ matrix.pg }} --mode heavy --out-dir target/postgres-matrix/pg${{ matrix.pg }}-heavy
      - name: Upload PostgreSQL matrix report
        if: always()
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
        with:
          name: postgres-${{ matrix.pg }}-matrix-report
          path: target/postgres-matrix/pg${{ matrix.pg }}-heavy
      - name: Upload release artifact report
        if: always()
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
        with:
          name: postgres-${{ matrix.pg }}-release-artifact-report
          path: target/release-artifacts/pg${{ matrix.pg }}

  release-artifact-summary:
    name: Combined release artifact evidence
    runs-on: ubuntu-latest
    needs: supported-postgres
    if: ${{ always() }}
    steps:
      - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
      - uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # pinned
        with:
          toolchain: 1.96.0
      - name: Install cargo-pgrx
        run: |
          source release/tool-versions.env
          cargo install cargo-pgrx --version "${CARGO_PGRX_VERSION}" --locked
      - name: Download generated SQL artifacts
        uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
        with:
          pattern: postgres-*-release-sql
          path: target/release-sql
          merge-multiple: true
      - name: Record combined release artifact report
        run: |
          scripts/run-release-artifact-report.sh \
            --artifact target/release-sql/pg17.sql \
            --artifact target/release-sql/pg18.sql \
            --out-dir target/release-artifacts/all-postgres
      - name: Upload combined release artifact report
        if: always()
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
        with:
          name: combined-release-artifact-report
          path: target/release-artifacts/all-postgres

  postgres-matrix-summary:
    name: Combined PostgreSQL matrix evidence
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
      - uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # pinned
        with:
          toolchain: 1.96.0
          components: rustfmt, clippy
      - name: Install supported PostgreSQL development files
        run: |
          sudo apt-get update
          sudo apt-get install -y postgresql-common
          sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -y
          sudo apt-get install -y \
            postgresql-17 postgresql-server-dev-17 \
            postgresql-18 postgresql-server-dev-18
      - name: Install cargo-pgrx
        run: |
          source release/tool-versions.env
          cargo install cargo-pgrx --version "${CARGO_PGRX_VERSION}" --locked
      - name: Record combined PostgreSQL matrix report
        run: |
          scripts/run-postgres-matrix-gates.sh \
            --mode all \
            --out-dir target/postgres-matrix/all-postgres
      - name: Upload combined PostgreSQL matrix report
        if: always()
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
        with:
          name: combined-postgres-matrix-report
          path: target/postgres-matrix/all-postgres

  worker-platform-builds:
    name: Worker ${{ matrix.platform }} contract
    runs-on: ${{ matrix.runner }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - runner: ubuntu-24.04
            platform: linux-x86_64
          - runner: ubuntu-24.04-arm
            platform: linux-aarch64
          - runner: macos-15-intel
            platform: darwin-x86_64
          - runner: macos-15
            platform: darwin-aarch64
    steps:
      - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
      - uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # pinned
        with:
          toolchain: 1.96.0
          components: clippy
      - name: Verify runner architecture
        run: |
          case "${{ matrix.platform }}:$(uname -m)" in
            linux-x86_64:x86_64|darwin-x86_64:x86_64|linux-aarch64:aarch64|darwin-aarch64:arm64) ;;
            *) echo "worker runner architecture mismatch" >&2; exit 1 ;;
          esac
      - name: Build release worker without test hooks
        run: cargo build --release -p pgcontext-worker --bin pgcontext-worker
      - name: Test worker contracts
        run: |
          cargo test -p pgcontext-worker --all-targets
          cargo test -p pgcontext-worker --features worker-test-hooks --test worker_binary
          cargo clippy -p pgcontext-worker --all-targets -- -D warnings
      - name: Verify frozen platform manifest
        run: |
          cargo run -q -p context-test --bin p12_semantic_rerank_manifest \
            | awk -F '\t' -v platform="${{ matrix.platform }}" \
                '$1 == "required_platforms" && index("," $2 ",", "," platform ",") { found=1 } END { exit !found }'
      - name: Upload worker binary
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
        with:
          name: pgcontext-worker-${{ matrix.platform }}
          path: target/release/pgcontext-worker

  platform-builds:
    name: ${{ matrix.os }} fast gates
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest]
    steps:
      - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
      - uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # pinned
        with:
          toolchain: 1.96.0
          components: rustfmt, clippy
      - name: Format
        run: cargo fmt --check
      - name: Lint
        run: cargo clippy --workspace --exclude context-pg --all-targets --all-features -- -D warnings
      - name: Test
        run: cargo test --workspace --exclude context-pg --all-features
      - name: Docs
        run: cargo doc --workspace --exclude context-pg --no-deps
      - name: Public docs navigation, links, and drift
        run: scripts/check-public-docs.py --check
      - name: Public docs gate smoke
        run: tests/shell/check_public_docs_smoke.sh
      - name: Parity matrix
        run: scripts/check-parity-matrix.sh
      - name: Parity matrix smoke
        run: tests/shell/check_parity_matrix_smoke.sh
      - name: Supported feature marker smoke
        run: tests/shell/check_supported_feature_markers_smoke.sh
      - name: Benchmark report smoke
        run: tests/shell/run_benchmark_report_smoke.sh
      - name: Release artifact report smoke
        run: tests/shell/run_release_artifact_report_smoke.sh
      - name: Release gates workflow smoke
        run: tests/shell/check_release_gates_workflow_smoke.sh
      - name: Security review report smoke
        run: tests/shell/run_security_review_report_smoke.sh
      - name: PostgreSQL matrix report smoke
        run: tests/shell/run_postgres_matrix_gates_smoke.sh
      - name: Upgrade matrix staging smoke
        run: tests/shell/upgrade_matrix_staging_smoke.sh
      - name: Platform build report smoke
        run: tests/shell/run_platform_build_report_smoke.sh
      - name: Fast release gate report smoke
        run: tests/shell/run_fast_release_gate_report_smoke.sh
      - name: Source hygiene
        run: scripts/check-source-hygiene.sh
      - name: Platform build report
        run: |
          case "${RUNNER_OS}" in
            Linux) platform=linux ;;
            macOS) platform=macos ;;
            *)
              echo "unsupported runner OS for platform report: ${RUNNER_OS}" >&2
              exit 2
              ;;
          esac
          scripts/run-platform-build-report.sh \
            --platform "${platform}" \
            --out-dir "target/platform-builds/${platform}"
      - name: Upload platform build report
        if: always()
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
        with:
          name: platform-build-report-${{ matrix.os }}
          path: target/platform-builds

  platform-build-summary:
    name: Combined platform build evidence
    runs-on: ubuntu-latest
    needs: platform-builds
    if: ${{ always() }}
    steps:
      - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
      - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
        with:
          pattern: platform-build-report-*
          path: target/platform-builds
          merge-multiple: true
      - name: Merge platform build reports
        run: |
          scripts/run-platform-build-report.sh \
            --merge-report target/platform-builds/linux/report.md \
            --merge-report target/platform-builds/macos/report.md \
            --out-dir target/platform-builds/release-candidate
      - name: Upload combined platform build report
        if: always()
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
        with:
          name: combined-platform-build-report
          path: target/platform-builds/release-candidate

  supply-chain:
    name: Supply chain and licenses
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
      - uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # pinned
        with:
          toolchain: 1.96.0
      - name: Install cargo-audit
        run: |
          source release/tool-versions.env
          cargo install cargo-audit --version "${CARGO_AUDIT_VERSION}" --locked
      - name: Install cargo-deny
        run: |
          source release/tool-versions.env
          cargo install cargo-deny --version "${CARGO_DENY_VERSION}" --locked
      - name: Audit
        run: cargo audit
      - name: Deny
        run: cargo deny check
      - name: Supply-chain report smoke
        run: tests/shell/run_supply_chain_report_smoke.sh

  nightly-hardening:
    name: Nightly hardening smoke
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
      - uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # nightly
        with:
          toolchain: nightly
          components: miri, rust-src
      - uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # pinned
        with:
          toolchain: 1.96.0
      - name: Fuzz target compile check
        run: cargo check --manifest-path fuzz/Cargo.toml --bins
      - name: Fuzz campaign report smoke
        run: tests/shell/run_fuzz_campaigns_smoke.sh
      - name: Storage Miri smoke
        run: |
          env MIRIFLAGS=-Zmiri-disable-isolation cargo +nightly miri test -p context-storage --test segment_format
          env MIRIFLAGS=-Zmiri-disable-isolation cargo +nightly miri test -p context-storage --test mapped_hnsw_view
      - name: Mapped generation AddressSanitizer subprocess
        run: env RUSTFLAGS=-Zsanitizer=address cargo +nightly test -Zbuild-std --target x86_64-unknown-linux-gnu -p context-storage --test mapped_generation_subprocess
      - name: Mapped generation ThreadSanitizer subprocess
        run: env RUSTFLAGS=-Zsanitizer=thread cargo +nightly test -Zbuild-std --target x86_64-unknown-linux-gnu -p context-storage --test mapped_generation_subprocess

  fuzz-release-campaign:
    name: Release fuzz campaign
    runs-on: ubuntu-latest
    if: ${{ github.event_name == 'workflow_dispatch' && inputs.run_fuzz_campaign == 'true' }}
    steps:
      - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
      - uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # nightly
        with:
          toolchain: nightly
      - uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # pinned
        with:
          toolchain: 1.96.0
      - name: Install cargo-fuzz
        run: cargo +nightly install cargo-fuzz --locked
      - name: Run release fuzz campaign
        run: |
          scripts/run-fuzz-campaigns.sh \
            --duration "${{ inputs.fuzz_duration_seconds }}" \
            --jobs "${{ inputs.fuzz_jobs }}" \
            --out-dir target/fuzz-campaigns/release-candidate
      - name: Upload release fuzz campaign report
        if: always()
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
        with:
          name: release-fuzz-campaign-report
          path: target/fuzz-campaigns/release-candidate
