Files
2026-07-13 12:38:34 +08:00

266 lines
8.7 KiB
YAML

name: Test Python SDK
on:
push:
branches: [master, next]
paths:
- 'python/**/*.py'
- '.github/workflows/py.test.yml'
- '.github/actions/setup-python-uv/action.yml'
- 'mise.toml'
- 'mise.lock'
- 'toolchain-versions.json'
- 'python/pyproject.toml'
- 'python/requirements*.txt'
pull_request:
branches: [master, next]
paths:
- 'python/**/*.py'
- '.github/workflows/py.test.yml'
- '.github/actions/setup-python-uv/action.yml'
- 'mise.toml'
- 'mise.lock'
- 'toolchain-versions.json'
- 'python/pyproject.toml'
- 'python/requirements*.txt'
concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
permissions:
contents: read
jobs:
toolchain-versions:
name: Read toolchain test matrix
runs-on: ubuntu-latest
outputs:
python: ${{ steps.versions.outputs.python }}
steps:
- name: Checkout Code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Read versions
id: versions
run: echo "python=$(jq -c '.python' toolchain-versions.json)" >> "$GITHUB_OUTPUT"
test:
name: Test Python SDK
needs: toolchain-versions
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ${{ fromJSON(needs.toolchain-versions.outputs.python) }}
steps:
- name: Checkout Code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: ${{ matrix.python-version }}
- name: Cache uv dependencies
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ~/.cache/uv
key: uv-${{ matrix.python-version }}-${{ hashFiles('python/pyproject.toml', 'mise.toml') }}
restore-keys: |
uv-${{ matrix.python-version }}-
- name: Install UV
run: |
UV_VERSION="$(sed -n 's/^uv[[:space:]]*=[[:space:]]*"\([^"]*\)"/\1/p' mise.toml)"
pip install "uv==${UV_VERSION}"
- name: Install Dependencies
run: |
cd python/
uv venv --python ${{ matrix.python-version }}
source .venv/bin/activate
uv pip install -e .
uv pip install -e providers/langchain
uv pip install -e providers/autogen
uv pip install pytest pytest-mock
- name: Run Import Tests
run: |
cd python/
source .venv/bin/activate
python -c "from composio import Composio; print('✓ Basic import successful')"
# Guards against the autogen provider becoming un-importable on a fresh
# install (e.g. a broken framework dependency). A hard import here fails
# loudly, unlike the importorskip-guarded unit tests, which would skip.
python -c "import composio_autogen; print('✓ Autogen provider import successful')"
- name: Run Unit Tests
run: |
cd python/
source .venv/bin/activate
python -m pytest tests/ -v --tb=short
- name: Test Package Installation
run: |
cd python/
# Test that the package can be installed and imported in a fresh environment
uv venv test-env --python ${{ matrix.python-version }}
source test-env/bin/activate
uv pip install -e .
python -c "
from composio import Composio, ToolkitVersionParam
from composio.types import Modifiers
from composio.core.types import ToolkitVersion
print('✓ All critical imports successful')
"
test-circular-imports:
name: Test Circular Import Prevention
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Setup Python with UV
uses: ./.github/actions/setup-python-uv
- name: Install Dependencies
run: |
cd python/
uv venv
source .venv/bin/activate
uv pip install -e .
- name: Test Circular Import Prevention
run: |
cd python/
source .venv/bin/activate
python -c "
# Test various import combinations that previously caused circular imports
import sys
# Test 1: Basic imports
from composio import Composio
print('✓ Basic Composio import')
# Test 2: Import toolkit version types
from composio import ToolkitVersionParam
from composio.core.types import ToolkitVersion
print('✓ Toolkit version types import')
# Test 3: Import from types module
from composio.types import Modifiers
print('✓ Types module import')
# Test 4: Import core models
from composio.core.models.tools import Tools
print('✓ Core models import')
# Test 5: Cross-module imports that caused the original circular import
from composio.core.models.tools import Modifiers as CoreModifiers
from composio.types import Modifiers as TypesModifiers
assert CoreModifiers is TypesModifiers
print('✓ Cross-module import consistency')
print('✓ All circular import prevention tests passed!')
"
lint-and-format:
name: Lint and Format Check
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Setup Python with UV
uses: ./.github/actions/setup-python-uv
- name: Install Dependencies
run: |
cd python/
uv venv
source .venv/bin/activate
uv pip install -e .
uv pip install ruff
- name: Run Ruff Linter
run: |
cd python/
source .venv/bin/activate
ruff check --config config/ruff.toml composio/ tests/
- name: Run Ruff Formatter Check
run: |
cd python/
source .venv/bin/activate
ruff format --check --config config/ruff.toml composio/ tests/
integration-tests:
name: Integration Tests
runs-on: ubuntu-22.04 # Use Ubuntu 22.04 for stability
permissions: read-all
env:
COMPOSIO_API_KEY: ${{ secrets.COMPOSIO_API_KEY }}
COMPOSIO_BASE_URL: ${{ secrets.COMPOSIO_BASE_URL_STAGING }}
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Install UV
id: setup-python
uses: ./.github/actions/setup-python-uv
- name: Cache UV dependencies
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ~/.cache/uv
key: uv-${{ hashFiles('mise.lock') }}-py${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('python/pyproject.toml') }}
restore-keys: |
uv-${{ hashFiles('mise.lock') }}-py${{ steps.setup-python.outputs.python-version }}-
- name: Install Python Dependencies
working-directory: ./python
run: |
# Let UV manage Python version to satisfy workspace requirements
uv sync --group dev
- name: Check API key
id: api-key
run: |
if [ -z "$COMPOSIO_API_KEY" ]; then
echo "available=false" >> "$GITHUB_OUTPUT"
if [ "$GITHUB_ACTOR" = "dependabot[bot]" ]; then
echo "::notice::Skipping secret-backed Python integration tests for Dependabot; missing COMPOSIO_API_KEY."
exit 0
fi
echo "::error::COMPOSIO_API_KEY is not set"
exit 1
fi
echo "available=true" >> "$GITHUB_OUTPUT"
echo "✅ API key is configured"
- name: Run Integration Tests
if: steps.api-key.outputs.available == 'true'
working-directory: ./python
run: |
echo "🧪 Running Integration Tests..."
# Run with per-test timeout of 2 minutes and overall timeout
# pytest-timeout should be installed via pyproject.toml dev dependencies
uv run pytest composio/integration_test/ -v --tb=short --maxfail=3 --timeout=120 --timeout-method=thread
timeout-minutes: 10
- name: Upload Test Results
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: integration-test-results
path: |
python/composio/integration_test/
retention-days: 7