name: QC
on:
  pull_request:
  push:
    branches: [main]

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

permissions:
  checks: write
  contents: read

jobs:
  prettier:
    runs-on: ubicloud-standard-2-ubuntu-2204
    steps:
      - uses: actions/checkout@v4
      - uses: actionsx/prettier@v3
        with:
          args: --check .

  shellcheck:
    name: Shellcheck
    runs-on: ubicloud-standard-2-ubuntu-2204
    steps:
      - uses: actions/checkout@v4
      - name: Run ShellCheck
        uses: ludeeus/action-shellcheck@master

  rustfmt:
    name: Rust code formatting
    runs-on: ubicloud-standard-2-ubuntu-2204
    steps:
      - uses: actions/checkout@v4
      - uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            target/
          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
      - name: Install nightly toolchain
        run: |
          rustup toolchain install nightly
          rustup override set nightly
      - run: rustup component add rustfmt
      - name: Run Cargo Fmt
        run: cargo fmt --all --check
      - name: Run Rust Markdown code block Formatting Script
        run: bash format_rust_code.sh --mode check

  cargo-bench:
    runs-on: ubicloud-standard-2-ubuntu-2204
    steps:
      - uses: actions/checkout@v4
      - uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            target/
          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
        # liboqs requires quite a lot of stack memory, thus we adjust
        # the default stack size picked for new threads (which is used
        # by `cargo test`) to be _big enough_. Setting it to 8 MiB
      - run: RUST_MIN_STACK=8388608 cargo bench --workspace --exclude rosenpass-fuzzing

  mandoc:
    name: mandoc
    runs-on: ubicloud-standard-2-ubuntu-2204
    steps:
      - name: Install mandoc
        run: sudo apt-get install -y mandoc
      - uses: actions/checkout@v4
      - name: Check rp.1
        run: doc/check.sh doc/rp.1

  cargo-audit:
    runs-on: ubicloud-standard-2-ubuntu-2204
    steps:
      - uses: actions/checkout@v4
      - uses: actions-rs/audit-check@v1
        with:
          token: ${{ secrets.GITHUB_TOKEN }}

  cargo-clippy:
    runs-on: ubicloud-standard-2-ubuntu-2204
    steps:
      - uses: actions/checkout@v4
      - uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            target/
          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
      - run: rustup component add clippy
      - uses: actions-rs/clippy-check@v1
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          args: --all-features

  cargo-doc:
    runs-on: ubicloud-standard-2-ubuntu-2204
    steps:
      - uses: actions/checkout@v4
      - uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            target/
          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
      - run: rustup component add clippy
      # `--no-deps` used as a workaround for a rust compiler bug. See:
      # - https://github.com/rosenpass/rosenpass/issues/62
      # - https://github.com/rust-lang/rust/issues/108378
      - run: RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --document-private-items

  cargo-test:
    runs-on: ubicloud-standard-2-ubuntu-2204
    steps:
      - uses: actions/checkout@v4
      - uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            target/
          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
        # liboqs requires quite a lot of stack memory, thus we adjust
        # the default stack size picked for new threads (which is used
        # by `cargo test`) to be _big enough_. Setting it to 8 MiB
      - run: RUST_MIN_STACK=8388608 cargo test --workspace --all-features

  cargo-test-nix-devshell-x86_64-linux:
    runs-on:
      - ubicloud-standard-2-ubuntu-2204
    steps:
      - uses: actions/checkout@v4
      - uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            target/
          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
      - uses: cachix/install-nix-action@v30
        with:
          nix_path: nixpkgs=channel:nixos-unstable
      - uses: cachix/cachix-action@v15
        with:
          name: rosenpass
          authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
      - run: nix develop --command cargo test --workspace --all-features

  cargo-fuzz:
    runs-on: ubicloud-standard-2-ubuntu-2204
    steps:
      - uses: actions/checkout@v4
      - uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            target/
          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
      - name: Install nightly toolchain
        run: |
          rustup toolchain install nightly
          rustup override set nightly
      - name: Install cargo-fuzz
        run: cargo install cargo-fuzz
      - name: Run fuzzing
        run: |
          cargo fuzz run fuzz_aead_enc_into -- -max_total_time=5
          cargo fuzz run fuzz_blake2b -- -max_total_time=5
          cargo fuzz run fuzz_handle_msg -- -max_total_time=5
          ulimit -s 8192000 && RUST_MIN_STACK=33554432000 && cargo fuzz run fuzz_kyber_encaps -- -max_total_time=5
          cargo fuzz run fuzz_mceliece_encaps -- -max_total_time=5
          cargo fuzz run fuzz_box_secret_alloc_malloc -- -max_total_time=5
          cargo fuzz run fuzz_box_secret_alloc_memfdsec -- -max_total_time=5
          cargo fuzz run fuzz_box_secret_alloc_memfdsec_mallocfb -- -max_total_time=5
          cargo fuzz run fuzz_vec_secret_alloc_malloc -- -max_total_time=5
          cargo fuzz run fuzz_vec_secret_alloc_memfdsec -- -max_total_time=5
          cargo fuzz run fuzz_vec_secret_alloc_memfdsec_mallocfb -- -max_total_time=5

  codecov:
    runs-on: ubicloud-standard-2-ubuntu-2204
    env:
      RUSTUP_TOOLCHAIN: nightly
    steps:
      - uses: actions/checkout@v4
      - uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            target/
          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
      - name: Install nightly toolchain
        run: |
          rustup toolchain install nightly
          rustup override set nightly
      - run: rustup component add llvm-tools-preview
      - run: |
          cargo install cargo-llvm-cov || true
          cargo install grcov || true
          ./coverage_report.sh
      # If using tarapulin
      #- run: cargo install cargo-tarpaulin
      #- run: cargo tarpaulin --out Xml
      - name: Upload coverage reports to Codecov
        uses: codecov/codecov-action@v5
        with:
          files: ./target/grcov/lcov
          verbose: true
          CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
