Writing Sane YAML
YAML is a markup language that has some neat features but also many traps and pitfalls.
Using comment lines¶
You can use comment lines in YAML. Just start a line with the hash/pound character, just like in many shell-scripting languages:
# comment here do: ### indenting is not important for comments # now for some action - npm install yaml # some self referencing here... # this is important too: - npm install someotherthing
Comments are stripped out during parsing and do not interfere with your commands.
Error handling¶
When a rulebook is processed, the very first thing the Clarive rulebook engine does is parse the YAML structure.
The Clarive rulebook parser tries to catch as many YAML errors as possible during the YAML parsing phase. YAML parsing errors look like this:
error parsing YAML YAML::XS::Load Error: The problem: mapping values are not allowed in this context was found at document: 1, line: 2, column: 16 1: 2: - echo: hello: ------------------^ 3:
The above error is pointing to an invalid YAML structure, one unexpected colon
inside the value for the op echo
. The line-and-arrow ------^
underneath
line 2 points to the invalid character detected by the YAML parser.
Common pitfalls¶
Most YAML errors can be avoided following a few guidelines highlighted here.
Nesting¶
Make sure to nest your structures correctly. The rulebook YAML parser requires at least 1 space for indenting elements in YAML.
# one space indenting is pushing it a little do: - ls /tmp - exit 0
Be careful with flat hash ops, such as try-catch
and if-then-else
.
The keys need to be perfectly aligned for it to be parsed and compiled
correctly:
do: - if: '{{ 1 == 1 }}' then: - npm install yaml else: - fail: not true there
Pay attention to the above if-then-else
ops. They are perfectly aligned at
column 6. Any misaligning and they will not be interpreted correctly.
Use quotes abundantly¶
YAML slurps in key values without quotes, which can be very convenient. But get used to quoting your strings. It improves readability and reduces errors.
do: # this works - echo: hello world # but this is more readable - echo: "hello world"
Values that look like nested YAML¶
As in the error shown above, using colons inside your string values can be interpreted as hash keys by the parser:
do: # nasty errors here - echo: hello: world
Handlebar template errors¶
Handlebar template blocks {{ ... }}
can be easily confused
with hash structures such as { foo: 100, bar: 200 }
.
The YAML parser most likely will not error off on this one and
your handlebar block will be treated as an invalid hash that will
generate errors further down the road, into the compiling or running phases.
The solution is to use quotes around handlebar blocks to prevent confusing the rulebook engine.
do: - echo: "{{ 'this is ' + 10 + ' times better' }}"
Escaping special characters¶
YAML interprets special control characters, such as \n
or \t
.
When combined with certain ops or shell commands it may generate unexpected errors
at odd spots that look right, specially with handlebar {{ ... }}
ClaJS code.
This for instance will not be correctly parsed by the ClaJS engine. The newline needs to be escaped, otherwise the YAML parser will introduce a newline before the text is processed by the ClaJS runner.
do: - mydata =: | line1 line2 - lines =: "{{ mydata.split('\n') }}" # this will fail with a JS error - lines =: "{{ mydata.split('\\n') }}" # now that's better
Be aware that strings values built with the greater-than and pipe operators actually ignore newline characters, therefore no escaping is necessary.
do: - mydata =: | line1 line2 # this is the same as above, but no escaping needed - lines =: | {{ mydata.split('\n') }} # same here with a do:, no escaping is necessary: - lines = do: | mydata.split('\n')
The Difference between >
and |
¶
The greater-than operator >
will slurp all lines as a single line.
The pipe operator |
will maintain the newline character at the end of each line.