DOC_INDEX
THEME
DOCS/Specification/Templates

Templates

Go template syntax, Sprig functions, regex extraction, and JavaScript expressions in OrchStep

OrchStep uses Go templates with Sprig functions for variable interpolation, and supports JavaScript expressions via the Goja VM for complex logic.

Go Template Syntax

Expressions are enclosed in {{ }}:

steps:
  - func: shell
    do: echo "Deploying {{ vars.version }} to {{ vars.environment }}"

Variable Access

PatternDescription
{{ vars.name }}Workflow variable
{{ steps.step_name.field }}Step output
{{ env.VAR_NAME }}Environment variable
{{ result.output }}Current step result (in outputs:)
{{ loop.item }}Current loop item
{{ loop.index }}Current loop index (zero-based)

Conditionals in Templates

do: |
  echo "Deploying to {{ vars.env }}"
  {{- if eq vars.env "production" }}
  echo "Extra production checks enabled"
  {{- end }}

Iteration in Templates

do: |
  {{ range vars.servers }}
  echo "Server: {{ . }}"
  {{ end }}

Sprig Functions

OrchStep includes Sprig v3 with 100+ utility functions.

String Functions

FunctionExampleResult
upper{{ "hello" | upper }}HELLO
lower{{ "HELLO" | lower }}hello
title{{ "hello world" | title }}Hello World
trim{{ " hello " | trim }}hello
trimSuffix{{ "hello.txt" | trimSuffix ".txt" }}hello
replace{{ "hello" | replace "l" "r" }}herro
contains{{ contains "hello" "ell" }}true
hasPrefix{{ hasPrefix "hello" "hel" }}true
hasSuffix{{ hasSuffix "hello" "llo" }}true
repeat{{ "ab" | repeat 3 }}ababab
substr{{ substr 0 5 "hello world" }}hello
trunc{{ trunc 5 "hello world" }}hello
camelcase{{ "my-service" | camelcase }}myService
snakecase{{ "myService" | snakecase }}my_service
kebabcase{{ "myService" | kebabcase }}my-service
split{{ split "," "a,b,c" }}list [a, b, c]
join{{ list "a" "b" "c" | join "," }}a,b,c

Math Functions

FunctionExampleResult
add{{ add 1 2 }}3
sub{{ sub 10 3 }}7
mul{{ mul 3 4 }}12
div{{ div 10 3 }}3
mod{{ mod 10 3 }}1
max{{ max 5 10 }}10
min{{ min 5 10 }}5
ceil{{ ceil 1.5 }}2
floor{{ floor 1.5 }}1

List Functions

FunctionDescription
firstFirst element of a list
lastLast element of a list
restAll elements except first
appendAdd element to end of list
concatMerge two lists
uniqRemove duplicate elements
hasCheck if list contains element
withoutRemove elements from list
sliceSub-list extraction
reverseReverse list order

Dictionary Functions

FunctionDescription
getGet value by key
setSet value for key
hasKeyCheck if key exists
keysGet all keys
valuesGet all values
pickSelect subset of keys
omitExclude subset of keys
mergeMerge dictionaries

Type Conversion

FunctionDescription
atoiString to integer
toStringConvert to string
toJsonSerialize to JSON string
toPrettyJsonSerialize to formatted JSON
fromJsonParse JSON string to object
toYamlSerialize to YAML string

Date/Time Functions

FunctionExample
nowCurrent time
date{{ now | date "2006-01-02" }}
dateModify{{ now | dateModify "+24h" }}
unixEpoch{{ now | unixEpoch }}

Encoding Functions

FunctionDescription
b64encBase64 encode
b64decBase64 decode
sha256sumSHA-256 hash
urlqueryURL-encode string
uuidv4Generate UUID v4

Logic Functions

FunctionExample
default{{ vars.port | default 8080 }}
empty{{ empty vars.name }}
coalesce{{ coalesce vars.a vars.b "fallback" }}
ternary{{ ternary "yes" "no" (eq vars.env "prod") }}

Regex Functions

FunctionDescriptionExample
regexMatchTest if string matches pattern{{ regexMatch "v[0-9]+" vars.version }}
regexFindExtract first capture group{{ result.output | regexFind "ID=(.+)" }}
regexFindAllExtract all matches{{ regexFindAll "[0-9]+" result.output -1 }}
regexReplaceAllReplace all matches{{ regexReplaceAll "[0-9]+" result.output "X" }}

Semantic Versioning

FunctionExample
semver{{ semver "1.2.3" }} -- parse to semver object
semverCompare{{ semverCompare ">=1.2.0" vars.version }} -- compare versions

Output Extraction Patterns

Use regex in outputs: to extract structured data from command output:

steps:
  - name: build
    func: shell
    do: |
      echo "Building..."
      echo "IMAGE=myapp:v1.2.3"
      echo "DIGEST=sha256:abc123"
      echo "SIZE=42MB"
    outputs:
      image: '{{ result.output | regexFind "IMAGE=(.+)" }}'
      digest: '{{ result.output | regexFind "DIGEST=(.+)" }}'
      size: '{{ result.output | regexFind "SIZE=(.+)" }}'

Common Extraction Patterns

# Extract key=value pair
output_field: '{{ result.output | regexFind "KEY=(.+)" }}'

# Extract JSON field from mixed output
json_field: '{{ result.data.field_name }}'

# Trim whitespace from output
clean_output: '{{ result.output | trim }}'

# Default value if empty
safe_value: '{{ result.output | default "unknown" }}'

# Extract version number
version: '{{ result.output | regexFind "([0-9]+\\.[0-9]+\\.[0-9]+)" }}'

JavaScript Expressions

For complex logic that goes beyond Go templates, OrchStep supports JavaScript via the Goja VM. JavaScript is used in:

  • assert conditions (when no {{ }} wrapper)
  • retry.when conditions
  • loop.until conditions
  • transform function do: blocks
# Assert with JavaScript
- func: assert
  args:
    condition: 'steps.api.status_code >= 200 && steps.api.status_code < 300'

# Retry with JavaScript condition
retry:
  when: |
    result.exit_code != 0 &&
    !result.output.includes('invalid') &&
    retry.attempt < 3

# Loop until with JavaScript
loop:
  count: 30
  until: 'steps.check.output.includes("READY")'

Best Practices

  • Use single quotes around Go template conditions to avoid YAML escaping: '{{ eq vars.x "y" }}'
  • Prefer regexFind over complex shell parsing for output extraction
  • Use default to provide fallback values: {{ vars.port | default 8080 }}
  • Use trim on extracted outputs to remove trailing newlines
  • Use JavaScript syntax for complex boolean logic (more readable than nested Go template and/or)