name: build

on:
  push:
    branches:
      - main
  pull_request:
    branches: [ '**' ]
  schedule:
    # At 23:25 on Thursday.
    - cron: "25 23 * * 4"

jobs:
  test:
    strategy:
      fail-fast: false
      matrix:
        runs-on: [ubuntu-20.04, windows-2022, macos-12]
        toolchain:
          - "1.48"
          - stable
          - nightly
        versions:
          - ""
          - "-Zminimal-versions"
    runs-on: ${{ matrix.runs-on }}
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - uses: maxim-lobanov/setup-xcode@v1
        if: matrix.runs-on == 'macos-12' && matrix.toolchain == '1.48'
        with:
          xcode-version: "13.4.1"
      - name: Install Rust
        id: actions-rs
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: ${{ matrix.toolchain }}
          override: true
      - name: Update lockfile
        run: cargo generate-lockfile ${{ matrix.versions }}
        env:
          RUSTC_BOOTSTRAP: 1
      - run: cargo test --all-targets
      - run: cargo run --example stress-test

  build-wasm:
    strategy:
      fail-fast: false
      matrix:
        versions:
          - ""
          - "-Zminimal-versions"
        toolchain:
          - stable
          - nightly
        include:
          # Without `-Zminimal-versions` a too recent bumpalo version is selected. Newer versions use `edition = "2021"`.
          - versions: "-Zminimal-versions"
          - toolchain: "1.48"
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Install Rust
        id: actions-rs
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: ${{ matrix.toolchain }}
          override: true
          target: wasm32-unknown-unknown
      - name: Update lockfile
        run: cargo generate-lockfile ${{ matrix.versions }}
        env:
          RUSTC_BOOTSTRAP: 1
      - run: cargo build --lib

  test-wasm:
    strategy:
      fail-fast: false
      matrix:
        versions:
          - ""
          - "-Zminimal-versions"
        toolchain:
          - stable
          - nightly
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Install Rust
        id: actions-rs
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: ${{ matrix.toolchain }}
          override: true
          target: wasm32-unknown-unknown
      - name: Install Node
        uses: actions/setup-node@v3
        with:
          node-version: 14
      - name: Update lockfile
        run: cargo generate-lockfile ${{ matrix.versions }}
        env:
          RUSTC_BOOTSTRAP: 1
      - run: which wasm-pack || cargo +stable install wasm-pack
      - run: wasm-pack test --node

  build-cross:
    strategy:
      fail-fast: false
      matrix:
        target:
          - x86_64-unknown-freebsd
          - x86_64-unknown-illumos
          - x86_64-unknown-netbsd
          - x86_64-linux-android
          - i686-linux-android
          - arm-linux-androideabi
          - aarch64-linux-android
          - sparcv9-sun-solaris
        versions:
          - ""
          - "-Zminimal-versions"
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Install Rust
        id: actions-rs
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: stable
          override: true
          target: ${{ matrix.target }}
      - name: Update lockfile
        run: cargo generate-lockfile ${{ matrix.versions }}
        env:
          RUSTC_BOOTSTRAP: 1

        # The command is derived from `cargo-quickinstall`'s description:
        # https://github.com/cargo-bins/cargo-quickinstall/blob/49f09436/README.md#use-in-ci-systems
        #
        # I.e. Download the file into STDOUT, follow redirects, don't give status reports, except
        # if there are HTTP errors, and in case of HTTP errors don't pipe out anything at all.
        # Extract everything into Cargo's `cargo install` destination, which is in your $PATH already.
        #
        # Updated pre-compiled binaries can be found in <https://github.com/cargo-bins/cargo-quickinstall/releases>
        # by searching for their project name.
      - name: Install "cross"
        run: curl --location --silent --show-error --fail https://github.com/cargo-bins/cargo-quickinstall/releases/download/cross-0.2.4-x86_64-unknown-linux-gnu/cross-0.2.4-x86_64-unknown-linux-gnu.tar.gz | tar -xzvvf - -C $HOME/.cargo/bin

      - run: cross build --target ${{ matrix.target }} --examples

  build-ios-cross:
    strategy:
      fail-fast: false
      matrix:
        toolchain:
          - "1.48"
          - stable
        target:
          - aarch64-apple-ios-sim
          - aarch64-apple-ios
          - x86_64-apple-ios
        versions:
          - ""
          - "-Zminimal-versions"
        exclude:
          # Support for this target was added quite recently.
          - target: aarch64-apple-ios-sim
          - toolchain: "1.48"
    runs-on: macos-12
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Install Rust
        id: actions-rs
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: ${{ matrix.toolchain }}
          override: true
          target: ${{ matrix.target }}
      - name: Update lockfile
        run: cargo generate-lockfile ${{ matrix.versions }}
        env:
          RUSTC_BOOTSTRAP: 1
      - name: Install "cross"
        run: curl --location --silent --show-error --fail https://github.com/cargo-bins/cargo-quickinstall/releases/download/cross-0.2.4-x86_64-apple-darwin/cross-0.2.4-x86_64-apple-darwin.tar.gz | tar -xzvvf - -C $HOME/.cargo/bin
      - run: cross build --target ${{ matrix.target }} --examples

  check:
    strategy:
      fail-fast: false
      matrix:
        toolchain:
          - "1.48"
          - stable
          - nightly
        versions:
          - ""
          - "-Zminimal-versions"
    runs-on: ubuntu-latest
    env:
      RUSTFLAGS: -D warnings
      RUST_BACKTRACE: 1
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Install Rust
        id: actions-rs
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: ${{ matrix.toolchain }}
          override: true
          components: clippy
      - name: Update lockfile
        run: cargo generate-lockfile ${{ matrix.versions }}
        env:
          RUSTC_BOOTSTRAP: 1
      - run: cargo check --all-targets
      - run: cargo clippy --all-targets

  no-docker-image-check-only:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Install Rust
        id: actions-rs
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: nightly
          override: true
          components: rust-src
      - run: cargo +nightly check --target x86_64-unknown-haiku -Z build-std --examples

  doc:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Install Rust
        id: actions-rs
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: nightly
          override: true
      - run: RUSTDOCFLAGS="-D warnings" cargo doc --all-features

  audit:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Audit
        uses: actions-rs/audit-check@v1
        with:
          token: ${{ secrets.GITHUB_TOKEN }}

  fallback:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Install Rust
        id: actions-rs
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: stable
          target: x86_64-fortanix-unknown-sgx
          override: true
      # Should fail (outcome is negated):
      - run: if cargo build --lib --target x86_64-fortanix-unknown-sgx; then exit 1; fi
      # Should succeed:
      - run: cargo build --lib --target x86_64-fortanix-unknown-sgx --features fallback

  c:
    name: Lint and format C
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Setup Node.js runtime
        uses: actions/setup-node@v3
        with:
          node-version: 16

      - name: Install npm
        run: npm i -f -g npm@8.16.0

      - name: Lint and check formatting with clang-format
        run: npx github:artichoke/clang-format --check

  test-haiku:
    strategy:
      fail-fast: false
      matrix:
        runs-on: [ubuntu-20.04, windows-2022, macos-12]
        toolchain:
          - stable
        versions:
          - ""
    runs-on: ${{ matrix.runs-on }}
    env:
      RUSTFLAGS: -D warnings
      RUST_BACKTRACE: 1
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Install Rust
        id: actions-rs
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: ${{ matrix.toolchain }}
          override: true
      - name: Update lockfile
        run: cargo generate-lockfile ${{ matrix.versions }}
        working-directory: haiku
        env:
          RUSTC_BOOTSTRAP: 1
      - run: cargo test --all-targets
        working-directory: haiku

  check-haiku:
    strategy:
      fail-fast: false
      matrix:
        toolchain:
          - stable
        versions:
          - ""
    runs-on: ubuntu-latest
    env:
      RUSTFLAGS: -D warnings
      RUST_BACKTRACE: 1
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Install Rust
        id: actions-rs
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: ${{ matrix.toolchain }}
          override: true
          components: clippy
      - name: Update lockfile
        run: cargo generate-lockfile ${{ matrix.versions }}
        working-directory: haiku
        env:
          RUSTC_BOOTSTRAP: 1
      - run: cargo check --all-targets
        working-directory: haiku
      - run: cargo clippy --all-targets
        working-directory: haiku

  check-all-versions:
    runs-on: ubuntu-20.04
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Install Rust
        id: actions-rs
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: stable
          override: true
      - run: which cargo-hack || cargo +stable install cargo-hack
      - run: cargo hack check --version-range 1.36..
