Contributing to the SDK
Thank you for your interest in contributing to the Kubiya Workflow SDK! This guide will help you get started.
Getting Started
Fork and Clone
# Fork the repository on GitHub
# Then clone your fork
git clone https://github.com/YOUR-USERNAME/kubiya-workflow-sdk.git
cd kubiya-workflow-sdk
# Add upstream remote
git remote add upstream https://github.com/kubiya-sandbox/kubiya-workflow-sdk.git
Development Setup
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install in development mode
pip install -e ".[dev]"
# Install pre-commit hooks
pre-commit install
Development Workflow
1. Create a Feature Branch
# Update your fork
git fetch upstream
git checkout main
git merge upstream/main
# Create feature branch
git checkout -b feature/your-feature-name
2. Make Your Changes
Follow these guidelines:
- Code Style: Follow PEP 8 and use Black for formatting
- Type Hints: Add type hints to all functions
- Docstrings: Use Google-style docstrings
- Tests: Write tests for new features
Example:
from typing import Dict, List, Optional
def process_workflow(
workflow: Dict[str, Any],
params: Optional[Dict[str, str]] = None
) -> WorkflowResult:
"""Process a workflow with given parameters.
Args:
workflow: Workflow specification dictionary
params: Optional parameters to pass to workflow
Returns:
WorkflowResult object containing execution details
Raises:
ValidationError: If workflow format is invalid
ExecutionError: If workflow execution fails
"""
# Implementation
pass
3. Write Tests
# tests/test_your_feature.py
import pytest
from kubiya_workflow_sdk import YourNewFeature
class TestYourFeature:
def test_basic_functionality(self):
"""Test basic feature functionality."""
feature = YourNewFeature()
result = feature.do_something()
assert result == expected_value
def test_error_handling(self):
"""Test error cases."""
with pytest.raises(ExpectedError):
YourNewFeature().do_invalid_thing()
@pytest.mark.integration
def test_integration(self):
"""Test integration with other components."""
# Integration test
pass
4. Run Tests
# Run all tests
pytest
# Run specific test file
pytest tests/test_your_feature.py
# Run with coverage
pytest --cov=kubiya_workflow_sdk --cov-report=html
# Run linting
flake8 kubiya_workflow_sdk/
black --check kubiya_workflow_sdk/
mypy kubiya_workflow_sdk/
5. Update Documentation
# Generate API docs
make docs
# Build documentation locally
cd docs
make html
# View docs
open _build/html/index.html
Code Architecture
Directory Structure
kubiya_workflow_sdk/
├── __init__.py # Public API exports
├── client.py # Client implementation
├── core/ # Core functionality
│ ├── __init__.py
│ ├── workflow.py # Workflow classes
│ ├── step.py # Step classes
│ └── executor.py # Execution engine
├── dsl/ # DSL implementation
│ ├── __init__.py
│ ├── decorators.py # @workflow decorator
│ └── builder.py # Fluent API
├── providers/ # Provider implementations
│ ├── __init__.py
│ ├── base.py # Base provider class
│ └── adk/ # ADK provider
├── utils/ # Utilities
│ ├── __init__.py
│ └── validation.py # Validation helpers
└── errors.py # Exception classes
Adding a New Feature
1. Provider
# kubiya_workflow_sdk/providers/custom.py
from .base import BaseProvider
class CustomProvider(BaseProvider):
"""Custom workflow provider."""
def __init__(self, config: Dict[str, Any]):
super().__init__(config)
# Initialize provider
async def compose(self, task: str, **kwargs) -> Dict[str, Any]:
"""Generate workflow from task description."""
# Implementation
pass
async def execute_workflow(self, workflow: Workflow, **kwargs):
"""Execute workflow with custom logic."""
# Implementation
pass
2. Step Type
# kubiya_workflow_sdk/core/steps/custom_step.py
from ..step import Step, StepType
@register_step_type("custom")
class CustomStep(Step):
"""Custom step implementation."""
def __init__(self, name: str, **kwargs):
super().__init__(name, **kwargs)
self.custom_field = kwargs.get("custom_field")
def validate(self) -> List[str]:
"""Validate step configuration."""
errors = super().validate()
if not self.custom_field:
errors.append("custom_field is required")
return errors
def to_container_spec(self) -> Dict[str, Any]:
"""Convert to container specification."""
return {
"image": self.image,
"command": self.build_command(),
"env": self.build_env()
}
3. DSL Extension
# kubiya_workflow_sdk/dsl/extensions.py
from .builder import step
@step.register("custom")
def custom_step(name: str, custom_field: str, **kwargs):
"""Create a custom step.
Args:
name: Step name
custom_field: Custom field value
**kwargs: Additional step options
Returns:
CustomStep instance
"""
return CustomStep(
name=name,
custom_field=custom_field,
**kwargs
)
Testing Guidelines
Unit Tests
# Test individual components
def test_workflow_creation():
workflow = Workflow(name="test")
assert workflow.name == "test"
assert workflow.steps == []
Integration Tests
# Test component interactions
@pytest.mark.integration
def test_workflow_execution():
client = Client()
workflow = create_test_workflow()
result = client.execute_workflow(workflow)
assert result.success
End-to-End Tests
# Test full user scenarios
@pytest.mark.e2e
def test_ai_workflow_generation():
provider = get_provider("adk")
result = provider.compose("Deploy a web app")
assert "workflow" in result
Documentation Standards
Code Documentation
def complex_function(
param1: str,
param2: Optional[int] = None,
**kwargs: Any
) -> Tuple[bool, str]:
"""Brief description of function.
Longer description explaining the function's purpose,
behavior, and any important details.
Args:
param1: Description of param1
param2: Description of param2. Defaults to None.
**kwargs: Additional keyword arguments:
- option1: Description
- option2: Description
Returns:
Tuple containing:
- bool: Success status
- str: Result message
Raises:
ValueError: If param1 is invalid
RuntimeError: If operation fails
Example:
>>> result, message = complex_function("test", param2=42)
>>> print(f"Success: {result}, Message: {message}")
Success: True, Message: Operation completed
"""
# Implementation
pass
User Documentation
When adding features, update:
- API Reference (
docs/api/
)
- User Guide (
docs/guide/
)
- Examples (
examples/
)
- Changelog (
CHANGELOG.md
)
Pull Request Process
1. Before Submitting
2. PR Description Template
## Description
Brief description of changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Testing
- [ ] Unit tests pass
- [ ] Integration tests pass
- [ ] Manual testing completed
## Checklist
- [ ] Code follows style guidelines
- [ ] Self-review completed
- [ ] Comments added for complex code
- [ ] Documentation updated
- [ ] No new warnings
3. Review Process
- CI checks must pass
- Code review by maintainer
- Address feedback
- Maintainer merges PR
Release Process
Version Numbering
We follow Semantic Versioning:
- MAJOR: Breaking changes
- MINOR: New features (backward compatible)
- PATCH: Bug fixes
Release Steps
# Update version
bumpversion minor # or major, patch
# Update changelog
# Edit CHANGELOG.md with release notes
# Create release PR
git add -A
git commit -m "Release v2.1.0"
git push origin release/v2.1.0
# After merge, tag release
git tag v2.1.0
git push origin v2.1.0
Getting Help
Code of Conduct
We follow the Contributor Covenant. Please be respectful and inclusive in all interactions.
Recognition
Contributors are recognized in:
CONTRIBUTORS.md
file
- Release notes
- GitHub contributors page
Thank you for contributing to Kubiya! 🎉