Skip to content

Variables

Variables are named values injected into deployments and runbooks. They let one release deploy to many environments with different settings.

A variable can be scoped to any combination of dimensions. When several definitions of the same name apply, the most specific scope wins:

infrastructure (target) > tenant > environment > channel > service

Each dimension is weighted so a higher dimension always beats any combination of lower ones: a variable scoped to an infrastructure beats one scoped to an environment and a service together. A variable with no scope applies everywhere. On a tie the project-level definition wins over org-wide, then the newest, then ID, so resolution is deterministic.

Example Scope
LOG_LEVEL=info Project (everywhere)
LOG_LEVEL=debug Environment staging
REPLICAS=12 Environment production
REPLICAS=2 Infrastructure prod-eu-canary (beats the environment value)
DB_HOST Tenant acme in a multi-tenant service

Values may reference other variables and release data with ${{ ... }}:

API_URL = https://${{ vars.REGION }}.api.example.com
IMAGE = ${{ release.artifacts.image.ref }}
VERSION_TAG = ${{ release.version }}

References are resolved with a bounded depth, and cycles are rejected with an error naming the variables involved.

A variable can be sensitive, in which case it stores only a secret reference (see Secrets) and is resolved at deployment time. Previews and logs show ******** for sensitive values.

When a release is created, Slipway snapshots every variable definition that could apply to it (sensitive ones keep only their reference). Deployments resolve against that snapshot first, then fall back to live definitions for names the snapshot does not have. Consequences:

  • Changing a variable never rewrites history. Redeploying an old release restores the values it originally had.
  • New names still work. A variable added after the release (for a new environment, say) resolves through the fallback.

EnvironmentService.PreviewVariables (and Preview in the UI) shows every variable’s resolved value for a release and environment, with the scope that won. Use it before a risky deployment.

Every pipeline reads the same store as vars.<k>: org- and project-wide, non-sensitive definitions, with ${{ vars.x }} templates expanded, in pipeline-level expressions (env, dynamic matrices, input defaults) and in job expressions. A job bound to an environment (environment: {name: production, service: api}) sees the definitions narrowed to that service and environment, as environment.vars.<k> and as vars.<k> alike, and environment-scoped secrets are injected into it. Generic webhook triggers can filter on vars too (filter: vars.REGION == "eu-west-1"). Sensitive variables never reach pipeline expressions; they are resolved for deployments only, and pipelines use secrets.<name>. See Contexts.

A sensitive variable’s secret_ref, and any secret_ref or secret_env entry in infrastructure config, may name a stored secret or be an external reference such as vault://kv/data/app#password or aws-sm://eu-west-1/app/db, resolved through the organisation’s external secret connection at deploy time and never stored.