sourceconditiontarget

✔

✔

✔

Description

The yaml resource reads and writes a key in a YAML file, addressed by a yamlpath expression.

source

Returns the value of one key from one file.

condition

Checks that the key holds value, or the source output when value is unset. With keyonly, checks only that the key exists.

target

Writes the value at the key. Keys already holding it are reported as up to date and left untouched, so a target that changes nothing does not create a commit.

Parameters

NameTypeDescriptionRequired
appendtoarrayboolean

“appendtoarray” appends the value as a new entry of the yaml sequence selected by “key”.

compatible:

  • target

default: false

remark:

  • appending is skipped when the sequence already holds the value, so running it twice changes nothing.
  • combined with “createmissingkey”, a missing sequence is created with the value as its only entry.
  • “key” must select the sequence itself, not one of its entries.
  • not supported by the “yamlpath” engine.

example:

  • key: $.allowedTags appendtoarray: true
commentstring

“comment” defines a comment added after the value.

compatible:

  • target

default: empty

remark:

  • the comment is only added when Updatecli changes the value.
createmissingkeyboolean

“createmissingkey” creates the key when the yaml document does not hold it yet.

compatible:

  • target

default: false

remark:

  • missing intermediate keys are created as nested maps.
  • the key is only ever created, never removed, and existing keys are left untouched.
  • a missing sequence index such as $.agents[0].name cannot be created.
  • a key selecting several nodes, such as $.agents[*].tag or $..tag, is rejected because the key cannot be created under each selected node.
  • not supported by the “yamlpath” engine.
  • the yaml file itself must already exist.

example:

  • key: $.image.tag createmissingkey: true
documentindexinteger

“documentindex” defines the index of the document to use in a multi document yaml file.

compatible:

  • source
  • condition
  • target

default: empty

remark:

  • when unset in a source, the value is retrieved from the first document matching the query.
  • when unset in a condition or a target, every document is evaluated by the query.

example:

  • documentindex: 0
  • documentindex: 1
enginestring

“engine” defines the library used to manipulate the yaml file.

No single Go library handles yaml well in every case, and each has its own strengths, so Updatecli lets you pick the one that suits your file.

default: go-yaml

remark:

  • accepted values are “yamlpath”, “go-yaml”, “default” or empty.
  • “go-yaml”, “default” and empty are equivalent.
filestring

“file” defines the path of the yaml file to use.

compatible:

  • source
  • condition
  • target

remark:

  • “file” and “files” are mutually exclusive.
  • the schemes “https://”, “http://” and “file://” are supported in a source or a condition.
filesarray

“files” defines the list of yaml file paths to use.

compatible:

  • condition
  • target

remark:

  • “file” and “files” are mutually exclusive.
  • the schemes “https://”, “http://” and “file://” are supported in a condition.
keystring

“key” defines the yaml key path.

compatible:

  • source
  • condition
  • target

remark:

  • “key” is a simpler version of yamlpath.
  • in a target, a key that a document does not hold is an error, so that a manifest never reports success for an update it did not make. The same rule applies to a wildcard such as $.agents[*].name: every position it selects must hold the key, otherwise the target fails instead of updating only some of them. Set “searchpattern” to update the positions holding the key and ignore the others.
  • a recursive selector such as $..name cannot report a partial match: it searches for the key itself, so it only selects the positions already holding it and never fails on the others.
  • a field path filtering on a key and value is not supported yet, see https://github.com/goccy/go-yaml/issues/290

example:

  • key: $.name
  • key: $.agent.name
  • key: $.agents[0].name
  • key: $.agents[*].name
  • key: $.‘agents.name’
  • key: $.repos[?(@.repository == ‘website’)].owner (requires engine “yamlpath”)
keyonlyboolean

“keyonly” checks only that the key exists, whatever its value.

compatible:

  • condition

default: false

keysarray

“keys” defines several yaml key paths to update with the same value.

compatible:

  • target

remark:

  • “key” and “keys” are mutually exclusive.
  • each entry accepts the same syntax as “key”.
  • every key is updated with the same value.

example:

  • keys:
    • $.image.tag
    • $.sidecar.tag
  • keys:
    • $.agents[0].version
    • $.agents[1].version
searchpatternboolean

“searchpattern” treats “file” and “files” as path patterns instead of exact paths.

The pattern must match the whole path, not just a substring.

The pattern syntax is:

    pattern:
        { term }
    term:
        '*'         matches any sequence of non-Separator characters
        '?'         matches any single non-Separator character
        '[' [ '^' ] { character-range } ']'
                    character class (must be non-empty)
        c           matches character c (c != '*', '?', '\\', '[')
        '\\' c      matches character c

