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
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
First published: 31st August 2022