CI/CD Pipeline¶
Comprehensive continuous integration and deployment setup for Pyvider RPC Plugin using GitHub Actions, automated testing, and release management.
GitHub Actions Workflows¶
Main CI Pipeline¶
.github/workflows/ci.yml
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ["3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip uv
uv pip install -e ".[dev,test]"
- name: Run tests
run: |
pytest --cov=pyvider.rpcplugin --cov-report=xml
- name: Upload coverage
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
flags: unittests
name: codecov-${{ matrix.os }}-py${{ matrix.python-version }}
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Run linters
run: |
pip install ruff mypy
ruff check src tests
mypy src/
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Security scan
run: |
pip install bandit safety
bandit -r src/
safety check
Release Workflow¶
.github/workflows/release.yml
name: Release
on:
push:
tags:
- 'v*'
jobs:
build-and-publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install build tools
run: |
pip install --upgrade build twine
- name: Build distribution
run: python -m build
- name: Publish to PyPI
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
run: |
twine upload dist/*
- name: Create GitHub Release
uses: softprops/action-gh-release@v1
with:
files: dist/*
generate_release_notes: true
Testing Strategy¶
Test Matrix¶
| Component | Test Type | Coverage Target | Tools |
|---|---|---|---|
| Core | Unit | 90% | pytest, pytest-cov |
| Transport | Integration | 85% | pytest-asyncio |
| Protocol | Unit + Integration | 88% | pytest, mock |
| Security | Security | N/A | bandit, safety |
| Performance | Benchmark | N/A | pytest-benchmark |
Test Configuration¶
pyproject.toml
[tool.pytest.ini_options]
minversion = "7.0"
testpaths = ["tests"]
python_files = ["test_*.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
asyncio_mode = "auto"
markers = [
"slow: marks tests as slow",
"integration: marks integration tests",
"benchmark: marks performance tests"
]
addopts = """
-ra
--strict-markers
--cov=pyvider.rpcplugin
--cov-branch
--cov-report=term-missing
--cov-report=html
--cov-report=xml
"""
[tool.coverage.run]
source = ["src"]
omit = ["*/tests/*", "*/*_pb2*.py"]
[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"def __repr__",
"raise AssertionError",
"raise NotImplementedError",
"if __name__ == .__main__.:",
"if TYPE_CHECKING:"
]
Code Quality¶
Linting Configuration¶
pyproject.toml
[tool.ruff]
target-version = "py311"
line-length = 88
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort
"B", # flake8-bugbear
"C4", # flake8-comprehensions
"UP", # pyupgrade
]
ignore = ["E501"] # line too long
exclude = ["*_pb2.py", "*_pb2_grpc.py"]
[tool.ruff.per-file-ignores]
"tests/*" = ["S101"] # assert allowed in tests
[tool.mypy]
python_version = "3.11"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true
disallow_any_unimported = false
no_implicit_optional = true
check_untyped_defs = true
show_error_codes = true
exclude = ["*_pb2.py", "*_pb2_grpc.py"]
Pre-commit Hooks¶
.pre-commit-config.yaml
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.3.0
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.9.0
hooks:
- id: mypy
additional_dependencies: [types-all]
exclude: "_pb2(_grpc)?\\.py$"
- repo: https://github.com/PyCQA/bandit
rev: 1.7.7
hooks:
- id: bandit
args: [-r, src/]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
Performance Testing¶
Benchmark Suite¶
tests/benchmarks/test_performance.py
import pytest
from pyvider.rpcplugin import plugin_server, plugin_client
@pytest.mark.benchmark
def test_rpc_throughput(benchmark):
"""Benchmark RPC throughput."""
async def make_calls():
client = await plugin_client(host="localhost", port=50051)
for _ in range(1000):
await client.call("Echo", message="test")
await client.close()
result = benchmark(asyncio.run, make_calls)
assert result is not None
@pytest.mark.benchmark
def test_connection_pool(benchmark):
"""Benchmark connection pooling."""
async def pool_operations():
pool = ConnectionPool(size=10)
await pool.initialize()
tasks = []
for _ in range(100):
conn = await pool.acquire()
tasks.append(pool.release(conn))
await asyncio.gather(*tasks)
await pool.close_all()
benchmark(asyncio.run, pool_operations)
Performance Monitoring¶
GitHub Action for Performance
name: Performance
on:
pull_request:
paths:
- 'src/**'
- 'tests/benchmarks/**'
jobs:
benchmark:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run benchmarks
run: |
pip install -e ".[test]"
pytest tests/benchmarks/ --benchmark-json=benchmark.json
- name: Store benchmark results
uses: benchmark-action/github-action-benchmark@v1
with:
tool: 'pytest'
output-file-path: benchmark.json
github-token: ${{ secrets.GITHUB_TOKEN }}
auto-push: true
alert-threshold: '150%'
comment-on-alert: true
fail-on-alert: true
Release Management¶
Semantic Versioning¶
Version Bumping Script
#!/bin/bash
# scripts/bump-version.sh
set -e
BUMP_TYPE=${1:-patch} # major, minor, patch
CURRENT=$(python -c "import pyvider.rpcplugin; print(pyvider.rpcplugin.__version__)")
case $BUMP_TYPE in
major) NEW=$(echo $CURRENT | awk -F. '{printf "%d.0.0", $1+1}') ;;
minor) NEW=$(echo $CURRENT | awk -F. '{printf "%d.%d.0", $1, $2+1}') ;;
patch) NEW=$(echo $CURRENT | awk -F. '{printf "%d.%d.%d", $1, $2, $3+1}') ;;
esac
echo "Bumping version: $CURRENT → $NEW"
# Update version
sed -i "s/__version__ = \"$CURRENT\"/__version__ = \"$NEW\"/" src/pyvider/rpcplugin/__init__.py
# Create git tag
git add -A
git commit -m "Release v$NEW"
git tag -a "v$NEW" -m "Release version $NEW"
echo "✅ Version bumped to $NEW"
echo "📦 Push with: git push && git push --tags"
Changelog Generation¶
Release Notes Template
## [VERSION] - DATE
### 🎯 Highlights
- Major feature or improvement
- Performance enhancement
- Security update
### ✨ Added
- New feature description
- New API endpoint
### 🔄 Changed
- Updated behavior
- Improved performance
### 🐛 Fixed
- Bug fix description
- Security vulnerability patch
### 📚 Documentation
- Documentation improvements
- New examples
### ⚠️ Breaking Changes
- Breaking change description
- Migration guide
### 🙏 Contributors
- @contributor1
- @contributor2
Deployment¶
PyPI Publishing¶
Automated via GitHub Actions on tag push: 1. Tag push triggers release workflow 2. Build wheel and sdist 3. Upload to PyPI using API token 4. Create GitHub release with artifacts
Monitoring¶
Status Badges¶
[](https://github.com/provide-io/pyvider-rpcplugin/actions)
[](https://codecov.io/gh/provide-io/pyvider-rpcplugin)
[](https://pypi.org/project/pyvider-rpcplugin/)
[](https://pypi.org/project/pyvider-rpcplugin/)
[](https://github.com/provide-io/pyvider-rpcplugin/blob/main/LICENSE)
Dependency Updates¶
Dependabot Configuration (.github/dependabot.yml):
version: 2
updates:
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "weekly"
reviewers:
- "maintainer-team"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
Best Practices¶
- Branch Protection: Require PR reviews and passing CI
- Automated Testing: Run tests on every push
- Code Coverage: Maintain >80% coverage
- Security Scanning: Regular dependency and code scanning
- Performance Monitoring: Track benchmarks over time
- Semantic Versioning: Follow semver for releases
- Documentation: Update docs with code changes
- Dependency Updates: Keep dependencies current and secure