Templates and environments
An EnvironmentTemplate describes the services that make up a preview environment: which Helm charts to deploy, in what order, and how they connect. It is typically set up once per cluster; individual environments supply per-instance overrides on top of it.
EnvironmentTemplate
Each component entry in a template specifies a Helm chart source, which can be a path in a Git repository, a separate Git repository with an optional fallback ref, or a published OCI or Helm registry chart.
Component entries also accept:
values- Go template strings rendered at deploy time. Available variables include{{.Env.Name}},{{.Env.Slug}},{{.Env.GeneratedSecret}}, and{{.Components.NAME.KEY}}for binding values from shared components.env- environment variables injected via Helm. Entries can be plain strings or references to a shared component binding Secret.dependsOn- component names that must reach the Ready phase before this component starts deploying.readiness- an optional HTTP health check the operator polls before advancing dependent components.sharedComponentRef- a reference to aSharedComponentinstead of a Helm chart, used when a component is pooled across environments.
At the template level, you can configure the ingress domain pattern (a Go template accepting {{.Name}}), a default TTL applied to all environments that do not set their own, and a deploy timeout per component (default 15 minutes).
EphemeralEnvironment
One EphemeralEnvironment CR represents one running environment. You create it with kubectl, the API server, a CI job, or any other tool that can write Kubernetes resources. The operator picks it up and drives it through its lifecycle.
apiVersion: petri.run/v1alpha1
kind: EphemeralEnvironment
metadata:
name: my-environment
namespace: <management namespace>
spec:
template: default
source: # optional metadata; the operator never reads the repository
repo: https://github.com/org/myapp
branch: feature/my-feature
sha: abc123def
values: # flat map; keys are Helm dot-notation paths
image.tag: abc1234
env: # per-environment env overrides
FEATURE_X: "true"
ttl: 48h # overrides template TTL; "0" disables expiry
spec.source is provenance metadata only. The operator never clones or reads the repository; whoever creates the EphemeralEnvironment is responsible for resolving artifact references and passing them in as spec.values.
spec.values and spec.env replace their entire map in the template when supplied. Passing {} clears the map. Omitting a field leaves the template's map in place.
Status
The operator writes the current state back to status:
status:
phase: Ready # Pending | Deploying | Ready | Failed | Terminating
targetNamespace: petri-env-a3f2c1b9
url: https://my-environment.preview.example.com
expiresAt: "2026-07-25T10:00:00Z"
components:
- name: postgres
phase: Ready
shared: true
- name: api
phase: Ready
- name: frontend
phase: Ready
targetNamespace is the workload namespace allocated for this environment. url is the ingress URL rendered from the template's domain pattern. expiresAt reflects the effective TTL; it is absent when TTL is disabled. Each component entry in status.components tracks its own phase and whether it is backed by a shared component.
See Deployment lifecycle and readiness for how the operator moves an environment through its phases.