preview-glide-rust 0.2.0

Valkey GLIDE — native Rust client for Valkey and Redis OSS, built on glide-core.
# CI for the glide-rust crate.
#
# Parity with the upstream valkey-glide test strategy: the `test` job runs as a
# matrix over **engine version × architecture**, mirroring
# `valkey-glide/.github/json_matrices/engine-matrix.json` (valkey 8.1/8.0/7.2 +
# redis 7.2) and `build-matrix.json` (x86_64 + aarch64). Because our integration
# harness *spawns a local server binary* (via VALKEY_SERVER_PATH), each cell
# builds the matching engine from source and caches it.
#
# The crate links glide-core + its vendored redis-rs via *git* deps pinned to a
# rev of valkey-io/valkey-glide, so Cargo fetches them automatically (no monorepo
# checkout). crates.io publishing remains blocked by git deps (see README).
name: CI

on:
    push:
        branches: [master, main]
    pull_request: {}

permissions:
    contents: read

jobs:
    lint:
        runs-on: ubuntu-24.04
        steps:
            - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
            - name: Install Rust toolchain
              run: rustup toolchain install stable --profile minimal --component rustfmt,clippy && rustup default stable
            - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
              with:
                  path: target
                  key: x86_64-unknown-linux-gnu-lint
            - name: Format
              run: cargo fmt --all -- --check
            - name: Clippy (all features)
              run: cargo clippy --all-features --all-targets -- -D warnings
            - name: Clippy (no features)
              run: cargo clippy --all-targets -- -D warnings
            - name: Docs
              env:
                  RUSTDOCFLAGS: "-D warnings"
              run: cargo doc --no-deps --document-private-items

    build:
        runs-on: ubuntu-24.04
        steps:
            - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
            - name: Install Rust toolchain
              run: rustup toolchain install stable --profile minimal && rustup default stable
            - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
              with:
                  path: target
                  key: x86_64-unknown-linux-gnu-build
            - name: Build (debug)
              run: cargo build --verbose
            - name: Build (release)
              run: cargo build --release --verbose
            - name: Feature check
              run: |
                  cargo check --no-default-features
                  cargo check --all-features
                  cargo check --benches --all-features

    test:
        name: test (${{ matrix.engine.type }} ${{ matrix.engine.version }}, ${{ matrix.arch }})
        runs-on: ${{ matrix.runner }}
        # Don't let one engine/arch combination cancel the others.
        strategy:
            fail-fast: false
            matrix:
                include:
                    # ---- x86_64 ----
                    - { runner: ubuntu-24.04, arch: x64, engine: { type: valkey, version: "8.1" } }
                    - { runner: ubuntu-24.04, arch: x64, engine: { type: valkey, version: "8.0" } }
                    - { runner: ubuntu-24.04, arch: x64, engine: { type: valkey, version: "7.2" } }
                    - { runner: ubuntu-24.04, arch: x64, engine: { type: redis, version: "7.2" } }
                    # ---- aarch64 (GitHub-hosted ARM; requires public repo or paid runners) ----
                    - { runner: ubuntu-24.04-arm, arch: arm64, engine: { type: valkey, version: "8.1" } }
                    - { runner: ubuntu-24.04-arm, arch: arm64, engine: { type: valkey, version: "8.0" } }
                    - { runner: ubuntu-24.04-arm, arch: arm64, engine: { type: valkey, version: "7.2" } }
                    - { runner: ubuntu-24.04-arm, arch: arm64, engine: { type: redis, version: "7.2" } }
        steps:
            - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
            - name: Install Rust toolchain
              run: rustup toolchain install stable --profile minimal && rustup default stable
            - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
              with:
                  path: target
                  key: ${{ matrix.arch }}-test-${{ matrix.engine.type }}-${{ matrix.engine.version }}
            - name: Cache ${{ matrix.engine.type }} ${{ matrix.engine.version }} build
              id: engine-cache
              uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
              with:
                  path: ~/engine-install
                  key: engine-${{ matrix.arch }}-${{ matrix.engine.type }}-${{ matrix.engine.version }}
            - name: Build ${{ matrix.engine.type }} ${{ matrix.engine.version }} from source
              if: steps.engine-cache.outputs.cache-hit != 'true'
              run: |
                  set -euo pipefail
                  sudo apt-get update
                  sudo apt-get install -y build-essential pkg-config libssl-dev tcl
                  if [ "${{ matrix.engine.type }}" = "valkey" ]; then
                      REPO="https://github.com/valkey-io/valkey.git"
                  else
                      REPO="https://github.com/redis/redis.git"
                  fi
                  git clone --depth 1 --branch "${{ matrix.engine.version }}" "$REPO" engine-src
                  make -C engine-src -j"$(nproc)" BUILD_TLS=yes
                  mkdir -p "$HOME/engine-install"
                  cp engine-src/src/*-server engine-src/src/*-cli "$HOME/engine-install/"
            - name: Register engine on PATH
              run: |
                  set -euo pipefail
                  echo "$HOME/engine-install" >> "$GITHUB_PATH"
                  if [ -x "$HOME/engine-install/valkey-server" ]; then
                      echo "VALKEY_SERVER_PATH=$HOME/engine-install/valkey-server" >> "$GITHUB_ENV"
                  else
                      echo "VALKEY_SERVER_PATH=$HOME/engine-install/redis-server" >> "$GITHUB_ENV"
                  fi
            - name: Server version
              run: "${VALKEY_SERVER_PATH} --version"
            - name: Build tests
              run: cargo test --no-run --verbose
            - name: Test
              run: cargo test --verbose

    coverage:
        runs-on: ubuntu-24.04
        steps:
            - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
            - name: Install Rust toolchain
              run: rustup toolchain install stable --profile minimal --component llvm-tools-preview && rustup default stable
            - name: Install cargo-llvm-cov
              run: cargo install --locked cargo-llvm-cov
            - name: Install a Valkey/Redis server
              run: |
                  sudo apt-get update
                  sudo apt-get install -y valkey-server || sudo apt-get install -y redis-server
                  echo "VALKEY_SERVER_PATH=$(command -v valkey-server || command -v redis-server)" >> "$GITHUB_ENV"
            - name: Coverage
              # Cap test parallelism: under llvm-cov instrumentation the whole
              # suite runs at once and each integration test spawns its own
              # ephemeral server. Limiting to 2 threads keeps only a couple of
              # instrumented servers alive concurrently, avoiding server-startup
              # connect timeouts on the shared runner.
              run: cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info --summary-only -- --test-threads=2
            - name: Upload coverage to Codecov
              uses: codecov/codecov-action@v7
              with:
                  files: lcov.info
                  # Private repos require a CODECOV_TOKEN repo secret; public repos
                  # work tokenless. Don't fail CI if upload can't authenticate.
                  fail_ci_if_error: false
              env:
                  CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

    deny:
        runs-on: ubuntu-24.04
        steps:
            - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
            - name: Install Rust toolchain
              run: rustup toolchain install stable --profile minimal && rustup default stable
            # Cache the crates.io index/cache, the git-dependency clones
            # (glide-core/redis from valkey-io/valkey-glide), and the cargo-deny
            # binary. This avoids a cold registry+git fetch on every run — the
            # main source of transient failures for this job, since resolving the
            # git deps forces a crates.io index update that occasionally 403s.
            - name: Cache cargo registry, git deps, and cargo-deny
              uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
              with:
                  path: |
                      ~/.cargo/registry/index
                      ~/.cargo/registry/cache
                      ~/.cargo/git/db
                      ~/.cargo/bin/cargo-deny
                  key: deny-${{ hashFiles('Cargo.lock') }}
                  restore-keys: |
                      deny-
            - name: Install cargo-deny
              run: command -v cargo-deny >/dev/null 2>&1 || cargo install --locked cargo-deny
            - name: cargo-deny (retry transient network errors only)
              run: |
                  set -uo pipefail
                  for attempt in 1 2 3; do
                      out="$(cargo deny check 2>&1)"; status=$?
                      echo "$out"
                      if [ "$status" -eq 0 ]; then
                          exit 0
                      fi
                      # Retry only spurious registry/network failures; a real
                      # advisory/license/ban/source violation fails immediately.
                      if echo "$out" | grep -qiE 'spurious network error|failed to fetch|Updating crates.io index|http status code: (403|429|5[0-9][0-9])|failed to get .* as a dependency'; then
                          echo "::warning::cargo deny hit a transient network error (attempt ${attempt}); retrying..."
                          sleep $((attempt * 15))
                      else
                          echo "::error::cargo deny reported a policy violation (not a network error)."
                          exit "$status"
                      fi
                  done
                  echo "::error::cargo deny still failing after retries (persistent network issue)."
                  exit 1