diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..0c79747 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,37 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + +jobs: + test: + name: pytest (py${{ matrix.python-version }}) + runs-on: ubuntu-latest + # A hang must fail LOUDLY and fast, not sit burning runner time until the + # 6h default -- a job stuck at "in_progress" reads as "not done yet" + # rather than "broken", which is how a false green gets merged. + timeout-minutes: 10 + strategy: + fail-fast: false + matrix: + # requires-python = ">=3.11" -- cover the floor and a current minor. + python-version: ["3.11", "3.12"] + steps: + - uses: actions/checkout@v4 + + - name: Install uv + uses: astral-sh/setup-uv@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: uv sync --all-extras --dev + + - name: Run test suite + # Deselects tests marked `live`: the inherited + # test_list_models_returns_list makes a real network call to + # the configured vLLM/OpenAI-compatible endpoint. Run locally + # against a real server to validate. + run: uv run pytest -q -m "not live" diff --git a/pyproject.toml b/pyproject.toml index 91f7c41..5239b49 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,6 +45,9 @@ allow-direct-references = true testpaths = ["tests"] addopts = "--import-mode=importlib" asyncio_mode = "strict" +markers = [ + "live: requires a reachable vLLM/OpenAI-compatible server; deselected in CI via `-m \"not live\"`", +] [dependency-groups] dev = [ diff --git a/tests/test_behavioral.py b/tests/test_behavioral.py index 25788a5..5151583 100644 --- a/tests/test_behavioral.py +++ b/tests/test_behavioral.py @@ -3,6 +3,8 @@ Inherits authoritative tests from amplifier-core. """ +import pytest + from amplifier_core.validation.behavioral import ProviderBehaviorTests @@ -12,3 +14,17 @@ class TestVllmProviderBehavior(ProviderBehaviorTests): All tests from ProviderBehaviorTests run automatically. Add module-specific tests below if needed. """ + + @pytest.mark.live + @pytest.mark.asyncio + async def test_list_models_returns_list(self, provider_module): + """Override to mark this inherited test 'live'. + + ProviderBehaviorTests.test_list_models_returns_list calls + provider_module.list_models(), which makes a real network call + to the configured vLLM/OpenAI-compatible endpoint -- it cannot + pass in CI without a reachable server. Deselected in CI via + `-m "not live"`; run locally against a real vLLM server to + validate. + """ + await super().test_list_models_returns_list(provider_module)