name: Rust CI

# Cancel previously started workflow runs
# when the branch is updated.
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

on:
  pull_request:
  push:
    branches:
      - master

env:
  RUSTFLAGS: -Dwarnings

jobs:
  lint_rust:
    name: Lint Rust
    runs-on: ubuntu-latest
    env:
      RUSTUP_TOOLCHAIN: 1.68.2
    steps:
      - uses: actions/checkout@v3
      - name: Install rustfmt and clippy
        run: rustup toolchain install $RUSTUP_TOOLCHAIN --profile minimal --component rustfmt --component clippy
      - name: Cache rust cargo artifacts
        uses: swatinem/rust-cache@v2
      - name: Run rustfmt
        run: cargo fmt --all -- --check
      - name: Run clippy
        run: scripts/clippy.sh
      - name: Check
        run: cargo check --workspace --all-targets --all-features

  cargo_deny:
    name: cargo deny
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: EmbarkStudios/cargo-deny-action@v1
        with:
          arguments: --all-features --workspace
          command: check
          command-arguments: "-Dwarnings"

  provider_database:
    name: Check provider database
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Check provider database
        run: scripts/update-provider-database.sh

  docs:
    name: Rust doc comments
    runs-on: ubuntu-latest
    env:
      RUSTDOCFLAGS: -Dwarnings
    steps:
      - name: Checkout sources
        uses: actions/checkout@v3
      - name: Cache rust cargo artifacts
        uses: swatinem/rust-cache@v2
      - name: Rustdoc
        run: cargo doc --document-private-items --no-deps

  rust_tests:
    name: Rust tests
    strategy:
      matrix:
        include:
          - os: ubuntu-latest
            rust: 1.68.2
          - os: windows-latest
            rust: 1.68.2
          - os: macos-latest
            rust: 1.68.2

          # Minimum Supported Rust Version = 1.65.0
          #
          # Minimum Supported Python Version = 3.7
          # This is the minimum version for which manylinux Python wheels are
          # built.
          - os: ubuntu-latest
            rust: 1.65.0
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v3

      - name: Install Rust ${{ matrix.rust }}
        run: rustup toolchain install --profile minimal ${{ matrix.rust }}
      - run: rustup override set ${{ matrix.rust }}

      - name: Cache rust cargo artifacts
        uses: swatinem/rust-cache@v2

      - name: Tests
        run: cargo test --workspace

      - name: Test cargo vendor
        run: cargo vendor

  c_library:
    name: Build C library
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v3

      - name: Cache rust cargo artifacts
        uses: swatinem/rust-cache@v2

      - name: Build C library
        run: cargo build -p deltachat_ffi --features jsonrpc

      - name: Upload C library
        uses: actions/upload-artifact@v3
        with:
          name: ${{ matrix.os }}-libdeltachat.a
          path: target/debug/libdeltachat.a
          retention-days: 1

  rpc_server:
    name: Build deltachat-rpc-server
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v3

      - name: Cache rust cargo artifacts
        uses: swatinem/rust-cache@v2

      - name: Build deltachat-rpc-server
        run: cargo build -p deltachat-rpc-server

      - name: Upload deltachat-rpc-server
        uses: actions/upload-artifact@v3
        with:
          name: ${{ matrix.os }}-deltachat-rpc-server
          path: target/debug/deltachat-rpc-server
          retention-days: 1

  python_lint:
    name: Python lint
    runs-on: ubuntu-latest
    steps:
      - name: Checkout sources
        uses: actions/checkout@v3

      - name: Install tox
        run: pip install tox

      - name: Lint Python bindings
        working-directory: python
        run: tox -e lint

      - name: Lint deltachat-rpc-client
        working-directory: deltachat-rpc-client
        run: tox -e lint

  python_tests:
    name: Python tests
    needs: ["c_library", "python_lint"]
    strategy:
      fail-fast: false
      matrix:
        include:
          # Currently used Rust version.
          - os: ubuntu-latest
            python: 3.11
          - os: macos-latest
            python: 3.11

          # PyPy tests
          - os: ubuntu-latest
            python: pypy3.9
          - os: macos-latest
            python: pypy3.9

          # Minimum Supported Python Version = 3.7
          # This is the minimum version for which manylinux Python wheels are
          # built. Test it with minimum supported Rust version.
          - os: ubuntu-latest
            python: 3.7

    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v3

      - name: Download libdeltachat.a
        uses: actions/download-artifact@v3
        with:
          name: ${{ matrix.os }}-libdeltachat.a
          path: target/debug

      - name: Install python
        uses: actions/setup-python@v4
        with:
          python-version: ${{ matrix.python }}

      - name: Install tox
        run: pip install tox

      - name: Run python tests
        env:
          DCC_NEW_TMP_EMAIL: ${{ secrets.DCC_NEW_TMP_EMAIL }}
          DCC_RS_TARGET: debug
          DCC_RS_DEV: ${{ github.workspace }}
        working-directory: python
        run: tox -e mypy,doc,py

  aysnc_python_tests:
    name: Async Python tests
    needs: ["python_lint", "rpc_server"]
    strategy:
      fail-fast: false
      matrix:
        include:
          # Currently used Rust version.
          - os: ubuntu-latest
            python: 3.11
          - os: macos-latest
            python: 3.11

          # PyPy tests
          - os: ubuntu-latest
            python: pypy3.9
          - os: macos-latest
            python: pypy3.9

          # Minimum Supported Python Version = 3.7
          # This is the minimum version for which manylinux Python wheels are
          # built. Test it with minimum supported Rust version.
          - os: ubuntu-latest
            python: 3.7

    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v3

      - name: Install python
        uses: actions/setup-python@v4
        with:
          python-version: ${{ matrix.python }}

      - name: Install tox
        run: pip install tox

      - name: Download deltachat-rpc-server
        uses: actions/download-artifact@v3
        with:
          name: ${{ matrix.os }}-deltachat-rpc-server
          path: target/debug

      - name: Make deltachat-rpc-server executable
        run: chmod +x target/debug/deltachat-rpc-server

      - name: Add deltachat-rpc-server to path
        run: echo ${{ github.workspace }}/target/debug >> $GITHUB_PATH

      - name: Run deltachat-rpc-client tests
        env:
          DCC_NEW_TMP_EMAIL: ${{ secrets.DCC_NEW_TMP_EMAIL }}
        working-directory: deltachat-rpc-client
        run: tox -e py
