# CI for punktfunk (Gitea Actions). Linux jobs run on the `ubuntu-latest` runner; the Rust
# job runs inside the prebuilt builder image (ci/rust-ci.Dockerfile — system FFmpeg 8,
# PipeWire, GL/GBM, libcuda link stub, pinned-channel rustup) so the workspace links the
# same libs as the dev boxes. Apple client CI lives in apple.yml (macOS runner).
name: ci

on:
  push:
    branches: [main]
  pull_request:

jobs:
  rust:
    runs-on: ubuntu-24.04
    container:
      image: git.unom.io/unom/punktfunk-rust-ci:latest
    timeout-minutes: 90
    steps:
      - uses: actions/checkout@v4

      # punktfunk-client-linux link deps. Also baked into rust-ci.Dockerfile — but ci.yml
      # runs against the image from the PREVIOUS push (docker.yml bootstrap note), so this
      # keeps the job green across image-content changes; a no-op once the image has them.
      - name: GTK4/libadwaita/SDL3 dev packages
        run: |
          apt-get update
          apt-get install -y --no-install-recommends libgtk-4-dev libadwaita-1-dev libsdl3-dev

      # Best-effort caches (act_runner's built-in cache server). Keyed on Cargo.lock:
      # registry/git are download caches, target/ the incremental build. The target key
      # carries the rustc version — rust-toolchain.toml pins the floating "stable"
      # channel, so the file alone wouldn't invalidate stale incremental state.
      - name: Cache keys
        run: echo "rustc=$(rustc --version | cut -d' ' -f2)" >> "$GITHUB_ENV"
      - uses: actions/cache@v4
        with:
          path: |
            /usr/local/cargo/registry
            /usr/local/cargo/git
          key: cargo-home-${{ hashFiles('Cargo.lock') }}
          restore-keys: cargo-home-
      - uses: actions/cache@v4
        with:
          path: target
          # -v3-: the prior `cargo-target-<rustc>-*` cache was poisoned when the runner ran
          # out of disk mid-build and actions/cache saved a truncated target/ (a dep's .rmeta
          # went missing -> E0463 "can't find crate"). A suffix bump wouldn't help — restore-keys
          # would fall back to the poisoned prefix — so the prefix itself is versioned.
          key: cargo-target-v3-${{ env.rustc }}-${{ hashFiles('Cargo.lock') }}
          restore-keys: cargo-target-v3-${{ env.rustc }}-

      - name: Format
        run: cargo fmt --all --check

      - name: Clippy (deny warnings)
        run: cargo clippy --workspace --all-targets --locked -- -D warnings

      - name: Build
        run: cargo build --workspace --locked

      - name: Test (unit + loopback + proptest + C ABI harness)
        run: cargo test --workspace --locked

      - name: C ABI harness (standalone link proof)
        run: bash crates/punktfunk-core/tests/c/run.sh

      - name: Verify generated header is committed & up to date
        run: |
          cargo build -p punktfunk-core --locked
          git config --global --add safe.directory "$PWD"
          git diff --exit-code include/punktfunk_core.h \
            || (echo "include/punktfunk_core.h is stale — commit the regenerated header" && exit 1)

  web:
    runs-on: ubuntu-24.04
    container:
      image: oven/bun:1
    timeout-minutes: 30
    defaults:
      run:
        working-directory: web
    steps:
      # oven/bun ships neither git nor a real node (only a bun shim) — actions/checkout
      # needs both. The slim Debian base also lacks ca-certificates, so without it git's
      # HTTPS fetch of the repo dies with "Problem with the SSL CA cert (path? access
      # rights?)" — no CA bundle to validate git.unom.io's (public) Let's Encrypt cert.
      - name: Install git + node + CA certs
        working-directory: /
        run: apt-get update && apt-get install -y --no-install-recommends ca-certificates git nodejs
      - uses: actions/checkout@v4
      - name: Install dependencies
        run: bun install --frozen-lockfile --ignore-scripts
      # Build first: it generates the orval API client + paraglide messages that
      # typechecking imports.
      - name: Build
        run: bun run build
      - name: Typecheck
        run: bun run lint

  docs-site:
    runs-on: ubuntu-24.04
    container:
      image: oven/bun:1
    timeout-minutes: 30
    defaults:
      run:
        working-directory: docs-site
    steps:
      # ca-certificates: the slim Debian base lacks a CA bundle, so actions/checkout's
      # HTTPS fetch otherwise fails with "Problem with the SSL CA cert" (see web job).
      - name: Install git + CA certs
        working-directory: /
        run: apt-get update && apt-get install -y --no-install-recommends ca-certificates git
      - uses: actions/checkout@v4
      - name: Install dependencies
        run: bun install --frozen-lockfile --ignore-scripts
      # Build first: fumadocs-mdx emits the .source typegen the typecheck imports.
      - name: Build
        run: bun run build
      - name: Typecheck
        run: bun run lint

  bench:
    # Tier-1 (criterion microbenchmarks) + Tier-2 (FEC loss recovery) — GPU-free, so they run here.
    # Report-only: prints the numbers + a diff vs the committed baseline to the job summary and never
    # fails the build (shared CI hardware is too noisy to gate on). The tight regression gate + the
    # real encode/stream path live on the self-hosted GPU runner (Tier 3, bench-gpu.yml).
    runs-on: ubuntu-24.04
    container:
      image: git.unom.io/unom/punktfunk-rust-ci:latest
    timeout-minutes: 30
    steps:
      - uses: actions/checkout@v4
      - name: Prep
        run: |
          git config --global --add safe.directory "$PWD"
          command -v python3 >/dev/null || { apt-get update && apt-get install -y --no-install-recommends python3; }
      - name: Tier-1 microbenchmarks (criterion)
        run: cargo bench -p punktfunk-core --bench pipeline -- --warm-up-time 1 --measurement-time 3
      - name: Tier-2 FEC loss recovery (loss-harness)
        run: cargo run -q -p loss-harness
      - name: Compare vs baseline (report-only)
        run: python3 scripts/bench/compare.py --threshold 0.5
