Skip to content

fix(ci): a PR based on any branch but main runs no unit tests, no lint and no agent suites #2358

fix(ci): a PR based on any branch but main runs no unit tests, no lint and no agent suites

fix(ci): a PR based on any branch but main runs no unit tests, no lint and no agent suites #2358

Workflow file for this run

# Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
# SPDX-License-Identifier: MIT
# This workflow tests the GAIA OpenAI-compatible API server functionality
# Tests include: Chat completions, streaming SSE, model listing, error handling
name: API Server Tests
on:
workflow_call:
push:
branches: ["main"]
paths:
- 'src/gaia/version.py'
- '.github/actions/install-lemonade/**'
- 'src/gaia/api/**'
- 'src/gaia/agents/base/**'
- 'src/gaia/llm/**'
- 'hub/agents/routing/python/**'
- 'hub/agents/code/python/**'
- 'tests/test_api.py'
- 'setup.py'
- '.github/workflows/test_api.yml'
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
paths:
- 'src/gaia/version.py'
- '.github/actions/install-lemonade/**'
- 'src/gaia/api/**'
- 'src/gaia/agents/base/**'
- 'src/gaia/llm/**'
- 'hub/agents/routing/python/**'
- 'hub/agents/code/python/**'
- 'tests/test_api.py'
- 'setup.py'
- '.github/workflows/test_api.yml'
merge_group:
workflow_dispatch:
# Cancel in-progress runs when a new run is triggered
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
test-api:
name: API Tests
runs-on:
- self-hosted
- Windows
- ${{ contains(github.event.pull_request.labels.*.name, 'stx-test') && 'stx-test' || 'stx' }}
timeout-minutes: 30
if: github.event_name != 'pull_request' || github.event.pull_request.draft == false || contains(github.event.pull_request.labels.*.name, 'ready_for_ci')
steps:
- uses: actions/checkout@v7
- name: Setup Python environment
uses: ./.github/actions/setup-venv
with:
python-version: '3.12'
install-package: '.[dev,api]'
- name: Install additional test dependencies
shell: powershell
run: |
uv pip install pytest pytest-timeout requests --python .venv\Scripts\python.exe
# The 'gaia-code' API model routes through RoutingAgent, which now
# ships as the standalone gaia-agent-routing wheel (#1102). Install
# both local hub packages (routing first, since gaia-agent-code
# depends on it and it isn't on PyPI) so the gaia-code streaming
# tests exercise the real agent instead of the missing-wheel error.
uv pip install -e hub/agents/routing/python --python .venv\Scripts\python.exe
uv pip install -e hub/agents/code/python --python .venv\Scripts\python.exe
# The email REST router only mounts when gaia-agent-email is
# importable; without it every /v1/email test in tests/test_api.py
# 404s (red on main since the email agent moved to a hub wheel).
uv pip install -e hub/agents/email/python --python .venv\Scripts\python.exe
- name: Install Lemonade Server
uses: ./.github/actions/install-lemonade
- name: Start Lemonade + API server and run API tests
shell: powershell
run: |
# Set console to UTF-8 for Unicode support
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
$OutputEncoding = [System.Text.Encoding]::UTF8
$env:PYTHONIOENCODING = "utf-8"
$env:PYTHONUTF8 = "1"
chcp 65001 | Out-Null
try {
# Start Lemonade via the shared launcher (server + tests run in ONE
# step so the detached server survives for the test run). It launches
# LemonadeServer.exe --port directly (the `lemonade-server serve`
# shim was removed in Lemonade v10.5), captures stdout/stderr to
# logs, waits for health (dumping the logs on failure), and sets
# LEMONADE_PROCESS_ID for cleanup.
.\installer\scripts\start-lemonade.ps1 -Port 13305 -NoModel
if ($LASTEXITCODE -ne 0) { throw "Lemonade server failed to start" }
# Pull + load + verify the LLM via GAIA's LemonadeClient so CI
# validates our interface to Lemonade (incl. the model-load retry),
# not raw REST.
Write-Host "`n=== Pull + load + verify LLM via LemonadeClient ==="
uv run python tests/ci_lemonade_check.py --model Qwen3-0.6B-GGUF --chat
if ($LASTEXITCODE -ne 0) {
Write-Host "=== Server stdout (last 100 lines) ==="
Get-Content lemonade-server-stdout.log -Tail 100 -ErrorAction SilentlyContinue
Write-Host "=== Server stderr (last 100 lines) ==="
Get-Content lemonade-server-stderr.log -Tail 100 -ErrorAction SilentlyContinue
throw "LLM setup/verify via LemonadeClient failed"
}
# Start API server using gaia CLI (runs on default port 8080)
Write-Host "`n=== Starting GAIA API Server ==="
$apiJob = Start-Job -ScriptBlock {
Set-Location $using:PWD
& .\.venv\Scripts\Activate.ps1
$env:AGENT_ROUTING_MODEL = "Qwen3-0.6B-GGUF"
& gaia api start 2>&1
}
Write-Host "Started API server job with ID: $($apiJob.Id)"
$env:API_JOB_ID = $apiJob.Id
# Wait for API server to start
Write-Host "Waiting for API server to start..."
$maxWaitTime = 30
$waitTime = 0
$apiReady = $false
while ($waitTime -lt $maxWaitTime -and -not $apiReady) {
Start-Sleep -Seconds 2
$waitTime += 2
try {
$response = Invoke-RestMethod -Uri "http://localhost:8080/health" -Method GET -TimeoutSec 5
Write-Host "[OK] API server is running and healthy"
$apiReady = $true
} catch {
Write-Host "Waiting for API server... ($waitTime/$maxWaitTime seconds)"
}
}
if (-not $apiReady) {
Write-Host "[ERROR] API server failed to start after $maxWaitTime seconds"
if ($env:API_JOB_ID) {
Write-Host "=== API server job output ==="
Receive-Job -Id $env:API_JOB_ID -ErrorAction SilentlyContinue
}
throw "API server failed to start"
}
# Run tests in same session while servers are running
Write-Host "`n=== Running API Integration Tests ==="
$env:CI = "true"
uv run pytest tests/test_api.py -v --tb=short --capture=no
if ($LASTEXITCODE -ne 0) { throw "Tests failed with exit code $LASTEXITCODE" }
} finally {
# Always cleanup both servers (same-session vars).
Write-Host "`n=== Stopping Servers ==="
if ($env:API_JOB_ID) {
Stop-Job -Id $env:API_JOB_ID -ErrorAction SilentlyContinue
Remove-Job -Id $env:API_JOB_ID -ErrorAction SilentlyContinue
Write-Host "[OK] API server stopped"
}
if ($env:LEMONADE_PROCESS_ID) {
Stop-Process -Id $env:LEMONADE_PROCESS_ID -Force -ErrorAction SilentlyContinue
Write-Host "[OK] Lemonade server stopped (PID $env:LEMONADE_PROCESS_ID)"
}
}
- name: Upload API Server Logs
if: failure()
uses: actions/upload-artifact@v7
with:
name: api-server-logs
path: |
gaia.api.log
gaia_api.log
*.log