name: Build and test rust code

on:
    workflow_dispatch:
    pull_request:
        paths:
            - "src/rust/**"
            - "Cargo.toml"
            - "Cargo.lock"
    push:
        paths:
            - "src/rust/**"
            - "Cargo.toml"
            - "Cargo.lock"

permissions:
    contents: read

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

jobs:
    build_and_test:
        runs-on: ubuntu-latest
        name: Build and test
        steps:
            - name: Cache cargo registry
              uses: actions/cache@v4
              with:
                  path: ~/.cargo/registry
                  key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
            - name: Cache cargo index
              uses: actions/cache@v4
              with:
                  path: ~/.cargo/git
                  key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
            - name: Cache cargo binaries
              uses: actions/cache@v4
              with:
                  path: ~/.cargo/bin
                  key: ${{ runner.os }}-cargo-bin-${{ hashFiles('**/Cargo.lock') }}
            - name: Cache cargo build
              uses: actions/cache@v4
              with:
                  path: target
                  key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
            - name: Checkout repository
              uses: actions/checkout@v4
            - name: Set up toolchain
              uses: actions-rs/toolchain@v1
              with:
                  profile: minimal
                  toolchain: 1.74
                  override: true
                  components: rustfmt, llvm-tools-preview
            - name: Build
              uses: actions-rs/cargo@v1
              with:
                  command: build
                  args: --release
              env:
                  CARGO_INCREMENTAL: "0"
                  RUSTFLAGS: "-Cinstrument-coverage"
                  RUSTDOCFLAGS: "-Cinstrument-coverage"
            - name: Test
              uses: actions-rs/cargo@v1
              with:
                  command: test
                  args: --all-features --no-fail-fast
              env:
                  CARGO_INCREMENTAL: "0"
                  RUSTFLAGS: "-Cinstrument-coverage"
                  RUSTDOCFLAGS: "-Cinstrument-coverage"
            - name: Install grcov
              run: |
                mkdir -p "${HOME}/.local/bin"
                curl -sL https://github.com/mozilla/grcov/releases/download/v0.8.19/grcov-x86_64-unknown-linux-gnu.tar.bz2 | tar jxf - -C "${HOME}/.local/bin"
                echo "$HOME/.local/bin" >> $GITHUB_PATH
            - name: Run grcov
              run: grcov . --binary-path target/debug/deps/ -s . -t lcov --branch --ignore-not-existing --ignore '../**' --ignore '/*' -o coverage.lcov
            - uses: codecov/codecov-action@v4
              with:
                  files: ./coverage.lcov
                  flags: rust
                  fail_ci_if_error: true # optional (default = false)
                  token: ${{ secrets.CODECOV_TOKEN }}
