name: main

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  # skip ci if the last commit contains the appropriate tag
  skip-commit:
    name: Conditionally skip ci
    runs-on: ubuntu-latest
    steps:
      - if: "contains(github.event.head_commit.message, '[skip-ci]')
          || contains(github.event.head_commit.message, '[skip ci]')
          || contains(github.event.head_commit.message, '[ci-skip]')
          || contains(github.event.head_commit.message, '[ci skip]')"
        run: exit 78

  # verify that Cargo.lock passes audit
  cargo-audit:
    name: Run cargo audit
    needs: [skip-commit]
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Fetch latest release version of cargo-audit
      run: |
        mkdir -p .github/caching
        cargo search cargo-audit | grep '^cargo-audit' | awk '{gsub(/"/,"",$3); print $3}' > .github/caching/cargo-audit.lock
    - name: Cache cargo-audit/bin
      id: cache-cargo-audit
      uses: actions/cache@v1
      with:
        path: ${{ runner.tool_cache }}/cargo-audit/bin
        key: cargo-audit-bin-${{ hashFiles('.github/caching/cargo-audit.lock') }}
    - name: Install cargo-audit
      if: "steps.cache-cargo-audit.outputs.cache-hit != 'true'"
      uses: actions-rs/cargo@v1
      with:
        command: install
        args: --root ${{ runner.tool_cache }}/cargo-audit --force cargo-audit
    - run: echo "${{ runner.tool_cache }}/cargo-audit/bin" >> $GITHUB_PATH
    - run: cargo audit

  # verify that project passes clippy lints
  cargo-clippy:
    name: Run cargo clippy
    needs: [skip-commit]
    runs-on: ubuntu-latest
    env:
      RUST_TOOLCHAIN: stable
    steps:
      - uses: actions/checkout@v2
      - name: Install Rust toolchain
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          components: clippy
          toolchain: ${{ env.RUST_TOOLCHAIN }}
          override: true
      - name: Run cargo clippy
        uses: actions-rs/clippy-check@v1
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          args: --all-targets --workspace -- -D warnings

  # build the documentation
  cargo-docs:
    name: Run cargo docs
    needs: [skip-commit]
    runs-on: ubuntu-latest
    env:
      RUST_TOOLCHAIN: nightly
    steps:
      - uses: actions/checkout@v2
      - name: Install Rust toolchain
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: ${{ env.RUST_TOOLCHAIN }}
          override: true
      - name: Run cargo doc
        uses: actions-rs/cargo@v1
        with:
          command: doc
          args: --no-deps
      - uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./target/doc
        if: github.event_name == 'push' && github.ref == 'refs/heads/main'

  # verify that code is formatted
  cargo-fmt:
    name: Run cargo fmt
    needs: [skip-commit]
    runs-on: ubuntu-latest
    env:
      RUST_TOOLCHAIN: nightly
    steps:
      - uses: actions/checkout@v2
      - name: Install Rust toolchain
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          components: rustfmt
          toolchain: ${{ env.RUST_TOOLCHAIN }}
          override: true
      - name: Run cargo fmt
        uses: actions-rs/cargo@v1
        with:
          toolchain: ${{ env.RUST_TOOLCHAIN }}
          command: fmt
          args: --all -- --check

  # verify that tests pass and calculate coverage with tarpaulin
  cargo-test-coverage:
    name: Run cargo tarpaulin
    needs: [skip-commit]
    runs-on: ubuntu-latest
    env:
      RUST_TOOLCHAIN: nightly
    steps:
      - uses: actions/checkout@v2
      - name: Install Rust toolchain
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: ${{ env.RUST_TOOLCHAIN }}
          override: true
      - name: Fetch latest release version of cargo-tarpaulin
        run: |
          mkdir -p .github/caching
          curl -sL https://api.github.com/repos/xd009642/tarpaulin/releases/latest | jq -r '.name' > .github/caching/cargo-tarpaulin.lock
      - name: Cache cargo-tarpaulin/bin
        id: cache-cargo-tarpaulin
        uses: actions/cache@v1
        with:
          path: ${{ runner.tool_cache }}/cargo-tarpaulin/bin
          key: cargo-tarpaulin-bin-${{ hashFiles('.github/caching/cargo-tarpaulin.lock') }}
      - name: Install cargo-tarpaulin
        if: "steps.cache-cargo-tarpaulin.outputs.cache-hit != 'true'"
        uses: actions-rs/cargo@v1
        with:
          command: install
          args: --root ${{ runner.tool_cache }}/cargo-tarpaulin --force cargo-tarpaulin
      - run: echo "${{ runner.tool_cache }}/cargo-tarpaulin/bin" >> $GITHUB_PATH
      - name: Run cargo xtask tarpaulin
        uses: actions-rs/cargo@v1
        with:
          command: xtask
          args: tarpaulin
      - name: Upload to codecov.io
        uses: codecov/codecov-action@v1
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          fail_ci_if_error: true

  # verify that tests pass
  cargo-test-agnostic:
    name: Run cargo test (runtime-agnostic)
    needs: [skip-commit]
    strategy:
      matrix:
        os: [macos-latest, ubuntu-latest, windows-latest]
    runs-on: ${{ matrix.os }}
    env:
      RUST_TOOLCHAIN: stable
    steps:
      - uses: actions/checkout@v2
      - name: Install Rust toolchain
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: ${{ env.RUST_TOOLCHAIN }}
          override: yes
      - name: Run cargo test
        uses: actions-rs/cargo@v1
        with:
          command: test
          args: --lib --no-default-features --features runtime-agnostic

  # verify that tests pass
  cargo-test-tokio:
    name: Run cargo test (runtime-tokio)
    needs: [skip-commit]
    strategy:
      matrix:
        os: [macos-latest, ubuntu-latest, windows-latest]
    runs-on: ${{ matrix.os }}
    env:
      RUST_TOOLCHAIN: stable
    steps:
      - uses: actions/checkout@v2
      - name: Install Rust toolchain
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: ${{ env.RUST_TOOLCHAIN }}
          override: yes
      - name: Run cargo test (without docs)
        uses: actions-rs/cargo@v1
        with:
          command: test
          args: --workspace --no-default-features --features runtime-tokio
