Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions .github/workflows/test-example-collection.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Validate example collection

on:
pull_request:
paths:
- "examples/mcp_server/**"
- "examples/openai_api/**"
- "tests/test_example_smoke_collection.py"
- "tests/test_mcp_server_example.py"
- "tests/test_openai_api_docker_validation.py"
- ".github/workflows/test-example-collection.yml"
push:
branches: [main]
paths:
- "examples/mcp_server/**"
- "examples/openai_api/**"
- "tests/test_example_smoke_collection.py"
- "tests/test_mcp_server_example.py"
- "tests/test_openai_api_docker_validation.py"
- ".github/workflows/test-example-collection.yml"

permissions:
contents: read

jobs:
collection:
runs-on: ubuntu-latest
timeout-minutes: 5
strategy:
fail-fast: false
matrix:
python: ["3.10", "3.12"]
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
- name: Install test runner
run: python -m pip install pytest
- name: Check collection and standalone CLI compatibility
run: |
git rev-parse HEAD > source-commit.txt
python -m pip freeze > resolved-dependencies.txt
python -m pytest -q \
tests/test_example_smoke_collection.py \
tests/test_mcp_server_example.py \
tests/test_openai_api_docker_validation.py \
--junitxml=example-results.xml
- uses: actions/upload-artifact@v4
if: always()
with:
name: example-collection-${{ matrix.python }}
path: |
source-commit.txt
resolved-dependencies.txt
example-results.xml
1 change: 1 addition & 0 deletions examples/mcp_server/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Standalone MCP server example and its validation utilities."""
1 change: 1 addition & 0 deletions examples/openai_api/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Standalone OpenAI-compatible API example and its validation utilities."""
52 changes: 52 additions & 0 deletions tests/test_example_smoke_collection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""Keep the standalone smoke CLIs collectable together with default pytest."""

import os
from pathlib import Path
import shutil
import subprocess
import sys

import pytest


ROOT = Path(__file__).resolve().parents[1]
EXAMPLES = ("mcp_server", "openai_api")


@pytest.mark.parametrize("import_mode", ["prepend", "append", "importlib"])
def test_smoke_scripts_collect_together(tmp_path, import_mode):
# Use real source files in the same directory layout, without local plugins.
scripts = []
for name in EXAMPLES:
source = ROOT / "examples" / name
target = tmp_path / "examples" / name
target.mkdir(parents=True)
for filename in ("smoke_test.py", "__init__.py"):
if (source / filename).exists():
shutil.copyfile(source / filename, target / filename)
scripts.append(str(target / "smoke_test.py"))
sentinel = tmp_path / "test_sentinel.py"
sentinel.write_text("def test_collection_sentinel():\n pass\n", encoding="utf-8")
env = dict(os.environ, PYTEST_DISABLE_PLUGIN_AUTOLOAD="1")
env.pop("PYTEST_ADDOPTS", None)
env.pop("PYTEST_PLUGINS", None)
result = subprocess.run(
[sys.executable, "-m", "pytest", "--collect-only", "-q",
"--import-mode=" + import_mode, *scripts, str(sentinel)],
cwd=tmp_path, env=env, capture_output=True, text=True, timeout=30,
)
assert result.returncode == 0, result.stdout + result.stderr
assert "test_sentinel.py::test_collection_sentinel" in result.stdout
assert "1 test collected" in result.stdout


@pytest.mark.parametrize("example", EXAMPLES)
def test_smoke_script_help_still_runs_directly(example):
result = subprocess.run(
[sys.executable, str(ROOT / "examples" / example / "smoke_test.py"), "--help"],
cwd=ROOT / "examples" / example,
capture_output=True, text=True, timeout=30,
)
assert result.returncode == 0, result.stdout + result.stderr
assert "usage:" in result.stdout
assert "--timeout" in result.stdout
Loading