drizzle 0.1.7

A type-safe SQL query builder for Rust
Documentation
name: CI

on:
  # CI runs on pull requests only. The PR's head commit is the same code that
  # gets merged into main (modulo conflict resolution), so re-running on the
  # push event after merge would duplicate the work that already gated the PR.
  # Branch protection should require this workflow to be green before merge.
  pull_request:
    branches: [main]

env:
  CARGO_TERM_COLOR: always
  RUST_BACKTRACE: 1

jobs:
  lint:
    name: Lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Install Rust
        uses: dtolnay/rust-toolchain@nightly
        with:
          components: rustfmt, clippy

      - name: Cache Rust dependencies
        uses: Swatinem/rust-cache@v2
        with:
          shared-key: nightly
          save-if: ${{ github.ref == 'refs/heads/main' }}

      - name: Check formatting
        run: cargo fmt --all -- --check

      - name: Run clippy
        run: cargo clippy --workspace --all-targets --all-features -- -D warnings

  test-matrix:
    name: Test Matrix
    runs-on: ubuntu-latest
    needs: lint
    outputs:
      sqlite: ${{ steps.matrix.outputs.sqlite }}
      pg: ${{ steps.matrix.outputs.pg }}
    steps:
      - uses: actions/checkout@v6

      - name: Install just
        uses: taiki-e/install-action@just

      - name: Generate matrices
        id: matrix
        run: |
          echo "sqlite=$(just test::sqlite-matrix-json)" >> $GITHUB_OUTPUT
          echo "pg=$(just test::pg-matrix-json)" >> $GITHUB_OUTPUT

  test-sqlite:
    name: "test::sqlite (${{ matrix.features }})"
    runs-on: ubuntu-latest
    needs: test-matrix
    strategy:
      fail-fast: false
      matrix:
        features: ${{ fromJson(needs.test-matrix.outputs.sqlite) }}
    steps:
      - uses: actions/checkout@v6

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable

      - name: Install just
        uses: taiki-e/install-action@just

      - name: Cache Rust dependencies
        uses: Swatinem/rust-cache@v2
        with:
          shared-key: stable
          save-if: ${{ github.ref == 'refs/heads/main' }}

      - name: Run tests
        run: just test::sqlite "${{ matrix.features }}"

      - name: Run example
        if: contains(matrix.features, 'uuid')  && startsWith(matrix.features, 'rusqlite')
        run: cargo run --example rusqlite --features "rusqlite,uuid,serde"

  test-pg:
    name: "test::pg (${{ matrix.features }})"
    runs-on: ubuntu-latest
    needs: test-matrix
    strategy:
      fail-fast: false
      matrix:
        features: ${{ fromJson(needs.test-matrix.outputs.pg) }}
    steps:
      - uses: actions/checkout@v6

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable

      - name: Install just
        uses: taiki-e/install-action@just

      - name: Cache Rust dependencies
        uses: Swatinem/rust-cache@v2
        with:
          shared-key: stable
          save-if: ${{ github.ref == 'refs/heads/main' }}

      - name: Run tests
        run: just test::pg "${{ matrix.features }}"

  test-turso:
    name: Test (Turso - Experimental)
    runs-on: ubuntu-latest
    needs: lint
    continue-on-error: true
    steps:
      - uses: actions/checkout@v6

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable

      - name: Cache Rust dependencies
        uses: Swatinem/rust-cache@v2
        with:
          shared-key: stable
          save-if: ${{ github.ref == 'refs/heads/main' }}

      - name: Run tests
        id: test
        run: |
          mkdir -p test-output
          cargo test --workspace --features "turso,uuid,serde" 2>&1 | tee test-output/output.txt || true

          if grep -q "FAILED" test-output/output.txt; then
            echo "has_failures=true" >> $GITHUB_OUTPUT
            echo "::warning::Turso tests failed (expected - turso is experimental)"
          else
            echo "has_failures=false" >> $GITHUB_OUTPUT
            echo "::notice::Turso tests passed"
          fi

      - name: Extract failure reports
        id: extract
        if: steps.test.outputs.has_failures == 'true'
        run: |
          python3 -c "
          import sys

          text = open('test-output/output.txt').read()
          reports = []
          in_report = False
          buffer = []
          prev_line = ''
          box_chars = set('╔═╗║╚╝├─┤│')

          for line in text.splitlines(True):
              if 'TEST FAILURE REPORT' in line:
                  in_report = True
                  buffer = []
                  if any(c in box_chars for c in prev_line):
                      buffer.append(prev_line)
                  buffer.append(line)
              elif in_report:
                  if line.strip() == '' or any(c in box_chars for c in line):
                      buffer.append(line)
                  else:
                      reports.append(''.join(buffer))
                      buffer = []
                      in_report = False
              prev_line = line

          if buffer:
              reports.append(''.join(buffer))

          if reports:
              with open('test-output/failure-reports.txt', 'w') as f:
                  for i, report in enumerate(reports):
                      if i > 0:
                          f.write('\n' + '=' * 80 + '\n\n')
                      f.write(report)
              print(f'Extracted {len(reports)} failure report(s)')
          else:
              print('No structured failure reports found in output')
          "

          # Set output based on whether the file was created
          if [ -f test-output/failure-reports.txt ]; then
            echo "has_reports=true" >> $GITHUB_OUTPUT
          fi

      - name: Upload failure reports
        if: steps.extract.outputs.has_reports == 'true'
        uses: actions/upload-artifact@v7
        with:
          name: turso-failure-reports
          path: test-output/failure-reports.txt
          retention-days: 7

  docs:
    name: Documentation
    runs-on: ubuntu-latest
    needs: lint
    steps:
      - uses: actions/checkout@v6

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable

      - name: Cache Rust dependencies
        uses: Swatinem/rust-cache@v2
        with:
          shared-key: stable
          save-if: ${{ github.ref == 'refs/heads/main' }}

      - name: Check documentation
        run: cargo doc --workspace --all-features --no-deps

  build-matrix:
    name: Build (${{ matrix.rust }})
    runs-on: ubuntu-latest
    needs: lint
    strategy:
      matrix:
        rust: [stable, nightly]

    steps:
      - uses: actions/checkout@v6

      - name: Install Rust ${{ matrix.rust }}
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: ${{ matrix.rust }}

      - name: Cache Rust dependencies
        uses: Swatinem/rust-cache@v2
        with:
          shared-key: ${{ matrix.rust }}
          save-if: ${{ github.ref == 'refs/heads/main' }}

      - name: Build
        run: cargo build --workspace --all-features

  msrv:
    name: MSRV Check
    runs-on: ubuntu-latest
    needs: lint
    steps:
      - uses: actions/checkout@v6

      - name: Get Rust version
        id: rust-version
        run: |
          RUST_VERSION=$(grep '^rust-version = ' Cargo.toml | sed 's/rust-version = "\(.*\)"/\1/')
          echo "version=$RUST_VERSION" >> $GITHUB_OUTPUT

      - name: Install Rust (MSRV)
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: ${{ steps.rust-version.outputs.version }}

      - name: Cache Rust dependencies
        uses: Swatinem/rust-cache@v2
        with:
          shared-key: msrv
          save-if: ${{ github.ref == 'refs/heads/main' }}

      - name: Check MSRV
        run: cargo check --workspace --all-targets --all-features