Programster's Blog

Tutorials focusing on Linux, programming, and open-source

YAML Cheatsheet

YAML is yet another markup language that is a lot more powerful than I originally realized. With PHP, it is easy to serialize to/from both JSON and YAML formats, but one can do "extra" things that you might not realize, when just writing the YAML file directly. You probably already know that you can add comments, something JSON doesn't support, but there are a whole bunch of other things too, that I will cover in this tutorial.

Related Posts

Table Of Contents

Anchors and Aliases

YAML has support for a really neat/useful feature for anchors and aliases, whereby one can re-use a chunk of YAML configuration without duplicating it. This is really useful in CI/CD pipelines, where one may wish to re-use a deployment step for multiple different environments, and the only thing that is different, are the environment variables.

The best way to demonstrate this is with an example. The example below shows a pipeline, where the "build and test" steps have been defined once, and then re-used in the develop and master branches:

definitions: 
  steps:
    - step: &build-test
        name: Build and test
        script:
          - mvn package
        artifacts:
          - target/**

pipelines:
  branches:
    develop:
      - step: *build-test
    master:
      - step: *build-test

The native PHP YAML supports this, so that when one parses such a file, it will automatically be "expanded out". Below is the formatted print_r output, of parsing such a config file:

Array
(
  [definitions] => Array
    (
      [steps] => Array
        (
          [0] => Array
            (
              [step] => Array
                (
                  [name] => Build and test
                  [script] => Array
                    (
                      [0] => mvn package
                    )
                  [artifacts] => Array
                    (
                      [0] => target/**
                    )
                )
            )
        )
    )
  [pipelines] => Array
    (
      [branches] => Array
        (
          [develop] => Array
            (
              [0] => Array
                (
                  [step] => Array
                    (
                      [name] => Build and test
                      [script] => Array
                        (
                          [0] => mvn package
                        )
                      [artifacts] => Array
                        (
                          [0] => target/**
                        )
                    )
                )
            )
          [master] => Array
            (
              [0] => Array
                (
                  [step] => Array
                    (
                      [name] => Build and test
                      [script] => Array
                        (
                          [0] => mvn package
                        )
                      [artifacts] => Array
                        (
                          [0] => target/**
                        )
                    )
                )
            )
        )
    )
)

As you can see, the alias has been resolved to the anchor.

Below is the code I used to generate such output:

<?php
$yamlString ='definitions: 
  steps:
    - step: &build-test
        name: Build and test
        script:
          - mvn package
        artifacts:
          - target/**

pipelines:
  branches:
    develop:
      - step: *build-test
    master:
      - step: *build-test';

// generate a YAML representation of the invoice
$obj = yaml_parse($yamlString);

$output = print_r($obj, true);

# remove empty lines
$output = implode(PHP_EOL, array_filter((explode("\n", $output))));

# convert from 4 spaces to 2 spaces
$output = str_replace("    ", "\t", $output);
$output = str_replace("\t", "  ", $output);

print $output;

Overrides

Sometimes one needs to use a defined reference block, but need to adjust a few attributes. Luckily, this can be done with the overrides syntax <<. This is demonstrated below whereby we set the deployment attribute to Production in the production branch, and Staging in the staging branch.

definitions:
  steps:
    - step: &deploy
        name: deploy
        runs-on:
          - self.hosted
          - linux
        script:
          - 'apt-get update -qq'
          - 'apt-get install php8.1-cli -y'

pipelines:
  branches:
    staging:
      - step:
          <<: *deploy
          deployment: Staging

    production:
      - step:
          <<: *deploy
          deployment: Production
          trigger: manual

In this case we were adding the deployment attribute, but if it already existed in the original reference, it would be overridden.

Array Merging - Not Possible

Once you learn about anchors, references, and overrides its easy to get very excited and convert all of your CI/CD pipeline files. However, there is one massive caveat, which is that those features were for merging objects with named keys, and does not work with arrays. E.g, it is not possible to take the merge a bunch of steps from the script section in previous examples, with a bunch of new elements.

E.g. the following effort to try and extend the script array is not possible:

definitions:
  script: &myScript
    - 'apt-get update -qq'
    - 'apt-get install php8.1-cli -y'

pipelines:
  branches:
    staging:
      - step:
        - script:
          <<: *myScript
          - echo "another line in script"
        deployment: Production
        trigger: manual

For more info about array merging not being possible, please refer to this Stack Overflow post, and this YAML Github issue. If you have found that there is a way, please comment, as I would love t be wrong.

References

Last updated: 31st August 2022
First published: 31st August 2022

This blog is created by Stuart Page

I'm a freelance web developer and technology consultant based in Surrey, UK, with over 10 years experience in web development, DevOps, Linux Administration, and IT solutions.

Need support with your infrastructure or web services?

Get in touch