Skip to content
Open
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
2 changes: 1 addition & 1 deletion .github/actions/setup-runner/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ runs:
# Install specific client version after sync if needed
if [ "${{ steps.client-config.outputs.install-after-sync }}" = "true" ]; then
echo "Installing llama-stack-client from: ${{ steps.client-config.outputs.install-source }}"
uv pip install ${{ steps.client-config.outputs.install-source }}
uv pip install --upgrade ${{ steps.client-config.outputs.install-source }}
fi

echo "Installed llama packages"
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Llama Stack uses GitHub Actions for Continuous Integration (CI). Below is a tabl
| Prepare release | [prepare-release.yml](prepare-release.yml) | Prepare release |
| Test Llama Stack Build | [providers-build.yml](providers-build.yml) | Test llama stack build |
| Test llama stack list-deps | [providers-list-deps.yml](providers-list-deps.yml) | Test llama stack list-deps |
| Publish OpenAPI SDK to PyPI | [publish-openapi-sdk.yml](publish-openapi-sdk.yml) | Publish llama-stack-open-client to PyPI |
| Build, test, and publish packages | [pypi.yml](pypi.yml) | Build, test, and publish packages |
| Integration Tests (Record) | [record-integration-tests.yml](record-integration-tests.yml) | Auto-record missing test recordings for PR |
| Release Branch Scheduled CI | [release-branch-scheduled-ci.yml](release-branch-scheduled-ci.yml) | Scheduled CI checks for active release branches |
Expand Down
47 changes: 45 additions & 2 deletions .github/workflows/openapi-generator-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,9 @@ jobs:
echo "OpenAPI spec generated successfully"
ls -lh openapi.yml

- name: Generate Python SDK
- name: Generate Python SDK (for CI testing with llama_stack_client name)
working-directory: client-sdks/openapi
run: make sdk
run: make sdk OPEN=0

- name: Validate generated SDK
working-directory: client-sdks/openapi
Expand All @@ -214,3 +214,46 @@ jobs:
# Show directory structure for debugging
echo "=== Generated SDK structure ==="
find sdks/python -type f -name "*.py" | head -20

- name: Install generated SDK
run: |
echo "Installing OpenAPI-generated SDK (llama_stack_client)..."
# Uninstall existing client (note: uv pip uninstall doesn't support -y flag)
uv pip uninstall llama-stack-client || true

# Install SDK using uv pip - this ensures proper editable install
uv pip install -e client-sdks/openapi/sdks/python

echo "Verifying installation..."
# Use 'uv run python' to ensure we use the correct Python in the venv
uv run python -c "import llama_stack_client; print(f'Installed: {llama_stack_client.__name__}')"

- name: Setup Ollama (for integration tests)
if: runner.os == 'Linux'
uses: ./.github/actions/setup-ollama

- name: Run integration tests with OpenAPI SDK
if: runner.os == 'Linux'
run: |
echo "Running integration tests with OpenAPI-generated SDK..."

# Run a smoke test suite - basic functionality tests
uv run pytest tests/integration/inspect/test_inspect.py \
--stack-config="inference=ollama" \
-v \
|| echo "::warning::Some integration tests failed - this may indicate SDK compatibility issues"

# Show which SDK is actually being used
uv run python -c "import llama_stack_client; import inspect; print(f'SDK location: {inspect.getfile(llama_stack_client)}')"

- name: Summary
if: runner.os == 'Linux'
run: |
echo "## OpenAPI SDK Validation Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "✅ SDK generation completed successfully" >> $GITHUB_STEP_SUMMARY
echo "✅ SDK installed and importable" >> $GITHUB_STEP_SUMMARY
echo "✅ Integration tests executed (check logs for results)" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Platform**: ${{ matrix.os }}" >> $GITHUB_STEP_SUMMARY
echo "**Package**: llama_stack_client (OpenAPI-generated)" >> $GITHUB_STEP_SUMMARY
2 changes: 1 addition & 1 deletion .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ jobs:
# Install specific client version after sync if needed
if [ "${{ steps.client-config.outputs.install-after-sync }}" = "true" ]; then
echo "Installing llama-stack-client from: ${{ steps.client-config.outputs.install-source }}"
uv pip install ${{ steps.client-config.outputs.install-source }}
uv pip install --upgrade ${{ steps.client-config.outputs.install-source }}
fi

- name: Run mypy (full type_checking)
Expand Down
151 changes: 151 additions & 0 deletions .github/workflows/publish-openapi-sdk.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
name: Publish OpenAPI SDK to PyPI

run-name: Publish llama-stack-open-client to PyPI

