Skip to content
Merged
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
85 changes: 85 additions & 0 deletions .commitlintrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Copyright 2025 Vantage Compute Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# .commitlintrc.yml
# Enforces: <type>[(<scope>)]: [<task-id>] <summary> (#<pr-number>)
# - scope is optional
# - [task-id] is optional
# - "(#<pr-number>)" is optional
# - No "type!:"; use BREAKING CHANGE footer instead.

extends:
- "@commitlint/config-conventional"

parserPreset:
# Inline custom parser (no external package needed)
parserOpts:
headerPattern: "^([a-z]+)(?:\\(([^)]+)\\))?:\\s(?:\\[(.+?)\\]\\s)?(.+?)(?:\\s\\(#\\d+\\))?$"
headerCorrespondence:
- type
- scope
- task
- subject

rules:
# Allowed types
type-enum:
- 2
- always
- [fix, feat, cherry-pick, chore, security, ci, docs, test, refactor, perf, release]

type-case:
- 2
- always
- lower-case

# Scope is optional; if present, keep it lowercase
scope-case:
- 2
- always
- lower-case

# Require concise subject (your "summary")
subject-empty:
- 2
- never
subject-max-length:
- 2
- always
- 80
subject-full-stop:
- 2
- never

# Enforce blank lines before body/footer when present
body-leading-blank:
- 2
- always
footer-leading-blank:
- 2
- always

# Soft cap on full header length (subject already capped to 80)
header-max-length:
- 1
- always
- 120

type-empty:
- 2
- never

