enprot 0.4.1

Engyon Protected Text (EPT) — confidentiality processor and capability ledger
name: tests

on:
  pull_request:
  push:
    branches:
      - main
    tags:

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

env:
  RUST_BACKTRACE: full
  BOTAN_VERSION: 3.7.0
  PREFIX: /usr

jobs:
  typos:
    name: Spell Check
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: crate-ci/typos@v1

  security:
    name: Security Audit
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - name: Generate Cargo.lock
        run: cargo generate-lockfile
      - name: Run cargo-audit
        uses: rustsec/audit-check@v2
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
      - name: Install cargo-deny
        uses: taiki-e/install-action@v2
        with:
          tool: cargo-deny
      - name: Check licenses and advisories
        run: cargo deny check licenses advisories

  test-unix-stable:
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        rust: [stable, beta, "1.85"]
        exclude:
          # Beta on Windows is low-value and burns CI minutes; the
          # stable + 1.85 pair catches Windows-specific regressions.
          - os: windows-latest
            rust: beta
    name: Test on ${{ matrix.rust }} (${{ matrix.os }})
    runs-on: ${{ matrix.os }}
    timeout-minutes: 30
    steps:
      - if: "startsWith(matrix.os, 'windows')"
        run: git config --global core.autocrlf false
      - uses: actions/checkout@v7
      - name: Install rust toolchain
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: ${{ matrix.rust }}
      - name: Install dependencies
        if: "!startsWith(matrix.os, 'windows')"
        run: ./ci/install.sh
      - name: Install dependencies
        if: "startsWith(matrix.os, 'windows')"
        env:
          GIT_REDIRECT_STDERR: '2>&1'
        shell: pwsh
        run: |
          $Env:PREFIX = (Join-Path $PWD 'botan-install').Replace('\', '/')
          $Env:Path += ";$Env:PREFIX/lib"
          $Env:TARGET = "x86_64-pc-windows-msvc"
          ./ci/install.ps1
          New-Item -ItemType Directory -Force -Path '.cargo'
          $config = "[target.$Env:TARGET.botan-3]`nrustc-link-search = [`"native=$Env:PREFIX/lib`"]`nrustc-link-lib = [`"static=botan-3`"]"
          Set-Content -Path .cargo\config -Value $config
      - name: Build
        run: cargo build --verbose
      - name: Run tests
        run: cargo test --verbose -- --nocapture

  coverage:
    name: Code coverage
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - uses: actions/checkout@v7
      - name: Install rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          components: llvm-tools-preview
      - name: Install dependencies
        run: ./ci/install.sh
      - name: Install cargo-llvm-cov
        uses: taiki-e/install-action@v2
        with:
          tool: cargo-llvm-cov
      - name: Generate coverage
        run: cargo llvm-cov --lcov --output-path lcov.info
      - name: Upload to Codecov
        uses: codecov/codecov-action@v4
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          files: lcov.info
          fail_ci_if_error: false

  check-format:
    name: Check code format
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - uses: actions/checkout@v7
      - name: Install rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt
      - name: Validate code format
        run: cargo fmt --all --check

  check-clippy:
    name: Clippy
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - uses: actions/checkout@v7
      - name: Install rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          components: clippy
      - name: Install dependencies
        run: ./ci/install.sh
      - name: Clippy
        run: cargo clippy --all-targets -- -D warnings

  bench:
    name: Benchmarks
    runs-on: ubuntu-latest
    timeout-minutes: 30
    steps:
      - uses: actions/checkout@v7
      - name: Install rust toolchain
        uses: dtolnay/rust-toolchain@stable
      - name: Install dependencies
        run: ./ci/install.sh
      - name: Compile benchmarks
        run: cargo bench --no-run
      - name: Smoke-run benchmarks (quick)
        run: |
          cargo bench --bench merkle -- --quick --warm-up-time 1 --measurement-time 2
          cargo bench --bench crypto  -- --quick --warm-up-time 1 --measurement-time 2
          cargo bench --bench parser  -- --quick --warm-up-time 1 --measurement-time 2

  bench-compare:
    name: Benchmarks vs main
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request'
    timeout-minutes: 30
    steps:
      - uses: actions/checkout@v7
        with:
          fetch-depth: 0
      - name: Install rust toolchain
        uses: dtolnay/rust-toolchain@stable
      - name: Install dependencies
        run: ./ci/install.sh
      - name: Build benchmarks on PR head
        run: cargo bench --no-run
      - name: Save PR baseline
        run: |
          cargo bench --bench merkle -- --save-baseline pr --warm-up-time 1 --measurement-time 3
          cargo bench --bench crypto  -- --save-baseline pr --warm-up-time 1 --measurement-time 3
          cargo bench --bench parser  -- --save-baseline pr --warm-up-time 1 --measurement-time 3
      - name: Switch to merge-base (origin/main)
        run: git checkout origin/main
      - name: Build benchmarks on main
        run: cargo bench --no-run
      - name: Compare PR vs main (criterion auto-prints regression %)
        run: |
          cargo bench --bench merkle -- --benchmark pr --warm-up-time 1 --measurement-time 3
          cargo bench --bench crypto  -- --benchmark pr --warm-up-time 1 --measurement-time 3
          cargo bench --bench parser  -- --benchmark pr --warm-up-time 1 --measurement-time 3