on:
workflow_dispatch:
inputs:
publish_to:
description: 'Publish to PyPI or TestPyPI'
required: true
default: 'testpypi'
type: choice
options:
- testpypi
- pypi
dry_run:
description: 'Dry run (build only, no publish)'
type: boolean
default: false
push:
tags:
- 'openapi-sdk-v*' # Tags like openapi-sdk-v0.5.0

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false

permissions:
contents: read
id-token: write # Required for trusted publishing to PyPI

jobs:
publish-sdk:
runs-on: ubuntu-latest
environment:
name: ${{ github.event.inputs.publish_to || 'testpypi' }}

steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Setup Python environment
uses: ./.github/actions/setup-runner
with:
python-version: '3.12'

- name: Set up Java
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: 'temurin'
java-version: '11'

- name: Install openapi-generator-cli
run: npm install -g @openapitools/openapi-generator-cli

- name: Verify installations
working-directory: client-sdks/openapi
run: |
set -e
echo "=== Java version ==="
java -version

echo "=== OpenAPI Generator version ==="
openapi-generator-cli version

echo "=== SDK version from pyproject.toml ==="
make version

- name: Generate OpenAPI SDK
working-directory: client-sdks/openapi
run: |
echo "Generating SDK with OPEN=1 (llama_stack_open_client)..."
make sdk OPEN=1

- name: Verify SDK generation
working-directory: client-sdks/openapi
run: |
if [ ! -d sdks/python ]; then
echo "Error: SDK directory was not generated"
exit 1
fi

PY_FILE_COUNT=$(find sdks/python -name "*.py" | wc -l)
echo "Generated Python files: $PY_FILE_COUNT"

if [ "$PY_FILE_COUNT" -le 10 ]; then
echo "Error: Too few Python files generated"
exit 1
fi

echo "SDK generated successfully"
ls -lh sdks/python/

- name: Build package
working-directory: client-sdks/openapi/sdks/python
run: |
echo "Building Python package..."
uv build

echo "Built distribution files:"
ls -lh dist/

