Rendering a Baseline from git

A Baseline either declares its services inline in spec.services or points at a repository in spec.source. With a source, the operator clones the repository, renders the deployment definition and derives the service list. Inline entries then act as per-service overrides by name.

spec:
  application: shop
  source:
    url: https://git.bank.internal/retail/shop.git
    ref: release/2026.09        # branch, tag or commit sha
    path: deploy/chart
    kind: helm                  # helm | kustomize | manifests | compose
    secretRef: {name: shop-git}
    helm:
      valuesFiles: [values-prod.yaml]
      values: {logLevel: info}
    pollInterval: 5m            # optional; re-resolve the ref this often
  services:
    - name: shop-postgres       # override: rendered as StatefulSet, keep it shared
      shared: true

Credentials Secret

Key Use
token HTTPS token or password. username optional, defaults to nazeel.
ssh-privatekey SSH key. known_hosts is required; passphrase optional.
ca.crt PEM bundle for a private certificate authority on the git server.

The operator contacts nothing but this git server.

Formats

How Kubernetes objects become services

Each Service that selects a Deployment or StatefulSet becomes one nazeel service, named after the Service. Image, command, args, env, resources, replicas, working directory and the numeric uid come from the first container. Port protocol comes from appProtocol or the nazeel.sa/protocol annotation, otherwise http, except well-known database ports which default to tcp. The annotation nazeel.sa/shared: "true", or being a StatefulSet, marks a shared dependency. In compose, use the labels nazeel.sa/protocol and nazeel.sa/shared.

Health checks

A readiness probe in the source is carried over. A compose healthcheck becomes one too: CMD runs the command directly, CMD-SHELL and the bare string form run through /bin/sh, and disable: true or NONE means no probe at all.

Nothing is ever rendered as a liveness probe. A liveness probe restarts the pod, and a check written for production, or for a laptop, will restart a half-built preview environment forever. A readiness probe only decides whether traffic is sent, which is recoverable. Where a workload declares only a liveness probe, it is used as the readiness check and a warning says so.

With no check declared, nazeel infers a TCP probe on the service's first port, so the first request after nazeel up does not reach a process that has not started listening yet.

Volumes and mounted files

In the source Becomes Note
emptyDir, compose named or anonymous volume emptyDir Ephemeral. Nothing survives a restart.
configMap, secret, compose configs, compose secrets file mount The object must already exist in the namespace.
persistentVolumeClaim emptyDir, with a warning Mark the service shared if it owns real data.
compose bind mount (./src:/app) dropped, with a warning A host path does not exist in the cluster.

Two rules behind that table. A preview environment is rebuilt from the repository, so state that survived a rebuild would make it irreproducible, and nazeel never provisions persistent storage for one. And nazeel never copies secret material out of a git repository into the cluster: a compose secrets: entry names a Secret that an admin creates, it does not upload the file compose would have read from disk.

A ConfigMap or Secret mounted as a whole directory is not carried over, because its keys are only known at deploy time. List them under items in the source, or use subPath.

Every rendered pod has a read-only root filesystem, so a service that writes outside a declared scratch path will fail. Add an emptyDir mount in the source for the paths it needs.

Ordering

depends_on is not an ordering guarantee in Kubernetes. Everything starts at once and a service restarts until its dependencies answer, which usually converges within seconds. A service that reads its database once at startup and exits rather than retrying will crash-loop instead, so make startup connections retry.

What to look at

Failures retry every two minutes. Rendered output is cached by commit, so restarting the operator or re-applying the same Baseline does not re-render.