Skip to content

Inheritance & Worked Example

Both connections and environments support extends: for composition.

Connection inheritance — a base template

Section titled “Connection inheritance — a base template”

extends: on a connection is a base-template pattern. Define the shared fields once:

connections/akeneo-base/definition.yaml
type: zenvara/akeneo
TimeoutSeconds: 120
BatchSize: 100
MaxConcurrency: 4
AutoSanitizeCodes: true
# connections/akeneo-pim-prod/definition.yaml
extends: akeneo-base
BaseUrl: "https://prod.cloud.akeneo.com"
ClientId: "${secret:akeneo/pim-prod/client-id}"
ClientSecret: "${secret:akeneo/pim-prod/client-secret}"
Username: "${secret:akeneo/pim-prod/username}"
Password: "${secret:akeneo/pim-prod/password}"

Three overrides plus one base, instead of four near-identical files.

extends: on an environment is a list of parent environments composed in order — single-level only (no transitive chains), to keep the resolution graph easy to read.

environments/staging/definition.yaml
kind: staging
extends:
- common
connections:
db: warehouse-staging # overrides whatever `common` had under db

Two connections (one Postgres, one SFTP), two environments, one flow:

connections/audit-postgres-base/definition.yaml
type: zenvara/postgresql
TimeoutSeconds: 30
# connections/audit-postgres-dev/definition.yaml
extends: audit-postgres-base
ConnectionString: "${secret:audit/dev:connection-string}"
# connections/audit-postgres-prod/definition.yaml
extends: audit-postgres-base
ConnectionString: "${secret:audit/prod:connection-string}"
# environments/dev/definition.yaml
kind: development
connections: { audit: audit-postgres-dev, drop: drop-zone-dev }
# environments/prod/definition.yaml
kind: production
connections: { audit: audit-postgres-prod, drop: drop-zone-prod }
flows/incident-archive/definition.yaml
status: active
output:
archived: !int
steps:
- $rows:
invoke: postgresql.query
on: audit
with: { Query: "SELECT * FROM incidents WHERE archived = false" }
- $upload:
create: sftp.file
on: drop
with:
Path: "/incidents/${= str(_invocation-id)}.json"
Input: "${rows.body}"
- return:
archived: "${= len(rows.rows)}"

Run it twice:

Terminal window
zen invoke-flow incident-archive --env dev
zen invoke-flow incident-archive --env prod

Same flow, different audit DB, different SFTP drop zone. The environment is the only thing that changed — which is the whole point of the model.