name: CI

env:
  CARGO_TERM_COLOR: always
  CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
  # Keep in sync with version in `rust-toolchain.toml` and `xtask/src/ci.rs`
  NIGHTLY: nightly-2023-07-03

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

jobs:
  xtask:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repo
        uses: actions/checkout@v3

      - name: Check xtask cache
        uses: actions/cache@v3
        id: xtask-cache
        with:
          path: target/debug/xtask
          key: xtask-${{ hashFiles('Cargo.toml', 'xtask/src/**', 'xtask/Cargo.toml') }}

      - name: Install rust stable toolchain
        if: steps.xtask-cache.outputs.cache-hit != 'true'
        uses: dtolnay/rust-toolchain@stable

      - name: Build
        if: steps.xtask-cache.outputs.cache-hit != 'true'
        run: cargo build -p xtask

  style:
    name: Style
    needs: xtask
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repo
        uses: actions/checkout@v3

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

      - uses: Swatinem/rust-cache@v2

      - name: Check spelling
        uses: crate-ci/typos@v1.16.17

      - name: Install cargo-sort
        uses: taiki-e/cache-cargo-install-action@v1
        with:
          tool: cargo-sort

      - name: Get xtask
        uses: actions/cache@v3
        with:
          path: target/debug/xtask
          key: xtask-${{ hashFiles('Cargo.toml', 'xtask/src/**', 'xtask/Cargo.toml') }}

      - name: Run lints
        run: target/debug/xtask ci lint

  msrv:
    name: Rust 1.70 / ${{ matrix.name }}
    needs: xtask
    runs-on: ubuntu-latest
    strategy:
      matrix:
        include:
          - name: Check All Features
            cmd: msrv-all

          - name: Check Client
            cmd: msrv-client

          - name: Check Ruma
            cmd: msrv-ruma

          - name: Check Owned IDs with Box
            cmd: msrv-owned-id-box

          - name: Check Owned IDs with Arc
            cmd: msrv-owned-id-arc

    steps:
      - name: Checkout repo
        uses: actions/checkout@v3

      - name: Install rust 1.70 toolchain
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: "1.70"

      - uses: Swatinem/rust-cache@v2
        with:
          # A stable compiler update should automatically not reuse old caches.
          # Add the MSRV as a stable cache key too so bumping it also gets us a
          # fresh cache.
          shared-key: msrv1.70

      - name: Get xtask
        uses: actions/cache@v3
        with:
          path: target/debug/xtask
          key: xtask-${{ hashFiles('Cargo.toml', 'xtask/src/**', 'xtask/Cargo.toml') }}

      - name: Run checks
        run: target/debug/xtask ci ${{ matrix.cmd }}

  stable:
    name: Rust Stable / ${{ matrix.name }}
    needs: xtask
    runs-on: ubuntu-latest
    strategy:
      matrix:
        include:
          - name: Check All Features
            cmd: stable-all

          - name: Check Client
            cmd: stable-client

          - name: Check Common
            cmd: stable-common

          - name: Run Tests
            cmd: test-all

          - name: Run Doc Tests
            cmd: test-doc

    steps:
      - name: Checkout repo
        uses: actions/checkout@v3

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

      - uses: Swatinem/rust-cache@v2

      - name: Get xtask
        uses: actions/cache@v3
        with:
          path: target/debug/xtask
          key: xtask-${{ hashFiles('Cargo.toml', 'xtask/src/**', 'xtask/Cargo.toml') }}

      - name: Run checks
        run: target/debug/xtask ci ${{ matrix.cmd }}

  nightly:
    name: Rust Nightly / ${{ matrix.name }}
    needs: xtask
    runs-on: ubuntu-latest
    strategy:
      matrix:
        include:
          - name: Check Formatting
            cmd: fmt
            components: rustfmt

          - name: Full Features
            cmd: nightly-full

          - name: All Features
            cmd: nightly-all

          - name: Clippy Default Features
            cmd: clippy-default
            components: clippy

          - name: Clippy All Features
            cmd: clippy-all
            components: clippy

    steps:
      - name: Checkout repo
        uses: actions/checkout@v3

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

      - uses: Swatinem/rust-cache@v2

      - name: Get xtask
        uses: actions/cache@v3
        with:
          path: target/debug/xtask
          key: xtask-${{ hashFiles('Cargo.toml', 'xtask/src/**', 'xtask/Cargo.toml') }}

      - name: Run checks
        run: target/debug/xtask ci ${{ matrix.cmd }}

  docs:
    name: Docs
    needs: xtask
    runs-on: ubuntu-latest

    permissions:
      contents: read
      pages: write
      id-token: write

    steps:
      - name: Checkout repo
        uses: actions/checkout@v3

      - name: Install nightly rust toolchain
        # Nightly needed for use of unstable options
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: ${{ env.NIGHTLY }}

      - uses: Swatinem/rust-cache@v2

      - name: Get xtask
        uses: actions/cache@v3
        with:
          path: target/debug/xtask
          key: xtask-${{ hashFiles('Cargo.toml', 'xtask/src/**', 'xtask/Cargo.toml') }}

      - name: Build docs
        run: target/debug/xtask doc --deny-warnings

      - name: Compress docs
        if: github.event_name == 'pull_request'
        run: |
          tar --zstd -cf docs.tar.zstd -C target doc

      - name: Upload docs as artifact
        if: github.event_name == 'pull_request'
        uses: actions/upload-artifact@v3
        with:
          name: docs
          path: docs.tar.zstd

      - name: Upload docs as pages artifact
        if: github.event_name == 'push' && github.ref == 'refs/heads/main'
        uses: actions/upload-pages-artifact@v1
        with:
          path: target/doc

      - name: Deploy to GitHub Pages
        if: github.event_name == 'push' && github.ref == 'refs/heads/main'
        uses: actions/deploy-pages@v2
