Release Announcement: Garden 0.12.31

Garden 0.12.31 is out! :tada:

This release adds major new extensions to Garden’s templating system: For-loops for lists, and list concatenation. Generating highly dynamic configuration with Garden just became a lot easier!

In addition, this release includes several bug fixes and minor improvements—see the changelog in the release notes for a full list of changes.

Many thanks to Pavel Stetsuk (@pstetsuk-exadel) for his contribution to this release!

Templates: for-loops for lists

You can map through a list of values by using the special $forEach/$return object.

You specify an object with two keys, $forEach: <some list or object> and $return: <any value>. You can also optionally add a $filter: <expression> key, which if evaluates to false for a particular value, it will be omitted.

Template strings in the $return and $filter fields are resolved with the same template context as what’s available when resolving the for-loop, in addition to ${item.value} which resolves to the list item being processed, and ${item.key}.

You can loop over lists as well as mapping objects. When looping over lists, ${item.key} resolves to the index number (starting with 0) of the item in the list. When looping over mapping objects, ${item.key} is simply the key name of the key value pair.

Here’s an example where we kebab-case a list of string values:

kind: Module
...
variables:
  values:
    - some_name
    - AnotherName
    - __YET_ANOTHER_NAME__
tasks:
  - name: my-task
    # resolves to [some-name, another-name, yet-another-name]
    args:
      $forEach: ${var.values}
      $return: ${kebabCase(item.value)}

Here’s another example, where we create an object for each value in a list and skip certain values:

kind: Module
...
variables:
  ports:
    - 80
    - 8000
    - 8100
    - 8200
services:
  - name: my-service
    ports:
      # loop through the ports list declared above
      $forEach: ${var.ports}
      # only use values higher than 1000
      $filter: ${item.value > 1000}
      # for each port number, create an object with a name and a port key
      $return:
        name: port-${item.key}  # item.key is the array index, starting with 0
        containerPort: ${item.value}

Templates: array concatenation

Any list/array value now supports a special kind of value, which is an object with a single $concat key. This allows you to easily concatenate multiple arrays.

Here’s an example where we concatenate the same templated value into two arrays of test arguments:

kind: Module
...
variables:
  commonArgs:
    - yarn
    - test
    - -g
tests:
  - name: test-a
    # resolves to [yarn, test, -g, suite-a]
    args:
      - $concat: ${var.commonArgs}
      - suite-a
  - name: test-b
    # resolves to [yarn, test, -g, suite-b]
    args:
      - $concat: ${var.commonArgs}
      - suite-b

Happy hacking!