This document provides detailed information for developers working on helm-sdkpy.
helm-sdkpy follows a three-layer architecture:
-
Go Shim Layer (
go/shim/main.go)- Wraps Helm v4 Go API
- Exposes C-compatible FFI functions
- Handles memory management and error propagation
- Thread-safe with mutex protection
-
Python FFI Layer (
helm_sdkpy/_ffi.py)- Uses CFFI to interface with Go shared library
- Handles library loading and discovery
- Provides type conversion helpers
- Manages error checking
-
Python API Layer (
helm_sdkpy/actions.py,helm_sdkpy/chart.py)- Async-first Pythonic wrapper classes
- Type hints for IDE support
- Context manager support
- Exception hierarchy
- All methods use async/await for non-blocking execution
- Python 3.12+
- Go 1.22+
- Docker (for building the native library)
- just (recommended)
# Clone the repository
git clone https://github.com/vantagecompute/helm-sdkpy.git
cd helm-sdkpy
# Install Python dependencies
pip install -e ".[dev]"
# Build the native library
just build-lib
# Run tests
just unit
-
Make code changes to Python or Go files
-
If you modified Go code, rebuild the library:
just build-lib -
Run tests:
just unit # Run all tests with coverage just lint # Check code style just typecheck # Run static type checking -
Format code:
just fmt # Auto-format Python code
The Go shared library can be built in two ways:
This ensures consistent builds across different platforms:
just build-lib
This runs a multi-stage Docker build that:
- Sets up Go 1.22 build environment
- Downloads Helm v4 and all dependencies
- Compiles the Go shim to a shared library
- Extracts the library to
helm_sdkpy/_lib/linux-amd64/
For faster iteration during development:
cd go/shim
go build -buildmode=c-shared -o ../../helm_sdkpy/_lib/linux-amd64/libhelm-sdkpy.so main.go
Note: This requires Go 1.22+ and all dependencies to be available locally.
# Run all tests with coverage
just unit
# Run specific test file
pytest tests/test_basic.py -v
# Run with verbose output
pytest -vv
Tests are located in the tests/ directory. Follow these guidelines:
-
Import from top-level package:
import helm-sdkpy from helm-sdkpy import Configuration, Install -
Use pytest fixtures for common setup:
@pytest.fixture def config(): return helm-sdkpy.Configuration(namespace="test") -
Test exception handling:
async def test_install_error(): with pytest.raises(helm-sdkpy.InstallError): # Code that should raise await install.run(...)
We use ruff for linting and formatting:
just fmt # Auto-format code
just lint # Check for issues
just typecheck # Run pyright
Configuration is in pyproject.toml:
- Line length: 100 characters
- Target: Python 3.12+
- Type checking with pyright
Follow standard Go conventions:
- Use
gofmtfor formatting - Run
go vetfor issues - Use meaningful variable names
- Add comments for exported functions
To add support for a new Helm action:
-
Add FFI definition in
helm_sdkpy/_ffi.py:ffi.cdef(""" int helm-sdkpy_new_action(helm-sdkpy_handle handle, const char *param, char **result); """) -
Implement Go function in
go/shim/main.go://export helm-sdkpy_new_action func helm-sdkpy_new_action(handle C.helm-sdkpy_handle, param *C.char, result **C.char) C.int { // Implementation } -
Create Python wrapper in
helm_sdkpy/actions.pyorhelm_sdkpy/chart.py:class NewAction: def __init__(self, config: Configuration): self.config = config self._lib = get_library() async def run(self, param: str) -> Dict[str, Any]: def _new_action(): # Implementation calling FFI pass return await asyncio.to_thread(_new_action) -
Export in
__init__.py:from .actions import NewAction __all__ = [..., "NewAction"] -
Add tests in
tests/:import pytest @pytest.mark.asyncio async def test_new_action(): config = helm-sdkpy.Configuration(namespace="test") action = helm-sdkpy.NewAction(config) result = await action.run("param") assert result is not None
-
Update version in:
pyproject.tomlhelm_sdkpy/__init__.pygo/shim/main.go(versionCString)
-
Build and test:
just build-lib just unit just lint just typecheck -
Build wheel:
./scripts/build_wheel_docker.sh -
Tag release:
git tag -a v0.1.0 -m "Release v0.1.0" git push origin v0.1.0
If you get HelmLibraryNotFound:
-
Check if library exists:
ls -lh helm_sdkpy/_lib/linux-amd64/libhelm-sdkpy.so -
Rebuild if missing:
just build-lib -
Check library dependencies:
ldd helm_sdkpy/_lib/linux-amd64/libhelm-sdkpy.so
If Python can't find the module:
-
Install in development mode:
pip install -e . -
Or set PYTHONPATH:
export PYTHONPATH=/path/to/helm-sdkpy:$PYTHONPATH
If Go build fails:
-
Check Go version:
go version # Should be 1.22+ -
Clean and retry:
cd go go clean -cache go mod download go mod tidy -
Check for API changes in Helm v4:
cd /tmp git clone https://github.com/helm/helm # Check relevant action files
- Go shared library is ~115MB (includes Helm and Kubernetes clients)
- First library load takes ~100ms
- Subsequent operations are fast (Go performance)
- Thread-safe: safe to use from multiple Python threads
- Memory: Each Configuration object allocates minimal memory
- Always validate chart sources
- Use RBAC to limit Kubernetes permissions
- Don't pass untrusted values to chart installations
- Keep Helm and Kubernetes clients updated
- Report security issues privately
- Fork the repository
- Create a feature branch
- Make your changes
- Add/update tests
- Run linting and tests
- Submit a pull request
See CONTRIBUTING.md for detailed guidelines.