Skip to main content

Environment Promotion

Environment promotion dependencies define ordering and gating relationships between environments. They express the deployment pipeline flow — for example, staging must succeed before production can run.

This is separate from component-level dependsOn, which expresses service-to-service dependencies within an environment.

Syntax

Add promotion.dependsOn to any environment that requires prior environment success:

environments:
preview:
activation:
triggerRefs:
- github-pull-request
parameterDefaults:
"*":
lane: verify

staging:
activation:
triggerRefs:
- github-push-main
promotion:
dependsOn:
- environment: preview
parameterDefaults:
"*":
lane: verify

production:
activation:
triggerRefs:
- github-tag-release
promotion:
dependsOn:
- environment: staging
parameterDefaults:
"*":
lane: release

With defaults applied, each entry is equivalent to:

promotion:
dependsOn:
- environment: staging
strategy: same-component
condition: success
satisfy: same-plan-or-previous-success
match:
revision: source

How It Compiles

The behavior depends on whether the dependency environment is active in the same plan.

Same-plan (both environments active)

When both environments are activated by the same trigger (or selected with --env), promotion dependencies compile into normal DAG edges:

web-app@dev.deploy  →  web-app@staging.deploy
api@dev.deploy → api@staging.deploy

The plan output uses standard dependsOn:

{
"id": "web-app.staging.deploy",
"dependsOn": ["web-app.dev.deploy"]
}

Cross-plan (dependency environment not active)

When environments are activated by different triggers (e.g., PR activates preview, push activates staging), the dependency environment won't be in the same plan. In this case, promotion compiles into gates — evidence checks that require prior success:

{
"id": "web-app.production.release",
"dependsOn": [],
"gates": [
{
"type": "environment-promotion",
"environment": "staging",
"component": "web-app",
"condition": "success",
"match": { "revision": "source" }
}
]
}

Gates require that the same component succeeded in the referenced environment for the same source revision before execution is allowed.

Strategies

same-component (default)

Each component in the target environment depends only on the same component in the dependency environment:

web-app@dev  →  web-app@staging
api@dev → api@staging

Components not subscribed to both environments are gracefully skipped.

environment-barrier

Every job in the target environment waits for every job in the dependency environment:

web-app@dev  ─┬─→  web-app@staging
api@dev ─┘ ┌→ api@staging
web-app@dev ───┘
api@dev ────→ api@staging

Use this for strict release-train semantics where the entire environment must be green before promotion.

Satisfy Modes

The satisfy field controls how the dependency is checked:

ModeBehavior
same-planRequires both environments in the same plan. Errors if the dependency environment is not active.
previous-successAlways uses prior evidence gates, even if both environments happen to be active.
same-plan-or-previous-successUses DAG edges when both are active, falls back to gates otherwise. (default)

Match

The match field controls how prior success evidence is validated:

match:
revision: source

revision: source means the gate checks that the same source commit (or the commit pointed to by a tag) succeeded in the prior environment.

Interaction with Trigger Bindings

Promotion dependencies work alongside trigger bindings and environment activation:

  1. Trigger activation decides which environments are active in a given plan
  2. Promotion dependencies decide ordering and gating between those environments
  3. Component dependencies decide ordering within the active set

A typical setup:

automation:
triggerBindings:
github-pull-request:
on:
provider: github
event: pull_request
plan:
scope: changed

github-push-main:
on:
provider: github
event: push
branches: [main]
plan:
scope: changed

github-tag-release:
on:
provider: github
event: push
tags: ["v*"]
plan:
scope: full

environments:
preview:
activation:
triggerRefs: [github-pull-request]
parameterDefaults:
"*":
lane: verify

staging:
activation:
triggerRefs: [github-push-main]
promotion:
dependsOn:
- environment: preview
parameterDefaults:
"*":
lane: verify

production:
activation:
triggerRefs: [github-tag-release]
promotion:
dependsOn:
- environment: staging
parameterDefaults:
"*":
lane: release

This gives you:

  • PR → preview only (validate changes)
  • Push to main → staging only (gate: preview must have passed for this commit)
  • Tag → production only (gate: staging must have passed for this commit)

Validation

Orun validates promotion dependencies at normalization time:

  • Referenced environments must exist
  • Self-references are rejected
  • Cycles are detected (e.g., A → B → A)