- name: Publish to TestPyPI (dry-run or manual)
if: |
(github.event_name == 'workflow_dispatch' && inputs.publish_to == 'testpypi' && inputs.dry_run == false) ||
(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/openapi-sdk-v') && !contains(github.ref, '-'))
working-directory: client-sdks/openapi/sdks/python
run: |
echo "Publishing to TestPyPI..."
uv publish --publish-url https://test.pypi.org/legacy/ dist/*
env:
UV_PUBLISH_TOKEN: ${{ secrets.TEST_PYPI_API_TOKEN }}

- name: Publish to PyPI (production)
if: |
github.event_name == 'workflow_dispatch' &&
inputs.publish_to == 'pypi' &&
inputs.dry_run == false
working-directory: client-sdks/openapi/sdks/python
run: |
echo "Publishing to PyPI..."
uv publish dist/*
env:
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_API_TOKEN }}

- name: Upload build artifacts
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v4.6.0
with:
name: python-sdk-dist
path: client-sdks/openapi/sdks/python/dist/
retention-days: 30

- name: Summary
run: |
echo "## SDK Publishing Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **Event**: ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY
echo "- **Dry Run**: ${{ inputs.dry_run || 'false' }}" >> $GITHUB_STEP_SUMMARY
echo "- **Target**: ${{ inputs.publish_to || 'testpypi (default)' }}" >> $GITHUB_STEP_SUMMARY
echo "- **Package**: llama-stack-open-client" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY

if [ "${{ inputs.dry_run }}" = "true" ]; then
echo "✅ Package built successfully (dry-run, not published)" >> $GITHUB_STEP_SUMMARY
elif [ "${{ inputs.publish_to }}" = "testpypi" ] || [ "${{ github.event_name }}" = "push" ]; then
echo "✅ Package published to TestPyPI" >> $GITHUB_STEP_SUMMARY
echo "Install with: \`pip install --index-url https://test.pypi.org/simple/ llama-stack-open-client\`" >> $GITHUB_STEP_SUMMARY
else
echo "✅ Package published to PyPI" >> $GITHUB_STEP_SUMMARY
echo "Install with: \`pip install llama-stack-open-client\`" >> $GITHUB_STEP_SUMMARY
fi
2 changes: 1 addition & 1 deletion client-sdks/openapi/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ sdk: check-generator $(PROCESSED_SPEC) generate-config
@echo "Generating Python SDK (version: $(VERSION), package: $(PACKAGE_NAME))..."
@mkdir -p $(SDK_OUTPUT_DIR)
$(OPENAPI_GENERATOR) generate -i $(PROCESSED_SPEC) -g python -c $(OPENAPI_CONFIG) -o $(SDK_OUTPUT_DIR) \
--additional-properties=packageVersion=$(VERSION) -t $(TEMPLATE_DIR)
--additional-properties=packageVersion=$(VERSION),httpx=true -t $(TEMPLATE_DIR)
@cp -R $(TEMPLATE_DIR)/lib $(SDK_OUTPUT_DIR)/$(PACKAGE_NAME)
@echo "Patching SDK with hierarchical API structure..."
$(PYTHON) $(PATCH_SCRIPT) --hierarchy $(HIERARCHY_FILE) --sdk-dir $(SDK_OUTPUT_DIR) --package $(PACKAGE_NAME)
Expand Down
42 changes: 42 additions & 0 deletions client-sdks/openapi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,48 @@ merge_stainless_config.py -> build_hierarchy.py -> openapi-generator -> pa
- `sdks/python/` - Generated Python SDK
- `.openapi-generator/` - Generator metadata

## Publishing to PyPI

The SDK can be published to PyPI using the GitHub Actions workflow at `.github/workflows/publish-openapi-sdk.yml`.

### Manual Publishing (via GitHub UI)

1. Go to Actions → "Publish OpenAPI SDK to PyPI"
2. Click "Run workflow"
3. Select options:
- **publish_to**: `testpypi` (for testing) or `pypi` (production)
- **dry_run**: `true` to build only without publishing

### Automatic Publishing (via Git Tags)

Push a tag matching `openapi-sdk-v*` to trigger automatic publishing to TestPyPI:

```bash
git tag openapi-sdk-v0.5.0
git push origin openapi-sdk-v0.5.0
```

### Required Secrets

Configure these GitHub secrets for the repository:

- `TEST_PYPI_API_TOKEN` - TestPyPI API token
- `PYPI_API_TOKEN` - Production PyPI API token

### Testing the Published Package

After publishing to TestPyPI:

```bash
pip install --index-url https://test.pypi.org/simple/ llama-stack-open-client
```

After publishing to PyPI:

```bash
pip install llama-stack-open-client
```

## Files

- `Makefile` - Build orchestration
Expand Down
35 changes: 21 additions & 14 deletions client-sdks/openapi/templates/python/pyproject.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,32 @@
{{/poetry1}}
name = "{{{packageName}}}"
version = "{{{packageVersion}}}"
description = "{{{appName}}}"
description = "Python client SDK for Llama Stack - AI development framework"
{{#poetry1}}
authors = ["{{infoName}}{{^infoName}}OpenAPI Generator Community{{/infoName}} <{{infoEmail}}{{^infoEmail}}team@openapitools.org{{/infoEmail}}>"]
authors = ["Meta Llama Team <llama-oss@meta.com>"]
{{/poetry1}}
{{^poetry1}}
authors = [
{name = "{{infoName}}{{^infoName}}OpenAPI Generator Community{{/infoName}}",email = "{{infoEmail}}{{^infoEmail}}team@openapitools.org{{/infoEmail}}"},
{name = "Meta Llama Team", email = "llama-oss@meta.com"},
]
{{/poetry1}}
{{#licenseInfo}}
{{#poetry1}}
license = "{{{licenseInfo}}}"
{{/poetry1}}
{{^poetry1}}
license = { text = "{{{licenseInfo}}}" }
{{/poetry1}}
{{/licenseInfo}}
license = { text = "MIT" }
readme = "README.md"
{{#poetry1}}
repository = "https://{{{gitHost}}}/{{{gitUserId}}}/{{{gitRepoId}}}"
repository = "https://github.com/llamastack/llama-stack"
{{/poetry1}}
keywords = ["OpenAPI", "OpenAPI-Generator", "{{{appName}}}"]
keywords = ["llama", "llama-stack", "ai", "ml", "openai", "inference", "agents"]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Scientific/Engineering :: Artificial Intelligence",
]
{{#poetry1}}
include = ["{{packageName}}/py.typed"]

Expand Down Expand Up @@ -81,7 +85,10 @@ dependencies = [
]

[project.urls]
Repository = "https://{{{gitHost}}}/{{{gitUserId}}}/{{{gitRepoId}}}"
Homepage = "https://llamastack.github.io"
Documentation = "https://llamastack.github.io/docs"
Repository = "https://github.com/llamastack/llama-stack"
"Bug Tracker" = "https://github.com/llamastack/llama-stack/issues"

{{/poetry1}}
{{^poetry1}}
Expand Down
Loading