xoq 0.2.1

X-Embodiment over QUIC - P2P and relay communication for robotics
Documentation
name: CI

on:
  push:
    branches: [main, master]
  pull_request:
    branches: [main, master]

env:
  CARGO_TERM_COLOR: always
  RUST_BACKTRACE: 1

jobs:
  # Check Rust formatting
  fmt:
    name: Rustfmt
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt
      - run: cargo fmt --all -- --check

  # Python linting
  python-lint:
    name: Python Lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install linters
        run: pip install ruff mypy

      - name: Ruff check
        working-directory: python
        run: ruff check .

      - name: Ruff format check
        working-directory: python
        run: ruff format --check .

      - name: Mypy
        working-directory: python
        run: mypy . --ignore-missing-imports

  # Clippy linting
  clippy:
    name: Clippy
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: clippy
      - uses: Swatinem/rust-cache@v2
      - name: Install system dependencies
        run: sudo apt-get update && sudo apt-get install -y libudev-dev libv4l-dev
      - name: Clippy (no features)
        run: cargo clippy -- -D warnings
      - name: Clippy (all features)
        run: cargo clippy --features "iroh,serial,camera" -- -D warnings

  # Version consistency check across all packages
  version-check:
    name: Version Consistency
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Check version consistency
        run: |
          CARGO_VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
          PYTHON_VERSION=$(grep '^version' python/pyproject.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
          NPM_VERSION=$(jq -r '.version' js/package.json)

          echo "Cargo version: $CARGO_VERSION"
          echo "Python version: $PYTHON_VERSION"
          echo "npm version: $NPM_VERSION"

          if [ "$CARGO_VERSION" != "$PYTHON_VERSION" ]; then
            echo "ERROR: Cargo ($CARGO_VERSION) and Python ($PYTHON_VERSION) versions don't match"
            exit 1
          fi

          if [ "$CARGO_VERSION" != "$NPM_VERSION" ]; then
            echo "ERROR: Cargo ($CARGO_VERSION) and npm ($NPM_VERSION) versions don't match"
            exit 1
          fi

          echo "All versions match: $CARGO_VERSION"

  # Rust semver check (catches breaking API changes)
  semver-rust:
    name: Semver Check (Rust)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - name: Install system dependencies
        run: sudo apt-get update && sudo apt-get install -y libudev-dev libv4l-dev
      - name: Install cargo-semver-checks
        run: cargo install cargo-semver-checks --locked
      - name: Check semver
        run: cargo semver-checks check-release --features "iroh,serial,camera"
        continue-on-error: true  # Advisory for now

  # Python API check using griffe
  semver-python:
    name: Semver Check (Python)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install griffe
        run: pip install griffe

      - name: Check Python API
        working-directory: python
        run: |
          # Generate API signature from stub file
          griffe dump xoq.pyi -o current-api.json 2>/dev/null || echo "Stub check passed"
        continue-on-error: true  # Advisory for now

  # npm package check
  semver-npm:
    name: Semver Check (npm)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Check package.json validity
        working-directory: js
        run: npm pkg get name version

      - name: Validate semver
        working-directory: js
        run: |
          VERSION=$(jq -r '.version' package.json)
          if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then
            echo "ERROR: Invalid semver version: $VERSION"
            exit 1
          fi
          echo "Valid semver: $VERSION"

  # Build and test on multiple platforms
  build:
    name: Build (${{ matrix.os }})
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
          - os: macos-latest
            target: x86_64-apple-darwin
          - os: windows-latest
            target: x86_64-pc-windows-msvc

    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}

      - uses: Swatinem/rust-cache@v2
        with:
          key: ${{ matrix.os }}

      # Install system dependencies on Linux (required for serial and camera)
      - name: Install system dependencies (Linux)
        if: matrix.os == 'ubuntu-latest'
        run: sudo apt-get update && sudo apt-get install -y libudev-dev libv4l-dev

      # Build with no features
      - name: Build (no features)
        run: cargo build --verbose

      # Build with iroh feature
      - name: Build (iroh)
        run: cargo build --features iroh --verbose

      # Build with serial feature
      - name: Build (serial)
        run: cargo build --features serial --verbose

      # Build with camera feature
      - name: Build (camera)
        run: cargo build --features camera --verbose

      # Build with all features
      - name: Build (all features)
        run: cargo build --features "iroh,serial,camera" --verbose

      # Build examples
      - name: Build examples
        run: cargo build --examples --features "iroh,serial" --verbose

      # Run tests
      - name: Run tests
        run: cargo test --features "iroh,serial,camera" --verbose

  # Build Python bindings
  python:
    name: Python Bindings (${{ matrix.os }})
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]

    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@stable

      - uses: Swatinem/rust-cache@v2
        with:
          key: python-${{ matrix.os }}
          workspaces: python

      - uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      # Install system dependencies on Linux
      - name: Install system dependencies (Linux)
        if: matrix.os == 'ubuntu-latest'
        run: sudo apt-get update && sudo apt-get install -y libudev-dev libv4l-dev

      - name: Install maturin
        run: pip install maturin

      # Build Python package with all features
      - name: Build Python package
        working-directory: python
        run: maturin build --features "iroh,serial,camera"

      # Build wheel for release
      - name: Build wheel (release)
        working-directory: python
        run: maturin build --release --features "iroh,serial,camera"

      # Upload wheels as artifacts
      - name: Upload wheels
        uses: actions/upload-artifact@v4
        with:
          name: wheels-${{ matrix.os }}
          path: target/wheels/*.whl

  # Documentation build
  docs:
    name: Documentation
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2

      - name: Install system dependencies
        run: sudo apt-get update && sudo apt-get install -y libudev-dev libv4l-dev

      - name: Build documentation
        run: cargo doc --features "iroh,serial,camera" --no-deps
        env:
          RUSTDOCFLAGS: -D warnings

  # Release build (optimized)
  release:
    name: Release Build (${{ matrix.os }})
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]

    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@stable

      - uses: Swatinem/rust-cache@v2
        with:
          key: release-${{ matrix.os }}

      - name: Install system dependencies (Linux)
        if: matrix.os == 'ubuntu-latest'
        run: sudo apt-get update && sudo apt-get install -y libudev-dev libv4l-dev

      - name: Build release
        run: cargo build --release --features "iroh,serial,camera"

      - name: Build release examples
        run: cargo build --release --examples --features "iroh,serial"