character-range:
        c           matches character c (c != '\\', '-', ']')
        '\\' c      matches character c
        lo '-' hi   matches character c for lo <= c <= hi

compatible:

  • condition
  • target

default: false

remark:

  • in a target, it also relaxes the requirement that the key exists: a file that does not hold it is ignored instead of failing the target, and a wildcard key updates the positions holding it instead of failing on the others.
valuestring

“value” defines the value associated with the yaml key.

compatible:

  • condition
  • target

default: in a condition or a target, the output of the associated source.

The spec has two mutually exclusive pairs, and breaking either aborts the run before the pipeline starts:

file / files

One is mandatory. Setting both gives the attributes 'spec.file' and 'spec.files' are mutually exclusive; duplicates inside files are rejected too.

key / keys

One is mandatory. Setting both gives 'key' and 'keys' are mutually exclusive; duplicates inside keys are rejected.

Several parameters work in only one stage, which the table above does not make obvious:

keys

Target only. Updates several keys with the same value in one go - useful for an image tag repeated across a chart. A source or condition must use key.

keyonly

Condition only. Passes when the key exists, whatever its value.

comment

Target only. Appended inline after the value, and only when Updatecli actually changes it.

searchpattern

Not supported in a source. It turns file/files into glob patterns rather than exact names. A source using it fails with validation error in sources of type 'yaml': the attribute 'spec.searchpattern' is not supported for source.

Engines

engine picks the YAML library, because none of them handles every case well:

ValueBehaviour

default

Default when unset. Equivalent to go-yaml and to an empty value.

go-yaml

Same as default.

yamlpath

Required for filter expressions such as $.repos[?(@.repository == 'website')].owner.

Key syntax

Arrays are indexed with key[x], counting from zero, and can be chained with dots, key.array[3].key:

COUNTRY_CODE:
- BE
- FR
- LU

Here COUNTRY_CODE[1] is FR.

Escaping dots

A dot separates path elements, so a key that itself contains dots is escaped with a backslash. These two files are different:

image.tag: latest     # one key named "image.tag"  -> image\.tag
image:                # a key "tag" nested under "image" -> image.tag
    tag: latest

The escaped form must be written in single quotes, otherwise YAML consumes the backslash before Updatecli sees it:

targets:
  helm-chart-label:
    name: bump chart dependencies
    kind: yaml
    disablesourceinput: true
    spec:
      file: "/tmp/gateway.yaml"
      key: 'spec\.values\.labels\.service\.istio\.io/canonical-revision'
      value: "test"

Multi-document files

documentindex selects one document in a ----separated file, counting from zero. Its default is not "the first document" but something different per stage:

  • source - the value is taken from the first document matching the query.

  • condition - every document is evaluated.

  • target - every document is updated.

That last one surprises people. Given this file:

kind: Deployment
image:
  tag: 1.0.0
---
kind: Service
image:
  tag: 2.0.0

a target on $.image.tag with no documentindex rewrites both, even though the run report mentions a single key:

kind: Deployment
image:
  tag: 9.9.9 # updated by updatecli
---
kind: Service
image:
  tag: 9.9.9 # updated by updatecli

Set documentindex: 0 to touch only the first one.

Remote files

For a source and a condition, file accepts https://, http:// and file://. A target cannot write back to a URL and fails with URL scheme is not supported for YAML target.

Example

# updatecli.yaml
name: Example of YAML resources

scms:
  default:
    kind: github
    spec:
      user: "my git user"
      email: "my git email"
      owner: "olblak"
      repository: "chart"
      token: "{{ requiredEnv .github.token }}"
      username: "github username"
      branch: "main"

sources:
  lastRelease:
    kind: helmchart
    spec:
      url: https://charts.jenkins.io
      name: jenkins

conditions:
  chartVersion:
    name: "jenkinsci/jenkins Helm Chart used"
    kind: yaml
    scmid: default
    spec:
      file: "charts/jenkins/requirements.yaml"
      key: "dependencies[0].name"
      value: "jenkins"

targets:
  chartVersion:
    name: "jenkinsci/jenkins Helm Chart"
    kind: yaml
    scmid: default
    spec:
      file: "charts/jenkins/requirements.yaml"
      key: "dependencies[0].version"

What it says:

Source

Retrieve the version of the Jenkins helm chart from https://charts.jenkins.io.

Condition

Check that charts/jenkins/requirements.yaml has a dependencies array whose first element is jenkins. If not, the pipeline stops here.

Target

Update that first element to the source value in the GitHub repository olblak/chart, then publish the change as a pull request against master from a working branch.