name: CI

on:
  push:
    branches: [main]
  pull_request:

jobs:
  test:
    name: ${{ matrix.os }}
    runs-on: ${{ matrix.os }}
    # Hard cap.  Build + test on the slowest runner (Windows MSVC, cold
    # cache) finishes in ~6m; 20m gives 3× slack.  The default 6h
    # ceiling previously masked a real hang in writing_files Windows
    # path-resolution for an entire afternoon — fail loud, fail fast.
    timeout-minutes: 20
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - name: cargo build
        run: cargo build --release --locked
      - name: cargo test
        run: cargo test --release --locked
        timeout-minutes: 5
      - name: cargo clippy
        run: cargo clippy --release --all-targets -- -D warnings
        # macOS / Windows have platform-gated #[cfg] blocks that lint
        # differently than the linux dev path (sort_by_key, collapsible
        # match in writing_files / sysbackend).  Informational until
        # those blocks are cleaned up; doesn't block the matrix.
        continue-on-error: true
      - name: --version smoke
        run: ./target/release/agtop${{ matrix.os == 'windows-latest' && '.exe' || '' }} --version
        shell: bash
      - name: --list-builtins smoke
        run: ./target/release/agtop${{ matrix.os == 'windows-latest' && '.exe' || '' }} --list-builtins
        shell: bash
      - name: --json smoke
        run: ./target/release/agtop${{ matrix.os == 'windows-latest' && '.exe' || '' }} --json --once | head -1
        shell: bash

  fmt:
    name: rustfmt
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt
      # rustfmt is informational — the codebase uses hand-aligned const
      # tables and inline match-result patterns that rustfmt's default
      # style flattens.  Continue-on-error keeps it as an annotation
      # signal without blocking PRs on cosmetic churn.  Use a custom
      # rustfmt.toml if/when the team agrees on a single style.
      - run: cargo fmt --all -- --check
        continue-on-error: true

  # Linux-host cross-compile coverage.  The macOS targets were
  # historically excluded because libproc's bindgen step needed the
  # Apple SDK; that's no longer true — we use direct FFI to libSystem
  # for proc_pidinfo / proc_pidfdinfo, so the apple targets cross-
  # compile from ubuntu-latest fine.
  cross-targets:
    name: cargo check ${{ matrix.target }}
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        target:
          - aarch64-unknown-linux-gnu
          - x86_64-apple-darwin
          - aarch64-apple-darwin
          - x86_64-pc-windows-msvc
          - x86_64-pc-windows-gnu
          - x86_64-unknown-freebsd
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}
      - uses: Swatinem/rust-cache@v2
      - run: cargo check --target ${{ matrix.target }} --release --locked
