name: Test Suite on: push: branches: [main] paths-ignore: - docs/** pull_request: branches: [main] paths-ignore: - docs/** concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true permissions: contents: read jobs: test: name: Python (${{ matrix.name }}) runs-on: ${{ matrix.os }} timeout-minutes: 20 strategy: fail-fast: false matrix: include: - name: minimum, 3.11 os: ubuntu-latest python-version: "3.11" coverage: false - name: latest, 3.14 + coverage os: ubuntu-latest python-version: "3.14" coverage: true - name: Windows, 3.14 os: windows-latest python-version: "3.14" coverage: false steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install uv uses: astral-sh/setup-uv@v4 - name: Install system dependencies (Linux) if: runner.os == 'Linux' run: sudo apt-get update && sudo apt-get install -y libolm-dev build-essential - name: Install dependencies run: uv sync --all-extras --dev - name: Install channel dependencies run: uv run --no-sync python -m scripts.install_channel_dependencies --all-channels # Channel requirements live in manifests rather than uv.lock. Avoid a # later uv run sync pruning the packages installed by the previous step. - name: Lint with ruff if: matrix.coverage run: uv run --no-sync ruff check nanobot tests conftest.py - name: Run tests with coverage if: matrix.coverage run: >- uv run --no-sync python -m pytest --cov=nanobot --cov-report=term-missing:skip-covered --durations=25 --durations-min=1.0 - name: Run compatibility tests if: ${{ !matrix.coverage }} run: >- uv run --no-sync python -m pytest --durations=25 --durations-min=1.0 webui: runs-on: ubuntu-latest timeout-minutes: 15 steps: - uses: actions/checkout@v4 - name: Set up Bun uses: oven-sh/setup-bun@v2 with: bun-version: 1.3.6 - name: Verify npm lockfile working-directory: webui run: npm ci --ignore-scripts --dry-run - name: Install WebUI dependencies working-directory: webui run: bun install --frozen-lockfile - name: Lint WebUI working-directory: webui run: bun run lint - name: Test WebUI working-directory: webui run: bun run test - name: Build WebUI working-directory: webui run: bun run build docker: runs-on: ubuntu-latest timeout-minutes: 20 steps: - uses: actions/checkout@v4 - name: Build image with default channel dependencies run: docker build -t nanobot:test . - name: Verify default WhatsApp dependencies run: docker run --rm --entrypoint python nanobot:test -c "import neonize, segno" - name: Verify runtime dependency permissions run: >- docker run --rm --user 1000:1000 --entrypoint sh nanobot:test -c 'test -w /app/.venv && test ! -w /app && test ! -w /app/nanobot && python -m scripts.install_channel_dependencies discord && python -c "import discord"'