Quoted and Unquoted Template Variables in Concourse CI

October 18, 2018

Concourse CI is a powerful testing tool, and it is highly flexible and configurable. The integrated template engine replaces placeholders (named “variables” in CI) with content from external input. This system allows to create a pipeline definitions without exposing credentials to anyone except the person setting up the pipeline, or it allows to store volatile data (like version numbers) in external files, close together.

A lesser known fact is that Concourse supports two different types of placeholders, quoted and unquoted.

What is a placeholder?

A placeholder is a string in the pipeline definition which is defined somewhere else. This can be a name, a version number, a password, a ssh key, basically anything. Often this is used to hide credentials from anyone who can see or modify the code of the pipeline. Only in the end, when the pipeline is loaded using “fly set-pipeline”, the placeholders are replaced with the real data.

How to specify a placeholder

A variable, or placeholder, is specified using one of two different syntax forms:

  • ((variable))
  • {{variable}}

How to load variables

fly supports two commandline paratemers to specify variables:

  • –var “key=value”
  • –load-vars-from

Both parameters can be specified multiple times, values loaded later will overwrite values loaded earlier. All formats are loaded as YAML, the files specified with --load-vars-from must contain valid YAML.

Different types of placeholders

Unquoted placeholders

The version which is most common today, and which is documented in the set-pipeline documentation, is using two opening and two closing parenthesis.

Pipeline example:


Let’s assume the value of the $version variable is “11”, upon “flying” the pipeline this will be replaced to:


If the variable specified in (()) is not defined, no error will be raised. This is ignored by fly.

Quoted placeholders:

The older version of placeholders, but still valid and working is quoted placeholders. They use two opening and two closing curly braces.

For the example above, quoted placeholders will surely not be useful, the final pipeline would look like this:


Instead this can be used for places like when a variable is used as shell parameter, and the value might contain spaces or other problematic characters:

/usr/bin/transmit-message {{message-subject}} {{message-text}}
/usr/bin/transmit-message "Alert" "This is just a Test Message"

fly will raise an error during set-pipeline, if the variable specified in {{}} is not defined.

Understanding Keep-Alive Timeouts in the Cloud Foundry Networking Stack
Understanding Keep-Alive Timeouts in the Cloud Foundry Networking Stack

Introduction Setting up ingress routing is hard. Debugging problems when the routing tier is misconfigured ...

Let's Contribute to Golang!
Let's Contribute to Golang!

I want to share some particular insights I gained after attending the Contribution Workshop at GopherCon 20...