blstrs 0.7.1

High performance implementation of BLS12 381
Documentation
version: 2.1

parameters:
  nightly-version:
    type: string
    default: "nightly-2022-04-24"

orbs:
  codecov: codecov/codecov@1

executors:
  default:
    docker:
      - image: filecoin/rust:latest
    working_directory: /mnt/crate
    resource_class: 2xlarge
  arm:
    machine:
      image: ubuntu-2004:202101-01
    resource_class: arm.large

restore-workspace: &restore-workspace
  attach_workspace:
    at: /mnt

restore-cache: &restore-cache
  restore_cache:
    keys:
      - cargo-v8-{{ checksum "Cargo.toml" }}-{{ checksum "Cargo.lock" }}-{{ arch }}
      - repo-source-{{ .Branch }}-{{ .Revision }}

jobs:
  cargo_fetch:
    executor: default
    steps:
      - checkout
      - run:
          name: Calculate dependencies
          command: cargo generate-lockfile
      - restore_cache:
          keys:
            - cargo-v8-{{ checksum "Cargo.toml" }}-{{ checksum "Cargo.lock" }}-{{ arch }}
      - run: rm -rf ~/.rustup
      - run: rustup self update
      - run: rustup install stable
      - run: rustup default stable
      # A nightly build is needed for code coverage reporting and clippy
      - run: rustup toolchain install << pipeline.parameters.nightly-version >>
      - run: rustup component add --toolchain << pipeline.parameters.nightly-version >> llvm-tools-preview
      - run: rustc --version
      - run: rm -rf .git
      - run: cargo update
      - run: cargo fetch
      - persist_to_workspace:
          root: /mnt
          paths:
            - crate
      - save_cache:
          key: cargo-v8-{{ checksum "Cargo.toml" }}-{{ checksum "Cargo.lock" }}-{{ arch }}
          paths:
            - "~/.cargo"
            - "~/.rustup"

  rustfmt:
    executor: default
    steps:
      - *restore-workspace
      - *restore-cache
      - run:
          name: Run cargo fmt
          command: cargo fmt --all -- --check

  clippy:
    executor: default
    steps:
      - *restore-workspace
      - *restore-cache
      - run:
          name: Run cargo clippy
          # Nightly is needed as `--all-targets` also runs on the benchmarks
          command: cargo +<< pipeline.parameters.nightly-version >> clippy --all-targets --features gpu --workspace -- -D warnings
      - run:
         name: Run cargo clippy (benches)
         command: cargo +<< pipeline.parameters.nightly-version >> clippy --all-targets --features gpu,__private_bench  --workspace -- -D warnings

  build_default:
    executor: default
    steps:
      - *restore-workspace
      - *restore-cache
      - run:
          name: Run cargo build
          command: cargo build --workspace

  test_default:
    executor: default
    steps:
      - *restore-workspace
      - *restore-cache
      - run:
          name: Run cargo test
          command: cargo test --workspace

  test_portable:
    executor: default
    steps:
      - *restore-workspace
      - *restore-cache
      - run:
          name: Run cargo test
          command: cargo test --features portable --workspace

  test_arm:
    executor: arm
    steps:
      - checkout
      - run:
          name: Install Rust
          command: |
            curl https://sh.rustup.rs -sSf | sh -s -- --profile minimal --default-toolchain $(cat rust-toolchain) -y
      - run:
          name: Run cargo test
          command: cargo test --workspace
      - run:
          name: Run cargo test portable
          command: cargo test --workspace --features portable

  check_gpu:
    executor: default
    steps:
      - *restore-workspace
      - *restore-cache
      - run:
          name: Run cargo check
          command: cargo check --features gpu --workspace

  bench:
    executor: default
    steps:
      - *restore-workspace
      - *restore-cache
      - run:
          name: Run cargo bench
          command: cargo +<< pipeline.parameters.nightly-version >> bench

  coverage_run:
    executor: default
    environment:
      # Incremental build is not supported when profiling
      CARGO_INCREMENTAL: 0
      # -Zinstrument-coverage: enable llvm coverage instrumentation
      # -Ccodegen-units=1: building in parallel is not supported when profiling
      # -Copt-level=0: disable optimizations for more accurate coverage
      # -Clink-dead-code: dead code should be considered as not covered code
      # -Coverflow-checks=off: checking for overflow is not needed for coverage reporting
      # -Cinline-threshold=0: do not inline
      RUSTFLAGS: -Zinstrument-coverage -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Cinline-threshold=0
      # Make sure that each run of an executable creates a new profile file, with the default
      # name they would override each other
      LLVM_PROFILE_FILE: "%m.profraw"
    steps:
      - *restore-workspace
      - *restore-cache
      - run:
          name: Set the PATH env variable
          command: |
            # Also put the Rust LLVM tools into the PATH.
            echo 'export PATH="~/.rustup/toolchains/<< pipeline.parameters.nightly-version >>-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin:$PATH"' | tee --append $BASH_ENV
            source $BASH_ENV
      - run:
          name: Generate coverage report
          command: |
            RUST_LOG=info cargo +<< pipeline.parameters.nightly-version >> test -- --nocapture

            # Do *not* use sparse output. It leads to more lines that are not
            # taken into account at all
            llvm-profdata merge --output=default.profdata ./*.profraw

            # The compiled files contain the coverage information. From running the tests we don't
            # know what those files are called, hence use all files from the `./target/debug/deps`
            # directory which don't have an extension.
            OBJECT_FILES=$(find ./target/debug/deps/* -name '*' -not -name '*\.*' -printf '%p,'|head --bytes -1)
            # Only export the coverage of this project, we don't care about coverage of
            # dependencies
            llvm-cov export --ignore-filename-regex=".cargo|.rustup" --format=lcov -instr-profile=default.profdata --object=${OBJECT_FILES} > lcov.info
      # Codecov automatically merges the reports in case there are several ones uploaded
      - codecov/upload:
          file: lcov.info

workflows:
  version: 2.1

  test:
    jobs:
      - cargo_fetch
      - rustfmt:
          requires:
            - cargo_fetch
      - clippy:
          requires:
            - cargo_fetch
      - build_default:
          requires:
            - cargo_fetch
      - bench:
          requires:
            - cargo_fetch
      - test_default:
          requires:
            - cargo_fetch
      - test_portable:
          requires:
            - cargo_fetch
      - test_arm
      - check_gpu:
          requires:
            - cargo_fetch
      - coverage_run:
          requires:
            - cargo_fetch