Skip to content

Variables & Templating

Declaring variables

Add a vars section to your pipeline:

name: deploy
vars:
registry: "ghcr.io/myorg"
env: "staging"
steps:
- id: push
run: "docker push $PIPE_VAR_REGISTRY/app:latest"
- id: deploy
run: "kubectl apply -n $PIPE_VAR_ENV -f deploy.yaml"

Each variable is exposed as PIPE_VAR_<KEY> with hyphens converted to underscores and the name uppercased.

The vars contract

The vars block is the contract for what variables your pipeline accepts. All override sources — .env files, PIPE_VAR_* environment variables, and CLI KEY=value flags — can only override keys that are declared in vars.

If an override source provides a key that is not declared in vars, the key is ignored and a warning is shown:

WARN "SECRET_KEY" from dot_file has no effect — not declared in vars
WARN "PIPE_VAR_NONAME" is set but has no effect on this pipeline
WARN "custom_flag" passed via CLI has no effect — not declared in vars

This ensures pipelines are explicit about which variables they use. Warnings appear during both pipe run and pipe lint.

Bypassing the contract

Set PIPE_EXPERIMENTAL_UNSAFE_VARS to disable the vars contract. This allows override sources to introduce new keys not declared in vars, and suppresses all related warnings:

Terminal window
PIPE_EXPERIMENTAL_UNSAFE_VARS=1 pipe deploy custom_flag=true

This is experimental and unsafe — pipelines lose the guarantee that only expected variables are injected.

Loading variables from a .env file

Add a dot_file field to your pipeline to load variables from a standard .env file:

name: deploy
dot_file: ".env"
vars:
registry: "ghcr.io/myorg"
env: "staging"
steps:
- id: push
run: "docker push $PIPE_VAR_REGISTRY/app:latest"

The .env file uses plain NAME=value format (no PIPE_VAR_ prefix needed):

.env
registry=docker.io/myorg
env=production

Each key is matched against the vars block and automatically mapped to PIPE_VAR_<KEY>. Keys not declared in vars are ignored with a warning.

If the .env file is missing, the pipeline continues silently — use a full path or run pipe from the directory containing the file. Malformed lines (e.g., missing =) are skipped with a warning.

Precedence

Variables resolve from four sources with increasing priority:

PrioritySourceDescription
1 (lowest)YAML varsDefault values in the pipeline file
2.env fileValues from the dot_file path
3System environmentPIPE_VAR_* env vars set before running
4 (highest)CLI overridesKEY=value arguments after the pipeline name

Only keys declared in vars are accepted from any source.

Terminal window
# Uses YAML default for "registry", overrides "env"
pipe deploy env=production
# System env override
export PIPE_VAR_REGISTRY=docker.io/myorg
pipe deploy

Go template syntax

Variable values support Go text/template syntax, executed against the system environment:

vars:
user: "{{ .USER }}"
branch: "{{ .GITHUB_REF_NAME | default \"main\" }}"
home: "{{ .HOME }}/projects"

The default function provides a fallback when the environment variable is unset or empty:

vars:
region: "{{ .AWS_REGION | default \"us-east-1\" }}"

How it works

  1. Pipe reads each var value from the YAML.
  2. If the value contains {{, it is parsed as a Go template.
  3. The template is executed with the system environment as a flat map (e.g., .HOME, .USER, .PATH).
  4. If parsing or execution fails, the original string is used as-is (graceful degradation).