# GitHub Actions workflow to
# lint Rust and Python code
# and run Rust tests, Python tests and async Python tests.

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:
      - main

env:
  RUSTFLAGS: -Dwarnings

jobs:
  lint_rust:
    name: Lint Rust
    runs-on: ubuntu-latest
    env:
      RUSTUP_TOOLCHAIN: 1.78.0
    steps:
      - uses: actions/checkout@v4
        with:
          show-progress: false
      - 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@v4
        with:
          show-progress: false
      - 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@v4
        with:
          show-progress: false
      - name: Check provider database
        run: scripts/update-provider-database.sh

  docs:
    name: Rust doc comments
    runs-on: ubuntu-latest
    env:
      RUSTDOCFLAGS: -Dwarnings
    steps:
      - uses: actions/checkout@v4
        with:
          show-progress: false
      - 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.78.0
          - os: windows-latest
            rust: 1.78.0
          - os: macos-latest
            rust: 1.78.0

          # Minimum Supported Rust Version = 1.77.0
          - os: ubuntu-latest
            rust: 1.77.0
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v4
        with:
          show-progress: false

      - 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: Install nextest
        uses: taiki-e/install-action@v2
        with:
          tool: nextest

      - name: Tests
        env:
          RUST_BACKTRACE: 1
        run: cargo nextest run --workspace

      - name: Doc-Tests
        env:
          RUST_BACKTRACE: 1
        run: cargo test --workspace --doc

      - 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@v4
        with:
          show-progress: false

      - 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@v4
        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, windows-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v4
        with:
          show-progress: false

      - 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@v4
        with:
          name: ${{ matrix.os }}-deltachat-rpc-server
          path: ${{ matrix.os == 'windows-latest' && 'target/debug/deltachat-rpc-server.exe' || 'target/debug/deltachat-rpc-server' }}
          retention-days: 1

  python_lint:
    name: Python lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          show-progress: false

      - 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

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

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

          # 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@v4
        with:
          show-progress: false

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

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

      - name: Install tox
        run: pip install tox

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

  rpc_python_tests:
    name: JSON-RPC Python tests
    needs: ["python_lint", "rpc_server"]
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-latest
            python: 3.12
          - os: macos-latest
            python: 3.12
          - os: windows-latest
            python: 3.12

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

          # Minimum Supported Python Version = 3.7
          - os: ubuntu-latest
            python: 3.7

    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v4
        with:
          show-progress: false

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

      - name: Install tox
        run: pip install tox

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

      - name: Make deltachat-rpc-server executable
        if: ${{ matrix.os != 'windows-latest' }}
        run: chmod +x target/debug/deltachat-rpc-server

      - name: Add deltachat-rpc-server to path
        if: ${{ matrix.os != 'windows-latest' }}
        run: echo ${{ github.workspace }}/target/debug >> $GITHUB_PATH

      - name: Add deltachat-rpc-server to path
        if: ${{ matrix.os == 'windows-latest' }}
        run: |
          "${{ github.workspace }}/target/debug" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append

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