Skip to content

Python vs YAML

helm-me supports two spec formats. Both produce identical Kubernetes manifests.

YAML — Simple and Declarative

apiVersion: helm-me/v1alpha1
kind: Application
metadata:
  name: hello-app
  namespace: demo

components:
  backend:
    type: web
    image: traefik/whoami:latest
    port: 80
    replicas: 2

Best for:

  • Simple, static configurations
  • Teams where not everyone writes Python
  • CI/CD pipelines that read config from files

Python — Typed and Parameterized

from helm_me import App, image, param, web


class Deploy(App):
    name = "hello-app"
    namespace = param("NAMESPACE", "demo")

    backend = web(
        image=image("traefik/whoami:latest"),
        port=80,
        replicas=param("REPLICAS", 2),
    )

Best for:

  • IDE autocomplete and type hints
  • Dynamic configuration via param() (reads environment variables at render time)
  • Composing specs programmatically
  • Shared defaults across components

The param() Function

param() reads values from environment variables with a fallback default:

namespace = param("NAMESPACE", "staging")
# Reads $NAMESPACE, falls back to "staging"

This enables environment-specific deployments:

NAMESPACE=production APP_TAG=v2.1.0 helm-me deploy deploy.py --yes

Note

param() is Python-only. YAML specs use static values.

Side-by-Side Comparison

components:
  backend:
    type: web
    image:
      repository: ghcr.io/example/backend
      tag: "1.2.0"
    port: 8000
    env:
      DEBUG: "false"
    secretEnv:
      DATABASE_URL:
        component: db
        key: DATABASE_URL
backend = web(
    image=image("ghcr.io/example/backend", tag="1.2.0"),
    port=8000,
    env={"DEBUG": "false"},
    secret_refs={
        "DATABASE_URL": secret_ref("db", "DATABASE_URL"),
    },
)

Both formats render to the same Kubernetes manifests.