Expression Language Reference
The steps of a user-defined promotion process may take advantage of expressions in their configuration.
The documentation on this page assumes a general familiarity with the concept of Promotions and some knowledge of how a promotion process is defined as a sequence of discrete steps.
For an overview of Promotions, refer to the concepts doc.
For detailed coverage of individual promotion steps, refer to the Promotion Steps Reference.
Syntax
All steps in a user-defined promotion processes (i.e. those described by a
Stage
resource's spec.promotionTemplate.spec.steps
field) support the use of
expr-lang as a means of dynamically resolving values
in their configuration at promotion time.
All expressions must be enclosed within the ${{
and }}
delimiters. This is
not universally true for all applications of expr-lang. Kargo selected these
specific delimiters to mimic GitHub Actions expression syntax, which many users
will already be familiar with.
Basic example:
config:
message: ${{ "Hello, world!" }}
The above example will be evaluated as the following:
config:
message: Hello, world!
The expr-lang language definition docs provide a comprehensive overview of the language's syntax and capabilities, so this reference will continue to focus only on Kargo-specific extensions and usage.
Behavior
Kargo will evaluate expressions just-in-time as each step of a promotion process is executed. It will only evaluate expressions within values of a configuration block and will not evaluate expressions within keys. Expressions in values are evaluated recursively, so expressions may be nested any number of levels deep within a configuration block.
Validation
Kargo parses configuration blocks before evaluating expressions, so any configuration containing expressions must be well-formed YAML even prior to evaluation. Further validation (e.g. for adherence to a step-specific schema) is performed only after expressions are evaluated.
Types
Due to the requirement that configuration blocks be well-formed YAML, all fields
containing expressions must be string
s. Internally, all expressions will also
evaluate to string
s, however, Kargo will attempt to coerce the results to
other valid JSON types (YAML is a superset of JSON) including object
, array
,
number
, boolean
, and null
before concluding that the evaluated expression
should continue to be treated as a string
.
This behavior should be unsurprising and perhaps even familiar to experienced
YAML users, as YAML parsers behave in the same way. 42
, for example, is
interpreted as a JSON number
unless it is explicitly quoted (i.e. "42"
) to
specify that it should be interpreted as a string
.
In practice, this means care should be taken to use Kargo's built-in quote()
function in cases where an evaluated expression may appear to be a number
or
boolean
, for instance, but should be treated as a string
.
For example:
config:
numField: ${{ 40 + 2 }} # Will be treated as a number
strField: ${{ quote(40 + 2) }} # Will be treated as a string
The above example will be evaluated to the following:
config:
numField: 42
strField: "42"
Pre-Defined Variables
Kargo provides a number of pre-defined variables that are accessible within expressions. This section enumerates these variables, their structure, and use.
Name | Type | Description |
---|---|---|
ctx | object | string fields project , stage , and promotion provide convenient access to details of a Promotion . |
outputs | object | A map of output from previous promotion steps indexed by step aliases. |
secrets | object | A map of maps indexed by the names of all Kubernetes Secret s in the Promotion 's Project and the keys within the Data block of each. |
vars | object | A user-defined map of variable names to static values of any type. The map is derived from a Promotion 's spec.promotionTemplate.spec.vars field. Variable names must observe standard Go variable-naming rules. Variables values may, themselves, be defined using an expression. vars (contains previously defined variables) and ctx are available to expressions defining the values of variables, however, outputs and secrets are not. |
Expect other useful variables to be added in the future.
The following example promotion process clones a repository and checks out
two branches to different directories, uses Kustomize with source from one
branch to render some Kubernetes manifests that it commits to the other branch,
and pushes back to the repository. These steps make extensive use of the
pre-defined variables ctx
, outputs
, and vars
.
promotionTemplate:
spec:
vars:
- name: gitRepo
value: https://github.com/example/repo.git
- name: srcPath
value: ./src
- name: outPath
value: ./out
- name: targetBranch
value: stage/${{ ctx.stage }}
steps:
- uses: git-clone
config:
repoURL: ${{ vars.gitRepo }}
checkout:
- fromFreight: true
path: ${{ vars.srcPath }}
- branch: ${{ vars.targetBranch }}
create: true
path: ${{ vars.outPath }}
- uses: git-clear
config:
path: ${{ vars.outPath }}
- uses: kustomize-set-image
as: update-image
config:
path: ${{ vars.srcPath }}/base
images:
- image: public.ecr.aws/nginx/nginx
- uses: kustomize-build
config:
path: ${{ vars.srcPath }}/stages/${{ ctx.stage }}
outPath: ${{ vars.outPath }}
- uses: git-commit
as: commit
config:
path: ${{ vars.outPath }}
messageFromSteps:
- update-image
- uses: git-push
config:
path: ${{ vars.outPath }}
targetBranch: ${{ vars.targetBranch }}
- uses: argocd-update
config:
apps:
- name: example-${{ ctx.stage }}
sources:
- repoURL: ${{ vars.gitRepo }}
desiredRevision: ${{ outputs.commit.commit }}
Since the usage of expressions and pre-defined variables effectively
parameterizes the promotion process, the same promotion process can be reused in
other Projects
or Stages
with few, if any, modifications (other than the
definition of the static variables).
At present, such re-use can be achieved only through manual copy/paste, but
support for a new, top-level PromotionTemplate
resource type is planned for an
upcoming release.
Functions
Several functions are built-in to Kargo's expression language. This section describes each of them.
quote()
The quote()
function takes a single argument of any type and returns a string
representation. This is useful for scenarios where an expression evaluates to a
non-string
JSON type, but you wish to treat it as a string
regardless.
Example:
config:
numField: ${{ 40 + 2 }} # Will be treated as a number
strField: ${{ quote(40 + 2) }} # Will be treated as a string
warehouse()
The warehouse()
function takes a single argument of type string
, which is the
name of a Warehouse
resource in the same Project
as the Promotion
being
executed. It returns a FreightOrigin
object representing that Warehouse
.
The FreightOrigin
object can be used as an optional argument to the
commitFrom()
, imageFrom()
, or chartFrom()
functions to disambiguate the
desired source of an artifact when necessary.
See the next sections for examples.
commitFrom()
The commitFrom()
function takes the URL of a Git repository as its first
argument and returns a corresponding GitCommit
object from the Promotion
's
FreightCollection
.
In the event that a Stage
requests Freight
from multiple origins
(Warehouse
s) and more than one of those can provide a GitCommit
object from
the specified repository, a FreightOrigin
may be used as a second argument to
disambiguate the desired source.
Example:
config:
commitID: ${{ commitFrom("https://github.com/example/repo.git", warehouse("my-warehouse")).ID }}
imageFrom()
The imageFrom()
function takes the URL of a container image repository as its
first argument and returns a corresponding Image
object from the Promotion
's
FreightCollection
.
In the event that a Stage
requests Freight
from multiple origins
(Warehouse
s) and more than one of those can provide an Image
object from the
specified repository, a FreightOrigin
may be used as a second argument to
disambiguate the desired source.
Example:
config:
imageTag: ${{ imageFrom("public.ecr.aws/nginx/nginx", warehouse("my-warehouse")).Tag }}
chartFrom()
The chartFrom()
function takes the URL of a Helm chart repository as its first
argument and returns a corresponding Chart
object from the Promotion
's
FreightCollection
.
For Helm charts stored in OCI registries, the URL should be the full path to the repository within that registry.
For Helm charts stored in classic (http/s) repositories, which can store multiple different charts within a single repository, a second argument should be used to specify the name of the chart within the repository.
In the event that a Stage
requests Freight
from multiple origins
(Warehouse
s) and more than one of those can provide a Chart
object from the
specified repository, a FreightOrigin
may be used as a final argument to
disambiguate the desired source.
OCI registry example:
config:
chartVersion: ${{ chartFrom("oci://example.com/my-chart", warehouse("my-warehouse")).Version }}
Classic repository example:
config:
chartVersion: ${{ chartFrom("https://example.com/charts", "my-chart", warehouse("my-warehouse")).Version }}