Skip to main content

steps

The steps field is an ordered array of step objects. Atmos executes the steps in the order they appear.

workflows:
deploy:
steps:
- name: plan
type: atmos
command: terraform plan vpc
- name: apply
type: atmos
command: terraform apply vpc -auto-approve

Each array item is a step — the unit of work Atmos runs, whether it executes a command or renders interactive UI. The type field selects step behavior. Fields such as title, columns, prompt, retry, and timeout are parameters on that same step object; they are not separate steps.

steps:
- name: building
type: spin
title: Building application
command: npm run build
timeout: 60s

In this example, spin is the value of steps[].type. The fields title, command, and timeout configure that spin step.

Common Fields

name
Optional step identifier. Atmos generates names like step1 when omitted. Names are used by --from-step and by templates such as {{ .steps.plan.value }}.
type
Step behavior selector. Type atmos is the default for command steps. See type.
command
Command text for command-running step types such as atmos, shell, spin, and container run actions.
stack
Step-level stack override for type: atmos steps.
identity
Step-level auth identity. See identity.
when
Optional condition that decides whether the step runs. Built-in predicate keywords are evaluated first; other non-empty scalar strings are evaluated as CEL.
env
Step-level environment variables. See env.
working_directory
Step-level working directory override. See working_directory.
retry
Retry policy for the step. See retry.
output
Step-level output mode override. See output.
show
Step-level display settings override. See show.
outputs
Declared outputs derived from the step result. See outputs.
when
Condition controlling whether the step runs. Omitted means success-only: the step runs while the workflow status is still success. Use when: always for cleanup steps that must run after a previous step fails, such as stopping an emulator, restoring a backup file, or removing Terraform state.

Type-specific fields are documented with type.

Referencing values from other steps

A named step's result is available to later steps as {{ .steps.<name>.value }} (and {{ .steps.<name>.values }} for multi-value steps). These templates — along with {{ .env.* }} and {{ .flags.* }} and Sprig/Gomplate functions — resolve in shell, atmos, and exec step commands and in a step's env: values, the same way they do for custom command steps:

workflows:
deploy:
steps:
- name: component
type: choose
prompt: "Component"
options: [vpc, eks]
- type: atmos
command: terraform apply {{ .steps.component.value }} -auto-approve
env:
COMPONENT: "{{ .steps.component.value }}"

Interactive Steps in CI (non-TTY)

Interactive step types (choose, input, confirm, filter, file, write) prompt for input and need a terminal. When Atmos runs without a TTY — most commonly in CI — a step behaves based on whether it has a default:

  • With a default, the step uses the default value without prompting.
  • Without a default, the step fails with interactive terminal required for step. This preserves the previous behavior, so an unattended run never proceeds with an unintended value.

This lets the same workflow prompt locally and run unattended in CI. Source the default from the environment with the !env function (!env VAR fallback):

steps:
- name: account
type: choose
prompt: "Account"
options: [dev, prod]
default: !env STACK_ACCOUNT dev
- type: shell
command: 'echo "Deploying {{ .steps.account.value }}"'

Workflow step default, prompt, options, and placeholder evaluate the !env and !exec YAML functions. (Custom commands defined in atmos.yaml resolve these during config load.) The captured value — entered interactively or taken from the default — is available to later steps as {{ .steps.<name>.value }}.

Conditional Execution

Use when to skip a workflow step unless a condition is true. Bare predicate keywords keep their existing behavior:

steps:
- name: plan
type: atmos
command: terraform plan vpc
when: ci

Any other non-empty scalar string is evaluated as a CEL expression:

steps:
- name: prod-ci-check
type: shell
command: ./scripts/check-prod.sh
when: stack == "prod" && ci

Use the explicit !cel tag when the value is intended to be CEL or could look ambiguous:

steps:
- name: prod-ci-check
type: shell
command: ./scripts/check-prod.sh
when: !cel 'stack == "prod" && ci'

Workflow step CEL expressions can use ci, status, stack, component, workflow, step, and env. Predicate keywords win over CEL for bare strings, so when: ci uses the built-in predicate while when: !cel 'ci' evaluates CEL. status starts as success and becomes failure after a previous step fails.

Cleanup Steps

Atmos continues evaluating structured steps after a failure so failure-aware cleanup can run:

steps:
- type: shell
name: start-emulator
command: atmos emulator up aws -s dev --ephemeral

- type: shell
name: record-or-test
command: atmos terraform apply demo -s dev -auto-approve

- type: shell
name: stop-emulator
when: always
command: atmos emulator down aws -s dev

- type: shell
name: validate
command: atmos terraform output demo -s dev

If record-or-test fails, stop-emulator still runs because it declares when: always. The validate step is skipped because omitted when means success-only. The workflow still exits with the original failure; cleanup does not make the failed workflow look successful.