# Disallow "!" in the subject; "type!:" is already blocked by headerPattern
subject-exclamation-mark:
- 2
- never
7 changes: 6 additions & 1 deletion go/shim/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ func helm_sdkpy_history(handle C.helm_sdkpy_handle, release_name *C.char, result
// Pull action

//export helm_sdkpy_pull
func helm_sdkpy_pull(handle C.helm_sdkpy_handle, chart_ref *C.char, dest_dir *C.char) C.int {
func helm_sdkpy_pull(handle C.helm_sdkpy_handle, chart_ref *C.char, dest_dir *C.char, version *C.char) C.int {
state, err := getConfig(handle)
if err != nil {
return setError(err)
Expand All @@ -556,13 +556,18 @@ func helm_sdkpy_pull(handle C.helm_sdkpy_handle, chart_ref *C.char, dest_dir *C.

chartRef := C.GoString(chart_ref)
destDir := C.GoString(dest_dir)
chartVersion := C.GoString(version)

// Create pull action
client := action.NewPull()
client.Settings = state.envs
if destDir != "" {
client.DestDir = destDir
}
// Set version if provided
if chartVersion != "" {
client.Version = chartVersion
}

// Run the pull
_, err = client.Run(chartRef)
Expand Down
12 changes: 9 additions & 3 deletions helm_sdkpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

"""Python bindings for Helm - The Kubernetes Package Manager."""

from importlib.metadata import version as _get_version

from ._ffi import get_version
from .actions import (
Configuration,
Expand All @@ -28,7 +30,7 @@
Uninstall,
Upgrade,
)
from .chart import Lint, Package, Pull, Push, Show, Test
from .chart import Lint, Package, Pull, Push, ReleaseTest, Show
from .exceptions import (
ChartError,
ConfigurationError,
Expand All @@ -44,7 +46,10 @@
)
from .repo import RepoAdd, RepoList, RepoRemove, RepoUpdate

__version__ = "0.0.1"
# Backwards compatibility alias - ReleaseTest renamed to avoid pytest collection
Test = ReleaseTest

__version__ = _get_version("helm-sdkpy")

__all__ = [
# Core classes
Expand All @@ -63,7 +68,8 @@
# Chart classes
"Pull",
"Show",
"Test",
"Test", # Alias for ReleaseTest
"ReleaseTest",
"Lint",
"Package",
"Push",
Expand Down
4 changes: 2 additions & 2 deletions helm_sdkpy/_ffi.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
int helm_sdkpy_history(helm_sdkpy_handle handle, const char *release_name, char **result_json);

// Pull action
int helm_sdkpy_pull(helm_sdkpy_handle handle, const char *chart_ref, const char *dest_dir);
int helm_sdkpy_pull(helm_sdkpy_handle handle, const char *chart_ref, const char *dest_dir, const char *version);

// Show chart action
int helm_sdkpy_show_chart(helm_sdkpy_handle handle, const char *chart_path, char **result_json);
Expand All @@ -84,7 +84,7 @@
// Registry management actions
int helm_sdkpy_registry_login(helm_sdkpy_handle handle, const char *hostname, const char *username, const char *password, const char *options_json);
int helm_sdkpy_registry_logout(helm_sdkpy_handle handle, const char *hostname);

// Push action (for OCI registries)
int helm_sdkpy_push(helm_sdkpy_handle handle, const char *chart_ref, const char *remote, const char *options_json);

Expand Down
2 changes: 0 additions & 2 deletions helm_sdkpy/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,6 @@ async def run(
Raises:
RegistryError: If login fails
"""
from .exceptions import RegistryError

def _registry_login():
hostname_cstr = ffi.new("char[]", hostname.encode("utf-8"))
Expand Down Expand Up @@ -678,7 +677,6 @@ async def run(self, hostname: str) -> None:
Raises:
RegistryError: If logout fails
"""
from .exceptions import RegistryError

def _registry_logout():
hostname_cstr = ffi.new("char[]", hostname.encode("utf-8"))
Expand Down
15 changes: 11 additions & 4 deletions helm_sdkpy/chart.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,15 @@ def __init__(self, config):
self.config = config
self._lib = get_library()

async def run(self, chart_ref: str, dest_dir: str | None = None) -> None:
async def run(
self, chart_ref: str, dest_dir: str | None = None, version: str | None = None
) -> None:
"""Pull a chart asynchronously.

Args:
chart_ref: Chart reference (e.g., "repo/chart" or "oci://...")
dest_dir: Destination directory (default: current directory)
version: Chart version to pull (e.g., "1.2.3"). If not specified, uses latest

Raises:
ChartError: If pull fails
Expand All @@ -57,8 +60,12 @@ async def run(self, chart_ref: str, dest_dir: str | None = None) -> None:
def _pull():
ref_cstr = ffi.new("char[]", chart_ref.encode("utf-8"))
dest_cstr = ffi.new("char[]", dest_dir.encode("utf-8")) if dest_dir else ffi.NULL
version_str = version or ""
version_cstr = ffi.new("char[]", version_str.encode("utf-8"))

result = self._lib.helm_sdkpy_pull(self.config._handle_value, ref_cstr, dest_cstr)
result = self._lib.helm_sdkpy_pull(
self.config._handle_value, ref_cstr, dest_cstr, version_cstr
)

if result != 0:
check_error(result)
Expand Down Expand Up @@ -149,7 +156,7 @@ def _values():
return await asyncio.to_thread(_values)


class Test:
class ReleaseTest:
"""Helm test action.

Runs tests for a release.
Expand All @@ -160,7 +167,7 @@ class Test:
Example:
>>> import asyncio
>>> config = Configuration()
>>> test = Test(config)
>>> test = ReleaseTest(config)
>>> result = asyncio.run(test.run("my-release"))
"""

Expand Down
8 changes: 8 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ dev = [
# Testing
"coverage[toml] ~= 7.8",
"pytest ~= 8.3",
"pytest-asyncio ~= 0.24",
"pytest-mock ~= 3.14",
"pytest-order ~= 1.3",
"python-dotenv ~= 1.0",
Expand All @@ -38,6 +39,12 @@ dev = [
[tool.pytest.ini_options]
addopts = "-ra"
testpaths = ["tests"]
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"
filterwarnings = [
"ignore:'asyncio.get_event_loop_policy':DeprecationWarning",
"ignore:cannot collect test class 'ReleaseTest':pytest.PytestCollectionWarning",
]

[build-system]
requires = ["hatchling"]
Expand All @@ -47,6 +54,7 @@ build-backend = "hatchling.build"
dev = [
"codespell>=2.4.1",
"pyright>=1.1.406",
"pytest-asyncio>=0.24",
"pytest-cov>=7.0.0",
"ruff>=0.14.1",
]
Expand Down
Loading