name: CI

on:
  push:
    branches: [ "master" ]
  pull_request: {}
  merge_group:
    branches: [ "master" ]

env:
  RUSTFLAGS: "-D warnings"

jobs:

  rustfmt:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: hecrj/setup-rust-action@v2
      with:
        components: rustfmt
    - run: cargo fmt --all --check

  deny:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: hecrj/setup-rust-action@v2
    - uses: taiki-e/install-action@cargo-deny
    - run: cargo deny check

  clippy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: hecrj/setup-rust-action@v2
      with:
        components: clippy
    - uses: taiki-e/install-action@protoc
    - uses: Swatinem/rust-cache@v2
    - run: cargo clippy --workspace --all-features --all-targets

  codegen:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: hecrj/setup-rust-action@v2
    - uses: Swatinem/rust-cache@v2
    - run: cargo run --package codegen
    - run: git diff --exit-code

  udeps:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: dtolnay/rust-toolchain@master
      with:
        toolchain: nightly-2024-12-01
    - uses: taiki-e/install-action@cargo-hack
    - uses: taiki-e/install-action@cargo-udeps
    - uses: taiki-e/install-action@protoc
    - uses: Swatinem/rust-cache@v2
    - run: cargo hack udeps --workspace --exclude-features=_tls-any,tls,tls-aws-lc,tls-ring --each-feature
    - run: cargo udeps --package tonic --features tls-ring,transport
    - run: cargo udeps --package tonic --features tls-ring,server
    - run: cargo udeps --package tonic --features tls-ring,channel
    - run: cargo udeps --package tonic --features tls-aws-lc,transport
    - run: cargo udeps --package tonic --features tls-aws-lc,server
    - run: cargo udeps --package tonic --features tls-aws-lc,channel

  check:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macOS-latest, windows-latest]
    steps:
    - uses: actions/checkout@v4
    - uses: hecrj/setup-rust-action@v2
    - uses: taiki-e/install-action@cargo-hack
    - uses: taiki-e/install-action@protoc
    - uses: Swatinem/rust-cache@v2
    - name: Check features
      run: cargo hack check --workspace --no-private --each-feature --no-dev-deps
    - name: Check tonic feature powerset
      run: cargo hack check --package tonic --feature-powerset --depth 2
    - name: Check all targets
      run: cargo check --workspace --all-targets --all-features

  msrv:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: hecrj/setup-rust-action@v2
    - name: Resolve MSRV aware dependencies
      run: cargo update
      env:
        CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS: fallback
    - name: Get MSRV from manifest file
      id: msrv
      run: echo "version=$(yq '.workspace.package.rust-version' Cargo.toml)" >> $GITHUB_OUTPUT
    - uses: hecrj/setup-rust-action@v2
      with:
        rust-version: ${{ steps.msrv.outputs.version }}
    - uses: taiki-e/install-action@cargo-no-dev-deps
    - uses: Swatinem/rust-cache@v2
    - run: cargo no-dev-deps --no-private check --all-features
    - run: cargo no-dev-deps --no-private doc --no-deps --all-features
      env:
        RUSTDOCFLAGS: "-D warnings"

  test:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macOS-latest, windows-latest]
    steps:
    - uses: actions/checkout@v4
    - uses: hecrj/setup-rust-action@v2
    - uses: taiki-e/install-action@protoc
    - uses: taiki-e/install-action@cargo-hack
    - uses: taiki-e/install-action@cargo-nextest
    - uses: Swatinem/rust-cache@v2
    - run: cargo nextest run --workspace --all-features
      env:
        QUICKCHECK_TESTS: 1000  # run a lot of quickcheck iterations

  doc-test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: hecrj/setup-rust-action@v2
    - uses: taiki-e/install-action@cargo-hack
    - uses: Swatinem/rust-cache@v2
    - run: cargo hack --no-private test --doc --all-features

  interop:
    name: Interop Tests
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macOS-latest, windows-latest]
    steps:
    - uses: actions/checkout@v4
    - uses: hecrj/setup-rust-action@v2
    - uses: taiki-e/install-action@protoc
    - uses: Swatinem/rust-cache@v2
    - name: Run interop tests
      run: ./interop/test.sh
      shell: bash
    - name: Run interop tests with Rustls
      run: ./interop/test.sh --use_tls tls_rustls
      shell: bash

  semver:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: obi1kenobi/cargo-semver-checks-action@v2
      with:
        feature-group: all-features

  external-types:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: dtolnay/rust-toolchain@master
      with:
        toolchain: nightly-2024-06-30
    - name: Install cargo-check-external-types
      uses: taiki-e/cache-cargo-install-action@v2
      with:
        tool: cargo-check-external-types@0.1.13
    - uses: taiki-e/install-action@cargo-hack
    - uses: Swatinem/rust-cache@v2
    - run: cargo hack --no-private check-external-types
