on:
  pull_request:

name: CI

# If a new push on the PR is done, cancel the build
concurrency:
  group: ${{ github.head_ref }}
  cancel-in-progress: true

jobs:
  rustfmt:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: stable
          override: true
          components: rustfmt
      - run: cargo fmt -- --check

  clippy:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os:
          - ubuntu-latest
          - macos-latest
          - windows-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: nightly
          override: true
          components: clippy
      - run: cargo clippy --all-targets --features serde -- -D warnings

  check:
    name: Check ${{ matrix.toolchain }} / ${{ matrix.triple.target }}
    runs-on: ${{ matrix.triple.os }}
    strategy:
      fail-fast: false
      matrix:
        triple:
          - { os: 'ubuntu-latest',  target: 'x86_64-unknown-linux-gnu', cross: false }
          - { os: 'ubuntu-latest',  target: 'i686-unknown-linux-gnu',   cross: true }
          - { os: 'macos-latest',   target: 'x86_64-apple-darwin',      cross: false }
          - { os: 'windows-latest', target: 'x86_64-pc-windows-msvc',   cross: false }
          ## iOS
          - { os: 'macos-latest', target: 'aarch64-apple-ios', cross: true }
          - { os: 'macos-latest', target: 'x86_64-apple-ios', cross: true }
          ## ARM64
          - { os: 'ubuntu-latest', target: 'aarch64-unknown-linux-gnu',  cross: true }
          - { os: 'ubuntu-latest', target: 'aarch64-unknown-linux-musl', cross: true }
          ## ARMv7
          - { os: 'ubuntu-latest', target: 'armv7-unknown-linux-gnueabihf',  cross: true }
          - { os: 'ubuntu-latest', target: 'armv7-unknown-linux-musleabihf', cross: true }
          ## ARMv6
          - { os: 'ubuntu-latest', target: 'arm-unknown-linux-gnueabihf',  cross: true }
          - { os: 'ubuntu-latest', target: 'arm-unknown-linux-musleabihf', cross: true }
          # Android
          - { os: 'ubuntu-latest', target: 'aarch64-linux-android', cross: true }
          - { os: 'ubuntu-latest', target: 'armv7-linux-androideabi', cross: true }
          - { os: 'ubuntu-latest', target: 'x86_64-linux-android', cross: true }
          - { os: 'ubuntu-latest', target: 'i686-linux-android', cross: true }
        toolchain:
          - "1.69.0"  # minimum supported rust version
          - stable
          - nightly
    steps:
      - uses: actions/checkout@v2
      - name: Install toolchain
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: ${{ matrix.toolchain }}
          override: true

      - name: Install cross-target
        if: matrix.triple.cross
        run: rustup target add ${{ matrix.triple.target }}

      - name: Check
        uses: actions-rs/cargo@v1
        with:
          command: rustc
          args: --target=${{ matrix.triple.target }} --manifest-path=Cargo.toml -- -D warnings
          use-cross: ${{ matrix.triple.cross }}

      - name: Check debug feature
        uses: actions-rs/cargo@v1
        with:
          command: rustc
          args: --target=${{ matrix.triple.target }} --manifest-path=Cargo.toml --features=debug -- -D warnings
          use-cross: ${{ matrix.triple.cross }}

      - name: Check without multithreading
        uses: actions-rs/cargo@v1
        with:
          command: check
          args: --target=${{ matrix.triple.target }} --manifest-path=Cargo.toml --no-default-features
          use-cross: ${{ matrix.triple.cross }}

      - name: Check example
        uses: actions-rs/cargo@v1
        with:
          command: check
          args: --target=${{ matrix.triple.target }} --example simple
          use-cross: ${{ matrix.triple.cross }}

      - name: Check (Apple app store restrictions)
        if: matrix.triple.os == 'macos-latest'
        uses: actions-rs/cargo@v1
        with:
          command: check
          args: --features apple-sandbox --target=${{ matrix.triple.target }} --manifest-path=Cargo.toml
          use-cross: ${{ matrix.triple.cross }}
      - name: Check without multithreading (Apple app store restrictions)
        if: matrix.triple.os == 'macos-latest'
        uses: actions-rs/cargo@v1
        with:
          command: check
          args: --features apple-sandbox --target=${{ matrix.triple.target }} --manifest-path=Cargo.toml --no-default-features
          use-cross: ${{ matrix.triple.cross }}

  tests:
    needs: [check]
    name: Test ${{ matrix.os }} (rust ${{matrix.toolchain}})
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os:
          - ubuntu-latest
          - macos-latest
          - windows-latest
        toolchain:
          - "1.69.0"  # minimum supported rust version
          - stable
          - nightly
    steps:
      - uses: actions/checkout@v2
      - name: Install toolchain
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: ${{ matrix.toolchain }}
          override: true
      - name: Check docs
        run: cargo rustdoc -- -Z unstable-options --generate-link-to-definition
        if: matrix.toolchain == 'nightly'
      - name: Check docs with serde
        run: cargo rustdoc --features serde -- -Z unstable-options --generate-link-to-definition
        if: matrix.toolchain == 'nightly'
      - name: Execute tests (not mac)
        run: cargo test
        if: matrix.os != 'macos-latest'
        env:
          RUST_BACKTRACE: full
      - name: Execute tests (mac)
        run: cargo test -- --test-threads 1
        if: matrix.os == 'macos-latest'
        env:
          RUST_BACKTRACE: full
          APPLE_CI: 1 # FIXME: remove this once CI mac tests are fixed
      - name: Execute tests (not mac, no features)
        run: cargo test --no-default-features
        if: matrix.os != 'macos-latest'
        env:
          RUST_BACKTRACE: full
      - name: Execute tests (mac, no features)
        run: cargo test --no-default-features -- --test-threads 1
        if: matrix.os == 'macos-latest'
        env:
          RUST_BACKTRACE: full
          APPLE_CI: 1 # FIXME: remove this once CI mac tests are fixed
      - name: Run CPU test
        run: cargo test --lib -- --ignored --test-threads 1
        env:
          RUST_BACKTRACE: full
      - name: Check serde feature
        run: |
          cargo check --features serde
          cargo test --features serde --doc
        env:
          RUST_BACKTRACE: full

  c_interface:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: stable
          override: true
      - run: make

  unknown-targets:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        toolchain:
          - "1.69.0" # minimum supported rust version
          - stable
    steps:
      - uses: actions/checkout@v2
      - uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: ${{ matrix.toolchain }}
          override: true
          components: clippy
      - run: cargo clippy --features unknown-ci -- -D warnings
      - run: cargo check --features unknown-ci
      - run: cargo test --features unknown-ci
      - run: cargo install wasm-pack
        if: matrix.toolchain == 'stable'
      - run: cd test-unknown && wasm-pack build --target web
        if: matrix.toolchain == 'stable'