# This workflow calculates the test coverage for the Rust codebase.
# 1. The code is checked out.
# 2. Rust with the stable toolchain, minimal profile, and llvm-tools-preview component is set up.
# 3. Necessary tools like 'cargo-llvm-cov' are installed.
# 4. Proptest is minimized for efficient coverage test runs.
# 5. Tests are run without producing a report to gather coverage information.
# 6. A coverage report (lcov format) is generated based on the gathered information.
# 7. Finally, this report is uploaded to Codecov for visualization and analysis.
name: Coverage

# Ensures that only one workflow task will run at a time. Previous builds, if
# already in process, will get cancelled. Only the latest commit will be allowed
# to run, cancelling any workflows in between
concurrency:
  group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
  cancel-in-progress: true

on:
  workflow_dispatch:

  # we build Rust caches on main,
  # so they can be shared by all branches:
  # https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#restrictions-for-accessing-a-cache
  push:
    branches:
      - main
    paths:
      # code and tests
      - '**/*.rs'
      # hard-coded checkpoints and proptest regressions
      - '**/*.txt'
      # test data snapshots
      - '**/*.snap'
      # dependencies
      - '**/Cargo.toml'
      - '**/Cargo.lock'
      # configuration files
      - '.cargo/config.toml'
      - '**/clippy.toml'
      # workflow definitions
      - 'codecov.yml'
      - '.github/workflows/ci-coverage.yml'

  pull_request:
    paths:
      - '**/*.rs'
      - '**/*.txt'
      - '**/*.snap'
      - '**/Cargo.toml'
      - '**/Cargo.lock'
      - '.cargo/config.toml'
      - '**/clippy.toml'
      - 'codecov.yml'
      - '.github/workflows/ci-coverage.yml'

env:
  CARGO_INCREMENTAL: ${{ vars.CARGO_INCREMENTAL }}
  RUST_LOG: ${{ vars.RUST_LOG }}
  RUST_BACKTRACE: ${{ vars.RUST_BACKTRACE }}
  RUST_LIB_BACKTRACE: ${{ vars.RUST_LIB_BACKTRACE }}
  COLORBT_SHOW_HIDDEN: ${{ vars.COLORBT_SHOW_HIDDEN }}

jobs:
  coverage:
    name: Coverage on stable
    # The large timeout is to accommodate:
    # - stable builds (typically 50-90 minutes), and
    timeout-minutes: 120
    runs-on: ubuntu-latest-xl

    steps:
      - uses: actions/checkout@v4.1.2
        with:
          persist-credentials: false

      # Setup Rust with stable toolchain and minimal profile
      - name: Setup Rust
        run: |
          curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain=stable --profile=minimal --component=llvm-tools-preview

      - name: Install cargo-llvm-cov cargo command
        run: cargo install cargo-llvm-cov

      - name: Skip network tests on Ubuntu
        # Ubuntu runners don't have reliable network or DNS during test steps.
        shell: bash
        run: echo "ZEBRA_SKIP_NETWORK_TESTS=1" >> $GITHUB_ENV

      - name: Minimise proptest cases in Coverage tests
        # We set cases to 1, because some tests already run 1 case by default.
        # We set maximum shrink iterations to 0, because we don't expect failures in these tests.
        #
        # Coverage tests are much slower than other tests, particularly in hot loops.
        shell: bash
        run: |
          echo "PROPTEST_CASES=1" >> $GITHUB_ENV
          echo "PROPTEST_MAX_SHRINK_ITERS=0" >> $GITHUB_ENV

      - name: Run Zebra tests
        run: cargo llvm-cov --lcov --no-report

      - name: Generate coverage report
        run: cargo llvm-cov --lcov --no-run --output-path lcov.info

      - name: Upload coverage report to Codecov
        uses: codecov/codecov-action@v4.3.0
