mcp-cpp-server 0.2.2

A high-performance Model Context Protocol (MCP) server for C++ code analysis using clangd LSP integration
name: CI

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

env:
  CARGO_TERM_COLOR: always
  RUST_BACKTRACE: 1

jobs:
  # Rust jobs - run in parallel
  rust-format:
    name: Rust Format Check
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

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

      - name: Check formatting
        run: cargo fmt --all -- --check

  rust-clippy:
    name: Rust Clippy
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

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

      - name: Cache cargo registry
        uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
          key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-registry-

      - name: Cache cargo build
        uses: actions/cache@v4
        with:
          path: target
          key: ${{ runner.os }}-cargo-clippy-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-clippy-
            ${{ runner.os }}-cargo-

      - name: Run clippy
        run: cargo clippy --all-targets --all-features -- -D warnings

  rust-test:
    name: Rust Unit Tests
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

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

      - name: Cache cargo registry
        uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
          key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-registry-

      - name: Cache cargo build
        uses: actions/cache@v4
        with:
          path: target
          key: ${{ runner.os }}-cargo-test-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-test-
            ${{ runner.os }}-cargo-

      - name: Run unit tests
        run: cargo test --verbose

  rust-build:
    name: Rust Build Check
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

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

      - name: Cache cargo registry
        uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
          key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-registry-

      - name: Cache cargo build
        uses: actions/cache@v4
        with:
          path: target
          key: ${{ runner.os }}-cargo-build-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-build-
            ${{ runner.os }}-cargo-

      - name: Build debug
        run: cargo build --verbose

  cross-platform-build:
    name: Cross-Platform Build (${{ matrix.os }})
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

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

      - name: Cache cargo registry
        uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
          key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-registry-

      - name: Cache cargo build
        uses: actions/cache@v4
        with:
          path: target
          key: ${{ runner.os }}-cargo-build-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-build-
            ${{ runner.os }}-cargo-

      - name: Build release
        run: cargo build --release --verbose

      - name: Verify binary exists (Unix)
        if: runner.os != 'Windows'
        run: test -f target/release/mcp-cpp-server

      - name: Verify binary exists (Windows)
        if: runner.os == 'Windows'
        run: Test-Path target/release/mcp-cpp-server.exe
        shell: pwsh

  rust-integration-tests:
    name: Rust Integration Tests (clangd)
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

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

      - name: Install clangd
        run: |
          sudo apt-get update
          # Get Ubuntu codename dynamically
          UBUNTU_CODENAME=$(lsb_release -cs)
          echo "Detected Ubuntu codename: $UBUNTU_CODENAME"
          # Add LLVM repository
          curl -fsSL https://apt.llvm.org/llvm-snapshot.gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/llvm-archive-keyring.gpg
          echo "deb [signed-by=/usr/share/keyrings/llvm-archive-keyring.gpg] http://apt.llvm.org/${UBUNTU_CODENAME}/ llvm-toolchain-${UBUNTU_CODENAME}-20 main" | sudo tee /etc/apt/sources.list.d/llvm.list
          sudo apt-get update
          sudo apt-get install -y clangd-20 build-essential cmake

      - name: Cache cargo registry
        uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
          key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-registry-

      - name: Cache cargo build
        uses: actions/cache@v4
        with:
          path: target
          key: ${{ runner.os }}-cargo-integration-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-integration-
            ${{ runner.os }}-cargo-

      - name: Run clangd integration tests
        run: cargo test --features clangd-integration-tests,test-logging --verbose clangd
        env:
          CLANGD_PATH: /usr/bin/clangd-20
          RUST_LOG: trace

  project-integration-tests:
    name: Project Integration Tests (CMake + Meson)
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

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

      - name: Install build tools
        run: |
          sudo apt-get update
          sudo apt-get install -y cmake meson ninja-build

      - name: Verify build tools installation
        run: |
          cmake --version
          meson --version
          ninja --version

      - name: Cache cargo registry
        uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
          key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-registry-

      - name: Cache cargo build
        uses: actions/cache@v4
        with:
          path: target
          key: ${{ runner.os }}-cargo-project-tests-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-project-tests-
            ${{ runner.os }}-cargo-

      - name: Run project integration tests
        run: cargo test --features project-integration-tests,test-logging --verbose project
        env:
          RUST_LOG: trace

  # C++ jobs - run in parallel
  cpp-build:
    name: C++ Build Check (CMake + Meson)
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Install dependencies
        run: |
          sudo apt-get update
          sudo apt-get install -y build-essential cmake meson ninja-build

      - name: Verify build tools installation
        run: |
          cmake --version
          meson --version
          ninja --version

      - name: Cache CMake build
        uses: actions/cache@v4
        with:
          path: test/test-project/build
          key: ${{ runner.os }}-cmake-${{ hashFiles('test/test-project/CMakeLists.txt', 'test/test-project/**/*.cpp', 'test/test-project/**/*.h') }}
          restore-keys: |
            ${{ runner.os }}-cmake-

      - name: Cache Meson build
        uses: actions/cache@v4
        with:
          path: test/test-meson-project/builddir
          key: ${{ runner.os }}-meson-${{ hashFiles('test/test-meson-project/meson.build', 'test/test-meson-project/**/*.cpp', 'test/test-meson-project/**/*.h') }}
          restore-keys: |
            ${{ runner.os }}-meson-

      - name: Configure CMake project
        working-directory: test/test-project
        run: cmake -B build -S .

      - name: Build CMake project
        working-directory: test/test-project
        run: cmake --build build

      - name: Configure Meson project
        working-directory: test/test-meson-project
        run: meson setup builddir .

      - name: Build Meson project
        working-directory: test/test-meson-project
        run: meson compile -C builddir

      - name: Verify build artifacts
        run: |
          # Verify CMake artifacts
          test -f test/test-project/build/TestProject
          test -f test/test-project/build/libTestLib.a
          # Verify Meson artifacts
          test -f test/test-meson-project/builddir/test_meson_app
          test -f test/test-meson-project/builddir/libtest_meson_lib.a

  # TypeScript jobs - run in parallel
  ts-format-lint:
    name: TypeScript Format & Lint
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "18"
          cache: "npm"
          cache-dependency-path: test/e2e/package-lock.json

      - name: Install dependencies
        working-directory: test/e2e
        run: npm ci

      - name: Check formatting
        working-directory: test/e2e
        run: npm run format:check

      - name: Run linting
        working-directory: test/e2e
        run: npm run lint