name: rustls

permissions:
  contents: read

on:
  push:
  pull_request:
  merge_group:
  schedule:
    - cron: '0 18 * * *'

jobs:
  build:
    name: Build+test
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        # test a bunch of toolchains on ubuntu
        rust:
          - stable
          - beta
          - nightly
        os: [ubuntu-20.04]
        # but only stable on macos/windows (slower platforms)
        include:
          - os: macos-latest
            rust: stable
          - os: windows-latest
            rust: stable
    steps:
      - name: Checkout sources
        uses: actions/checkout@v4
        with:
          persist-credentials: false

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

      - name: Install NASM for aws-lc-rs on Windows
        if: runner.os == 'Windows'
        uses: ilammy/setup-nasm@v1

      - name: cargo build (debug; default features)
        run: cargo build --locked

      - name: cargo test (debug; all features)
        run: cargo test --locked --all-features
        env:
          RUST_BACKTRACE: 1

      - name: cargo test (debug; aws-lc-rs)
        run: cargo test --no-default-features --features aws_lc_rs,tls12,read_buf,logging
        env:
          RUST_BACKTRACE: 1

      - name: cargo build (debug; rustls-provider-example)
        run: cargo build --locked -p rustls-provider-example

      - name: cargo build (debug; rustls-provider-example lib in no-std mode)
        run: cargo build --locked -p rustls-provider-example --no-default-features

  msrv:
    name: MSRV
    runs-on: ubuntu-20.04
    steps:
      - name: Checkout sources
        uses: actions/checkout@v4
        with:
          persist-credentials: false

      - uses: dtolnay/rust-toolchain@master
        with:
          toolchain: "1.61"

      - run: cargo check --locked --lib --all-features -p rustls

  features:
    name: Features
    runs-on: ubuntu-latest
    steps:
      - name: Checkout sources
        uses: actions/checkout@v4
        with:
          persist-credentials: false

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

      - name: cargo build (debug; default features)
        run: cargo build --locked
        working-directory: rustls

      - name: cargo test (debug; default features)
        run: cargo test --locked
        working-directory: rustls
        env:
          RUST_BACKTRACE: 1

      - name: cargo test (debug; no default features)
        run: cargo test --locked --no-default-features
        working-directory: rustls

      - name: cargo test (debug; no default features; tls12)
        run: cargo test --locked --no-default-features --features tls12
        working-directory: rustls

      - name: cargo test (debug; no default features; aws-lc-rs,tls12)
        run: cargo test --no-default-features --features aws_lc_rs,tls12
        working-directory: rustls

      - name: cargo test (release; no run)
        run: cargo test --locked --release --no-run
        working-directory: rustls

  bogo:
    name: BoGo test suite
    runs-on: ubuntu-20.04
    steps:
      - name: Checkout sources
        uses: actions/checkout@v4
        with:
          persist-credentials: false

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

      - name: Install golang toolchain
        uses: actions/setup-go@v4
        with:
          go-version: "1.20"
          cache: false

      - name: Run test suite (ring)
        working-directory: bogo
        run: ./runme
        env:
          BOGO_SHIM_PROVIDER: ring

      - name: Run test suite (aws-lc-rs)
        working-directory: bogo
        run: ./runme
        env:
          BOGO_SHIM_PROVIDER: aws-lc-rs


  fuzz:
    name: Smoke-test fuzzing targets
    runs-on: ubuntu-20.04
    steps:
      - name: Checkout sources
        uses: actions/checkout@v4
        with:
          persist-credentials: false

      - name: Install nightly toolchain
        uses: dtolnay/rust-toolchain@nightly

      - name: Install cargo fuzz
        run: cargo install cargo-fuzz

      - name: Smoke-test fuzz targets
        run: |
          cargo fuzz build
          for target in $(cargo fuzz list) ; do
            cargo fuzz run $target -- -max_total_time=10
          done

  benchmarks:
    name: Run benchmarks
    runs-on: ubuntu-20.04
    steps:
      - name: Checkout sources
        uses: actions/checkout@v4
        with:
          persist-credentials: false

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

      - name: Smoke-test benchmark program (ring)
        run: cargo run -p rustls --release --locked --example bench

      - name: Smoke-test benchmark program (aws-lc-rs)
        run: cargo run -p rustls --release --locked --example bench --no-default-features --features aws_lc_rs,tls12

      - name: Run micro-benchmarks
        run: cargo bench --locked --all-features
        env:
          RUSTFLAGS: --cfg=bench

  docs:
    name: Check for documentation errors
    runs-on: ubuntu-20.04
    steps:
      - name: Checkout sources
        uses: actions/checkout@v4
        with:
          persist-credentials: false

      - name: Install rust toolchain
        uses: dtolnay/rust-toolchain@nightly

      - name: cargo doc (rustls; all features)
        run: cargo doc --locked --all-features --no-deps --document-private-items --package rustls
        env:
          RUSTDOCFLAGS: -Dwarnings

      - name: Check README.md
        run: |
          cargo build --locked --all-features
          ./admin/pull-readme
          ./admin/pull-usage
          git diff --exit-code

  coverage:
    name: Measure coverage
    runs-on: ubuntu-20.04
    steps:
      - name: Checkout sources
        uses: actions/checkout@v4
        with:
          persist-credentials: false

      - name: Install rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          components: llvm-tools

      - name: Install cargo-llvm-cov
        run: cargo install cargo-llvm-cov

      - name: Measure coverage
        run: ./admin/coverage --lcov --output-path final.info

      - name: Report to codecov.io
        uses: codecov/codecov-action@v3
        with:
          file: final.info
          fail_ci_if_error: false


  minver:
    name: Check minimum versions of direct dependencies
    runs-on: ubuntu-20.04
    steps:
      - name: Checkout sources
        uses: actions/checkout@v4
        with:
          persist-credentials: false

      - name: Install rust toolchain
        uses: dtolnay/rust-toolchain@nightly

      - name: Install cargo-minimal-versions
        uses: taiki-e/install-action@cargo-minimal-versions

      # cargo-minimal-versions requires cargo-hack
      - name: Install cargo-hack
        uses: taiki-e/install-action@cargo-hack

      - name: Check direct-minimal-versions
        run: cargo minimal-versions --direct --ignore-private check
        working-directory: rustls/

  cross:
    name: Check cross compilation targets
    runs-on: ubuntu-20.04
    steps:
      - name: Checkout sources
        uses: actions/checkout@v4
        with:
          persist-credentials: false

      - name: Install rust toolchain
        uses: dtolnay/rust-toolchain@stable
      - name: Install cross
        uses: taiki-e/install-action@cross
      - run: cross build --locked --target i686-unknown-linux-gnu

  semver:
    name: Check semver compatibility
    runs-on: ubuntu-latest
    steps:
      - name: Checkout sources
        uses: actions/checkout@v4
        with:
          persist-credentials: false

      - name: Check semver
        uses: obi1kenobi/cargo-semver-checks-action@v2

  format:
    name: Format
    runs-on: ubuntu-latest
    steps:
      - name: Checkout sources
        uses: actions/checkout@v4
        with:
          persist-credentials: false
      - name: Install rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt
      - name: Check formatting
        run: cargo fmt --all -- --check
      - name: Check formatting (connect-tests workspace)
        run: cargo fmt --all --manifest-path=connect-tests/Cargo.toml -- --check
      - name: Check formatting (fuzz workspace)
        run: cargo fmt --all --manifest-path=fuzz/Cargo.toml -- --check

  clippy:
    name: Clippy
    runs-on: ubuntu-latest
    steps:
      - name: Checkout sources
        uses: actions/checkout@v4
        with:
          persist-credentials: false
      - name: Install rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          components: clippy
        # because examples enable rustls' features, `--workspace --no-default-features` is not
        # the same as `--package rustls --no-default-features` so run it separately
      - run: cargo clippy --locked --package rustls --no-default-features --all-targets -- --deny warnings
      - run: cargo clippy --locked --workspace --all-features --all-targets -- --deny warnings
        # not part of the workspace
      - run: cargo clippy --locked --manifest-path=fuzz/Cargo.toml --all-features --all-targets -- --deny warnings

  clippy-nightly:
    name: Clippy (Nightly)
    runs-on: ubuntu-latest
    steps:
      - name: Checkout sources
        uses: actions/checkout@v4
        with:
          persist-credentials: false
      - name: Install rust toolchain
        uses: dtolnay/rust-toolchain@nightly
        with:
          components: clippy
      - run: cargo clippy --locked --package rustls --no-default-features --all-targets
      - run: cargo clippy --locked --workspace --all-features --all-targets
      - run: cargo clippy --locked --manifest-path=fuzz/Cargo.toml --all-features --all-targets

  check-external-types:
    name: Validate external types appearing in public API
    runs-on: ubuntu-latest
    steps:
      - name: Checkout sources
        uses: actions/checkout@v4
        with:
          persist-credentials: false
      - name: Install rust toolchain
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: nightly-2023-10-10
          # ^ sync with https://github.com/awslabs/cargo-check-external-types/blob/main/rust-toolchain.toml
      - run: cargo install --locked cargo-check-external-types
      - name: run cargo-check-external-types for rustls/
        working-directory: rustls/
        run: cargo check-external-types
