# Per-push fast feedback: cargo check on Linux + Windows + macOS, plus
# the Svelte build. Catches platform-specific compile errors (the M3
# fix that broke on Windows because std::sync::mpsc::TryRecvError lives
# in a different module on certain configurations, etc) without paying
# the cost of the full Tauri release build.
#
# For the full installer build (.msi, .dmg, .AppImage) see build.yml.
name: check

on:
  push:
    branches: [main]
  pull_request:
  workflow_dispatch:

# Cancel any earlier in-progress runs for the same branch — a fresh push
# supersedes the previous one.
concurrency:
  group: check-${{ github.ref }}
  cancel-in-progress: true

jobs:
  rust:
    name: cargo check (${{ matrix.os }})
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-22.04, windows-latest, macos-latest]
    runs-on: ${{ matrix.os }}
    timeout-minutes: 30

    steps:
      - uses: actions/checkout@v4

      # System packages whisper-rs-sys + llama-cpp-sys-2 + Tauri need on each OS.
      # - libclang-dev: bindgen (pulled by whisper-rs-sys + llama-cpp-sys-2)
      #   needs a libclang shared library at build time.
      # - Vulkan: llama-cpp-sys-2's `vulkan` feature wires `GGML_VULKAN=ON`
      #   for its embedded llama.cpp build, which runs `find_package(Vulkan)`
      #   and needs headers + loader + glslc at configure time (and
      #   libvulkan.so at link time). On Linux apt-get covers all four.
      # - LIBCLANG_PATH: set explicitly because bindgen-0.72.1's default
      #   search path does not include /usr/lib/llvm-*/lib on 22.04.
      - name: Install Linux deps
        if: matrix.os == 'ubuntu-22.04'
        run: |
          sudo apt-get update
          sudo apt-get install -y --no-install-recommends \
            libwebkit2gtk-4.1-dev \
            libappindicator3-dev \
            librsvg2-dev \
            libasound2-dev \
            libudev-dev \
            patchelf \
            cmake \
            build-essential \
            libclang-dev \
            clang \
            libvulkan-dev \
            glslang-tools \
            spirv-tools
          LIBCLANG_CANDIDATE=$(ls -d /usr/lib/llvm-*/lib 2>/dev/null | sort -V | tail -n1)
          if [ -z "$LIBCLANG_CANDIDATE" ]; then
            LIBCLANG_CANDIDATE=/usr/lib/x86_64-linux-gnu
          fi
          echo "LIBCLANG_PATH=$LIBCLANG_CANDIDATE" >> "$GITHUB_ENV"

      # macOS: cmake is preinstalled in macos-latest but pin via brew to
      # be explicit. Xcode CLT provides libclang but the runner's default
      # clang install does not ship libclang.dylib in a discoverable
      # location — use Homebrew's LLVM and point LIBCLANG_PATH at it.
      #
      # Vulkan on macOS is provided by MoltenVK (Vulkan → Metal shim).
      # We install the Homebrew formulae individually rather than the
      # LunarG macOS SDK, which ships as an interactive .dmg/.app and
      # doesn't scriptify cleanly. shaderc gives us glslc, which
      # find_package(Vulkan) requires at cmake configure time.
      - name: Install macOS deps
        if: matrix.os == 'macos-latest'
        run: |
          brew list cmake >/dev/null 2>&1 || brew install cmake
          brew list llvm >/dev/null 2>&1 || brew install llvm
          brew install vulkan-headers vulkan-loader molten-vk shaderc
          echo "LIBCLANG_PATH=$(brew --prefix llvm)/lib" >> "$GITHUB_ENV"
          BREW_PREFIX=$(brew --prefix)
          echo "VULKAN_SDK=$BREW_PREFIX" >> "$GITHUB_ENV"
          echo "CMAKE_PREFIX_PATH=$BREW_PREFIX" >> "$GITHUB_ENV"

      # Windows: cmake + clang (for whisper-rs-sys/llama-cpp-sys bindgen)
      # + Vulkan SDK (required by llama-cpp-sys-2 when the `vulkan`
      # feature is on — it hard-panics on a missing VULKAN_SDK env var).
      #
      # choco's `vulkan-sdk` package installs into
      # C:\VulkanSDK\<version>\; the canonical VULKAN_SDK path is that
      # directory. We resolve it dynamically so a minor-version bump in
      # the SDK doesn't hardcode-break this step.
      - name: Install Windows deps
        if: matrix.os == 'windows-latest'
        shell: pwsh
        run: |
          cmake --version
          choco install -y llvm --no-progress
          choco install -y vulkan-sdk --no-progress
          $sdkRoot = Get-ChildItem -Directory "C:\VulkanSDK" | Sort-Object Name -Descending | Select-Object -First 1
          if (-not $sdkRoot) {
            Write-Error "VulkanSDK directory not found under C:\VulkanSDK after choco install"
            exit 1
          }
          echo "VULKAN_SDK=$($sdkRoot.FullName)" >> $env:GITHUB_ENV
          echo "LIBCLANG_PATH=C:\Program Files\LLVM\bin" >> $env:GITHUB_ENV

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

      # Cache the Cargo target dir + registry per OS so the heavy
      # whisper-rs-sys C++ build only happens on a clean cache.
      # The workspace root is the repo root (see //Cargo.toml), so target/
      # lives at ./target — NOT src-tauri/target. Pointing the cache at
      # src-tauri/target produced silent cache misses on every run and was
      # the real reason Windows check times felt like they compiled sqlx
      # from scratch every time. Use the repo root as the workspace hint.
      - name: Cache Rust artifacts
        uses: Swatinem/rust-cache@v2
        with:
          workspaces: .
          shared-key: kon-${{ matrix.os }}

      - name: cargo check (workspace)
        run: cargo check --workspace --all-targets

      # Library tests only — no runtime/GPU deps. Linux-gated to keep
      # the macOS + Windows legs focused on compile coverage.
      - name: cargo test (workspace, libs)
        if: matrix.os == 'ubuntu-22.04'
        run: cargo test --workspace --lib

  frontend:
    name: svelte build + lint
    runs-on: ubuntu-22.04
    timeout-minutes: 15
    steps:
      - uses: actions/checkout@v4

      - name: Install Node
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm

      - name: Install JS deps
        run: npm ci

      # `tauri build` inside check.yml would trigger the full Rust build
      # which is owned by the rust job. Here we only validate that the
      # Svelte/Vite frontend compiles cleanly.
      - name: Build frontend (Vite only)
        run: npm run build

      # svelte-check catches type and template errors that Vite's build
      # step happily lets through (Vite only type-checks .ts; .svelte
      # type drift slips past until svelte-check runs).
      - name: svelte-check
        run: npm run check
