feat(sdk): add Python SDK with Makefile and CI workflow - #157
Conversation
Add Python SDK mirroring the .NET SDK architecture: - Domain layer: ISecretProvider Protocol, SecretProviderType enum, dataclasses - Application layer: MapFileParser ( support), EnvilderClient - Infrastructure: AwsSsmSecretProvider (boto3), AzureKeyVaultSecretProvider - SecretProviderFactory with options override - 21 unit tests (pytest, Should_* naming) + 8 acceptance tests (TestContainers) - Tooling: black, isort, mypy strict, py.typed marker Add root Makefile with per-stack targets (check/format/build/test) Add tests-python-sdk.yml workflow (Python 3.10 + 3.13 matrix)
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 32 minutes and 1 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (15)
WalkthroughAdds a new synchronous Python SDK for Envilder: domain models, application logic (map-file parsing and client), AWS/Azure secret providers, provider factory with runtime overrides, packaging/tests, containers/fixtures for acceptance tests, and documentation/tooling configuration. Changes
Sequence Diagram(s)sequenceDiagram
participant App as Consumer
participant Parser as MapFileParser
participant Factory as SecretProviderFactory
participant Client as EnvilderClient
participant Provider as ISecretProvider
App->>Parser: parse(json_content)
Parser-->>App: ParsedMapFile(config, mappings)
App->>Factory: create(config, options?)
Factory-->>App: ISecretProvider (AwsSsm or AzureKeyVault)
App->>Client: EnvilderClient(provider)
App->>Client: resolve_secrets(ParsedMapFile)
loop for each mapping
Client->>Provider: get_secret(path)
Provider-->>Client: secret_value or None
end
Client-->>App: dict[str, str] (only found secrets)
App->>Client: inject_into_environment(secrets)
Client->>Client: os.environ[k]=v
sequenceDiagram
participant Factory as SecretProviderFactory
participant Env as Environment
participant Boto as boto3.Session
participant SSM as AWS SSM
participant Provider as AwsSsmSecretProvider
Factory->>Env: read AWS_REGION / AWS_DEFAULT_REGION
alt options/config selects AWS with profile
Factory->>Boto: Session(profile_name, region_name?)
else
Factory->>Boto: Session(region_name?)
end
Boto-->>Factory: session
Factory->>SSM: session.client('ssm')
Factory-->>Provider: AwsSsmSecretProvider(ssm_client)
sequenceDiagram
participant Factory as SecretProviderFactory
participant Cred as DefaultAzureCredential
participant Vault as SecretClient
participant Provider as AzureKeyVaultSecretProvider
Factory->>Factory: determine vault_url from config/options
Factory->>Cred: DefaultAzureCredential()
Cred-->>Factory: credential
Factory->>Vault: SecretClient(vault_url, credential)
Vault-->>Factory: client
Factory-->>Provider: AzureKeyVaultSecretProvider(client)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Suggested labelsdocumentation, feature, python-sdk 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Devin Review found 1 new potential issue.
🐛 1 issue in files not directly in the diff
🐛 py.typed marker file placed outside package directory, won't be included in distribution (src/sdks/python/py.typed:1)
The PEP 561 py.typed marker file is at src/sdks/python/py.typed (the project root) instead of src/sdks/python/envilder/py.typed (inside the package directory). Hatchling only includes files from discovered package directories (envilder/), so this file won't be included in the built wheel/sdist. Consumers installing the package from PyPI won't get PEP 561 typed package recognition — type checkers like mypy will treat the package as untyped, despite the pyproject.toml declaring "Typing :: Typed" in classifiers and the documentation listing strict typing as a key feature.
View 8 additional findings in Devin Review.
- Guard top-level JSON type in MapFileParser (reject non-object) - Case-insensitive provider parsing in map file config - Add name validation to AzureKeyVaultSecretProvider - Narrow exception handling in SecretProviderFactory - Move py.typed to envilder/ package dir (PEP 561) - Remove unused ssl import from lowkey_vault_container - Simplify exception handling in container wrappers - Remove lambda assignments in tests (Ruff E731) - Remove unused imports from e2e tests - Gate AWS creds on version_changed in publish workflow - Narrow permissions in test report job - Fix matrix output aggregation in CI workflow - Remove duplicate Makefile dotnet targets - Add tests for JSON guard and mixed-case provider
…e, retry throttle, region chain
…tant - Fix test reporter glob to match versioned XML filenames - Wrap cd commands in subshells for isort and black checks - Remove unused _FALLBACK_REGION constant
Summary
Adds a Python SDK for Envilder that mirrors the .NET SDK architecture, enabling Python applications to load secrets directly from AWS SSM Parameter Store or Azure Key Vault using the shared map-file format. Includes a root Makefile for SDK development workflows, a GitHub Actions CI workflow, and a PyPI publish workflow using trusted publishers.
Changes
Python SDK (
src/sdks/python/)ISecretProviderProtocol,SecretProviderTypeenum, dataclasses (MapFileConfig,EnvilderOptions,ParsedMapFile)MapFileParserwith$configsection support,EnvilderClientwithresolve_secrets()andinject_into_environment()AwsSsmSecretProvider(boto3),AzureKeyVaultSecretProvider,SecretProviderFactorywith options overridepy.typedmarker__init__.pyproject.urlsmetadata for PyPI page linksTests (
tests/sdks/python/)LocalStackContainer,LowkeyVaultContainerwith explicitstart()/stop()lifecycle and HTTP health checksLocalStackContaineruses the SDK itself to resolveLOCALSTACK_AUTH_TOKENfrom real AWS SSM viasecrets-map.jsonMakefile
check-sdk-python,format-sdk-python,test-sdk-pythoncheck-sdk-dotnet,format-sdk-dotnet,build-sdk-dotnet,test-sdk-dotnetcheck-sdk,format-sdk,build-sdk,test-sdkCI (
.github/workflows/tests-python-sdk.yml)Publish (
.github/workflows/publish-pypi.yml)mainwhensrc/sdks/python/**changespyproject.tomlvs published PyPI version)uv build, publishes viapypa/gh-action-pypi-publishsdk-python/vX.Y.Zgit tag + GitHub releaseTesting
make check-sdk-pythonpasses (black, isort, mypy strict)make test-sdk-pythonpasses (29/29, 0 warnings)Setup Required
envilderpackage (owner:macalbert, repo:envilder, workflow:publish-pypi.yml, environment:pypi)pypienvironment in GitHub repo settingsSummary by CodeRabbit
New Features
Documentation
Tests
Chores