Kargo Expressions Reference
Complete reference for Kargo's expression language based on expr-lang.
Syntax
All expressions use the ${{ }} delimiter:
config:
message: ${{ "Hello, world!" }}
tag: ${{ imageFrom(vars.imageRepo).Tag }}
Pre-defined Variables
Promotion Context (ctx)
| Variable | Type | Description |
|---|---|---|
ctx.project |
string | Project name |
ctx.stage |
string | Stage name |
ctx.promotion |
string | Promotion name |
ctx.targetFreight |
object | Target freight object |
ctx.targetFreight.name |
string | Freight name/hash |
ctx.targetFreight.displayID |
string | Human-readable freight ID |
ctx.meta |
object | Promotion metadata |
Step Outputs (outputs)
Access output from previous steps by alias:
${{ outputs['step-alias'].fieldName }}
${{ outputs.push.commit }}
${{ outputs['open-pr'].pr.id }}
User Variables (vars)
Access variables defined at Stage or PromotionTemplate level:
${{ vars.gitRepo }}
${{ vars.targetBranch }}
${{ vars.imageRepo }}
Task Context (task)
Access outputs from previous steps within the same PromotionTask:
${{ task.previousStep.output }}
Built-in Functions
Artifact Functions
commitFrom
Get Git commit information from freight.
# Basic usage
${{ commitFrom("https://github.com/example/repo.git").ID }}
${{ commitFrom("https://github.com/example/repo.git").Branch }}
${{ commitFrom("https://github.com/example/repo.git").Message }}
${{ commitFrom("https://github.com/example/repo.git").Author }}
${{ commitFrom("https://github.com/example/repo.git").Committer }}
${{ commitFrom("https://github.com/example/repo.git").Tag }}
# With warehouse origin
${{ commitFrom("https://github.com/example/repo.git", warehouse("my-warehouse")).ID }}
Available Fields:
| Field | Type | Description |
|---|---|---|
ID |
string | Commit SHA |
Branch |
string | Branch name |
Tag |
string | Tag name |
Message |
string | Commit message |
Subject |
string | First line of message |
Author |
string | Author identity |
Committer |
string | Committer identity |
imageFrom
Get container image information from freight.
${{ imageFrom("public.ecr.aws/nginx/nginx").Tag }}
${{ imageFrom("public.ecr.aws/nginx/nginx").Digest }}
${{ imageFrom("public.ecr.aws/nginx/nginx").RepoURL }}
${{ imageFrom("public.ecr.aws/nginx/nginx").Annotations }}
# With warehouse origin
${{ imageFrom("public.ecr.aws/nginx/nginx", warehouse("my-warehouse")).Tag }}
Available Fields:
| Field | Type | Description |
|---|---|---|
Tag |
string | Image tag |
Digest |
string | Image digest |
RepoURL |
string | Repository URL |
Annotations |
map | OCI annotations |
chartFrom
Get Helm chart information from freight.
${{ chartFrom("https://charts.example.com", "my-chart").Version }}
${{ chartFrom("https://charts.example.com", "my-chart").RepoURL }}
${{ chartFrom("https://charts.example.com", "my-chart").Name }}
# OCI charts
${{ chartFrom("oci://registry.example.com/charts", "my-chart").Version }}
Available Fields:
| Field | Type | Description |
|---|---|---|
Version |
string | Chart version |
RepoURL |
string | Repository URL |
Name |
string | Chart name |
Origin Functions
warehouse
Get warehouse freight origin for artifact lookups.
${{ warehouse("my-warehouse") }}
# Usage with artifact functions
${{ imageFrom("ghcr.io/example/app", warehouse("my-warehouse")).Tag }}
Metadata Functions
freightMetadata
Retrieve freight metadata.
${{ freightMetadata("freight-id").label }}
${{ freightMetadata(ctx.targetFreight.name).annotation }}
stageMetadata
Retrieve stage metadata.
${{ stageMetadata("dev").labels.environment }}
${{ stageMetadata(ctx.stage).annotations.owner }}
Kubernetes Resources
configMap
Read ConfigMap data.
${{ configMap("my-config").someKey }}
${{ configMap("my-config", "custom-namespace").data }}
secret
Read Secret data.
${{ secret("my-secret").password }}
${{ secret("my-secret", "custom-namespace").apiKey }}
Status Functions
success
Returns true if all preceding steps succeeded.
if: ${{ success() }}
failure
Returns true if any preceding step failed.
if: ${{ failure() }}
always
Always returns true (for unconditional execution).
if: ${{ always() }}
status
Get status of a specific step by alias.
if: ${{ status("my-step") == "Succeeded" }}
if: ${{ status("my-step") == "Errored" }}
if: ${{ status("my-step") == "Skipped" }}
Status Values:
SucceededErroredSkippedRunningPending
Utility Functions
quote
Convert value to quoted string.
${{ quote(42) }} # "42"
${{ quote(true) }} # "true"
unsafeQuote
Convert to string with escaped quotes (use with caution).
${{ unsafeQuote("hello \"world\"") }}
semverDiff
Compare two semantic versions and return difference type.
${{ semverDiff("1.2.3", "1.3.0") }} # "Minor"
${{ semverDiff("1.2.3", "2.0.0") }} # "Major"
${{ semverDiff("1.2.3", "1.2.4") }} # "Patch"
${{ semverDiff("1.2.3", "1.2.3") }} # "None"
Return Values:
Major- Major version changedMinor- Minor version changedPatch- Patch version changedMetadata- Only metadata/prerelease changedNone- Versions are identicalIncomparable- Versions cannot be compared
Expression Operators
Comparison Operators
${{ vars.value == "expected" }}
${{ vars.count != 0 }}
${{ vars.count > 5 }}
${{ vars.count >= 10 }}
${{ vars.count < 100 }}
${{ vars.count <= 50 }}
Logical Operators
${{ vars.enabled && vars.ready }}
${{ vars.dev || vars.test }}
${{ !vars.disabled }}
String Operations
${{ vars.name + "-suffix" }}
${{ vars.message contains "error" }}
${{ vars.name startsWith "prod" }}
${{ vars.name endsWith "-v1" }}
${{ vars.name matches "^prod-.*" }}
Ternary Operator
${{ vars.prod ? "production" : "development" }}
Nil Coalescing
${{ vars.optional ?? "default" }}
Complex Expressions
Conditional Logic
# Major version check
if: ${{ semverDiff(imageFrom(vars.imageRepo).Tag, outputs['read-version'].current) == 'Major' }}
# Combined conditions
if: ${{ success() && outputs['test'].passed == true }}
# Null-safe access
message: ${{ outputs['step']?.value ?? "default" }}
String Interpolation
message: "Updated ${{ ctx.stage }} to image ${{ imageFrom(vars.imageRepo).Tag }}"
body: |
{
"project": "${{ ctx.project }}",
"stage": "${{ ctx.stage }}",
"version": "${{ imageFrom(vars.imageRepo).Tag }}"
}
JSON Construction
body: ${{ quote({
"channel": vars.slackChannel,
"text": "Deployed " + ctx.freight.displayID + " to " + ctx.stage
}) }}
Warehouse Expression Filters
Git Commit Filters
Available fields for expressionFilter:
id- Commit SHAcommitDate- Commit timestampauthor- Author identitycommitter- Committer identitysubject- First line of commit message
# Exclude bot commits
expressionFilter: !(author contains '<bot@example.com>')
# Filter by message pattern
expressionFilter: subject contains 'feat:' || subject contains 'fix:'
# Multiple conditions
expressionFilter: !(subject contains '[skip-ci]') && author != 'dependabot'
Git Tag Filters
Additional fields for tag-based selection:
tag- Tag namecreatorDate- Tag creation datetagger- Tagger identityannotation- Tag annotation message
# Filter by creation date
expressionFilter: creatorDate.Year() >= 2024
# Filter by tag pattern
expressionFilter: tag matches '^v[0-9]+\\.[0-9]+\\.[0-9]+$'
HTTP Response Expressions
For http step success/failure conditions:
successExpression: response.status >= 200 && response.status < 300
failureExpression: response.status >= 500
# Body checks (JSON)
successExpression: response.body.status == "success"
failureExpression: response.body.error != nil
# Header checks
successExpression: response.header("X-Request-Id") != ""
Note: Success/failure expressions should NOT be wrapped in ${{ }}.
Variable Scoping
Priority Order (highest to lowest)
- Step-level variables
- PromotionTask variables
- PromotionTemplate variables
- Stage variables
Example
# Stage
spec:
vars:
- name: repo
value: https://github.com/example/repo.git
- name: branch
value: main
# PromotionTemplate (overrides stage vars)
spec:
vars:
- name: branch
value: develop # Overrides stage value
# Step (can reference both)
steps:
- uses: git-clone
config:
repoURL: ${{ vars.repo }} # From stage
branch: ${{ vars.branch }} # From template (overridden)
Type Handling
# Numeric
numField: ${{ 40 + 2 }} # 42
# String
strField: ${{ quote(40 + 2) }} # "42"
# Boolean
enabled: ${{ vars.prod == true }}
# Array access
first: ${{ ctx.freight.images[0].tag }}
# Map access
value: ${{ ctx.freight.commits["repo-url"].ID }}
Best Practices
- Use
quote()for JSON strings - Ensures proper escaping - Validate expressions in expr-lang playground - Test complex expressions before deployment
- Use descriptive variable names - Improves readability
- Handle nil values - Use
??operator for optional values - Keep expressions simple - Break complex logic into multiple steps