name: Benchmarks

on:
  # Run on every release tag — results are the source of truth for BENCHMARKS.md.
  push:
    tags:
      - 'v*'
  # Allow manual triggering to collect results mid-cycle.
  workflow_dispatch:

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

env:
  CARGO_TERM_COLOR: always
  RUST_BACKTRACE: 1
  FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true

jobs:
  bench:
    name: Benchmark (${{ matrix.os }})
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest]

    steps:
      - uses: actions/checkout@v4
        with:
          # Include large corpus files if tracked via LFS or submodules
          lfs: false

      - name: Install Rust stable
        uses: dtolnay/rust-toolchain@stable

      - name: Cache Rust dependencies
        uses: Swatinem/rust-cache@v2
        with:
          key: bench-${{ matrix.os }}

      # Run codec benchmarks (always available — uses assets/references/)
      - name: Bench codecs
        run: cargo bench --bench codecs -- --output-format bencher 2>&1 | tee codec_bench.txt
        continue-on-error: true

      # Run render benchmarks (uses references/ assets)
      - name: Bench render
        run: cargo bench --bench render -- --output-format bencher 2>&1 | tee render_bench.txt
        continue-on-error: true

      # Show a readable summary
      - name: Print results
        run: |
          echo "=== Platform: ${{ matrix.os }} ==="
          echo "--- Codec benchmarks ---"
          grep "bench:" codec_bench.txt || echo "(no codec results)"
          echo ""
          echo "--- Render benchmarks ---"
          grep "bench:" render_bench.txt || echo "(no render results)"

      # Upload raw Criterion HTML reports and raw output as workflow artifacts.
      - name: Upload bench artifacts
        uses: actions/upload-artifact@v4
        with:
          name: bench-results-${{ matrix.os }}
          path: |
            codec_bench.txt
            render_bench.txt
            target/criterion/
          retention-days: 90
        if: always()
