Skip to content

Per-environment properties

config/production.yaml
deploy.region: us-central1
deploy.trafficPercent: 50
deploy.platforms: [linux/amd64, linux/arm64]
deploy.canary: false
oren.yaml
pipelines:
deploy:
propertyFiles:
production: ./config/production.yaml
staging: ./config/staging.yaml
steps:
- id: publish
task: techlite/gcp-cloud-deploy@^1.0.0
implementation: techlite/gcp-cloud-deploy-gcloud
inputs:
region: ${properties.deploy.region}
Terminal window
oren run deploy -p production

-p accepts an alias declared in propertyFiles or a direct path.

An alias can say which branch it belongs to

Section titled “An alias can say which branch it belongs to”

Only for oren generate, and only when you want CI to pick the environment on its own:

propertyFiles:
producao:
file: ./config/producao.yaml
branches: [main]
staging:
file: ./config/staging.yaml
branches: [develop, 'feature/*']

The short form still works, and both live side by side in the same pipeline.

branches changes nothing about oren run — there the alias stays an explicit choice by whoever runs it. It does not read git to guess the branch, or the same command would start meaning different things depending on where it is typed.

The map lives here, and not inside the properties file, because that file has no schema: it is free, and you put whatever keys you want in it. A reserved branch: field inside it would end that.

See Running in CI for what each platform generates from it.

A property value may itself be an expression:

config/main.yaml
versao: ${outputs['versao'].version}
# config/develop.yaml
versao: ${outputs['versao'].candidateTag}
inputs:
image: registry/app:${properties.versao}

This is the one thing no plain value can do: choose a different field of the same output. ${outputs['versao'].${properties.campo}} is not expressible, and should not be — so the choice moves into the property file, where it is one line per environment.

It is what lets a single pipeline serve two branches: main publishes 0.1.4, develop publishes 0.1.4-rc.b43c8f5.20260809035558, and nothing in oren.yaml changes.

Only outputs and env are resolved inside a properties file. A property cannot reference another property — which removes the cycle problem entirely, and keeps the file from becoming where the logic hides.

Secrets carry over. A property that interpolates a secret output comes out marked as secret, and is redacted the same way. Without that, passing a credential through a property would launder it into the logs.

enabled accepts a boolean or an expression:

- id: tag
enabled: ${properties.commita}
task: techlite/commit-and-tag@^2.0.0
implementation: techlite/commit-and-tag-alpine

Only properties and env — never outputs. Which steps run has to be known before the run starts; that is what lets oren validate and the CI generator say anything at all about the pipeline.

It must resolve to a real boolean. The string "false" is refused rather than coerced: accepting it would run the step exactly against what was written.

A step that vanished depending on a value would be the very defect this project exists to avoid. So it is always listed:

[8/8] Commit and tag · tag · commit-and-tag
conditional · enabled = ${properties.commita}

With --properties, the same line becomes concrete — → runs or → skipped. The flag is optional: without it every step is still validated, and only the decision is left open.

oren install needs no --properties, and locks the conditional step anyway.

The rule is that the lock excludes only what the file proves never runs. A literal enabled: false proves it, and stays out of the lock — which is what lets you park a step whose worker is not published yet. An expression proves nothing at install time, so it is locked, and the decision is left to the run.

That is what keeps oren.lock independent of which properties file was used.

A generated CI has a fixed set of jobs, and ${properties.commita} does not exist inside GitLab or Cloud Build to be evaluated there. So the decision has to be made at generation time:

Terminal window
oren generate gitlab entrega -p main # 8 jobs
oren generate gitlab entrega -p develop # 7 jobs

Without the flag, generating a pipeline that has a conditional step is refused and names the step. Deciding on its own would silently produce a CI different from the one asked for.

A dotted key gives the visual simplicity of a .properties file, but the format is YAML because of types: contracts declare integer, boolean and array, and a format where everything is a string would force conversion by the destination’s type — making the same file behave differently depending on who consumes it.

Here 50 is a number, false is a boolean and the list is a list.

Explicit nesting works too, and both forms coexist in the same file. What is not allowed is the same key being a value and a grouping at once — one of the two would be lost silently.