krafka 0.19.0

A pure Rust, async-native Apache Kafka client
Documentation
name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

env:
  CARGO_TERM_COLOR: always
  RUSTFLAGS: -Dwarnings

# Every job below runs a `just` recipe rather than an inline cargo command.
# The justfile is the single source of truth for what the checks are, so
# `just ci` locally runs exactly what CI runs and the two cannot drift.
# Feature strings in particular live in one place (justfile variables) instead
# of being duplicated across YAML.
#
# `ring` and `rustls-aws-lc-rs` are additive: when both are enabled,
# `rustls-aws-lc-rs` wins (see `auth::tls::resolve_crypto_provider`), so
# `--all-features` is valid and needs no hand-maintained exclusion list.

jobs:
  fmt:
    name: Format
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt
      - uses: extractions/setup-just@v3
      - run: just fmt-check

  clippy:
    name: Clippy
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: clippy
      - uses: Swatinem/rust-cache@v2
      - uses: extractions/setup-just@v3
      - run: just clippy

  check:
    name: Check
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - uses: extractions/setup-just@v3
      - run: just check

  test:
    name: Test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - uses: extractions/setup-just@v3
      - run: just test

  # `ring` is the DEFAULT backend, so it is what most downstream users compile.
  # It must be *tested*, not merely type-checked: the
  # `cfg(not(feature = "rustls-aws-lc-rs"))` arms in `auth/tls.rs` and
  # `schema_registry/http.rs` only run here.
  test-ring:
    name: Test (ring backend)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - uses: extractions/setup-just@v3
      - run: just test-ring

  # Guards the minimum viable configuration. A missing crypto backend used to
  # fail deep inside rustls; the `compile_error!` in lib.rs plus this job keep
  # that diagnostic honest, and the second command pins feature additivity.
  minimal-features:
    name: Minimal features
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - uses: extractions/setup-just@v3
      - run: just minimal-features

  # A network client's socket options, dual-stack connection racing and
  # filesystem handling are platform-sensitive. Without these jobs non-Linux
  # targets were never compiled at all.
  cross-platform:
    name: Test (${{ matrix.os }})
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [macos-latest, windows-latest]
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - uses: extractions/setup-just@v3
      - run: just test-cross-platform

  protocol-parity:
    name: Protocol version parity
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: extractions/setup-just@v3
      # Reads the vendored `xtask/kafka_protocol_snapshot.json`, so this job
      # needs no network and cannot flake on a GitHub API rate limit. Refresh
      # the snapshot deliberately with `just refresh-protocol-snapshot <tag>`.
      - run: just protocol-parity

  secret-debug:
    name: No secrets in Debug
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: extractions/setup-just@v3
      - run: just secret-debug

  version-check:
    name: Version consistency
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: extractions/setup-just@v3
      - run: just version-check

  test-reachability:
    name: No tests that cannot fail
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: extractions/setup-just@v3
      - run: just test-reachability

  config-reachability:
    name: No config field that cannot be set
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: extractions/setup-just@v3
      - run: just config-reachability

  protocol-reachability:
    name: No decoded field that is never read
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: extractions/setup-just@v3
      - run: just protocol-reachability

  doc:
    name: Documentation
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - uses: extractions/setup-just@v3
      - run: just doc

  supply-chain:
    name: Supply chain (cargo-deny)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: EmbarkStudios/cargo-deny-action@v2
        with:
          command: check advisories bans licenses sources

  integration:
    name: Integration Tests (Kafka ${{ matrix.kafka-version }})
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        include:
          # apache/kafka-native (GraalVM) is fast but segfaults on getpwuid in
          # some CI environments; use it only where it is known to be stable.
          - kafka-version: "3.9.0"
            kafka-image: "apache/kafka-native"
          # Kafka 4.x native images consistently segfault on GitHub Actions
          # (GraalVM Pwd.getpwuid bug); use the JVM image instead.
          #
          # 3.9 is the supported floor and 4.3 the protocol-parity target;
          # every minor between them runs so a version-specific regression
          # names the exact broker line that broke.
          - kafka-version: "4.0.0"
            kafka-image: "apache/kafka"
          - kafka-version: "4.1.0"
            kafka-image: "apache/kafka"
          - kafka-version: "4.2.0"
            kafka-image: "apache/kafka"
          - kafka-version: "4.3.0"
            kafka-image: "apache/kafka"
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - uses: extractions/setup-just@v3
      - name: Pre-pull Kafka image
        run: |
          for i in 1 2 3; do
            docker pull ${{ matrix.kafka-image }}:${{ matrix.kafka-version }} && break
            echo "Retry $i failed, waiting..."
            sleep 10
          done
      - run: just integration
        timeout-minutes: 45
        env:
          KAFKA_VERSION: ${{ matrix.kafka-version }}
          KAFKA_IMAGE: ${{ matrix.kafka-image }}

  # The SASL suite existed before this job did — it was runnable locally via
  # `just integration-sasl` but never ran in CI, so a SASL handshake
  # regression could only be caught by hand. Its harness uses the Confluent
  # image (the apache images do not ship the JAAS entrypoint hooks it needs).
  integration-sasl:
    name: Integration Tests (SASL)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - uses: extractions/setup-just@v3
      - name: Pre-pull Kafka image
        run: |
          for i in 1 2 3; do
            docker pull confluentinc/cp-kafka:7.5.0 && break
            echo "Retry $i failed, waiting..."
            sleep 10
          done
      - run: just integration-sasl
        timeout-minutes: 45

  # Redpanda speaks the Kafka wire protocol; krafka negotiates every API
  # version, so this suite pins the compatibility that negotiation is supposed
  # to buy — including the KIP-890 TV1 fallback (Redpanda has no server-side
  # TV2). `latest` rather than a pinned tag: the claim under test is "current
  # Redpanda works", and a pin would quietly narrow it to "one old Redpanda
  # once worked".
  integration-redpanda:
    name: Integration Tests (Redpanda)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - uses: extractions/setup-just@v3
      - name: Pre-pull Redpanda image
        run: |
          for i in 1 2 3; do
            docker pull redpandadata/redpanda:latest && break
            echo "Retry $i failed, waiting..."
            sleep 10
          done
      - run: just integration-redpanda
        timeout-minutes: 30

  msrv:
    name: MSRV (1.88)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@master
        with:
          toolchain: "1.88"
      - uses: Swatinem/rust-cache@v2
      # Not `just msrv`: that recipe shells out to `rustup run 1.88` so a
      # developer can check the MSRV without switching their default toolchain.
      # Here the job's toolchain already *is* 1.88, so the plain command is
      # both simpler and a genuine check that the pinned toolchain builds.
      - run: cargo check