Composition contract
This is the field reference for the documents that make up a golden path. For why the path is split this way and what orun enforces about it, read compositions first.
A composition source exports self-describing documents. The primary contract is a Composition document grouped under a Stack package. Compositions support both inline authoring (single file) and split-kind authoring (multiple files).
Document kinds
| Kind | Purpose | Required fields |
|---|---|---|
Composition | Type binding, defaults, references | metadata.name, spec.type, spec.defaultJob, spec.jobs |
ComponentSchema | Input validation contract | metadata.name, spec.type, spec.schema |
JobTemplate | Reusable execution template | metadata.name, spec.steps |
ExecutionProfile | Behavior overlay per context | metadata.name, spec.jobs |
Composition document
A Composition is the public facade for a component type. It can define everything inline or reference split-kind documents via schemaRef, templateRef, and profileRef.
Required fields (inline):
metadata.namespec.typespec.defaultJobspec.parameterSchemaorspec.schemaRefspec.jobs
Example (split-kind):
apiVersion: sourceplane.io/v1alpha1
kind: Composition
metadata:
name: terraform
spec:
type: terraform
description: Terraform validation jobs for infra components
schemaRef:
name: terraform-component
defaultJob: validate
defaultProfile: verify
jobs:
- name: validate
templateRef:
name: terraform-validate
profiles:
- name: pull-request
profileRef:
name: terraform-pull-request
- name: verify
profileRef:
name: terraform-verify
- name: release
profileRef:
name: terraform-release
Example (inline):
apiVersion: sourceplane.io/v1alpha1
kind: Composition
metadata:
name: helm
spec:
type: helm
defaultJob: deploy
parameterSchema:
$schema: http://json-schema.org/draft-07/schema#
type: object
properties:
type:
const: helm
parameters:
type: object
properties:
chart:
type: string
jobs:
- name: deploy
runsOn: ubuntu-22.04
timeout: 15m
retries: 2
steps:
- name: deploy
run: helm upgrade --install {{.orun.component.name}} {{.parameters.chart}}
defaultJob must be explicit. Orun no longer relies on implicit "first job wins" behavior.
ComponentSchema document
Defines the JSON Schema validation contract for component parameters. Referenced by schemaRef.name in the Composition.
apiVersion: sourceplane.io/v1alpha1
kind: ComponentSchema
metadata:
name: terraform-component
spec:
type: terraform
schema:
$schema: http://json-schema.org/draft-07/schema#
type: object
required: [name, type, parameters]
properties:
name:
type: string
type:
const: terraform
parameters:
type: object
required: [stackName, terraformDir]
properties:
stackName:
type: string
terraformDir:
type: string
terraformVersion:
type: string
additionalProperties: false
additionalProperties: true
JobTemplate document
Defines a reusable job with capability-tagged steps. Referenced by templateRef.name in the Composition's jobs list.
apiVersion: sourceplane.io/v1alpha1
kind: JobTemplate
metadata:
name: terraform-validate
spec:
description: Validate Terraform stacks
runsOn: ubuntu-22.04
timeout: 20m
retries: 0
labels:
scope: infra
capabilities:
- terraform.setup
- terraform.fmt
- terraform.init
- terraform.validate
- terraform.plan
steps:
- id: setup
name: setup
capability: terraform.setup
use: hashicorp/setup-terraform@v4
with:
terraform_version: "{{.parameters.terraformVersion}}"
- id: fmt
name: fmt
capability: terraform.fmt
run: terraform fmt -check
onFailure: stop
- id: init
name: init
capability: terraform.init
run: terraform init -backend=false
onFailure: stop
- id: validate
name: validate
capability: terraform.validate
run: terraform validate -no-color
onFailure: stop
- id: plan
name: plan
capability: terraform.plan
run: terraform plan -no-color
onFailure: stop
The capability field on each step enables semantic selection by profiles.
ExecutionProfile document
Defines which steps to run and how to override them for a specific execution context. Referenced by profileRef.name in the Composition's profiles list.
apiVersion: sourceplane.io/v1alpha1
kind: ExecutionProfile
metadata:
name: terraform-pull-request
spec:
description: Fast PR validation with speculative planning
jobs:
validate:
includeCapabilities:
- terraform.setup
- terraform.fmt
- terraform.init
- terraform.validate
- terraform.plan
stepOverrides:
init:
run: terraform init -backend=false
plan:
run: terraform plan -no-color -lock=false
Profiles can also declare policies. They are parsed and carried onto each component instance, but orun does not enforce them yet; see standards.
spec:
policies:
requireCleanGitTree: true
requirePinnedTerraformVersion: true
requireApproval: true
Profile step selection
Profiles select which steps to run using one of two mechanisms:
includeCapabilities(recommended): Selects steps by theircapabilitytag. This is resilient to step ID renames.stepsEnabled(legacy): Selects steps by theiridorname. Works with inline compositions that don't use capabilities.
Profile step overrides
stepOverrides patches specific step fields without duplicating the entire step definition:
stepOverrides:
init:
run: terraform init -backend=false
plan:
with:
lock: "false"
Stack manifest
A Stack manifest (stack.yaml) declares package metadata and an optional OCI registry target.
apiVersion: orun.io/v1
kind: Stack
metadata:
name: my-platform-stack
version: 1.0.0
description: Platform compositions
owner: my-org
registry:
host: ghcr.io
namespace: my-org
repository: my-platform-stack
visibility: public
Package layout (split-kind):
my-platform/
├── stack.yaml
└── compositions/
└── terraform/
├── composition.yaml
├── schema.yaml
├── jobs/
│ └── terraform-validate.yaml
└── profiles/
├── terraform-pull-request.yaml
├── terraform-verify.yaml
└── terraform-release.yaml
Template namespaces
Job steps resolve against a namespaced template context:
| Namespace | Purpose | Example |
|---|---|---|
.orun | System/compiler-provided context | {{ .orun.component.name }} |
.parameters | Resolved component parameters | {{ .parameters.terraformDir }} |
.env | Resolved runtime env map | {{ .env.AWS_REGION }} |
.orun fields
.orun.component.name— component name.orun.component.type— composition type.orun.component.domain— group/domain name.orun.environment.name— environment name.orun.composition.type— composition type.orun.profile.name— execution profile name.orun.job.id— job ID (e.g.api.dev.deploy).orun.job.name— job name (e.g.deploy)
.parameters fields
All resolved component parameters after merge (parameterDefaults + component parameters + subscription parameters):
.parameters.terraformDir.parameters.chartPath.parameters.nodeVersion
One parameter name is meaningful to the runner itself: secretOutputs
declares the job's output secrets ("KEY=hint,KEY2=hint") and causes
$ORUN_SECRET_OUTPUTS to be exported to every step — see
Secrets → job output secrets.
.env fields
Runtime environment variables declared in intent or component env blocks:
.env.AWS_REGION.env.TF_LOG
Execution semantics
Jobs can declare: runsOn, timeout, retries, resources, labels, capabilities, steps.
resources is what the job needs, for packing lanes and sizing a lane's concurrency to its runner; it changes nothing about what runs:
resources:
cpu: 2 # cores the job keeps busy (fractions allowed)
memory: 4Gi # informational, for a runner pool
estimatedSeconds: 90 # the job's usual duration: its packing weight
Steps can declare: run or use, capability, phase, order, scope, with, env, shell, working-directory, timeout, retry, caches, onFailure.
scope: lane marks a run step that every job of a lane would execute identically — an install, a cache warm. The first job to reach it runs it once in the shared source tree; every other job of the lane whose step is the same after templating (same command, shell, environment and working directory) reuses the result. Lane-scoped steps must come first in a job, before its private tree is staged, and apply to run steps only: an action's exported environment stays with the job that ran it.
caches names the directories under the job's working directory a step fills and orun keeps on the machine between jobs and runs — a framework's build cache, a browser download — which a freshly staged tree and a per-job HOME would otherwise leave cold every time:
- name: build
run: pnpm exec next build
caches:
- name: next-web
path: .next/cache
Before the job's first step runs in its tree, each named cache is copied in from the machine's copy (~/.orun/actions/shared/caches/<name>) unless the tree already holds that path; after the job succeeds, what it left at the path becomes the machine's copy, swapped in whole under a lock. A failed job saves nothing. The name is a directory name (letters, digits, dots, dashes, underscores); the path is relative to the job's working directory and stays inside it.
Breaking changes (v2.0.0)
Flat template context removed. Prior to v2.0.0, step templates could use flat context variables like {{ .component }}, {{ .environment }}, {{ .type }}. These have been removed. All templates must use the namespaced form:
| Old (removed) | New (required) |
|---|---|
{{ .component }} | {{ .orun.component.name }} |
{{ .environment }} | {{ .orun.environment.name }} |
{{ .type }} | {{ .orun.component.type }} |
PlanJob.config removed. The config field on plan job output has been removed. Use parameters instead.
inputs/defaults renamed. Component inputs is now parameters. Intent defaults is now parameterDefaults. The old names are no longer accepted.